ucn 5.4.1 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/.claude/skills/ucn/SKILL.md +58 -236
  2. package/.claude/skills/ucn/references/commands.md +144 -68
  3. package/.claude/skills/ucn/references/resolution-rules.md +171 -0
  4. package/.claude/skills/ucn/references/trust-contract.md +27 -33
  5. package/README.md +18 -12
  6. package/cli/index.js +42 -16
  7. package/core/accessors.js +118 -3
  8. package/core/account.js +30 -0
  9. package/core/analysis.js +508 -264
  10. package/core/ast-analysis.js +76 -117
  11. package/core/async-producers.js +1729 -0
  12. package/core/bridge.js +1877 -268
  13. package/core/brief.js +6 -0
  14. package/core/build-worker.js +78 -14
  15. package/core/cache.js +522 -31
  16. package/core/callers.js +12053 -1047
  17. package/core/check.js +30 -38
  18. package/core/class-identity.js +1028 -0
  19. package/core/command-contracts.js +6 -6
  20. package/core/configuration-items.js +86 -0
  21. package/core/contract-membership.js +2262 -0
  22. package/core/cpp-scope.js +532 -0
  23. package/core/deadcode.js +171 -49
  24. package/core/decorator-binding.js +260 -0
  25. package/core/discovery.js +281 -164
  26. package/core/errors.js +52 -0
  27. package/core/execute.js +21 -9
  28. package/core/external-macros.js +326 -0
  29. package/core/graph-build.js +277 -8
  30. package/core/graph.js +35 -2
  31. package/core/ignore-rules.js +472 -0
  32. package/core/imports.js +504 -42
  33. package/core/index-ir.js +94 -11
  34. package/core/inprocess-clients.js +636 -0
  35. package/core/ir.js +87 -8
  36. package/core/macro-expansion.js +1416 -0
  37. package/core/output/analysis-ext.js +6 -6
  38. package/core/output/analysis.js +18 -2
  39. package/core/output/brief.js +3 -0
  40. package/core/output/doctor.js +4 -0
  41. package/core/output/endpoints.js +15 -6
  42. package/core/output/find.js +11 -2
  43. package/core/output/lines.js +8 -2
  44. package/core/output/refactoring.js +121 -14
  45. package/core/output/reporting.js +31 -3
  46. package/core/output/shared.js +14 -0
  47. package/core/output-budget.js +316 -122
  48. package/core/parallel-build.js +124 -47
  49. package/core/parser.js +3 -2
  50. package/core/project.js +457 -60
  51. package/core/provenance-facts.js +156 -12
  52. package/core/provenance-overload.js +30 -3
  53. package/core/provenance.js +104 -30
  54. package/core/pytest-fixtures.js +434 -0
  55. package/core/python-fixture-flow.js +17 -3
  56. package/core/python-modules.js +173 -0
  57. package/core/reflection.js +877 -0
  58. package/core/registry.js +1 -1
  59. package/core/reporting.js +234 -52
  60. package/core/request-helpers.js +561 -0
  61. package/core/route-graph.js +1922 -0
  62. package/core/route-lists.js +2414 -0
  63. package/core/rust-macro-expansion.js +2113 -0
  64. package/core/rust-modules.js +185 -0
  65. package/core/search.js +121 -29
  66. package/core/shared.js +19 -1
  67. package/core/test-name-bindings.js +256 -0
  68. package/core/type-denotation.js +1161 -0
  69. package/core/type-references.js +3229 -0
  70. package/core/verify.js +3360 -672
  71. package/languages/adapter.js +31 -5
  72. package/languages/c-family.js +4061 -212
  73. package/languages/c-macro-invocations.js +380 -0
  74. package/languages/c-preprocessor.js +254 -0
  75. package/languages/csharp.js +1406 -49
  76. package/languages/go.js +1243 -70
  77. package/languages/index.js +728 -6
  78. package/languages/java.js +473 -61
  79. package/languages/javascript.js +1270 -197
  80. package/languages/lexical-scope.js +1280 -0
  81. package/languages/python.js +1557 -72
  82. package/languages/rust-macro-rules.js +1020 -0
  83. package/languages/rust-value-flow.js +416 -0
  84. package/languages/rust.js +2237 -115
  85. package/languages/utils.js +298 -4
  86. package/mcp/server.js +25 -11
  87. package/package.json +1 -1
@@ -1,67 +1,46 @@
1
1
  # UCN command reference
2
2
 
3
- UCN exposes exactly 18 task-oriented public commands. CLI uses hyphenated names; MCP uses snake case.
3
+ UCN exposes exactly 18 public commands. CLI spells multiword names with hyphens (`audit-async`), MCP with snake case (`audit_async`) through one `ucn` tool whose `command` parameter selects the command.
4
4
 
5
- Use grep/ripgrep for simple literals, error messages, configuration, filenames,
6
- Markdown, and unsupported languages. Use UCN for exact symbol identity,
7
- callers/callees, change impact, test linkage, dependency/API questions, and AST
8
- structural or code-only search.
5
+ Use text search (grep/ripgrep) for simple literals, error messages, configuration, filenames, Markdown, and unsupported languages. Use UCN for exact symbol identity, callers/callees, change impact, test linkage, dependency/API questions, and AST structural or code-only search.
9
6
 
10
7
  ## Understand and navigate
11
8
 
12
9
  | Command | Purpose |
13
10
  |---|---|
14
- | `show <handle>` | Default symbol summary, callers, and callees. Select `summary,callers,callees,source,dependencies,tests,types,example,related` with `--sections`. |
15
- | `find <name>` | Locate definitions and stable handles. Activity counts are pinned call candidates (confirmed + visible unverified); proved other-target calls are separate. Use `--type=type`, `--limit=N`, and `--with-source` as needed. |
16
- | `usages <name>` | Inventory definitions, calls, imports, type references, and literal comment/string/docstring text. Those text sites appear under `OTHER TEXT` unless `--code-only`. |
17
- | `search [pattern]` | Literal text search by default; add `--regex` for RE2-compatible linear-time regular expressions, or use structural filters such as `--type`, `--param`, `--receiver`, `--returns`, or `--decorator`. Unsafe nested repetition is rejected; use ripgrep for unsupported advanced syntax. |
18
- | `source <handle\|file:range>` | Extract a function, class-like declaration, or exact line range. |
19
- | `trace <handle>` | Traverse callees by default. Use `--direction=callers` for blast radius and add `--to=entrypoints` for paths to roots. |
11
+ | `show <handle>` | Symbol summary, callers, and callees. `--sections=summary,callers,callees,source,dependencies,tests,types,example,related` selects projections. |
12
+ | `find <name>` | Locate definitions and their stable handles. Text shows the top 5 in detail and counts the rest; JSON returns up to 500; `--limit=N` raises both. `--type=type`, `--with-source`, `--compact`, `--exact`. |
13
+ | `usages <name>` | Every line where the name occurs: definitions, calls, imports, type references, and comment/string/docstring text (`OTHER TEXT`), test files included. `--code-only`, `--exclude-tests`, `--context=N`. |
14
+ | `search [term]` | Literal text by default; `--regex` for RE2-compatible linear-time regular expressions; structural filters `--type`, `--param`, `--receiver`, `--returns`, `--decorator`, `--exported`, `--unused`. |
15
+ | `source <handle\|file:range>` | Extract a function, class-like declaration, or exact line range (`src/a.js:10-30`, or `--file=PATH --range=N-M`). `--raw`, `--max-lines=N`. |
16
+ | `trace <handle>` | Callees by default (depth 3). `--direction=callers` for blast radius, `--to=entrypoints` for paths to roots, `--depth=N`, `--expand-unverified`. |
20
17
 
21
18
  ## Change and validation
22
19
 
23
20
  | Command | Purpose |
24
21
  |---|---|
25
- | `impact [handle]` | Show direct symbol impact when given a handle; accessor targets include receiver-tiered property reads/writes as a separate dependency band. Without a handle, analyze the Git diff. |
26
- | `tests <handle\|file>` | Find statically linked direct tests. Set `--depth=N` for transitive affected tests. Empty results are not runtime coverage proof. |
27
- | `check [handle]` | Validate confirmed call-site arity for a symbol; without one, run the composed pre-commit diagnostic. |
28
- | `plan <handle>` | Preview `--rename-to`, `--add-param`, or `--remove-param` edits. For renames, the proven closure can include overload/signature groups, inheritance/trait/Go-interface slots, accessor reads/writes, exact call/reference tokens, imports/exports, Python `__all__` strings, and module-attribute references. Source comments/strings are explicit `reviewItems`; non-source files get a search handoff. Open ownership or method sets stay `needsReview`; the command never applies or compiles edits. |
22
+ | `impact [handle]` | Direct impact of one symbol; without a handle, the Git diff (`--base=<ref>`, `--staged`). Property targets add an access-site band, type targets a reference-site band. |
23
+ | `tests <handle\|file>` | Statically linked direct tests; `--depth=N` adds transitively affected tests; `--calls-only` keeps direct calls and test-case matches. |
24
+ | `check [handle]` | Call-site validation for one symbol against its declaration at `--base` (default `HEAD`); without a handle, the composed pre-commit check of the diff (`--base`, `--staged`). |
25
+ | `plan <handle>` | Preview `--rename-to=X`, `--add-param=p` (`--default-value=v`), or `--remove-param=p`. Never edits files. |
29
26
 
30
27
  ## Repository and architecture
31
28
 
32
29
  | Command | Purpose |
33
30
  |---|---|
