ucn 5.5.1 → 5.5.2
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.
- package/.claude/skills/ucn/SKILL.md +35 -9
- package/.claude/skills/ucn/references/commands.md +38 -16
- package/.claude/skills/ucn/references/resolution-rules.md +126 -20
- package/.claude/skills/ucn/references/trust-contract.md +5 -3
- package/README.md +30 -21
- package/cli/index.js +1 -1
- package/core/accessors.js +341 -54
- package/core/account.js +74 -20
- package/core/analysis.js +257 -125
- package/core/ast-analysis.js +12 -3
- package/core/brief.js +8 -4
- package/core/build-worker.js +2 -1
- package/core/cache.js +137 -6
- package/core/call-name-cache.js +134 -0
- package/core/callable-scope.js +21 -0
- package/core/callers.js +4726 -940
- package/core/check.js +22 -5
- package/core/class-identity.js +399 -12
- package/core/constructor-calls.js +831 -0
- package/core/constructor-hierarchy.js +147 -0
- package/core/constructor-protocol.js +196 -0
- package/core/contract-membership.js +346 -140
- package/core/cpp-conversion-constraints.js +123 -0
- package/core/cpp-conversion-syntax.js +216 -0
- package/core/cpp-conversions.js +414 -0
- package/core/cpp-scope.js +245 -44
- package/core/deadcode.js +35 -15
- package/core/decorator-binding.js +137 -3
- package/core/enum-reference-syntax.js +134 -0
- package/core/execute.js +17 -1
- package/core/external-macros.js +42 -10
- package/core/go-packages.js +171 -0
- package/core/graph-build.js +2 -0
- package/core/graph.js +75 -59
- package/core/ignore-rules.js +2 -1
- package/core/imports.js +145 -19
- package/core/index-ir.js +41 -4
- package/core/ir.js +27 -6
- package/core/macro-expansion.js +38 -2
- package/core/out-of-class-members.js +182 -0
- package/core/output/analysis-ext.js +4 -2
- package/core/output/analysis.js +89 -20
- package/core/output/graph.js +12 -3
- package/core/output/lines.js +4 -3
- package/core/output/public.js +1 -0
- package/core/output/reporting.js +6 -1
- package/core/output/shared.js +2 -0
- package/core/output/tracing.js +28 -22
- package/core/output-budget.js +2 -2
- package/core/parallel-build.js +52 -1
- package/core/project.js +217 -112
- package/core/provenance-constructor-base.js +161 -0
- package/core/provenance-facts.js +257 -27
- package/core/provenance-overload.js +458 -54
- package/core/provenance-type.js +487 -0
- package/core/provenance.js +234 -15
- package/core/public-command.js +17 -2
- package/core/query-bodies.js +159 -0
- package/core/reflection.js +255 -2
- package/core/rename-token-syntax.js +111 -0
- package/core/reporting.js +13 -7
- package/core/rust-macro-expansion.js +151 -19
- package/core/rust-modules.js +1 -1
- package/core/rust-names.js +607 -0
- package/core/search.js +70 -17
- package/core/shared.js +98 -1
- package/core/source-memo.js +201 -0
- package/core/text-usage-syntax.js +38 -0
- package/core/tracing.js +7 -1
- package/core/type-denotation.js +124 -37
- package/core/type-references.js +615 -246
- package/core/value-references.js +2777 -0
- package/core/verify.js +1097 -281
- package/languages/adapter.js +28 -4
- package/languages/c-family.js +1118 -164
- package/languages/constructor-bases.js +105 -0
- package/languages/cpp-platform.js +26 -0
- package/languages/cpp-site-syntax.js +83 -0
- package/languages/csharp-scope.js +439 -0
- package/languages/csharp.js +428 -68
- package/languages/go.js +385 -207
- package/languages/html.js +4 -2
- package/languages/index.js +397 -2
- package/languages/java-platform.js +226 -0
- package/languages/java-unicode.js +269 -0
- package/languages/java.js +461 -117
- package/languages/javascript.js +418 -66
- package/languages/lexical-scope.js +190 -23
- package/languages/python.js +404 -54
- package/languages/rust.js +510 -82
- package/languages/utils.js +67 -8
- package/mcp/server.js +8 -2
- package/package.json +2 -2
|
@@ -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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
|
@@ -62,7 +64,7 @@ Use text search (grep/ripgrep) for simple literals, error messages, configuratio
|
|
|
62
64
|
| `--all` | Lift result and formatter caps where a command supports it; the truncation notice says when it does. |
|
|
63
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`. JSON is not transport-truncated. |
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -165,9 +185,11 @@ Route paths include router mount prefixes composed from the code: FastAPI `inclu
|
|
|
165
185
|
|
|
166
186
|
### deadcode
|
|
167
187
|
|
|
168
|
-
|
|
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.
|
|
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)
|
|
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
|
|