ucn 5.5.1 → 5.5.3

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 (97) hide show
  1. package/.claude/skills/ucn/SKILL.md +35 -9
  2. package/.claude/skills/ucn/references/commands.md +40 -18
  3. package/.claude/skills/ucn/references/resolution-rules.md +126 -20
  4. package/.claude/skills/ucn/references/trust-contract.md +5 -3
  5. package/README.md +32 -21
  6. package/cli/index.js +2 -1
  7. package/core/accessors.js +341 -54
  8. package/core/account.js +74 -20
  9. package/core/analysis.js +257 -125
  10. package/core/ast-analysis.js +12 -3
  11. package/core/bridge.js +15 -65
  12. package/core/brief.js +8 -4
  13. package/core/build-worker.js +2 -1
  14. package/core/cache.js +137 -6
  15. package/core/call-name-cache.js +134 -0
  16. package/core/callable-scope.js +21 -0
  17. package/core/callers.js +4726 -940
  18. package/core/check.js +22 -5
  19. package/core/class-identity.js +399 -12
  20. package/core/client-receivers.js +189 -0
  21. package/core/constructor-calls.js +831 -0
  22. package/core/constructor-hierarchy.js +147 -0
  23. package/core/constructor-protocol.js +196 -0
  24. package/core/contract-membership.js +346 -140
  25. package/core/cpp-conversion-constraints.js +123 -0
  26. package/core/cpp-conversion-syntax.js +216 -0
  27. package/core/cpp-conversions.js +414 -0
  28. package/core/cpp-scope.js +245 -44
  29. package/core/deadcode.js +61 -16
  30. package/core/decorator-binding.js +137 -3
  31. package/core/enum-reference-syntax.js +134 -0
  32. package/core/execute.js +17 -1
  33. package/core/external-macros.js +42 -10
  34. package/core/go-packages.js +171 -0
  35. package/core/graph-build.js +2 -0
  36. package/core/graph.js +75 -59
  37. package/core/ignore-rules.js +2 -1
  38. package/core/imports.js +145 -19
  39. package/core/index-ir.js +41 -4
  40. package/core/inprocess-clients.js +41 -15
  41. package/core/ir.js +27 -6
  42. package/core/macro-expansion.js +38 -2
  43. package/core/out-of-class-members.js +182 -0
  44. package/core/output/analysis-ext.js +4 -2
  45. package/core/output/analysis.js +89 -20
  46. package/core/output/graph.js +12 -3
  47. package/core/output/lines.js +4 -3
  48. package/core/output/public.js +2 -0
  49. package/core/output/reporting.js +12 -1
  50. package/core/output/shared.js +2 -0
  51. package/core/output/tracing.js +28 -22
  52. package/core/output-budget.js +2 -2
  53. package/core/parallel-build.js +52 -1
  54. package/core/project.js +217 -112
  55. package/core/provenance-constructor-base.js +161 -0
  56. package/core/provenance-facts.js +257 -27
  57. package/core/provenance-overload.js +458 -54
  58. package/core/provenance-type.js +487 -0
  59. package/core/provenance.js +234 -15
  60. package/core/public-command.js +17 -2
  61. package/core/query-bodies.js +159 -0
  62. package/core/reflection.js +270 -2
  63. package/core/rename-token-syntax.js +111 -0
  64. package/core/reporting.js +13 -7
  65. package/core/request-helpers.js +63 -7
  66. package/core/rust-macro-expansion.js +151 -19
  67. package/core/rust-modules.js +1 -1
  68. package/core/rust-names.js +607 -0
  69. package/core/search.js +70 -17
  70. package/core/shared.js +98 -1
  71. package/core/source-memo.js +201 -0
  72. package/core/text-usage-syntax.js +38 -0
  73. package/core/tracing.js +7 -1
  74. package/core/type-denotation.js +124 -37
  75. package/core/type-references.js +615 -246
  76. package/core/value-references.js +2777 -0
  77. package/core/verify.js +1097 -281
  78. package/languages/adapter.js +28 -4
  79. package/languages/c-family.js +1118 -164
  80. package/languages/constructor-bases.js +105 -0
  81. package/languages/cpp-platform.js +26 -0
  82. package/languages/cpp-site-syntax.js +83 -0
  83. package/languages/csharp-scope.js +439 -0
  84. package/languages/csharp.js +428 -68
  85. package/languages/go.js +385 -207
  86. package/languages/html.js +4 -2
  87. package/languages/index.js +397 -2
  88. package/languages/java-platform.js +226 -0
  89. package/languages/java-unicode.js +269 -0
  90. package/languages/java.js +461 -117
  91. package/languages/javascript.js +418 -66
  92. package/languages/lexical-scope.js +190 -23
  93. package/languages/python.js +404 -54
  94. package/languages/rust.js +510 -82
  95. package/languages/utils.js +67 -8
  96. package/mcp/server.js +8 -2
  97. package/package.json +3 -3