34
- | `repo` | Repository orientation. Select `summary,files,stats,health` with `--sections`; `--deep` includes readiness evidence. Skipped unsupported source is listed with a grep/language-tool handoff. |
35
- | `deps <file>` | File dependency graph. Use `--direction=imports\|importers\|both`, `--detailed`, or `--cycles`. Cycles distinguish eager edges from function-local, Python typing-guarded, and TypeScript type-only edges. Complete cycle groups remain visible when enumeration is capped. |
36
- | `api [file]` | Static exported/public surface for a project or file. An exact file includes tests; broader scans exclude tests with a count. Use `--include-tests` to include them. |
37
- | `entrypoints` | Framework, route, task, test, and runtime entry points. |
38
- | `endpoints` | Server/client HTTP surface; `--bridge` adds advisory matching. Test sites carry `[test]`; `--exclude-tests` removes them and `--in=DIR` scopes the inventory. |
31
+ | `repo` | Orientation. `--sections=summary,files,stats,health`; `--deep` adds readiness evidence; `--hot`, `--functions`, `--detailed`, `--top-level`, `--in=DIR`. |
32
+ | `deps <file>` | File dependency graph: `--direction=imports\|importers\|both`, `--depth=N`, `--detailed`. `deps --cycles` (no file target) reports circular imports. |
33
+ | `api [file]` | Exported/public surface of a project or file. An exact file includes tests; broader scans exclude tests with a count unless `--include-tests`. |
34
+ | `entrypoints` | Framework, route, task, test, and runtime entry points. `--type`, `--framework`; tests excluded unless `--include-tests`. |
35
+ | `endpoints` | Server/client HTTP surface. `--bridge`, `--server-only`, `--client-only`, `--unmatched`, `--method`, `--prefix`, `--hide-uncertain`, `--exclude-tests`, `--in=DIR`. |
39
36
 
40
37
  ## Focused audits and runtime evidence
41
38
 
42
39
  | Command | Purpose |
43
40
  |---|---|
44
- | `deadcode` | Conservative unreferenced-symbol candidates for review. Statically named reflection targets, modeled computed-dispatch members, unknown decorated/annotated callables, and member-assigned event handlers are withheld by default. Recognized dynamic reflection is counted and warned because it cannot be attributed. |
45
- | `audit-async` | Potential missing-await sites in JavaScript/TypeScript/Python and C#. MCP spelling: `audit_async`. |
46
- | `stacktrace <text>` | Advisory stack-frame parsing and source lookup. |
47
-
48
- ## Stable symbol identity
49
-
50
- Symbol-listing commands emit handles such as `src/api.ts:42:handler`. Pass the full handle to symbol commands. `path:line` also works. Handles prevent same-named definitions from being silently combined.
51
-
52
- Definition handles and source spans start at the first decorator or annotation when present; literal usages point at the actual token line. Use a symbol's `nameLine` (when present, otherwise `startLine`) to compare declaration tokens with usages.
53
-
54
- Structural `search --param` matches parameter names, types, and defaults; `--returns` matches return annotations. Both exclude AST comments and preserve string contents. `--unused` lists callable symbols without call edges, not safe-delete candidates; decorated runtime registrations may still appear. Its safety note and decorator tags are retained in `--lines` output. Use `deadcode` and `usages` before deletion.
55
-
56
- `repo` summary/stats `buildTime` is the duration of the last index build (discovery, parsing, and graphs), retained in the cache. It excludes cache loading/saving and query execution, so it is not command wall time; `buildTimeNote` states this boundary.
57
-
58
- `--lines` writes one record per output line. `usages --lines` groups occurrences by source line and tags their kinds and counts. JSON retains individual occurrence records.
59
-
60
- Public JSON source paths (`file`, caller files, dependency roots and edges) are project-relative, with the absolute base in `meta.pathBase`. Project roots and external paths remain absolute. Indexed absolute handles are accepted as well as relative handles.
61
-
62
- Default test exclusions follow language conventions. Python `spec.py` and `*_spec.py` are included; `test_*.py`, `*_test.py`, and test directories are excluded. Structural search reports hidden test-file counts, including on empty results. `--include-tests` disables these defaults; explicit `--exclude` patterns still apply.
63
-
64
- `audit-async` checks recognized async producers, including Python coroutine calls discarded in synchronous functions or module scope and captured JS/TS/HTML promises used as resolved values in the same lexical scope. Promise returns and handlers are valid; alias flow and unknown receivers require compiler/type-checker review.
41
+ | `deadcode` | Conservative unreferenced-symbol candidates for review. `--include-exported`, `--include-decorated`, `--include-tests`, `--in=DIR`. |
42
+ | `audit-async` | Missing-await findings in JavaScript/TypeScript/HTML, Python and C#, and unpolled futures in Rust. MCP spelling: `audit_async`. |
43
+ | `stacktrace <text>` | Advisory stack-frame parsing and source lookup (MCP parameter `stack`). |
65
44
 
66
45
  ## Common flags
67
46
 
@@ -70,29 +49,31 @@ Default test exclusions follow language conventions. Python `spec.py` and `*_spe
70
49
  | `--sections=a,b` | Select `show` or `repo` projections. |
71
50
  | `--file=<pattern>` | Scope or disambiguate by file. |
72
51
  | `--class-name=<name>` | Scope a member when no handle is available. |
52
+ | `--line=N` | Pin the definition at this line (the middle component of a handle). |
73
53
  | `--in=<directory>` | Limit query scope to a directory. |
74
- | `--exclude=<patterns>` | Exclude matching paths. |
75
- | `--limit=N` | Default maximum of 500 results for `find`, text `search`, `deadcode`, `api`, and `repo` files; structural `search` defaults to 50. Explicit limits override these caps; `usages` and `--lines` are uncapped by default. |
76
- | `--include-bundled` | Include `*.min.js` and `*.bundle.js` in discovery, respecting user exclusions and bypassing the shared cache. By default these and `*.map` are disclosed as skipped sources and completeness is partial. Source maps remain unindexed. MCP: `include_bundled=true`. |
77
- | `--depth=N` | Set trace/dependency/test traversal depth. |
78
- | `--direction=<value>` | Select trace or dependency direction. |
79
- | `--all` | Lift result and formatter caps where supported. It is recommended only for commands that accept it. |
80
- | `--max-chars=N` | Set the hard CLI text budget, including notices and preserved trust metadata (10K targeted / 3K broad by default; 100K ceiling). MCP spelling: `max_chars`. JSON is not transport-truncated. |
81
- | `--compact` / `--no-compact` | Select token-efficient or full semantic output. |
82
- | `--range=N-M` | Extract an explicit line range with `source --file=<path>`. |
83
- | `--json` | Emit the stable CLI `{ meta, data }` envelope; `meta.contract` carries the truth boundary, decision safety, and next actions. |
84
- | `--lines` | `find/usages/search/show/impact`: uncapped `path:line:text` listings, with tier tags after a tab. `show` accepts callers/callees sections; default callers. Accounting and notes go to stderr. Exit 0 for records, 1 for none, 2 for errors. Explicit row limits disclose omissions. |
85
- | `--raw` | `source`: code only, including full large classes. Notes and explicit `--max-lines` truncation travel on stderr. In CLI shell modes, exceeding an explicit `--max-chars` fails before stdout instead of truncating it. |
86
- | `--expand-unverified` | Follow possible caller edges while preserving their unverified status. |
87
- | `--base=<ref>` / `--staged` | Scope Git-diff `impact` or target-less `check`. |
88
- | `--no-cache` / `--clear-cache` | Bypass or clear the current project's per-user cache. Set `UCN_CACHE_DIR` to override its root. |
89
- | `--workers=N` | Set build workers; `0` disables parallel build. |
90
- | `--include-exported` | Include exported symbols in `deadcode`. |
91
- | `--include-decorated` | Include decorated symbols in `deadcode`. |
54
+ | `--exclude=<patterns>` | Exclude matching paths (`--not` is an alias). |
55
+ | `--limit=N` | Default maximum of 500 results for `find`, text `search`, `deadcode`, `api`, and `repo` files; structural `search` defaults to 50. Explicit limits override these caps and disclose omissions; `usages` and `--lines` are uncapped by default. |
56
+ | `--top=N` | Cap listed callers/callees and ranked results; the header discloses the cut (`3 shown of 21`). Caller lists have no default cap. |
57
+ | `--context=N` | Lines of context around `search`/`usages` matches. |
58
+ | `--include-tests` / `--exclude-tests` | Lift or apply the language's test-file exclusions where a command filters them (`--exclude-tests`: `usages`, `endpoints`, `entrypoints`). `usages` ignores `--include-tests` (tests are listed by default) and says so. |
59
+ | `--include-bundled` | Index `*.min.js` and `*.bundle.js`, respecting user exclusions and bypassing the shared cache. By default these and `*.map` are disclosed as skipped sources and completeness is partial. Source maps remain unindexed. MCP: `include_bundled=true`. |
60
+ | `--depth=N` | Trace, dependency, or test traversal depth. |
61
+ | `--direction=<value>` | Trace (`callees`/`callers`) or dependency (`imports`/`importers`/`both`) direction. |
62
+ | `--all` | Lift result and formatter caps where a command supports it; the truncation notice says when it does. |
63
+ | `--max-chars=N` | Text budget in characters (10K targeted / 3K broad by default; 100K ceiling), including notices and trust lines. Trust lines are reserved first; a limit too small for them withholds the answer and names the budget that carries them. MCP: `max_chars`. JSON is not transport-truncated. |
64
+ | `--compact` / `--no-compact` | Token-efficient or full presentation (`show`/`impact` default compact, `usages` full). |
65
+ | `--range=N-M` | Explicit line range with `source --file=<path>`. |
66
+ | `--json` | Stable `{ meta, data }` envelope; `meta.contract` carries the truth boundary, decision safety, and next actions. |
67
+ | `--lines` | `find`/`usages`/`search`/`show`/`impact`: uncapped `path:line:text` records with tier tags after a tab. `show` accepts the callers/callees sections (default callers). Accounting and notes go to stderr. Exit 0 for records, 1 for none, 2 for errors. |
68
+ | `--raw` | `source`: code only, including full large classes. Notes and `--max-lines` truncation travel on stderr. In shell modes an explicit `--max-chars` fails before stdout instead of truncating. |
69
+ | `--expand-unverified` | `trace --direction=callers`: follow possible edges; descendants stay marked possible. |
70
+ | `--base=<ref>` / `--staged` | Git scope for target-less `impact` and `check`. `check <handle> --base=<ref>` reads the old declaration at that ref. `impact <handle>` takes neither; `check <handle>` does not take `--staged`. |
71
+ | `--no-cache` / `--clear-cache` | Bypass or clear the project's per-user cache (`--clear-cache --all` clears every project). `UCN_CACHE_DIR` overrides the cache root. |
72
+ | `--workers=N` | Build workers; `0` disables the parallel build. |
92
73
  | `--code-only` | Exclude comments and strings in `search`/`usages`. |
93
- | `--regex` | Interpret a `search` term as a regular expression. Without it, the term is literal. |
74
+ | `--regex` | Interpret a `search` term as a regular expression; without it the term is literal. |
94
75
 
95
- ## Target forms
76
+ ## Target forms and exit codes
96
77
 
97
78
  ```text
