Levels rise in cost far faster than they rise in number, and deciding out loud where to stop is a better outcome than a project that stalls at 4 while everyone assumes it is heading for 8.
0-2 names that do not resolve. free, and every fix is an improvement.
3 return types and property types the code does not state.
4 dead code and always-true conditions. mostly real.
5 argument types on every call. a lot of docblocks.
6 no missing typehints anywhere. months, on a mature codebase.
7-8 union handling and nullability. worth it for a library.
9 mixed is forbidden. rarely worth it for an application.
Level 3 is the first that asks for information the codebase does not contain, and the annotations it wants are usually describing a structure that has outgrown being an array — so the errors point at something real even when the fix is a docblock. Writing the chosen level and the reason into the configuration file as a comment is what stops the next person quietly raising it and generating a four-thousand-line baseline.