ucn 4.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/ucn/SKILL.md +31 -7
- package/README.md +89 -50
- package/cli/index.js +199 -94
- package/core/account.js +3 -1
- package/core/analysis.js +322 -304
- package/core/bridge.js +13 -8
- package/core/cache.js +109 -19
- package/core/callers.js +969 -77
- package/core/check.js +19 -8
- package/core/deadcode.js +368 -40
- package/core/discovery.js +31 -11
- package/core/entrypoints.js +149 -17
- package/core/execute.js +330 -43
- package/core/graph-build.js +61 -10
- package/core/graph.js +282 -61
- package/core/imports.js +72 -3
- package/core/output/analysis-ext.js +70 -10
- package/core/output/analysis.js +52 -33
- package/core/output/check.js +4 -1
- package/core/output/endpoints.js +8 -3
- package/core/output/extraction.js +12 -1
- package/core/output/find.js +23 -9
- package/core/output/graph.js +32 -9
- package/core/output/refactoring.js +147 -49
- package/core/output/reporting.js +104 -5
- package/core/output/search.js +30 -3
- package/core/output/shared.js +31 -4
- package/core/output/tracing.js +22 -11
- package/core/parser.js +8 -6
- package/core/project.js +167 -7
- package/core/registry.js +20 -16
- package/core/reporting.js +131 -13
- package/core/search.js +270 -55
- package/core/shared.js +240 -1
- package/core/stacktrace.js +23 -1
- package/core/tracing.js +278 -36
- package/core/verify.js +352 -349
- package/languages/go.js +29 -17
- package/languages/index.js +56 -0
- package/languages/java.js +133 -16
- package/languages/javascript.js +215 -27
- package/languages/python.js +113 -47
- package/languages/rust.js +89 -26
- package/languages/utils.js +35 -7
- package/mcp/server.js +69 -30
- package/package.json +4 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ucn
|
|
3
|
-
description: "Code intelligence toolkit — extract functions, trace callers, analyze impact, detect dead code without reading whole files. PREFER over grep+read when you need: who calls a function, what breaks if you change it, or the full call chain of a pipeline. One `ucn about` replaces 3-4 grep+read cycles. One `ucn trace` maps an entire execution flow without reading any files. Works on JS/TS, Python, Go, Rust, Java, HTML. Skip for plain text search or codebases under 500 LOC."
|
|
3
|
+
description: "Code intelligence toolkit — extract functions, trace callers, analyze impact, detect dead code without reading whole files. PREFER over grep+read when you need: who calls a function, what breaks if you change it, or the full call chain of a pipeline. `ucn orient` gives a one-screen overview of any new repo. One `ucn about` replaces 3-4 grep+read cycles. One `ucn trace` maps an entire execution flow without reading any files. Works on JS/TS, Python, Go, Rust, Java, HTML. Skip for plain text search or codebases under 500 LOC."
|
|
4
4
|
allowed-tools: Bash(ucn *), Bash(npx ucn *)
|
|
5
5
|
argument-hint: "[command] [symbol-name] [--flags]"
|
|
6
6
|
---
|
|
@@ -13,6 +13,7 @@ Extract functions, trace call chains, find callers, and detect dead code — wit
|
|
|
13
13
|
|
|
14
14
|
**Use UCN when the next action would be:**
|
|
15
15
|
|
|
16
|
+
- "I just opened this repo, where do I start?" → `ucn orient` — one screen: size, top dirs, hot functions, entry points, trust verdict
|
|
16
17
|
- "Let me grep for all callers of this function" → `ucn impact <name>` — finds every call site, grouped by file, with args shown
|
|
17
18
|
- "Let me read this 800-line file to find one function" → `ucn fn <name> --file=<hint>` — extracts just that function
|
|
18
19
|
- "Let me trace through this code to understand the flow" → `ucn trace <name> --depth=3` — shows the full call tree without reading any files
|
|
@@ -88,7 +89,7 @@ ucn class MarketDataFetcher
|
|
|
88
89
|
|
|
89
90
|
### 6. `deadcode` — Find unused code
|
|
90
91
|
|
|
91
|
-
Lists all functions and classes with zero callers across the project. Framework entry points (Express routes, Spring controllers, Celery tasks, etc.) and exported/public API symbols — including methods of exported classes in JS/TS/Python — are automatically excluded (`--include-exported` audits them). Interface/trait method declarations are labeled `[declared on interface X — contract surface, not executable code]`: unreferenced is true, but deleting one changes the API contract, not dead logic.
|
|
92
|
+
Lists all functions and classes with zero callers across the project — class-like symbols (classes, structs, interfaces, traits, enums, namespaces) are audited alongside functions. Framework entry points (Express routes, Spring controllers, Celery tasks, etc.) and exported/public API symbols — including methods of exported classes in JS/TS/Python — are automatically excluded (`--include-exported` audits them). Interface/trait method declarations are labeled `[declared on interface X — contract surface, not executable code]`: unreferenced is true, but deleting one changes the API contract, not dead logic. Symbols whose only call sites sit inside their own same-name definitions are claimed and marked `[only self-references — recursive]` — the group is unreachable from outside.
|
|
92
93
|
|
|
93
94
|
```bash
|
|
94
95
|
ucn deadcode # Everything
|
|
@@ -149,6 +150,17 @@ ucn entrypoints --file=routes/ # Scoped to files
|
|
|
149
150
|
ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pytest, Rust #[test], etc.)
|
|
150
151
|
```
|
|
151
152
|
|
|
153
|
+
### 11. `orient` — First command in a new repo
|
|
154
|
+
|
|
155
|
+
One screen: size + language mix, densest directories, most-called production functions, entry-point counts, and the trust verdict. Composes what would otherwise take four calls (`toc` + `stats --hot` + `entrypoints` + `doctor`).
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
ucn orient # run this before anything else in an unfamiliar codebase
|
|
159
|
+
ucn orient --top=15 # longer dir/hot lists
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The `Next:` line suggests concrete follow-ups, starting with `about` on the hottest production function.
|
|
163
|
+
|
|
152
164
|
## When to Use the Other Commands
|
|
153
165
|
|
|
154
166
|
| Situation | Command | What it does |
|
|
@@ -164,6 +176,7 @@ ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pyte
|
|
|
164
176
|
| Understanding who depends on a file | `ucn exporters <file>` | Which files import it |
|
|
165
177
|
| See what a file exports | `ucn file-exports <file>` | All exported functions, classes, variables with signatures |
|
|
166
178
|
| Quick project overview | `ucn toc` | Every file with function/class counts and line counts |
|
|
179
|
+
| Just entered an unfamiliar repo | `ucn orient` | One screen: size, top dirs, hot functions, entry points, trust verdict. Run it first |
|
|
167
180
|
| Project complexity stats | `ucn stats` | File counts, symbol counts, lines by language. `--functions` for per-function line counts. `--hot --top=N` for the most-called functions (orientation primitive on a new repo) |
|
|
168
181
|
| Find by glob pattern | `ucn find "handle*"` | Locate definitions matching a glob (supports * and ?) |
|
|
169
182
|
| Text search with context | `ucn search term --context=3` | Like grep -C 3, shows surrounding lines |
|
|
@@ -217,7 +230,7 @@ ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pyte
|
|
|
217
230
|
|
|
218
231
|
`audit-async` is the focused tool for the `awaited=false` case across an entire async function body.
|
|
219
232
|
|
|
220
|
-
## Reading Tiered Output (about / context / impact / trace / blast / reverse-trace / affected-tests)
|
|
233
|
+
## Reading Tiered Output (about / context / impact / trace / blast / reverse-trace / affected-tests / diff-impact / verify / plan / check)
|
|
221
234
|
|
|
222
235
|
Caller answers are a **partition of every text occurrence** of the symbol — nothing is silently hidden. Sections:
|
|
223
236
|
|
|
@@ -232,7 +245,18 @@ Caller answers are a **partition of every text occurrence** of the symbol — no
|
|
|
232
245
|
|
|
233
246
|
Resolution labels in `evidence:` lines (high to low): `exact-binding` (0.98, import/binding evidence) · `same-class` (0.92) · `receiver-hint` (0.80, inferred receiver type) · `scope-match` (0.65, import/receiver-binding scope evidence) · `name-only` (0.40) · `uncertain` (0.25). Confirmed tier = scope-match and above. JSON output keeps per-edge decimals plus `tier`.
|
|
234
247
|
|
|
235
|
-
Flags: `--min-confidence=0.7` filters confirmed edges (hidden count appears in FILTERED). `--include-uncertain`
|
|
248
|
+
Flags: `--min-confidence=0.7` filters confirmed edges (hidden count appears in FILTERED). `--include-uncertain` and `--include-methods` have **no effect** on tiered commands (about/context/impact/trace/blast/reverse-trace/affected-tests/diff-impact/verify/plan/smart) — everything is always shown, tiered by evidence.
|
|
249
|
+
|
|
250
|
+
### Refactor commands run the same contract (v4)
|
|
251
|
+
|
|
252
|
+
- `verify` arg-checks the **confirmed** band only; candidates without evidence render in `UNVERIFIED CALL SITES (N)` with reasons and are NOT arg-checked (they may target another symbol). A wrong-arity method call with binding evidence is flagged **by default** now. The `ACCOUNT:` line reconciles.
|
|
253
|
+
- `plan` plans changes for confirmed sites; `UNVERIFIED CALL SITES` lists sites that MAY also need the change — review them before refactoring. Plan and verify agree by construction.
|
|
254
|
+
- `diff-impact` reports per-changed-function confirmed `Callers` + `Unverified call sites` + a per-symbol `ACCOUNT:` line. `check` shows `N callers (+M unverified)` per changed function; ORPHAN requires zero candidates in BOTH tiers.
|
|
255
|
+
- `context`/`smart` also account the **callee** side: `CALLEES — UNVERIFIED (N)` entries + a `CALLEE ACCOUNT:` arithmetic line.
|
|
256
|
+
|
|
257
|
+
### Advisory commands self-label
|
|
258
|
+
|
|
259
|
+
`related`, `example`, `stacktrace`, and `endpoints --bridge` print an `Advisory:` line (and carry an `advisory` field in JSON): their answers are ranked heuristics, not verified claims. Contracted commands carry accounts; advisory commands say so — there is no third category.
|
|
236
260
|
|
|
237
261
|
### Tree commands (trace / blast / reverse-trace / affected-tests)
|
|
238
262
|
|
|
@@ -281,7 +305,7 @@ ucn [target] <command> [name] [--flags]
|
|
|
281
305
|
| `--expand-unverified` | `blast`/`reverse-trace`: follow unverified caller edges in the tree. Downstream nodes are marked as unverified chains — possible, not confirmed, impact |
|
|
282
306
|
| `--include-tests` | Include test files in usage counts (`about`) and results (`find`, `usages`, `deadcode`). Callers always include tests. |
|
|
283
307
|
| `--exclude-tests` | Exclude test entries from `entrypoints` (tests are included by default since they ARE entry points). |
|
|
284
|
-
| `--include-methods` | Include `obj.method()`
|
|
308
|
+
| `--include-methods` | Include `obj.method()` callee expansion in `trace`/`smart`. No effect on caller-direction commands (`about`/`context`/`impact`/`verify`/`blast`/`reverse-trace`/`affected-tests`) — method calls are always analyzed and tiered by receiver evidence |
|
|
285
309
|
| `--base=<ref>` | Git ref for diff-impact (default: HEAD) |
|
|
286
310
|
| `--staged` | Analyze staged changes (diff-impact) |
|
|
287
311
|
| `--no-cache` | Force re-index after editing files |
|
|
@@ -292,7 +316,7 @@ ucn [target] <command> [name] [--flags]
|
|
|
292
316
|
| `--hot` | List top N most-called functions in `stats` (use with `--top=N`, default 10). Best orientation primitive when entering a new repo |
|
|
293
317
|
| `--diverse` | Cluster `example` call sites by argument shape and return one representative per cluster (use with `--top=N`, default 3) |
|
|
294
318
|
| `--git` | Attach git enrichment to `about` / `brief`: last commit (ISO + author) and recent change count (last 30 days). Skipped silently when not a git repo |
|
|
295
|
-
| `--json` | Machine-readable JSON output.
|
|
319
|
+
| `--json` | Machine-readable JSON output. Most commands wrap in `{meta, data}` (e.g., `find`, `deadcode`, `context`, `verify`, `plan`, `diff-impact` — completeness signals and the ACCOUNT live in `meta`); `about` and `impact` return their full result object flat — check each command's output shape |
|
|
296
320
|
| `--code-only` | Exclude matches in comments and strings (`search`/`usages`) |
|
|
297
321
|
| `--with-types` | Include related type definitions in `smart`/`about` output |
|
|
298
322
|
| `--detailed` | Show full symbol listing per file in `toc` |
|
|
@@ -303,7 +327,7 @@ ucn [target] <command> [name] [--flags]
|
|
|
303
327
|
| `--max-lines=N` | Max source lines for `class` (large classes show summary by default) |
|
|
304
328
|
| `--case-sensitive` | Case-sensitive text search (default: case-insensitive) |
|
|
305
329
|
| `--exact` | Exact name match only in `find`/`typedef` (no substring) |
|
|
306
|
-
| `--include-uncertain` |
|
|
330
|
+
| `--include-uncertain` | No effect on tiered commands — unverified candidates are always shown in their own section with reasons |
|
|
307
331
|
| `--hide-confidence` | Hide confidence scores (shown by default) in `context`/`about` |
|
|
308
332
|
| `--min-confidence=N` | Filter edges below confidence threshold (e.g., `--min-confidence=0.7` keeps only high-confidence edges) |
|
|
309
333
|
| `--calls-only` | Only show call/test-case matches in `tests` (skip file-level results) |
|
package/README.md
CHANGED
|
@@ -39,8 +39,9 @@ And it's built to be **trusted**: every "who calls this?" splits into what UCN c
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
npm install -g ucn
|
|
42
|
+
npm install -g ucn # Node.js 20+
|
|
43
43
|
|
|
44
|
+
ucn orient # first look at any repo: size, hot spots, trust
|
|
44
45
|
ucn trace main --depth=3 # full execution flow
|
|
45
46
|
ucn about handleRequest # definition + callers + callees + tests
|
|
46
47
|
ucn impact handleRequest # every call site with arguments
|
|
@@ -53,28 +54,28 @@ ucn deadcode --exclude=test # unused code, AST-verified
|
|
|
53
54
|
$ ucn trace build --depth=2
|
|
54
55
|
|
|
55
56
|
build
|
|
56
|
-
├── detectProjectPattern (core/discovery.js:
|
|
57
|
+
├── detectProjectPattern (core/discovery.js:450) 1x
|
|
57
58
|
├── parseGitignore (core/discovery.js:131) 1x
|
|
58
|
-
├── expandGlob (core/discovery.js:
|
|
59
|
-
│ ├── parseGlobPattern (core/discovery.js:
|
|
60
|
-
│ ├── walkDir (core/discovery.js:
|
|
61
|
-
│ └── compareNames (core/discovery.js:
|
|
59
|
+
├── expandGlob (core/discovery.js:199) 1x
|
|
60
|
+
│ ├── parseGlobPattern (core/discovery.js:238) 1x
|
|
61
|
+
│ ├── walkDir (core/discovery.js:295) 1x
|
|
62
|
+
│ └── compareNames (core/discovery.js:178) 1x
|
|
62
63
|
├── parallelBuild (core/parallel-build.js:25) 1x
|
|
63
|
-
├── indexFile (core/project.js:
|
|
64
|
-
│ ├── addSymbol (core/project.js:
|
|
65
|
-
│ ├── detectLanguage (languages/index.js:
|
|
64
|
+
├── indexFile (core/project.js:397) 1x
|
|
65
|
+
│ ├── addSymbol (core/project.js:502) 4x
|
|
66
|
+
│ ├── detectLanguage (languages/index.js:344) 1x
|
|
66
67
|
│ ├── parse (core/parser.js:69) 1x
|
|
67
68
|
│ ├── extractImports (core/imports.js:19) 1x
|
|
68
69
|
│ └── extractExports (core/imports.js:44) 1x
|
|
69
|
-
├── buildImportGraph (core/project.js:
|
|
70
|
-
└── buildInheritanceGraph (core/project.js:
|
|
70
|
+
├── buildImportGraph (core/project.js:798) 1x
|
|
71
|
+
└── buildInheritanceGraph (core/project.js:803) 1x
|
|
71
72
|
… calls UCN can't prove a receiver for (arr.push(), obj.get()) show as
|
|
72
73
|
[unverified] leaves — abridged here
|
|
73
74
|
|
|
74
|
-
CALLEE ACCOUNT:
|
|
75
|
+
CALLEE ACCOUNT: 26 nodes expanded · 394 call sites = 61 confirmed + 162 unverified (162 uncertain-receiver) + 68 external/builtin + 103 excluded
|
|
75
76
|
```
|
|
76
77
|
|
|
77
|
-
One command, no files opened — and the `CALLEE ACCOUNT:` line proves all
|
|
78
|
+
One command, no files opened — and the `CALLEE ACCOUNT:` line proves all 394 calls were sorted, nothing dropped.
|
|
78
79
|
|
|
79
80
|
---
|
|
80
81
|
|
|
@@ -87,19 +88,19 @@ $ ucn about expandGlob
|
|
|
87
88
|
|
|
88
89
|
expandGlob (function)
|
|
89
90
|
════════════════════════════════════════════════════════════
|
|
90
|
-
core/discovery.js:
|
|
91
|
+
core/discovery.js:199-233 → core/discovery.js:199:expandGlob
|
|
91
92
|
expandGlob (pattern: string, options: number = {}) : string[]
|
|
92
93
|
|
|
93
|
-
USAGES:
|
|
94
|
-
3 calls, 3 imports,
|
|
94
|
+
USAGES: 8 total
|
|
95
|
+
3 calls, 3 imports, 2 references
|
|
95
96
|
|
|
96
97
|
CALLERS — CONFIRMED (7, 3 prod + 4 test):
|
|
97
98
|
evidence: scope-match (all)
|
|
98
|
-
cli/index.js:
|
|
99
|
+
cli/index.js:1267 [runGlobCommand]
|
|
99
100
|
const files = expandGlob(pattern);
|
|
100
|
-
core/cache.js:
|
|
101
|
+
core/cache.js:548 [isCacheStale] [unreachable]
|
|
101
102
|
const currentFiles = expandGlob(pattern, globOpts);
|
|
102
|
-
core/project.js:
|
|
103
|
+
core/project.js:257 [build]
|
|
103
104
|
files = expandGlob(pattern, globOpts);
|
|
104
105
|
test callers:
|
|
105
106
|
test/integration.test.js:167
|
|
@@ -108,12 +109,12 @@ CALLERS — CONFIRMED (7, 3 prod + 4 test):
|
|
|
108
109
|
|
|
109
110
|
CALLEES (3):
|
|
110
111
|
evidence: exact-binding (all)
|
|
111
|
-
parseGlobPattern [utility] - core/discovery.js:
|
|
112
|
-
walkDir [utility] {fs} - core/discovery.js:
|
|
113
|
-
compareNames [utility] - core/discovery.js:
|
|
112
|
+
parseGlobPattern [utility] - core/discovery.js:238 (1x)
|
|
113
|
+
walkDir [utility] {fs} - core/discovery.js:295 (1x)
|
|
114
|
+
compareNames [utility] - core/discovery.js:178 (1x)
|
|
114
115
|
|
|
115
116
|
ACCOUNT: "expandGlob" occurs on 14 lines in 6 files: 7 confirmed, 0 unverified,
|
|
116
|
-
7 non-call (4 import, 1 definition,
|
|
117
|
+
7 non-call (4 import, 1 definition, 2 reference, 0 other-text), 0 other-target, 0 unaccounted
|
|
117
118
|
|
|
118
119
|
TESTS: 5 matches in 1 file(s)
|
|
119
120
|
```
|
|
@@ -127,30 +128,31 @@ UCN doesn't just find a name — it tells you how sure it is. Every answer from
|
|
|
127
128
|
```
|
|
128
129
|
$ ucn impact saveCache
|
|
129
130
|
|
|
130
|
-
CALL SITES: 2 confirmed +
|
|
131
|
+
CALL SITES: 2 confirmed + 11 unverified
|
|
131
132
|
|
|
132
133
|
test/regression-go.test.js (2 calls)
|
|
133
|
-
:
|
|
134
|
+
:2007
|
|
134
135
|
saveCache(index, cachePath);
|
|
135
136
|
|
|
136
|
-
UNVERIFIED CALL SITES (
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
UNVERIFIED CALL SITES (11) — call syntax, no binding/receiver evidence:
|
|
138
|
+
core/project.js:2126: saveCache(cachePath) { ... } (call-not-resolved)
|
|
139
|
+
mcp/server.js:810: try { index.saveCache(); } catch (_) ... (method-ambiguous)
|
|
140
|
+
test/cache.test.js:1804: index.saveCache(); (method-ambiguous)
|
|
141
|
+
... (8 more)
|
|
140
142
|
|
|
141
|
-
ACCOUNT: "saveCache" occurs on
|
|
142
|
-
|
|
143
|
+
ACCOUNT: "saveCache" occurs on 55 lines in 8 files: 2 confirmed, 11 unverified,
|
|
144
|
+
11 non-call (2 import, 1 definition, 1 reference, 7 other-text), 31 other-target, 0 unaccounted
|
|
143
145
|
```
|
|
144
146
|
|
|
145
|
-
UCN sorts every one of the
|
|
147
|
+
UCN sorts every one of the 55 places the name appears:
|
|
146
148
|
|
|
147
149
|
- **2 confirmed** — call sites it can prove resolve to *this* `saveCache`.
|
|
148
|
-
- **
|
|
149
|
-
- **
|
|
150
|
-
- **
|
|
150
|
+
- **11 unverified** — real call sites it found but won't claim. `index.saveCache()` has an untyped receiver, so UCN can't prove which `saveCache` runs; it shows the site and the reason (`method-ambiguous`) instead of guessing.
|
|
151
|
+
- **31 other-target** — occurrences that belong to a *different* `saveCache`, kept separate so they never pollute the answer.
|
|
152
|
+
- **11 non-call** — imports, the definition, plain text.
|
|
151
153
|
- **`0 unaccounted`** — the partition is complete. Nothing was dropped on the floor.
|
|
152
154
|
|
|
153
|
-
The payoff: a **confirmed** answer is safe to refactor against, and
|
|
155
|
+
The payoff: a **confirmed** answer is safe to refactor against, and a clean zero — no confirmed, no unverified, `0 unaccounted` — is a trustworthy zero (measured: 68 of 69 clean-zero samples across the 10-repo board agree with the compiler oracles; the one disagreement is a `new X()` on an old-style constructor function, which lands in the non-call counts, still visible). One caveat before deleting anything: callers aren't the only usages — if the NON-CALL counts are nonzero, run `ucn usages` to see what they are.
|
|
154
156
|
|
|
155
157
|
### Measured against ground truth
|
|
156
158
|
|
|
@@ -161,10 +163,10 @@ This isn't a promise — it's a gate. CI re-derives UCN's caller answers from re
|
|
|
161
163
|
| TypeScript / JavaScript | ts-morph | 99.4–100% |
|
|
162
164
|
| Python | pyright (LSP) | 97.7–99.9% |
|
|
163
165
|
| Go | gopls | 99.9–100% |
|
|
164
|
-
| Rust | rust-analyzer |
|
|
165
|
-
| Java | jdtls | 96.
|
|
166
|
+
| Rust | rust-analyzer | 99.0–100% |
|
|
167
|
+
| Java | jdtls | 96.6% |
|
|
166
168
|
|
|
167
|
-
Ten pinned real-world repos (zod, express, httpx, rich, cobra, grpc-go, ripgrep, cursive, gson, preact-signals), three sampling seeds, every run gated at `missing-unexplained = 0
|
|
169
|
+
Ten pinned real-world repos (zod, express, httpx, rich, cobra, grpc-go, ripgrep, cursive, gson, preact-signals), three sampling seeds, every run gated at `missing-unexplained = 0` — plus a weekly fresh-repo arm: two unpinned repos the engine was never tuned on, same gate. The tree commands — `trace`, `blast`, `reverse-trace`, `affected-tests` — follow the same rule: confirmed trunk, uncertain branches flagged (`--expand-unverified` to follow). Run `ucn doctor` for the trust report on *your* repo.
|
|
168
170
|
|
|
169
171
|
## Change code without breaking things
|
|
170
172
|
|
|
@@ -237,6 +239,36 @@ Changed: 3 functions
|
|
|
237
239
|
|
|
238
240
|
## Get the lay of the land in a new repo
|
|
239
241
|
|
|
242
|
+
One command answers "what is this codebase?" — size and language mix, where the code lives, the most-called production functions, entry points, and how far to trust the index:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
$ ucn orient
|
|
246
|
+
|
|
247
|
+
PROJECT ORIENTATION — /path/to/project
|
|
248
|
+
════════════════════════════════════════════════════════════
|
|
249
|
+
169 files · 2111 symbols · javascript 67%, rust 8%, typescript 8%, java 7%, go 5%, python 5%
|
|
250
|
+
|
|
251
|
+
TOP DIRS (by symbols):
|
|
252
|
+
core 516 symbols · 29 file(s)
|
|
253
|
+
languages 282 symbols · 8 file(s)
|
|
254
|
+
test 209 symbols · 29 file(s)
|
|
255
|
+
core/output 142 symbols · 14 file(s)
|
|
256
|
+
...
|
|
257
|
+
|
|
258
|
+
HOT (most-called production functions, top 8 of 1028):
|
|
259
|
+
execute — 1124 call(s) · core/execute.js:1608
|
|
260
|
+
ProjectIndex.build — 340 call(s) · core/project.js:221
|
|
261
|
+
getParser — 150 call(s) · languages/index.js:312
|
|
262
|
+
...
|
|
263
|
+
|
|
264
|
+
ENTRY POINTS: 389 — test 284, runtime 72, http 32, di 1
|
|
265
|
+
TRUST: MEDIUM — 41 dynamic import(s), 13 eval, 6 reflection (ucn doctor for detail)
|
|
266
|
+
|
|
267
|
+
Next: ucn about execute · ucn toc --detailed · ucn stats --hot --top=20 · ucn doctor --deep
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Then drill in:
|
|
271
|
+
|
|
240
272
|
```
|
|
241
273
|
$ ucn brief fetch_user
|
|
242
274
|
fetch_user(user_id: int): dict
|
|
@@ -251,9 +283,9 @@ fetch_user(user_id: int): dict
|
|
|
251
283
|
$ ucn doctor
|
|
252
284
|
|
|
253
285
|
UCN Trust Report — /path/to/project
|
|
254
|
-
Index:
|
|
255
|
-
Languages: javascript (
|
|
256
|
-
Cache: fresh,
|
|
286
|
+
Index: 169 files, 2104 symbols
|
|
287
|
+
Languages: javascript (72%), typescript (14%), java (4%), python (4%), rust (4%), go (3%)
|
|
288
|
+
Cache: fresh, 344ms build
|
|
257
289
|
...
|
|
258
290
|
Trust level: HIGH
|
|
259
291
|
```
|
|
@@ -289,10 +321,10 @@ Test files to run (20):
|
|
|
289
321
|
POSSIBLY AFFECTED (1) — reachable only through unverified call edges:
|
|
290
322
|
doctor
|
|
291
323
|
|
|
292
|
-
Uncovered (
|
|
324
|
+
Uncovered (12): runGlobCommand, main, isCacheStale, runProjectCommand, runFileCommand, ...
|
|
293
325
|
⚠ These affected functions have no test references
|
|
294
326
|
|
|
295
|
-
Summary: 15 affected → 20 test files,
|
|
327
|
+
Summary: 15 affected → 20 test files, 3/15 functions covered (20%) · 1 possibly affected (unverified chains)
|
|
296
328
|
```
|
|
297
329
|
|
|
298
330
|
The confirmed closure is what you run; `POSSIBLY AFFECTED` lists functions reached only through unverified edges — extra tests worth a look, kept separate.
|
|
@@ -300,17 +332,24 @@ The confirmed closure is what you run; `POSSIBLY AFFECTED` lists functions reach
|
|
|
300
332
|
## Find unused code
|
|
301
333
|
|
|
302
334
|
```
|
|
303
|
-
$ ucn deadcode --exclude=test
|
|
335
|
+
$ ucn deadcode --exclude=test # run on ripgrep
|
|
304
336
|
|
|
305
|
-
Dead code:
|
|
337
|
+
Dead code: 8 unused symbol(s)
|
|
306
338
|
|
|
307
|
-
|
|
308
|
-
[
|
|
309
|
-
[
|
|
339
|
+
crates/globset/src/serde_impl.rs
|
|
340
|
+
[ 38- 42] Glob.deserialize (method)
|
|
341
|
+
[ 70- 74] GlobSet.deserialize (method)
|
|
342
|
+
crates/matcher/src/lib.rs
|
|
343
|
+
[ 397- 399] Captures.as_match (method)
|
|
344
|
+
[ 669- 678] Matcher.try_find_iter (method) [only self-references — recursive]
|
|
345
|
+
[ 796- 806] Matcher.try_captures_iter (method) [only self-references — recursive]
|
|
346
|
+
...
|
|
310
347
|
|
|
311
|
-
|
|
348
|
+
921 exported symbol(s) excluded from the audit (public API may have external callers). Use --include-exported to audit them.
|
|
312
349
|
```
|
|
313
350
|
|
|
351
|
+
Classes, structs, traits, and enums are audited alongside functions. Symbols whose only call sites live inside their own definitions are claimed too, marked `[only self-references — recursive]`. Deadcode claims are re-derived against compiler/LSP ground truth in CI — a default-audit claim with an oracle-visible reference fails the build.
|
|
352
|
+
|
|
314
353
|
Find missing-await bugs:
|
|
315
354
|
|
|
316
355
|
```
|