@@ -5,7 +5,7 @@ description: AST code intelligence for JavaScript/TypeScript, Python, Go, Rust,
5
5
 
6
6
  # UCN
7
7
 
8
- UCN answers semantic questions about a codebase from a tree-sitter index: where a symbol is defined, who calls it, what it calls, what a change touches, which tests reach it. Every answer labels its evidence and accounts for every line it looked at; nothing is silently dropped.
8
+ UCN answers semantic questions about a codebase from a tree-sitter index: where a symbol is defined, who calls it, what it calls, what a change touches, which tests reach it. Caller and impact answers label uncertain relationships and account for observed name occurrences. Other commands expose their own scope and evidence limits.
9
9
 
10
10
  ## When to use it
11
11
 
@@ -17,11 +17,25 @@ UCN answers semantic questions about a codebase from a tree-sitter index: where
17
17
 
18
18
  1. `ucn repo` in an unfamiliar repository; `--deep` adds index health and readiness. Skipped unsupported source is listed with a handoff: use text search and a language-native tool for those files. An `UNSUPPORTED` or `PARTIAL` scope is never a semantic zero.
19
19
  2. `ucn find <name>` pins a definition. Pass its `path:line:name` handle to every later command. A plain name that matches several definitions carries an ambiguity warning in `show`, `source`, `trace`, `impact`, `tests`, `check` and `plan`; never treat the auto-selected definition as the repository-wide target.
20
- 3. `ucn show <handle>` gives the summary, callers and callees. Add `--sections=source,tests,types,dependencies,example,related` for more.
20
+ 3. `ucn show <handle>` gives the summary, callers and callees. `--sections` replaces that selection; for example, `--sections=summary,source,tests` requests those three sections.
21
21
  4. Before a change: `ucn impact <handle>` and `ucn tests <handle> --depth=3`.
22
22
  5. After a signature change: `ucn check <handle>`; before committing: target-less `ucn check`. Both compare a changed declaration with its parameters at `--base` (default `HEAD`), so the call sites bound to the old declaration are checked against the new one; a site that fits no remaining overload is a mismatch, never an excluded other-target line.
23
23
  6. `ucn source <handle>` or `ucn source path/to/file:10-30` for exact code, only when inspection is needed.
24
24
 
25
+ The direct tests in `show <handle> --sections=tests` match `tests <handle>`. Equivalent file and line parameters preserve the same exact declaration, including overloads.
26
+
27
+ Rust calls to trait implementations on external types require review when unseen inherent methods could win. This applies even when a query includes several target definitions.
28
+
29
+ Python inherited members respect base order. Unknown earlier bases and explicit `super(Class, value)` receivers can keep calls unverified. A lambda's own `self` or `cls` parameter does not prove a field owner; captured method receivers retain their binding.
30
+
31
+ An explicit constructor has its own handle, including Java overloads, compact record constructors and C++ constructors defined outside their class. Proven construction calls appear under that handle and supply arguments to `check`. Review unverified construction sites before changing the signature. A function that constructs a class lists the class as a callee and, when proven, the constructor body it runs `(constructs C)`. C++ template calls inside parenthesized object initializers remain visible.
32
+
33
+ C# `this(...)` and `base(...)` initializers keep the generic type's arity. Nested constructions under a generic containing type stay visible for review when that owner's identity is unproven. `tests` also includes nested-type annotation and qualifier references, with their evidence tier. Arguments such as `Outer<T>.Inner<U>` can keep C# overload choices unverified when the enclosing type identity is unresolved.
34
+
35
+ C++ overload checks resolve standard string types by qualified name and inspect project constructors and constraints. A sole surviving overload can be confirmed; unknown constraints or several viable conversions stay unverified. C# implicit operators keep potentially reachable overloads visible.
36
+
37
+ C++ integer literals with value zero keep pointer overloads reachable as null pointer constants.
38
+
25
39
  ## Choose a command