98
79
  ucn [target] <command> [argument] [flags]
@@ -100,13 +81,108 @@ ucn [target] <command> [argument] [flags]
100
81
 
101
82
  Omit the target for the current project. A target may be a file, directory, or quoted glob such as `"src/**/*.py"`.
102
83
 
103
- Ordinary text and shell command errors exit 2. JSON command errors retain
104
- exit 1 with `meta.ok: false` and an `error` field; successful empty JSON
105
- results exit 0. Target-less `check` exits 1 for `TRUST: BLOCKED`, 0 for other
106
- completed checks, and 2 when the check could not run. Working-tree `impact`
107
- and `check` count untracked documentation/configuration in their non-source
108
- path note; `--staged` excludes all untracked paths.
84
+ Text and shell command errors exit 2. JSON command errors exit 1 with `meta.ok: false` and an `error` field; successful empty JSON results exit 0. Target-less `check` exits 1 for `TRUST: BLOCKED`, 0 for other completed checks, and 2 when the check could not run; `check <handle>` exits 1 when it reports a mismatch or an unverified call site. An exception inside UCN is an internal error: the message starts `Internal error:` on every surface and CLI JSON adds `meta.internalError: true`; the exit code is that of any command error.
85
+
86
+ ## Stable symbol identity
87
+
88
+ Symbol-listing commands emit handles such as `src/api.ts:42:handler`. Pass the full handle to symbol commands; `path:line` also works. Handles prevent same-named definitions from being silently combined. When a plain name selects more than one definition, `show`, `source`, `trace`, `impact`, `tests`, `check` and `plan` carry the same ambiguity warning; `show` lists the competing handles once above the sites.
89
+
90
+ Definition handles and source spans start at the first decorator or annotation when present; literal usages point at the actual token line. Use a symbol's `nameLine` (when present, otherwise `startLine`) to compare declaration tokens with usages.
91
+
92
+ Public JSON source paths (`file`, caller files, dependency roots and edges) are project-relative, with the absolute base in `meta.pathBase`. Project roots and external paths remain absolute. Indexed absolute handles are accepted as well as relative handles.
93
+
94
+ Default test exclusions follow language conventions. Python `spec.py` and `*_spec.py` are production paths; `test_*.py`, `*_test.py`, and test directories are test paths. Structural search reports hidden test-file counts, including on empty results. `--include-tests` disables these defaults; explicit `--exclude` patterns still apply (`--exclude=spec` means the requested path exclusion).
95
+
96
+ ## Command notes
97
+
98
+ ### find
99
+
100
+ Activity counts are definition-pinned: confirmed plus visible unverified call candidates. Calls proved to belong to another same-name target are disclosed separately and excluded from the activity total. Broad queries rank candidates by inexpensive approximate usage totals before applying the row limit; only returned definitions receive caller adjudication, and the selection note discloses that approximation. Text shows the top 5 results in detail and counts the rest; JSON returns up to 500; `--limit=N` raises both.
101
+
102
+ ### usages
103
+
104
+ `usages` is a literal-name inventory, not target binding: it lists every line the caller `ACCOUNT` counts. Comment/string/docstring occurrences and non-code text (JSX children, HTML markup and attributes) appear under `OTHER TEXT` unless `--code-only`; test files are listed unless `--exclude-tests`, which states how many test-file usages it hid. Identifier boundaries are Unicode-aware and match `grep -w`: `hit` never matches inside `hitΔ`, while `$` is a boundary (`buy${...}`, `$fail`, `ws$close()` all count). `usages --lines` emits one record per source line, combining occurrence kinds and disclosing repeated occurrences (JSX open/close tags included); JSON keeps the individual occurrence records, so a source line can appear more than once there.
105
+
106
+ ### search
107
+
108
+ The term is literal by default; pass `--regex` only when regular-expression semantics are intended. Ordinary regex patterns run through an RE2-compatible linear-time engine; unsafe nested repetition is rejected, and unsupported advanced syntax should be handed to ripgrep. Structural `--param` matches parameter names, types, and defaults; `--returns` matches return annotations; both exclude AST comments and preserve string contents. `--type` accepts `function`, `class`, `call`, `method`, `type`, `state`, `field`, `constant`, `macro`. `--unused` lists callable symbols without call edges, not safe-delete candidates: decorated runtime registrations may still appear, and its safety note and decorator tags are kept in `--lines` output. Structural search discloses hidden test files, including on empty results; `--include-tests` gives the full indexed inventory.
109
+
110
+ ### show and impact
111
+
112
+ `show --lines` lists callers by default; `--sections=callees` switches bands; unverified records end in a tab and `# unverified: <reason>`. Under a text budget, `show` and `impact` keep a head of every tier section (confirmed, runtime dispatch, unverified, callees) with a `+N more` line each, so a long confirmed list never hides the unverified band.
113
+
114
+ When the selected definition is a property/getter/setter, `impact` adds a separate `PROPERTY ACCESS SITES` band: confirmed reads/writes have receiver identity, matching attribute syntax with an unresolved receiver stays unverified. Reads and writes carry the access kind and token column; getter/setter handles describe the same property, and unambiguous inherited properties share the owner evidence. These are change dependencies, not caller edges, so the caller `ACCOUNT` stays call-shaped. When the selected definition is a type, interface, enum, trait, or record, `impact` adds a `TYPE REFERENCE SITES` band: annotation and reference sites confirmed by an import link to the definition's file (or package scope in Go/Java), the rest unverified with a reason. `DEPENDENCY SITES` counts them; `CALL SITES` stays call-shaped.
115
+
116
+ Target-less `impact` and `check` diff the working tree against `HEAD` and include untracked, non-ignored source files as whole-file additions, so new modules are checked before `git add`; `--staged` keeps its index-only meaning and excludes all untracked paths. The changed-path note also counts untracked documentation and configuration. Classes, interfaces, types, and fields appear in separate declaration bands with their dependency sites. Target-less `impact --lines` lists Git-diff callers with per-target accounting.
117
+
118
+ ### tests
119
+
120
+ `tests` finds statically linked direct tests through the same re-export and rename chains callers follow (`export * from`). Every test-file call site the caller engine attributes to the target is listed in its tier (unverified ones for a uniquely named target), whatever its shape or file layout: implicit-`this` and static-import calls, calls in `TEST_F` bodies, receivers a pytest fixture injects. A property or getter target lists test reads whose receiver is typed as its owner (`result = runner.invoke(); result.stdout` with `invoke() -> Result`). `--depth=N` adds transitively affected tests. Empty results are not runtime coverage proof; treat paths without static test links as test-planning signals. Script `tests` and `trace` with `--json`.
121
+
122
+ ### check
123
+
124
+ `check <handle>` validates confirmed call-site arity and compares the declaration with its version at `--base` (default `HEAD`): call sites the old declaration bound are checked against the new signature and the remaining overloads. A site that fits no overload is a mismatch, never an excluded other-target line; one that another overload may take after the change is uncertain. Target-less `check` composes the diff impact, signature validation and affected tests for the pending change; modified or deleted declarations make it `BLOCKED` until reviewed with the language toolchain, because arity checks cannot validate shape or inheritance compatibility.
125
+
126
+ ### plan
127
+
128
+ The selected declaration is only the starting point. When the index proves the relationship, the rename unit closes over overload/signature groups, base and override declarations across the whole resolved hierarchy (through intermediate classes that do not redeclare the member; same-signature slot only where overloads exist, with the type arguments of generic base clauses substituted, so `Fmt : Visitor<TextWriter, bool>` overrides `Visit(TState, ..)` as `Visit(TextWriter, ..)`), overrides in anonymous classes (`new Listener<String>() { .. }`) and JS/TS class expressions, declared `implements` slots and interface-typed object literals, Rust trait slots (generic traits included; including `macro_rules!` template tokens it can attribute), configuration alternatives (Rust `#[cfg]`, C/C++/C# `#if` definitions of the same item), Python alternative bindings of one scope variable (version-conditional `def`/assignment, try/except import fallbacks, class-body aliases such as `close = release`, `@prop.setter`), Go interface slots and their satisfiers (complete method sets with promoted methods, plus conversions of a type to an interface), exact call and value-reference tokens (C# method groups such as `new(Build, 4)`, `x += OnChanged`, `.Select(Build)`, `this.Build` and `nameof(Build)` by C# simple-name lookup, a method group of overloads or one a local of that name may hide being a review item; Java `this::m`/`super::m` by the enclosing class; a local function only in its block, never a same-name member access; a C# explicit interface implementation only with its interface's slot, and a `protected`, `private` or `internal` member never with an interface slot), imports/exports, Python `__all__` strings, and module-attribute references.
129
+
130
+ A member that fills a slot of a contract outside the project cannot be renamed in project code: an external trait impl (also a trait name bound to an external trait under some `cfg`), an override marker whose overridden member is not located in the project, a language protocol member (Python dunders), a compiler-required type (C# `IsExternalInit`), a declaration in a standard-library namespace (a C# `System.*` polyfill, a C++ `namespace std` specialization) or a root-supertype member (`toString`, `ToString`) sets `contract.blocked` and withholds every edit. When the owner only declares outside supertypes (including a Java serialization member of a class deriving from a JDK type that may be Serializable, and JS/TS and Python members named with a leading `_`, such as a stream subclass's `_transform`; only language-private names, `#x`, TS `private` and Python `__x`, override nothing), a member belongs to an object literal declared with an outside type (`const traps: ProxyHandler<T> = {..}`), or a Go type is used as an outside or open interface (including a value passed to an out-of-project function such as `sort.Sort(x.(*T))` or stored in an out-of-project struct field, for exported methods), the edits stay but the definition requires review and each contract site is listed with `contractDependency`. Macro template tokens it cannot attribute are listed with `templateDependency`.
131
+
132
+ Type renames cover TypeScript namespaces, Java annotation types (`@interface`) and Rust unions; a C# written arity (`typeof(Outcome<>)`, `Outcome<,>`, `nameof(Outcome)`) selects the type of that arity. Renaming a Java annotation element edits its `name = value` keys, and a single-element use (`@Marker("x")`, which sets `value`) becomes `@Marker(renamed = "x")`; one whose annotation type does not resolve stays unverified `annotation-shorthand`.
133
+
134
+ A reference is edited where the language's scoping proves it names the renamed binding (inside function bodies, on decorator lines, in default values; a local binding of the name is left alone, a local import is a review item), and each same-name call on a line is decided by its own call node. A decorator that replaces the callable may bind it by name (pytest fixtures, CLI commands, endpoints, registries keyed by `__name__`, a TS member decorator reading the property key): the definition is a review item (`decorator-name-binding`) unless every decorator is a standard name-preserving one (`property`, `staticmethod`, `functools.wraps`, `lru_cache`, `contextmanager`, ...), the member's own property accessor, or a project decorator that only calls, returns or wraps the function. A pytest fixture is resolved the way pytest resolves it (class fixtures, the module, then `conftest.py` files up the directory tree): the test and fixture parameters that receive it are renamed with it, with the uses that bind them; a parametrized name, a module pytest does not collect by default, a module or class that binds the name otherwise, and requests of a fixture defined outside `conftest.py` and test modules (a plugin) are review items. A fixture named by `name=` keeps its parameters.
135
+
136
+ Exact token/expression spans keep a foreign same-named occurrence on the same line unchanged; a definition line renames only the declaration's own name, never a same-spelled parameter, named result, or type. Same-file member references rename exactly the `this.m`/`self.m` tokens of the member's own class (`this.m = this.m.bind(this)` changes both; `{ m: this.m }` keeps its key); in Java and Rust a paren-less `this.m` is a field and stays. A bound or stored method on a typed receiver (`obj.m.bind(obj)`, `const f = obj.m`) is edited like a call. A name destructured from the member (`const { run } = api; run()`) is renamed at the pattern key and keeps its local binding (`{ renamed: run }`). An object-literal shorthand of the renamed binding keeps its key (`{ gen }` becomes `{ gen: renamed }`), except in a module's export object (`module.exports = { gen }`), whose key is the export name the rename follows into every importer. A getter and a setter of one property (class or object literal) are renamed together, with `this.x` reads and writes in the owner and destructuring keys read from `this`; other receivers are review items when untyped. An import binds its local name only: `import { g as f }` and `const f = require('m').g` keep `f` and its uses, and edit `g` only when the module binds the renamed definition. A C# member rename edits the `cref` attributes that resolve to it (`<see cref="M"/>`, `cref="Type.M(int)"`) and lists the ones it cannot resolve for review. Imports and exports are edited only for module-level symbols they bind, never for a method or field, and an import only when the module it imports from binds the renamed definition. An ancestor that does not resolve to one project class is listed for review. The plan's ACCOUNT counts the sites it lists: edited calls are confirmed and listed candidates unverified, whichever slot member's sweep found them. Go examples bound by name follow the rename (`editKind: "example"`): `Example<Type>_<Method>[_suffix]` and `Example<Ident>[_suffix]` in `_test.go` files, bound the way `go vet` binds them (the example's own package, else the packages it imports; members promoted through embedding count); an example whose name could bind to two imported packages is a review item. A finding that holds at many sites (one type used as an outside interface everywhere, one comment dependency) is stated once with its site list.
137
+
138
+ Renaming a type (class, struct, interface, trait, enum, record, union, type alias, typedef) edits every token that names it, each resolved by the language's own name lookup: base/implements clauses, field, parameter, return, local and generic-argument types, casts and type tests, static qualifiers (`Widget.X`, `Widget::f`), constructor and destructor names and C++ member initializers, construction expressions and struct literals, qualified spellings (`pkg.Widget`, `app::Widget`, `crate::m::Widget`), imports, re-exports and `use` trees (an import alias keeps its local name), Python forward-reference strings (`"Widget"`, `Union["Widget"]`, the value of `X: TypeAlias = "Widget | None"`), C# doc `cref`s, forward declarations and TS declaration merges, a Go embedded field's selectors and literal keys (the field is named after the type), and names a Go dot import (`import . "pkg"`) brings in when that package declares the type (an import path the index cannot resolve leaves the token for review). A redundant `X as X` alias in Python, JS/TS or Rust renames both tokens. Python module attributes follow aliased imports and nested package paths (`from pkg import sub as api; api.inner.Widget`); a shadowed or rebound module receiver requires review. A same-name type of another module, package, namespace or crate, a local binding, a type parameter and a member named like the type stay unchanged (so does an object-initializer member, `new Address { Country = .. }`). A C `typedef struct { .. } T;` is the typedef name T (no tag), and a C++ nested type (`struct Outer<K>::Node { .. }` or one in the class body) is reached through `Outer::Node` spellings in any file. A type or function name a macro spells by token pasting (`struct sdshdr##T`) lists the pasting macro and each invocation that produces the name (`SDS_HDR_VAR(8, s)`) for review (`macro-paste`). A C function's value references (`set_cb(on_event)`, a table entry) are edited like its calls, through a forward declaration or a header prototype; other external definitions of the same declared function (platform variants in other files) are renamed with it, and one that no declaration of it reaches is a review item. A call excluded inside a region the parser could not read is a review item (`parse-recovery`). A token the lookup cannot settle (a Python module variable that both an import of the type and an assignment bind, a name a macro expansion may bring into scope, a macro argument its replacement list also uses in another role, a specialization member through a dependent qualifier, text inside a macro body or a handler attribute) is a `needsReview` change with its `reviewReason`. Java moves a top-level type's `Widget.java` with it (`fileRenames`); a constructor or C# finalizer handle plans the class rename.
139
+
140
+ Open external interfaces, incomplete ownership, unresolved dispatch, an inexact token, or a property assignment onto a function-local or undeclared object (`reviewReason`) route to `needsReview` instead of a synthesized edit. Comment/string occurrences in indexed source appear in `reviewItems` and are never rewritten automatically; the result also tells you to search documentation, configuration, generated files, and unsupported languages for the old spelling. Read `changeSummary` and every review item. `plan` previews only: it does not modify files, run a compiler, or prove runtime compatibility.
141
+
142
+ ### repo
143
+
144
+ `repo` ranks HOT production functions by confirmed production callers, exactly (test call sites are not scanned for it). Each function appears once: overload signatures and C/C++ prototypes count with their implementation. Exact ranking has a work budget (call records examined); only a very large repository exceeds it, and then the header says the ranking is approximate while every shown count stays exact; narrow with `--in=<dir>` for an exact list. `repo --sections=stats --hot` ranks by all callers under a larger budget, disclosed the same way.
145
+
146
+ `repo` readiness is task-specific. Its headline is navigation readiness; refactor, deletion, semantic recall, and the sampled evidence mix are separate dimensions. The confirmed/unverified percentage is a classification profile, not an accuracy grade. Skipped unsupported source is listed with a text-search and language-tool handoff; `--sections=health` also reports `git-listing-failed` and unexpandable macro invocations.
147
+
148
+ Summary/stats `buildTime` is the duration of the last index build (discovery, parsing, and graphs), retained in the cache. It excludes cache loading/saving and query execution, so it is not command wall time; `buildTimeNote` states this boundary.
149
+
150
+ ### deps
151
+
152
+ Cycles distinguish eager edges from deferred ones. `eager` means every edge executes at module scope. `deferred` means at least one edge does not: a function-local import (Python `def`/`lambda` bodies; JS/TS `require()`/`import()` inside any function, including `() => require()` thunks), a Python `if TYPE_CHECKING:` import, or a TypeScript type-only import. Each deferred edge names its reason. A deferred chain is not an unconditional import-time cycle; function-local chains stay visible because invoking that function during initialization can still matter. Cycles are enumerated completely and independently of build history (capped at 500 with a disclosed truncation; groups above 2000 files skip enumeration); `CYCLE GROUPS` and the files-in-cycles count remain complete even when the enumerated cycle counts are lower bounds. `CYCLE GROUPS` lists each strongly connected file set, the unit a refactor has to break.
153
+
154
+ ### endpoints
155
+
156
+ `endpoints` labels test routes and requests with `[test]` (JSON `isTest`). Use `--exclude-tests` for a production inventory or `--in=api/` for a directory. `--bridge` matches server routes to client requests; the matching is advisory.
157
+
158
+ Route tables count too: Django URLconfs (`path`/`re_path`/`include`, composed from `ROOT_URLCONF`), DRF routers, Starlette `Route`/`Mount`/`Host` lists, Flask `add_url_rule`, aiohttp `add_routes`/`router.add_*`. Methods come from the view (`require_*` decorators, class-view handlers, viewset actions); an unresolved view serves `ALL`. Tags: `[regex]` (a `re_path` shown in path form, an unconvertible part as `{?...}`), `[drf-router]`, `[static]`, and `[include]`/`[mount]` for a target that cannot be resolved (shown as `prefix/{?target}`, matched only as uncertain). Django composes as Django does: an include prefix and the included pattern are concatenated as written (`path("api", include(...))` + `"items/"` serves `/apiitems/`); a `re_path` without `^` or, for a view, without `$` matches any text there, shown as `{?*}` (matched as a catch-all); a regex group that can match `/` is written `<path:name>`.
159
+
160
+ Client receivers are recognized by evidence (a receiver typed to an HTTP client class, or bound to a pytest fixture that constructs one), not only by name. Request-configuration calls (`request(OpenAPI, { method, url })`, `client.post({ url })`, `session.request(method=..., url=...)`, generated OpenAPI SDKs) count as clients when the callee's definition reaches an HTTP call (fetch, axios, requests, ...). Request-shaped calls on an unrecognized receiver or an unproven helper are listed under `Possible client requests` (JSON `uncertainRequests`, with the reason), counted in `meta`, never in the inventory.
161
+
162
+ A request through an in-process test client built from an app (`TestClient(app)`, a fixture's client, `app.test_client()`, `AsyncClient(transport=ASGITransport(app=app))`) bridges only to routes of that app or mounted under it; an app declared as a function or class serves the request itself and matches no route. A supertest client (`request(app).get('/x')`, `request.agent(app)`, a client bound to a local; the name bound to the `supertest` module, whatever it is called) is one too, its app followed through imports and `app.callback()` / `http.createServer(app)`; `request(this.app)` in a mocha test or hook takes the app its suite's `before`/`beforeEach` hook stores on `this` (the nearest suite assigning it, which writes it nowhere else and registers nothing through `this.app`). When the app does not resolve, every path match stays, marked `[unscoped]` (JSON `unscoped: true`). A HEAD request matches a GET route where the framework serves HEAD with GET (Starlette, Flask, Express).
163
+
164
+ Route paths include router mount prefixes composed from the code: FastAPI `include_router(prefix=)`, Flask `register_blueprint(url_prefix=)`, Express `use`, Hono `route`/`basePath`, Fastify `register({ prefix })`, gin/echo `Group`, chi `Route`/`Mount`, gorilla `PathPrefix().Subrouter()`, `http.StripPrefix`, Spring/JAX-RS class mappings, ASP.NET `[Route]` with `[controller]`/`[action]` and `MapGroup`, axum `nest`, actix `scope`. Each framework joins as it does at runtime: echo groups and koa-router prefixes concatenate (`Group("/api")` + `"items"` is `/apiitems`), Fastify route URLs concatenate to the plugin prefix (one shared `/`, a `/` route serves at the prefix), the others join with one `/`. The framework label is the router module the file imports (or the project's own package when the project is that framework); without one it is the family label (`express` for JS/TS, `go-http` for Go). The handler is the registration's handler argument (the last one; echo's first), `<anonymous>` for an inline function; an axum `.route(path, get(a).post(b))` lists one route per method. Catch-all parameters (`<path:x>`, `{x:path}`, `{*x}`, `*name`, a bare `*` in JS/Go routers, a `{x:regex}` that matches `/`) span segments (`**` in `normalizedPath`); a `:` in a Starlette route or a client URL is text. Go `http.NewRequest(method, url)` counts with its own method and URL; a URL with no scheme and host is served in process and bridges only to routes its own test function registers. Prefix expressions are folded (constants, f-strings, concatenation, a settings instance's field default). A prefix that cannot be proven appears as a `{?expr}` segment and matches clients only as `UNCERTAIN`; a router mounted twice lists both paths.
165
+
166
+ ### deadcode
167
+
168
+ `deadcode` is a candidate generator; every candidate is review-only. Computed dispatch such as `handlers[key]()` is a reported blind spot; registry members reached by a modeled computed receiver are withheld. Statically named reflection such as `getattr(obj, "run")` is positive liveness evidence, so every matching member spelling is withheld. A reflective name built from literal fragments around a runtime part (`getattr(self, "_get_%s_perms" % src)`, f-strings, `.format`, `"get" + name` in `getMethod`, `MethodByName(fmt.Sprintf(...))`, `obj["on" + evt]`) is a pattern: members it can spell on a receiver that may hold their class are withheld and counted per pattern, and `show`/`impact`/`plan` list the site as an unverified `reflection-pattern` caller. `eval(name)`/`globals()[name]` reach only their own module's top-level names. Reflection with no specific literal part is counted and warned because it cannot be attributed to one member.
169
+
170
+ Members the runtime or compiler invokes by name are hidden as runtime callbacks: Python dunders and Enum hooks (`_generate_next_value_`, `_missing_`) on Enum subclasses, Java serialization callbacks and `serialVersionUID` on Serializable types (also when written `implements java.io.Serializable` or inherited) and, as possible members with the protocol's signature, on classes that derive from another out-of-project type (`extends IOException`, `extends ArrayList`; `plan` keeps their edits and lists the definition for review), C# pattern members (`GetEnumerator`, `GetAwaiter`, `Deconstruct`), C# compiler-required types the project declares for a feature it uses (`System.Runtime.CompilerServices.IsExternalInit` with `init` accessors or positional records, `RequiredMemberAttribute` with `required` members, `System.Index`/`Range` with `^i`/`a..b`; unused when the feature is absent), JS `toJSON`/`then`/`[Symbol.*]`, C++ `begin`/`end`. Unknown decorators/annotations and member-assigned event handlers are also withheld by default because they can be the registration itself. Members of a class deriving from an outside base (underscore hooks such as a stream's `_transform` included) and members of an object literal declared with an outside type (`ProxyHandler` traps) may be called by that outside code and are hidden as external-contract surface.
171
+
172
+ In C/C++, names an expanded macro invocation produces are live; a token-pasting macro that is never seen expanded withholds every candidate its paste pattern could spell, and invocations that cannot be expanded are warned as `token-pasting macro dispatch` (also in `repo --sections=health --deep`). Rust definitions generated by project `macro_rules!` invocations are never candidates, calls their expansions make count as uses, and unexpandable invocations are warned.
173
+
174
+ ### audit-async
175
+
176
+ `audit-async` checks recognized async producers. An unawaited coroutine or promise is a finding only when it is lost (a bare statement, or stored in a local that is never read) or used as if resolved (member access, arithmetic, conditions, destructuring); a value passed as an argument, placed in a collection, generator or spread, returned, chosen by a ternary/logical expression, or assigned to a field, property or outer variable flows on and is not flagged. Awaiting, returning, promise handlers, reassignment, and shadowed bindings are distinguished.
177
+
178
+ In JS/TS/HTML it also checks captured promises used in arithmetic, conditions, or resolved-value member access within the same lexical scope. In Python, coroutine calls in sync functions count too (discarded ones at module scope as well), and a local assigned straight from a coroutine call is flagged where it is used as the result while every value it can hold there is that coroutine (`stored-coroutine-used-as-value`); identity tests, comparison with None, string formatting and uses in nested functions are not.
179
+
180
+ Producers are classified by what a call returns: async generators/iterators (consumed by `async for`, `for await`, `await foreach`) and `@asynccontextmanager` factories (entered by `async with`) are flagged only when the call is discarded; C# `async void` is never flagged; calls to async functions behind an unrecognized decorator are counted as not audited. Bare calls resolve through lexical scope, then import identity: the imported module's own definitions (Python star imports through `__all__` or public names) or an engine-established target. A same-name function elsewhere in the project is not a producer. A JS/TS import is read through re-exports (`export { default } from`, `export * from`) to the function its module declares, anonymous `export default async` functions included. JS/TS and Python member calls are audited when the engine types the receiver (`const s = new Svc(); s.fetchAll()`, an annotation, a field, `this`/`self`) and confirms the async callee; other member calls are not. C# member calls (`s.SaveAsync()`, `_svc.SaveAsync()`, `this.Local()`, `p?.SaveAsync()`) are audited through the receiver's type and its project ancestors; a typed receiver that owns none of the async definitions is not.
181
+
182
+ Rust: calling an `async fn`, a fn returning `impl Future`/`Pin<Box<dyn Future>>`/`BoxFuture` or a future type alias, or a local `|| async {..}` closure creates a lazy future, in sync functions too; it is flagged when discarded (`future-discarded`), dropped by `let _ =` (`future-dropped`), bound to a local never used (`future-unused`), or used as its Output (`?`, operators, a project method of the Output type: `async-result-used-as-value`, `stored-future-used-as-value`). Awaiting, passing (spawn, `join!`, `select!`, `block_on`), storing in a field or collection, `Box::pin` and returning flow on. Only engine-confirmed call targets are audited; `skippedFutures` counts futures of a type implementing `Future` or behind a non-builtin attribute (`#[tokio::main]`).
183
+
184
+ It is a bounded AST audit, not a compiler-wide proof that every missing await has been found; alias flow and unknown receivers need the compiler or type checker.
109
185
 
110
186
  ## Language notes
111
187
 
112
- Supported source families are JavaScript/TypeScript/TSX, Python, Go, Rust, Java, C, C++, C#, and HTML inline JavaScript/event handlers. C/C++ consumes `compile_commands.json` when present for header-language and include-path context, and retains AST-proven facts across recoverable preprocessor branches. C++ call identity uses namespace ownership, static overload shape (including arrays), and macro requalification; disagreeing conditional macro definitions remain visible as unverified. C# uses declared property/field receiver types and overload/hiding discipline. UCN remains portable AST analysis: it does not run a compiler, preprocessor, Roslyn, or an LSP during normal queries, and it does not assert which conditional branch a build activates.
188
+ Supported source families are JavaScript/TypeScript/TSX, Python, Go, Rust, Java, C, C++, C#, and HTML inline JavaScript/event handlers. C/C++ consumes `compile_commands.json` when present for header-language and include-path context and retains AST-proven facts across recoverable preprocessor branches; project function-like macros and Rust `macro_rules!` invocations are expanded, and what they generate is indexed at the invocation (`[via macro NAME]`). UCN is portable AST analysis: it does not run a compiler, preprocessor, Roslyn, or an LSP during queries, and it does not assert which conditional branch a build activates. The per-language identity rules (what confirms a call, what stays unverified with which reason, what is excluded) are in [resolution-rules.md](resolution-rules.md).
@@ -0,0 +1,171 @@
1
+ # UCN resolution rules
2
+
3
+ How UCN decides whether a call, reference or type name belongs to the pinned definition: what confirms, what stays unverified with which reason, what is excluded. Read the section for the language at hand when a tier or reason in an answer needs explaining. The reason names in backticks are the ones the output prints.
4
+
5
+ This is portable AST analysis, not a compiler build; macros, templates, generated code, reflection, and external dependency semantics can remain unverified.
6
+
7
+ ## Every language
8
+
9
+ ### Type names and type identity
10
+
11
+ A type name written at a call site (a constructor, `Type::f()` / `Type.f()`, an annotated or constructed receiver, a declared field type, a producer's return type) denotes what that file binds it to: when it names an external type that shares its name with a project type (`use std::fs::File`, `import java.io.File`, `from pathlib import Path`, `import { Server } from 'http'`, `using F = System.IO.File`, `std::mutex`), members of the project type are excluded (`external-receiver`), and a project impl on the external type itself stays unverified `possible-dispatch`.
12
+
13
+ A type declared in a function body (Python, Java, JS/TS, Rust, C++, Go) is visible only in its block: a same-name type outside never captures its references or members, and inside the block it shadows the outer one. A Python field assigned a function-local class (`self.channel = Channel()`) names that class, not a same-named module class.
14
+
15
+ In JS/TS, Python and Rust a type's identity is its module: `Shared::init()` / `Shared.init()` names the `Shared` its own module declares or imports, never a same-name type of a sibling module (excluded `path-type-mismatch`).
16
+
17
+ A module-level `Alias = Box` (Python: bound once, or on every module-level `if`/`try` path to the same class; JS/TS: `const`, or a `let`/`var` never assigned again) names Box in annotations and constructor calls, also when imported, and `Alias(..)` / `new Alias(..)` is a caller of the class; an alias whose paths name different classes stays `possible-dispatch`.
18
+
19
+ Type aliases and import renames are the same type on both the caller and callee side: a receiver annotated with Go `type IntFlag = FlagBase[int]`, TS `import { Box as B }`, Rust `use crate::Wrap as W` or C# `using IntBox = G.Box<int>` reaches the original type's methods; a Go alias of an external type (`type Ctx = context.Context`) is not a same-named project type.
20
+
21
+ ### Aliases, qualifiers and imports
22
+
23
+ Aliased and qualified calls resolve in every language: Rust `use m::f as g; g()` is a caller of `f` (listed as a beyond-text caller, since the line holds no target token); Java `pkg.Type.method()` and C# `Ns.Type.Method()` / `using T = Ns.Type; T.Method()` pick the type the qualifier names when several same-name types exist. A qualifier the resolver cannot place stays visible as `method-ambiguous`, never confirmed by first-definition order.
24
+
25
+ A bare name bound by an import resolves through that import only, never through another import whose package re-exports a same-named symbol. An import chain that reaches the target through any number of re-exports and renames (`export { a as b }`, then `import { b as c }`) is import evidence.
26
+
27
+ A one-hop local alias of a typed field, parameter or local (`config = self.config; config.load()`, `const c = this.config`, `var c = this.config`, `c := s.config`, `let c = &self.config`) receives like the aliased expression when the local is bound once and never reassigned.
28
+
29
+ A local value named like a function (`let f = g; f()`, C# delegates, C++ lambdas and function pointers) is the callee.
30
+
31
+ Explicit type arguments are call syntax (Go `f[T](x)` / `pkg.F[T](x)`, Rust `f::<T>(x)`, TS/C#/C++ `f<T>(x)` and `obj.template f<T>()`, Java `this.<T>f(x)`).
32
+
33
+ Inherited calls keep their declaring class; a shadowed or rebound module stays unverified, and a base-typed receiver can still dispatch to a subclass override.
34
+
35
+ ### Configuration alternatives
36
+
37
+ Definitions of one name, owner and signature in one file under different `#if` branches (C/C++/C#) or `#[cfg]` attributes (Rust) are one item: a call bound to any of them reaches every variant alike, a type declared once per configuration is one type (receivers typed by either declaration reach its impls), members inside a class body's `#if` blocks are indexed in each branch, and a C++ implicit-this call reaches its own class definition, never a same-named class defined in another file. Python exclusive branches are one item too (see Python below).
38
+
39
+ ### Callback references
40
+
41
+ Callable references passed to another function remain visible when a project method or function could be their target. An ordinary attribute read with no callable member candidate stays a non-call reference in ACCOUNT and `usages`. The caller model includes callback dependencies; it does not prove that the receiving function invokes every passed callable.
42
+
43
+ ## JavaScript / TypeScript
44
+
45
+ A bare JS/TS name never reaches a function assigned as an object member (`req.setTimeout = () => {}`, `exports.f = function () {}`, prototype and object-literal members) unless the object is the global object (`globalThis`, `window`, `self`, `global`) or the call is inside the function's own named expression; a member of an object that may be the global object (a parameter, a plain function's `this`) stays unverified `member-object-unresolved`; `var global = globalThis` names the global object too.
46
+
47
+ A bare call of a global assigned in another file (`globalThis.f = ..` in a test setup module) is unverified `possible-dispatch` via `global f — assigned in project`, one runtime family per global.
48
+
49
+ A JS/TS name destructured from an object (`const { run } = api`, `({ run }: Api) => run()`) reads that member: its calls are member calls on the source, confirmed when the source is typed and unverified otherwise, and a same-name free function is never their target.
50
+
51
+ A JS file's extensionless import resolves a TS source; a bare specifier naming a package of the repository (workspaces, `@scope/core`) resolves to that package's source (its `exports`/`source` entries, else `src/index`), and one whose manifest names only build output absent from the checkout stays unverified, never external.
52
+
53
+ A structural receiver whose class resolves to a definition reaches the target only through that definition's ancestry: a sibling class sharing an ancestor's name is excluded, not a possible dispatch.
54
+
55
+ ## Python
56
+
57
+ A Python name bound in one scope only in exclusive branches (`if`/`elif`/`else`, `try`/`except`, `match` cases: `if sys.platform == "win32": def getchar` / `else: def getchar`) is one item: a call inside one branch reaches that branch's definition, any other call reaches each definition alternative (confirmed for each, since it reaches it whenever that definition exists), and a definition reached only through one branch's import (`try: from ._speedups import f` / `except ImportError: def f`) is listed unverified `configuration-alternative`; `plan` renames every definition alternative and keeps the item's name on an import alternative (`from ._speedups import new as f`).
58
+
59
+ A name a Python module binds only by assignment is that module's value, never a re-export of what its other imports reach: `name = other` and `name = submodule.other` aliases are followed, `loads = registry.loads` with `registry = Registry()` is Registry's bound method (a call of the imported `loads` is no caller of another `loads`; it is an unverified `alias-call` of `Registry.loads`, and `plan` renames the attribute read `registry.loads`, never the variable or its calls), and any other value routes unverified `ambiguous-binding`.
60
+
61
+ Python qualified bases and receiver annotations follow the imported module, including aliased submodules and nested package paths.
62
+
63
+ An untyped `self.attr.m()` callee is unverified `single-owner` even when one class declares `m`. A `self` attribute a base class types is typed in its subclasses, by the declaring class's file, when no class on the way writes it, declares a member of its name or writes attributes dynamically and no outside base could set it; `def`s under `if`/`try`/`with`/loops in a class body are methods of the class, and `Union[X, None]` names X.
64
+
65
+ A `def` inside a function is visible only in that function (unless the function declares the name `global`), and a nested function's bare name binds what its enclosing functions bind before the module.
66
+
67
+ A structural receiver whose class resolves to a definition reaches the target only through that definition's ancestry: a sibling class sharing an ancestor's name is excluded, not a possible dispatch.
68
+
69
+ A Python string annotation that spells a call (`def cmd(v: "Annotated[int, typer.Argument()]")`) is parsed as the expression the runtime evaluates: its calls are callers and `plan` edits them; an annotation string that does not parse stays a text review item.
70
+
71
+ ## Go
72
+
73
+ A Go import that writes no name binds a project package by its package clause (`.../internal/helpers` declaring `package utils` is `utils.F()`); an outside package's name is only the one the Go tools suggest (`github.com/goccy/go-json` is `json`, `k8s.io/api/core/v1` is `v1`), so a qualifier the file neither declares nor imports by that name stays unverified `package-qualifier`, never a confirmed or renamed project call, and `plan` keeps a call it cannot type as a review item in a file of another build configuration (`//go:build`, `_linux.go`) than the renamed declaration's.
74
+
75
+ `pkg.F()` names the package's function (or function-valued variable), never a same-named method. A Go instantiated value (`id[int]`) or package-qualified value (`pkg.F` passed as an argument) is a reference to that function. A composite literal `T{...}` names the type, never a same-named method.
76
+
77
+ A Go package-level variable has one static type across its package: `var CommandLine = NewFlagSet(..)` types `CommandLine.VarP(..)` in every file of the package, before or after the declaration, and `pkg.CommandLine.VarP(..)` in importers.
78
+
79
+ ## Rust
80
+
81
+ Rust receivers are typed from annotations, closure parameters of the called function's `Fn` bounds, `Self::Assoc` returns, tuple `let` patterns, trait-provided methods, and range, tuple, slice, `vec!`, and `Some`/`Ok` values; owned versus `&` impls are told apart by the receiver's reference layer, and at one probe step an inherent method precedes a trait method (`self.key_mut()` inside a trait impl's own `key_mut` calls the inherent `key_mut`), on the caller and callee side; where a bound-conditional impl, a trait not provably in scope or a private inherent method could intervene, the site stays unverified.
82
+
83
+ Method probing follows the receiver's reference layer: a `self` receiver that reaches the member only after an autoref or deref step (a `&self` trait method called in a `&mut self` method) may be taken by an earlier impl, such as std's `impl AsRef<U> for &mut T`, so the site stays unverified `autoref-dispatch` unless the trait is the project's own and no impl for a reference type can intervene. A local bound from a producer returning `Self` or a value is owned and `-> &T` a reference, which selects between owned and `&` impls. An untyped `let` hides an outer binding's type, and calls in the item bodies of an item-position macro (`quickcheck! { fn p(..) { .. } }`, also when a project macro emits it) are read from the items, with their functions' locals typed.
84
+
85
+ A receiver behind a std deref wrapper (`Box`, `Rc`, `Arc`, `ManuallyDrop`, `LazyLock`, `Ref`/`RefMut` and lock guards, `Pin`, `Cow`; annotated, constructed with `W::new(..)` or a `LazyLock` static) reaches its target type's methods (a guard returned by a call such as `cell.borrow()` or `m.lock().unwrap()` is not typed, so its calls stay unverified); a name the wrapper itself may supply (`clone`, `as_ref`, std trait methods, project impls on the wrapper) stays unverified `autoref-dispatch`, and `rc.clone()` is the wrapper's.
86
+
87
+ Values of std containers, slices, arrays (`[a, b].iter()`), `str`, `Option`/`Result` and std iterator adaptors never reach a method owned by a project struct or enum. Raw pointers (`*const T`/`*mut T` parameters and locals, casts `(p as *const T)`, `as_ptr()` results and pointer arithmetic such as `p.add(n)`) reach `impl<T> Tr for *const T` members and never a struct's method.
88
+
89
+ A parameter typed `Self` is the enclosing impl's type. A receiver whose type is a generic parameter (including `self` in a trait's own methods) reaches only implementations of its bound traits (unverified `possible-dispatch` via the trait, external for std traits such as `Iterator`) and never an inherent method or another trait's impl. A Rust `const`/`static` item types its method receivers by its declared type (`FLAGS.iter()`; never a `static mut`), and a local destructured from `self` (`let Self { iter, .. } = self;`) is that field.
90
+
91
+ Crate aliases (`use x as y`, `extern crate x as y`), the package's own name in tests/examples, glob and `pub use` re-export chains, auto-deref wrappers, enum-variant values, unit-struct values (`S.m()`, also through `let w = S;`), tuple-struct and tuple-variant constructors (`T(1).m()`, `E::V(2).m()`, `Self(..)`), struct expressions, and in-scope blanket extension traits (`impl<T: Iterator> Ext for T`) are followed; a blanket-impl member confirms only when its where-clause holds through exactly one visible project impl. `Trait::f(..)` returned from a member of that trait's impl binds that impl; elsewhere it stays one trait family.
92
+
93
+ Impls of one generic trait for one type (`impl From<A> for Vec<u8>` beside `impl From<B> for Vec<u8>`) are selected by argument type (declared parameters and locals, struct literals, literals, range-indexed slices, locals bound from a `Type::ctor(..)` whose project definitions return the type): another argument type excludes the impl (`overload-mismatch`), an undecided argument stays `overload-ambiguous`, and an undecided argument never confirms the only project impl of an out-of-project trait such as `From`, whose other impls UCN cannot see.
94
+
95
+ Rust `crate::f()`, `super::f()`, `self::m::f()` and child-module paths resolve through the module tree (`mod` files in both layouts, `#[path]`, inline modules) and confirm as `module-owned`; a type path (`crate::tests::memchr::Runner::new()`) names the type that module declares, and a type a glob import (`use super::*`) brings in is that module's type; a bare call never resolves to a struct field.
96
+
97
+ ### Rust macros
98
+
99
+ Invocations of project `macro_rules!` macros are expanded (rules matched over token trees, nested and recursive project macros, hygiene for locals the macro introduces, `$crate`, every `cfg` alternative): functions, impls and calls the expansion generates are indexed at the invocation, marked `[via macro NAME]`. A call written in the invocation keeps its own line and is typed in its expanded context; an unresolved call from the macro's template joins the target's `macro template` family in the compile-time band, and `plan` edits a generated declaration only through the argument or template token that spells it. Macros that only pass their arguments along (logging, `try!`-style matches) keep the invocation's token-tree view. Macros from dependencies are never expanded; project invocations that cannot be expanded are listed in `repo --sections=health` and warned by `deadcode`.
100
+
101
+ Macro names are their own namespace: `name!(...)`, `#[name]` and `#[derive(Name)]` never count as calls or references of a same-named fn (excluded `macro-namespace`), and a fn declared inside another fn's body is visible only there.
102
+
103
+ ## Java and C# (shared)
104
+
105
+ Unimported Java and C# names follow the language's scoping: the same package or an enclosing namespace, then on-demand imports with the implicit `java.lang`, or `using` directives, global usings and project-file `<Using>` items (`Static="true"` items are `global using static`; `Directory.Build.props` above an indexed sub-project count up to the repository root). A `using` directive written inside a namespace resolves from that namespace outward (`namespace A.B; using Internal;` imports `A.Internal` when the project declares it), and nested `namespace` blocks name their members by the full path; a project type not in scope there is not the named type, and a project on-demand import beside a `java.lang` type of that name stays unverified.
106
+
107
+ Overload choice needs argument evidence (Java, C#): where the applicable overloads differ in a parameter and the argument's type is unknown, the site stays unverified `overload-ambiguous` for each of them (for `plan`, a review item at the site), including the fixed-arity versus varargs/`params` choice; explicit method type arguments (`M<int>(..)`), literals, typed locals, parameters, fields of the enclosing class and a lambda's parameter count against `Action`/`Func`/`java.util.function` shapes, project delegates and project functional interfaces (one abstract method) decide it; a C# generic method whose type parameter no parameter type mentions applies only with explicit type arguments; a C# target-typed `new(..)` constructs the type its position declares (a typed local or field, a property, the enclosing member's return type, a member it is assigned to, or the parameter of the overload a call, construction or `this(..)`/`base(..)` initializer binds, primary constructors and a platform collection field's element type included); a decided overload confirms it, an undecided one lists it unverified `overload-ambiguous` for each candidate type, and arguments that fit none of the pinned class's overloads (a C# extension method of another class) leave the site unverified, never confirmed.
108
+
109
+ In C# and Java a type name is no value: a bare argument spelled like a type (a property named like its type) is never the type's caller. In C# and Java a capitalized receiver that names a field or property of the enclosing class (declared in another `partial` part or inherited) is that member, typed in its declaring file's scope.
110
+
111
+ A bare Java/C# call binds a member of the enclosing classes (own or inherited, by class definition, never a same-name class of another package) before a static import (`import static`, `using static`); the import decides it, as caller and callee, only when every class in scope has a resolved project ancestry, and otherwise it stays unverified.
112
+
113
+ A Java/C# local's declared type is its static receiver type: `Shape s = new Circle(); s.area()` is a caller of `Shape.area` and a `possible-dispatch` candidate of each implementation, except those the constructed type cannot reach when the local is never reassigned. A field initializer types only its own class's field, and only a field that cannot be reassigned.
114
+
115
+ ## Java
116
+
117
+ A package-qualified Java type (`p.Node pn`) names that package's type. A type-qualified call (`Util.isEmpty(s)`) and a return type (`A.builder().get()`) name the class the name denotes where it is written, before any overload fit: a same-name class of another package, or another class's nested `Builder`, never lends its better-fitting overload or member.
118
+
119
+ `super.m()` binds the superclass member, never the override; in an enum constant's body it is the enum's member, and a bare call in an anonymous class or enum-constant body looks up that body's supertype first (a method the body declares itself is its own). A Java member of a nested class is not in the outer class's simple-name scope, and a constructor callee is the class the name denotes where it is written (a single-type import before a same-package class's nested namesake).
120
+
121
+ A Java enum implements its interfaces like a class (renames reach the enum's member and enum-constant bodies), and serialization callbacks of an enum are ordinary members (enum constants serialize by name).
122
+
123
+ ## C#
124
+
125
+ C# resolution uses declared property/field receiver types plus overload and hiding discipline. A C# `#if` that splits a declaration (a method body or expression body, a base-list entry, a parameter, alternative heads) is read one configuration at a time with every line number kept: the branch holding the most calls is primary, and the other alternatives' declarations and calls come from their own configuration.
126
+
127
+ C# generic arity is part of a type's identity: `Outcome`, `Outcome<T>` and `Outcome<T1, T2>` are distinct types, so a constructor `new Outcome<T>(..)`, a static call `Outcome.X()` / `Outcome<int>.X()`, a written receiver type and a base list name only the type of that arity (other-arity sites are excluded `generic-arity-mismatch`), and `partial` parts merge only with the same arity.
128
+
129
+ An extension-method call `x.Ext()` is a caller of the extension when the declaring static class is in scope and x's type fits the `this` parameter (directly, through project heritage, or through a type parameter's constraints); a receiver whose ancestry cannot decide it (an external type) stays unverified `extension-receiver-unresolved`, and an applicable instance method of the receiver type wins (also a platform collection's own member, `List<T>.Add(T)`, and `object` members). Type arguments must fit: a `List<string>` or `DbSet<Customer>` receiver never takes `this List<Transformer>`. Type arguments the receiver fixes type the other parameters (`TryAdd<T>(this List<T>, T)` never takes a `string[]`). An extension call on a project type that derives from an outside class (other than `object`, the modelled collections and the type the extension is declared for) stays unverified, since an inherited instance member may take it. A receiver typed by a type parameter converts only to its constraints.
130
+
131
+ A C# explicit interface implementation (`IEnumerator IEnumerable.GetEnumerator()`) is never reached by a simple-name or `this.` call, and through an interface-typed receiver only by runtime dispatch. An explicit interface implementation never types a member access on the class.
132
+
133
+ A C# static method is never reached through a value (a chained call's result, `this`, a field or a typed local), and `new X(..)` names the type X even where the enclosing class has a member named X. A C# static member path from a type (`Pool.Shared.Get()`, where `Pool` is no member of the enclosing class) is typed from that type's declared member, and a chained call (`Get().Initialize<T>()`) is typed from its producer or stays unverified, never read as a type name.
134
+
135
+ A C# `using static T` imports only the members T itself declares, never inherited ones. A using alias whose target starts with an alias of an enclosing scope resolves through it; a type written with an `extern alias` qualifier (`Old::Lib.Type`) is never resolved to a project type (its receivers stay unverified, `plan` lists its tokens for review).
136
+
137
+ A C# target-typed `new(..)` in a collection initializer or collection expression (`new List<T> { new(..) }`, `T[] a = [new(..)]`, dictionary `{ new(..), v }` pairs) constructs the element type, and an argument of a generic receiver's method (`Box<Item> b; b.Put(new(..))`) the type argument it binds.
138
+
139
+ ## C and C++
140
+
141
+ C/C++ uses `compile_commands.json` when available to classify headers and resolve include paths; free-function visibility follows the transitive `#include` closure, and a quoted include found only by a unique project basename is weaker evidence (rule `include-basename`). C++ resolution uses namespace ownership, static overload shape (including arrays), and macro-parameter requalification.
142
+
143
+ ### Declarations, linkage and configurations
144
+
145
+ Every non-static declaration of a free function (a header prototype or a local forward declaration in another file) is the same entity as its external definition, so its calls are the definition's callers and `plan` renames every declaration; a `static` forward declaration joins only its own file's definition. Several external-linkage definitions of one function (platform variants), or definitions in complementary `#if` branches, stay `link-ambiguous` on the caller and callee side unless the caller's own file (in the same branch) or the compile database separates them. A call in a header to a `static` function the header declares binds each including file's own definition: unverified `translation-unit-binding`.
146
+
147
+ Recoverable preprocessor branches contribute AST-proven source facts, so a single selected configuration does not silently erase definitions or calls; disagreeing conditional macro identities stay visible as unverified. Members a class declares only in a conditional branch the selected configuration skips are indexed too. In a C/C++ file too large for the configuration sweep, a conditional the parser could not place (in a member-initializer list, an expression, template arguments) or whose branches split a block's braces is read in one configuration.
148
+
149
+ A same-named class in a header that is only ever included in another branch of the same `#if` chain (`#ifdef _WIN32 #include "client-windows.h" #else #include "client.h"`) is that class in another configuration: calls its own members make are listed unverified `configuration-alternative` for this class's member, and `plan` renames the member in both.
150
+
151
+ ### Receivers, qualifiers and lookup
152
+
153
+ A C++ `v->m()` reaches what `->` yields: the pointee of a pointer, of a std smart pointer (also behind a project alias) or of a class's `operator->`; any other object stays unverified. A receiver typed by a template parameter of the enclosing function or class template stays unverified `possible-dispatch` via that parameter, and an alias whose target is a dependent type (`typename X<..>::type`) is not a class. A C++ receiver declared with an alias (`Value v;`) has the class the alias names where it is written: a same-name alias in a namespace the site cannot see does not count.
154
+
155
+ `::f()` names the global namespace, so a namespace member is not its target unless a global-scope using brings it in (unverified `global-qualified-using`); `plan` edits a qualified reference (an explicit instantiation `template auto ns::f(float) -> R;`, `&ns::f`) when its qualifier names the renamed function's namespace or class, and lists it for review when the qualifier cannot be resolved. A C++ `Q::f()` qualifier is resolved through `using` aliases, using-declarations, and macro-opened namespaces (a namespace an object-like macro names, `namespace LIB_NS {`, is the namespace the macro expands to, also where a qualifier or using-directive spells the macro): it excludes only when Q provably names a namespace or an unrelated class, and routes `unresolved-qualifier` or `dependent-qualifier` (template parameter) otherwise. `plan` also renames each C++ using-declaration that names the renamed declaration (`using ns::f;`, `using ns::Type;`) when its qualifier resolves to the declaration's namespace or class, and lists it for review when only the qualifier's suffix matches.
156
+
157
+ A C++ class member hides every base member of its name unless a `using Base::name;` in the class brings them in (default arguments count in the arity); `v[k].m()` on a class object takes the class its `operator[]` returns when every `operator[]` it declares returns that one class; `T v(X());` in a block is an object initialized by the call `X()` unless `X` is a type. A C++ receiver whose class declares several overloads of the name is never a caller of an unrelated class's member, even when the arguments cannot choose among the overloads. A C++ implicit-this call names the member the enclosing class's lookup finds; an override of it in a subclass is reached only by runtime dispatch, as an unverified `possible-dispatch` candidate when the member is virtual and not at all otherwise.
158
+
159
+ A C++ `friend` function declared or defined in a class body is a function of the enclosing namespace, not a member (argument-dependent calls reach it, its body sees the class's static members, `plan` renames the friend declaration with the definition), and a member of a nested class reaches the enclosing class's members by bare name.
160
+
161
+ ### Preprocessor macros
162
+
163
+ A C/C++ call spelled `NAME(` where a project `#define NAME` is in effect is the macro's, not a same-named function's; a macro defined under a preprocessor conditional routes the call unverified `macro-namespace`, and a header that both declares the function and defines the macro holds configuration alternatives. A macro whose replacement list calls its own name again (`#define f(x) f(x)`, never re-expanded) passes the call to the function; one that only spells the name without calling it routes unverified `macro-namespace`.
164
+
165
+ Invocations of project function-like macros that paste (`fs__##lc(req)`), call a parameter, or feed an X-macro list (`LIST(X)`, `#include "list.def"`) are expanded at the token level: a call the expansion produces is a caller at the invocation line, marked `[via macro NAME]` with rule `macro-expansion`; configuration-dependent definitions that disagree route `macro-definition-ambiguous`, and `plan --rename-to` lists such sites as manual review because the line does not spell the name.
166
+
167
+ A call spelled in a macro's replacement list binds at each place the macro is invoked (through other macros too): confirmed when every invocation sits where the call reaches the target (a member of the invoking class), unverified `macro-body-context` when only some do. A receiver the replacement list declares with a macro parameter as its type (`T v; v.f();` in `#define M(T)`) takes the class every project invocation passes for that parameter (through other macros too); invocations that disagree, or one that cannot be read, leave its calls unverified.
168
+
169
+ A decoration macro before a return type (`API std::string Cls::m()`, `bool API ns::Cls::m()`, `MACRO std::size_t f()` in a class) or in a class head (`class API Name : public Base<Name>`) is blanked before parsing, only when the file proves it decoration (its own `#define`, or a position no type can hold) and never the type, scope or keyword beside it; members after a class-body macro invocation take the access its definition spells, and when that definition is not in the project their access is unknown and `deadcode` treats them as public. Macros another header of the include closure defines are read by the recovery like the file's own when every project definition of the name agrees: decoration (`SPDLOG_INLINE`), removable statement (`TRY` / `CATCH` defined as `try` / a `catch` handler or nothing) and attribute or return-type macros (`ATTR(3)` before a member); `LUA_API int (lua_gettop)(..)` declares `lua_gettop`. Members that escaped a class body the parser closed early are disclosed as recovery-region lines.
170
+
171
+ An invocation of the file's own function-like macro that the parser reads as a declaration (`ERROR_DEF(Base, Name)` in a class body, `LIST(X)` statement lists) is read as the invocation: members its replacement list declares join the class at the invocation line (`generatedByMacro`), and a C++ declaration with no type outside a class body (`TEST(suite, name) { }`) is an invocation, never a function named after the macro. A namespace-scope invocation followed by a body (`TEST(suite, name) { }`, `TEST_CASE("text") { }`) defines a callable named from its arguments (`suite_name`, `text`), marked `generatedByMacro`: calls in the body belong to it, it is an entry point, and `plan` blocks its rename (`macro-generated-name`), as it does for a member a class-body invocation builds by token pasting (`Get##name##String`). A bare call in such a body to a member of a class one of its arguments names (`TEST_F(Fixture, Name)`) is unverified `macro-generated-scope via Fixture`, never excluded. A declaration named like a function-like macro in effect where it is written (`int seed_ GUARDED_BY(mu_);` under a conditional macro definition) is that macro's invocation, so `plan` blocks renaming it as a function (`macro-invocation`).