26
40
 
27
41
  | Decision | Command |
@@ -47,20 +61,30 @@ UCN answers semantic questions about a codebase from a tree-sitter index: where
47
61
 
48
62
  ## Read the evidence
49
63
 
50
- Caller-bearing views (`show`, `impact`, `trace`, `tests`, `check`) tier every candidate:
64
+ Caller candidates in `show`, `impact`, `trace` and `check` carry evidence tiers:
51
65
 
52
66
  - `CONFIRMED`: binding, receiver, import, or ownership evidence for the pinned target.
53
67
  - `UNVERIFIED`: call syntax that may reach the target, with the reason identity could not be established. Review it before a breaking change. When same-name definitions compete, `show` lists their stable handles once above the sites.
54
68
  - Excluded sites (another definition's caller, an incompatible receiver, an external package, an arity mismatch) are counted as other-target lines in `ACCOUNT`, each with its reason in JSON.
55
69
 
56
- Trust lines close every answer and survive truncation:
70
+ Caller, callee and trace views carry the applicable trust lines below, preserved through truncation. A source extraction, definition list or test-reference list does not provide a caller account; use `show` or `impact` when that account is needed.
57
71
 
58
72
  - `ACCOUNT` partitions every line where the name occurs: confirmed, unverified, non-call (definition, import, reference, other text), other-target, unaccounted. In mixed-language repositories it also counts occurrences in unsupported-language source files.
59
73
  - `CONTRACT` states what that partition covers. Semantic completeness is never claimed: aliases, generated code, reflection and runtime dispatch may exist.
60
74
  - `WARNING` lists unreadable, unparsed or partially indexed files and unsupported-language occurrence sites with their line text, so nothing text search would show is hidden. `usages` and `tests` carry the same disclosure as a note.
61
75
  - `FILTERED` means query options hid evidence. `CALLEE ACCOUNT` and `TREE ACCOUNT` do the same for callees and `trace` trees.
62
76
 
63
- A property/getter/setter target adds `PROPERTY ACCESS SITES` to `impact` (reads and writes with access kind; receiver identity confirms, an unresolved receiver stays unverified). A type target adds `TYPE REFERENCE SITES` (confirmed by an import link to the definition's file, or package scope in Go/Java). `DEPENDENCY SITES` counts them; `CALL SITES` stays call-shaped. Target-less `impact` and `check` diff the working tree against `HEAD` (`--staged` for the index), include untracked non-ignored source as whole-file additions, and put classes, interfaces, types and fields in declaration bands; a modified or deleted declaration makes `check` `BLOCKED` until reviewed with the language toolchain.
77
+ A field, constant, enum member or module value adds `VALUE ACCESS SITES` and a `VALUE ACCOUNT` to `impact`. Conditional value reexports and unresolved implementation owners stay visible for review. Its rename plan edits proven references by the language's own lookup and lists unresolved bindings for review.
78
+
79
+ Functions in a JavaScript/TypeScript declaration list have separate handles and extents, including inline HTML scripts. Neighboring module values retain their module scope. A Python construction keyword can name a field of a local dataclass or named tuple; an unresolved class binding remains a review item. Instance writes that wrap an inherited method remain indexed as fields. Later calls can still invoke that method through the wrapper, so callers and callees require review (`instance-attribute-wraps-method`); renames also review reads before the write. Qualified method values used in tests stay visible with their evidence tier.
80
+
81
+ Return-type flow follows imported aliases and declared field owners. An unresolved field hop or an unknown result on a known receiver cannot borrow an unrelated method's return annotation. Qualified methods remain visible even when their name is also a language builtin.
82
+
83
+ Rust chains follow the produced value through recorded field hops and proven standard lock guards. A trait impl on an external type cannot prove that `self.method()` or `Self::method(self)` calls itself: an unseen inherent method may win, so the call requires review. Struct constructions name the type declaration, never its impl block.
84
+
85
+ A property/getter/setter target adds `PROPERTY ACCESS SITES` to `impact` (reads and writes with access kind; receiver identity confirms, an unresolved receiver stays unverified). A type target (class, struct, interface, enum, trait, record, union, alias) adds `TYPE REFERENCE SITES`: every token naming the type outside its call sites (annotations, bases, casts, qualifiers, imports), decided by the language's own name lookup; constructions and static calls through the type stay in `CALL SITES`, and a `TYPE ACCOUNT` line partitions every name token (confirmed, unverified with a reason, excluded with a reason, at call sites, declaration). `DEPENDENCY SITES` counts each token once. Target-less `impact` and `check` diff the working tree against `HEAD` (`--staged` for the index), include untracked non-ignored source as whole-file additions, and put classes, interfaces, types and fields in declaration bands; a modified or deleted type or a deleted value makes `check` `BLOCKED`. A modified value requires review (`REVIEW_REQUIRED`) unless another finding blocks the check. Validate these changes with the language toolchain.
86
+
87
+ `tests` distinguishes calls and unverified calls from imports, references, strings and test-case matches. Those other match kinds are discovery hints, not confirmed call edges.
64
88
 
65
89
  Numeric evidence values are ordinal ranking weights, not probabilities. An observed-text zero is not a semantic zero or safe-delete proof.
66
90
 
@@ -79,10 +103,12 @@ ucn source handleRequest --raw # the code and nothing else, ready for
79
103
  ucn source src/server.js:40-80 --raw
80
104
  ```
81
105
 
82
- Records go to stdout; `ACCOUNT`/`CONTRACT`, notes and same-name disambiguation go to stderr as `# ` lines (MCP keeps them in the one text block; `--raw` appends its note as one trailing `# ` line there). `--lines` has no default row cap; explicit `--top`/`--limit` disclose what they omit; an explicit `--max-chars` fails before any output instead of truncating records. `grep -v '# unverified'` keeps the confirmed tier. `usages --lines` emits one record per source line and tags combined kinds; JSON keeps individual occurrences. `show --lines` accepts only the callers/callees sections (default callers); target-less `impact --lines` lists Git-diff callers with per-target accounting. `source --raw` extracts whole functions and large classes; `--max-lines` truncation is disclosed on stderr. Unusual path characters (backslash, tab, CR, LF) are escaped; use `--json` for exact filenames, and for `trace`/`tests` scripting. Closing the pipe with `head` is supported.
106
+ Records go to stdout; `ACCOUNT`/`CONTRACT`, notes and same-name disambiguation go to stderr as `# ` lines (MCP keeps them in the one text block; `--raw` appends its note as one trailing `# ` line there). `--lines` has no default row cap; explicit `--top`/`--limit` disclose what they omit; an explicit `--max-chars` fails before any output instead of truncating records. On `show --lines` caller or callee records, `grep -v '# unverified'` keeps the confirmed tier. `usages --lines` emits one record per source line and tags combined kinds; JSON keeps individual occurrences. `show --lines` accepts only the callers/callees sections (default callers); target-less `impact --lines` lists Git-diff callers with per-target accounting. `source --raw` extracts whole functions and large classes; `--max-lines` truncation is disclosed on stderr. Unusual path characters (backslash, tab, CR, LF) are escaped; use `--json` for exact filenames, and for `trace`/`tests` scripting. Closing the pipe with `head` is supported.
83
107
 
84
108
  Exit codes: 0 success; 1 for an empty `--lines` listing, a blocking `check` (target-less `check` with `TRUST: BLOCKED`, or `check <handle>` reporting a mismatch or an unverified call site), or a JSON command error (`meta.ok: false` plus `error`); 2 for a text-mode command error or a `check` that could not run. An exception inside UCN prints `Internal error: ...` on every surface (CLI JSON adds `meta.internalError: true`); it says nothing about the code, so rerun with a narrower target or report it.
85
109
 
110
+ File export queries report source-read and import-parser failures as errors. A failed query does not establish an empty public API.
111
+
86
112
  ## Surfaces, JSON and output budgets
87
113
 
88
114
  CLI, MCP and interactive mode run the same 18 commands through one registry, the same handlers and the same formatters. CLI spells multiword commands with hyphens (`audit-async`), MCP uses snake case (`audit_async`) through one `ucn` tool. `--json` returns `{ meta, data }`: `meta.command` keeps the surface spelling and may add `canonicalCommand`, `meta.contract` carries the truth boundary, and public `file` paths are relative to `meta.pathBase`. Definition handles start at a decorator when present; `nameLine` is the declaration token's line.
@@ -91,7 +117,7 @@ Text output has a character budget on both CLI and MCP: 3K for broad sweeps (`re
91
117
 
92
118
  ## Index and discovery
93
119
 
94
- Indexes live in a per-user, project-keyed cache outside the repository (`UCN_CACHE_DIR` overrides the root; `--no-cache` bypasses it; `--clear-cache` removes the project's cache; a `.ucn-cache` directory left in a project is migrated on first use). MCP keeps the process and index warm across calls. Concurrent cold starts share one build: the first process takes a build lock and the others wait for its cache (`Waiting for another ucn process building the index...` on stderr); a lock left by a dead process is broken automatically.
120
+ Indexes live in a per-user, project-keyed cache outside the repository (`UCN_CACHE_DIR` overrides the root; `--no-cache` bypasses it; `--clear-cache` removes the project's cache; a `.ucn-cache` directory left in a project is migrated on first use). MCP keeps the process and index warm across calls. Concurrent cold starts share one build: the first process takes a build lock and the others wait for its cache (with `--verbose`, `Waiting for another ucn process building the index...` on stderr); a lock left by a dead process is broken automatically.
95
121
 
96
122
  Discovery applies the project's `.gitignore` files (root and nested) with git's own matching rules; git-tracked files are indexed even when a rule matches them, and a failing `git ls-files` is disclosed as a partial index (`git-listing-failed` in `repo --sections=health` and in caller contracts), never a silently smaller one. `*.min.js`, `*.bundle.js` and `*.map` are skipped and disclosed, which makes observed-text completeness partial; `--include-bundled` (MCP `include_bundled=true`) indexes the JavaScript bundles, respecting user exclusions and bypassing the shared cache. Source maps stay unindexed; inspect them with text tools.
97
123
 
@@ -101,8 +127,8 @@ C/C++ uses `compile_commands.json` when present for header classification and in
101
127
 
102
128
  1. Pin the exact definition with `find`.
103
129
  2. Run `impact`; review every unverified, excluded, filtered, and warning entry.
104
- 3. Run `trace --direction=callers` for transitive behavioral impact.
105
- 4. Run `tests --depth=3`; treat paths without static test links as test-planning signals, not runtime coverage proof.
130
+ 3. Run `ucn trace <handle> --direction=callers` for transitive behavioral impact.
131
+ 4. Run `ucn tests <handle> --depth=3`; treat paths without static test links as test-planning signals, not runtime coverage proof.
106
132
  5. Make the change.
107
133
  6. Run `check <handle>`, the relevant compiler/type checker, and selected tests.
108
134
  7. Run target-less `check` to reconcile the repository diff.
@@ -12,7 +12,7 @@ Use text search (grep/ripgrep) for simple literals, error messages, configuratio
12
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
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
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`. |
15
+ | `source <handle\|file:range>` | Extract a function, class-like declaration, or exact line range (`src/a.js:10-30`, `src/a.js --range=10-30`, or `--file=PATH --range=N-M`; MCP `name` or `file` with `range`). `--raw`, `--max-lines=N`. |
16
16
  | `trace <handle>` | Callees by default (depth 3). `--direction=callers` for blast radius, `--to=entrypoints` for paths to roots, `--depth=N`, `--expand-unverified`. |
17
17
 
18
18
  ## Change and validation
@@ -22,7 +22,9 @@ Use text search (grep/ripgrep) for simple literals, error messages, configuratio
22
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
23
  | `tests <handle\|file>` | Statically linked direct tests; `--depth=N` adds transitively affected tests; `--calls-only` keeps direct calls and test-case matches. |
24
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. |
25
+ | `plan <handle>` | Preview `--rename-to=X`, `--add-param=p` (`--default-value=v`), or `--remove-param=p`. Never edits files. A Python param added beside `*args` or keyword-only params is keyword-only (after them, before `**kwargs`); calls passing arguments where a param is inserted before a rest param are listed. |
26
+
27
+ `show <handle> --sections=tests` and `tests <handle>` select direct tests for the same declaration. Equivalent `--file` and `--line` parameters preserve that pin, including overloaded methods.
26
28
 
27
29
  ## Repository and architecture
28
30
 
@@ -60,9 +62,9 @@ Use text search (grep/ripgrep) for simple literals, error messages, configuratio
60
62
  | `--depth=N` | Trace, dependency, or test traversal depth. |
61
63
  | `--direction=<value>` | Trace (`callees`/`callers`) or dependency (`imports`/`importers`/`both`) direction. |
62
64
  | `--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. |
65
+ | `--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`. CLI JSON is uncapped even with an explicit budget; `meta.maxChars` is `"not-applied"`. |
64
66
  | `--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>`. |
67
+ | `--range=N-M` | Explicit line range with `source <file>` or `source --file=<path>`. |
66
68
  | `--json` | Stable `{ meta, data }` envelope; `meta.contract` carries the truth boundary, decision safety, and next actions. |
67
69
  | `--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
70
  | `--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. |
@@ -97,7 +99,7 @@ Default test exclusions follow language conventions. Python `spec.py` and `*_spe
97
99
 
98
100
  ### find
99
101
 
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.
102
+ A name with no definition of exactly that name matches by similarity (substring and fuzzy), `*` and `?` are globs, and `--exact` keeps only the exact name. 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
103
 
102
104
  ### usages
103
105
 
@@ -109,33 +111,51 @@ The term is literal by default; pass `--regex` only when regular-expression sema
109
111
 
110
112
  ### show and impact
111
113
 
114
+ A field, constant, enum member or module value adds a `VALUE ACCESS SITES` dependency band to `impact` (`valueAccesses` in JSON). A Python instance attribute is a field of its class, declared by the first assignment on a method's receiver (`self.x = v`, `self.x: T = v`) unless the class body declares it, and so is a JS/TS property a class's methods assign on `this` (`this.x = v`); a member of an unnamed C/C++ struct or union is reached through the declarators of its type (`e->data.start`). Accesses are tiered by what they reach: a receiver of the field's own class confirms it, a receiver of an ancestor or interface declaring the member is `possible-dispatch`, and another member of the rename slot (a sibling class's own field, an override below it, another member's declaration) is excluded (`other-slot-member`, `slot-override`, `slot-member-declaration`); the rename still edits the whole slot. A keyword argument of a dataclass, NamedTuple or TypedDict construction names its field (`Segment(t, style=s)`), a Python dict key is a value read, a JS destructuring assignment (`[a, b] = f()`) writes its targets, a TS enum member written as a type (`kind: Kind.Text`) reads the member, and a namespace chain follows re-exported namespaces (`z.core.registry`). An import of a module whose whole value is the pin (`const req = require('./request')`, `import req from './request'`) is a dependency site; the importer's local name and its reads stay in a rename. A Rust type path (`Type::name()`) names an associated item, never a field; a bare name in a body a namespace-scope macro wraps (`TEST_F(Fixture, Name) { .. }`) is unverified (`macro-generated-scope`) when the class an argument names declares the member. It lists confirmed and unverified references with token columns, access kinds and, for unverified ones, the reason. `DEPENDENCY SITES` counts each token once (a value that is called is one site). A `VALUE ACCOUNT` line puts every name token of the scanned lines in one bucket: confirmed, unverified, excluded (with reasons) or declaration (`valueAccesses.account` in JSON); the caller `ACCOUNT` remains call-shaped.
115
+
112
116
  `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
117
 
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.
118
+ 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 (class, struct, interface, enum, trait, record, union or type alias), `impact` adds a `TYPE REFERENCE SITES` band: every token naming the type on the name's lines, decided by the same lookup a type rename uses (lexical shadows, type parameters, imports, packages, namespaces, include closures). A token the lookup proves names the type is confirmed with its kind (`type`, `value`, `import`, `member`, `attribute`) and column; one it cannot settle is unverified with its reason; one naming something else is excluded with its reason. Constructions and static member calls through the type (`new Foo()`, `Foo(..)`, `Key.get(..)`) are call sites, listed once under `CALL SITES`. `TYPE ACCOUNT` partitions every name token: confirmed, unverified, excluded (by reason), at call sites, declaration. `DEPENDENCY SITES` counts each token once.
115
119
 
116
120
  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
121
 
118
122
  ### tests
119
123
 
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`.
124
+ `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 or a line handle), 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`). A nested type also lists annotation and qualifier references decided by the type lookup, with unresolved references marked unverified. A line handle of an overload or a constructor lists that definition's calls, never its siblings'. `--depth=N` adds transitively affected tests. Import, reference, string and test-case matches are discovery hints rather than confirmed call edges; `--calls-only` keeps direct calls and test-case matches. Empty results are not runtime coverage proof; treat paths without static test links as test-planning signals. Script `tests` and `trace` with `--json`.
121
125
 
122
126
  ### check
123
127
 
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.
128
+ `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 type declarations, and deleted values, make it `BLOCKED` until reviewed with the language toolchain, because arity checks cannot validate shape or inheritance compatibility. A modified field, constant or module value is a `value_change` warning with its value access sites (`REVIEW_REQUIRED`). A changed line belongs to each callable whose own source changed: a member added to a one-line class is `ADDED`, and the members beside it on that line stay unchanged.
125
129
 
126
130
  ### plan
127
131
 
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.
132
+ Field, constant, enum-member and module-value handles rename the tokens whose binding the AST lookup proves. Unresolved receivers, shorthand keys, reassignments and inherited structural shadows require review. Java static imports and enum switch labels follow their declaring owner. JS/TS class values keep static and instance storage distinct; Rust constant patterns, including parameters, name the constant.
133
+
134
+ Each language's own lookup decides a value token. A Python module variable is one variable: every module-scope binding of the name in its file (another assignment, a `def`, `global` writes in functions) is renamed with it, an unaliased import of the name gains an alias (`import json as j`), defaults and decorators read the enclosing scope, and a class body reads the module variable before its own binding of the name and the class attribute after it. A JS/TS member names a module value only through a namespace import or `require` of an ES module; a named or default import, a shadowing local, and a CommonJS export key (`exports.x = x`) hold ordinary properties. A Go local declared from a package value hides the package name in its block. C++ `::x` names the global namespace only. C `extern` declarations and the external definition are one object (several external definitions leave the shared declarations for review, `link-alternatives`). Java pattern variables are scoped by their pattern's flow and C++ structured bindings are locals. In JS/TS, Python methods, Go and Rust a bare name never names a member, and an import never names one either. A JS/TS or Python field is renamed with the same-name fields of its slot: the interface a class body implements, the ancestors declaring it and overriding subclasses (accessors filling the slot are review items), and keys of object literals declared with that type (`const x: T = { .. }`).
135
+
136
+ Known aliases preserve a field receiver's type identity. C++ template arguments use ordinary name lookup; Rust generic arguments follow the declaration's type or const parameter. When a type and a module value share a name and line, select a unique declaration before renaming.
137
+
138
+ Private field names retain `#` and follow their lexical class, including outer classes. Anonymous structural member declarations require review when their relationship to the target is unresolved.
139
+
140
+ 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, ..)`, and method type parameters compared by position, so `Send<TRequest>(TRequest)` never takes the slot of `Send<T>(IRequest<T>)`), every other supertype a class in the slot fills with the member (a class implementing two interfaces that declare it; in Java, C# and TS a base-class method that implements an interface a subclass declares), where a C# `new` member starts a slot of its own, 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# definitions of the same item and generic arity in branches of an `#if` the other does not share, Go declarations of one package under other build constraints; overloads differing in generic arity and local functions of two methods are separate items), the declaring and implementing parts of a C# partial method, 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 Java method reference or C# method group to one of several overloads is a review item (`overload-ambiguous`), the overload being chosen by its target type; 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
141
 
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`.
142
+ 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; C++ member types the standard library reads by name, such as `value_type`, `reference` and `iterator_category`), 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
143
 
132
144
  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
145
 
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.
146
+ 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. Calls through different members of the renamed slot on one line are combined into one token-specific edit. 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
147
 
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.
148
+ Exact token/expression spans keep a foreign same-named occurrence on the same line unchanged. A definition line combines the declaration's name with independently resolved calls and value references, keeping same-spelled parameters, named results and types; an unresolved reference beside another edit is listed for review. 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
149
 
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.
150
+ C# property references include bare expressions resolved through local scopes (deconstruction and pattern designations included, each in its own scope), enclosing types and their nested types, bases and static imports, and object-initializer keys resolved through the constructed type (including target-typed `new()`). A nested collection initializer reads the property; compound assignments and increments read and write it. An unresolved initializer or pattern owner, or an inferred anonymous-object key, is listed for review. Bare `field` in a property body requires review because its binding depends on the language version. Namespace-scoped imports and aliases keep unrelated same-named types separate.
151
+
152
+ Generic method invocations keep the callable name separate from their type arguments and receiver. In C#, an invocation name is a method or delegate value; a type construction uses `new`. Generic method values remain method-group references, with unresolved receivers listed for review. In C++, a member template found by member lookup hides a same-named type at a bare call; qualified type constructions keep their type references.
153
+
154
+ In C#, a local function keeps the enclosing type's member lookup, including other partial parts; one in top-level statements reaches static imports directly unless the project declares parts of `Program`. C++ nested types keep access to enclosing static members when defined outside the enclosing type's body. Unresolved lexical ownership stays unverified.
155
+
156
+ A C++ namespace-scope name declared in one arm of a preprocessor group and imported by a using-declaration in another arm has a configuration-dependent binding. The plan edits references proven to be in the branch of the declaration or of one of its configuration alternatives, counts import-branch sites as another target in the ACCOUNT, and lists references outside the branches for review (`configuration-alternative`). Review those sites for every supported build configuration before applying the rename.
157
+
158
+ 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 (Java `outer.new Inner()` by the outer value's declared type) 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, C++ deduction guides (`W(T) -> W<T>;`) 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 (in C/C++ also a variable declared earlier in an enclosing block, which hides the type name), 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), a function-type typedef (`typedef int F(void *);`) is renamed at its declarator, a cast in a replacement list (`#define LOW(v) ((BYTE)(v))`) is an edit when every occurrence of the name on the line is such a cast, 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 named after its type or a C# finalizer handle plans the class rename. An out-of-class C++ constructor uses the type its qualifier denotes; an unresolved owner requires selecting the class declaration. A C/C++ member not named like a project type is an ordinary member rename. A rename the language's own protocol blocks (Python `__init__`) lists the calls that spell the name, never class constructions.
139
159
 
140
160
  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
161
 
@@ -149,7 +169,7 @@ Summary/stats `buildTime` is the duration of the last index build (discovery, pa
149
169
 
150
170
  ### deps
151
171
 
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.
172
+ In JS/TS and Python, where an import runs the imported module, 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. A cycle of Go, Rust, Java, C#, C or C++ files, whose imports and includes run no module code, is `static` (`STATIC CYCLES`, JSON `classification: "static"`), neither eager nor deferred.
153
173
 
154
174
  ### endpoints
155
175
 
@@ -157,7 +177,7 @@ Cycles distinguish eager edges from deferred ones. `eager` means every edge exec
157
177
 
158
178
  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
179
 
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.
180
+ Client receivers require HTTP import, constructor, or factory evidence; names such as `client`, `session`, or `api` alone stay possible and never create bridges. Python follows returned clients and fixture chains, including imported/class fixtures and fixtures returning factories; JavaScript/TypeScript follows imported client values and factories such as `axios.create`, `ky.create`, and `got.extend`. 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
181
 
162
182
  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
183
 
@@ -165,9 +185,11 @@ Route paths include router mount prefixes composed from the code: FastAPI `inclu
165
185
 
166
186
  ### deadcode
167
187
 
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.
188
+ Constructor declarations are not claims of their own (`N constructor(s) not listed`, JSON `excludedConstructors`): reflection, frameworks and the initializer the compiler generates when one is deleted can depend on them without a construction call. An unused type still appears as a whole-type candidate.
189
+
190
+ `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; a fully dynamic one (`eval(code)`) withholds them all and is listed as a caller of none. A reflective name that is a parameter of the enclosing function, never reassigned (`registry[type](..)` in a call, `getattr(self, name)`, `getMethod(name)`), takes the string literals the function's callers pass at that position: those members are withheld and listed as `reflection-pattern` callers. Reflection with no specific literal part is counted and warned because it cannot be attributed to one member. When a file contains dynamic reflection, `deadcode` also conservatively withholds candidates in that file whose exact spelling occurs as an AST string literal. Text and JSON (`reflection.withheldByTable`) list each name and literal location. This does not prove flow: even an unrelated literal in that file can withhold a candidate; another file without dynamic reflection is unaffected.
169
191
 
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.
192
+ 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), members of an object literal declared with an outside type (`ProxyHandler` traps) and members of impls of an outside Rust trait (`impl FromIterator for A`, however many project types implement it) may be called by that outside code and are hidden as external-contract surface.
171
193
 
172
194
  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
195
 
@@ -177,7 +199,7 @@ In C/C++, names an expanded macro invocation produces are live; a token-pasting
177
199
 
178
200
  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
201
 
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.
202
+ 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. A C# producer is a method declared `async`: a Task- or ValueTask-returning method without `async` (an interface member, `=> new(..)`) is not audited, and a task a member access consumes (`.ConfigureAwait(false)`) flows on.
181
203
 
182
204
  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
205