ucn 3.8.23 → 3.8.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.claude/skills/ucn/SKILL.md +127 -12
  2. package/README.md +152 -156
  3. package/cli/index.js +363 -37
  4. package/core/analysis.js +936 -32
  5. package/core/bridge.js +1095 -0
  6. package/core/brief.js +408 -0
  7. package/core/cache.js +105 -5
  8. package/core/callers.js +72 -18
  9. package/core/check.js +200 -0
  10. package/core/discovery.js +57 -34
  11. package/core/entrypoints.js +638 -4
  12. package/core/execute.js +304 -5
  13. package/core/git-enrich.js +130 -0
  14. package/core/graph.js +24 -2
  15. package/core/output/analysis.js +157 -25
  16. package/core/output/brief.js +100 -0
  17. package/core/output/check.js +79 -0
  18. package/core/output/doctor.js +85 -0
  19. package/core/output/endpoints.js +239 -0
  20. package/core/output/extraction.js +2 -0
  21. package/core/output/find.js +126 -39
  22. package/core/output/graph.js +48 -15
  23. package/core/output/refactoring.js +103 -5
  24. package/core/output/reporting.js +63 -23
  25. package/core/output/search.js +110 -17
  26. package/core/output/shared.js +56 -2
  27. package/core/output.js +4 -0
  28. package/core/parser.js +8 -2
  29. package/core/project.js +39 -3
  30. package/core/registry.js +30 -14
  31. package/core/reporting.js +465 -2
  32. package/core/search.js +130 -52
  33. package/core/shared.js +101 -5
  34. package/core/tracing.js +16 -6
  35. package/core/verify.js +982 -95
  36. package/languages/go.js +91 -6
  37. package/languages/html.js +10 -0
  38. package/languages/java.js +151 -35
  39. package/languages/javascript.js +290 -33
  40. package/languages/python.js +78 -11
  41. package/languages/rust.js +267 -12
  42. package/languages/utils.js +315 -3
  43. package/mcp/server.js +91 -16
  44. package/package.json +9 -1
@@ -71,6 +71,8 @@ ucn trace generate_report --all # all children at default depth
71
71
 
72
72
  Shows the entire pipeline — what `generate_report` calls, what those functions call, etc. — as an indented tree. No file reading needed. Invaluable for understanding orchestrator functions or entry points.
73
73
 
74
+ **Prefer `trace` over chained `about` calls.** If you find yourself running `ucn about` 4–5 times in a row to follow a call chain (entry → leaves), one `ucn trace <fn> --depth=N` returns the same information in a single call. Use `--depth=N` to limit how deep the tree goes.
75
+
74
76
  ### 5. `fn` / `class` — Extract without reading the whole file
75
77
 
76
78
  Pull one or more functions out of a large file. Supports comma-separated names for bulk extraction.
@@ -91,15 +93,56 @@ ucn deadcode --exclude=test # Skip test files (most useful)
91
93
  ucn deadcode --include-decorated # Include framework-registered functions
92
94
  ```
93
95
 
94
- ### 7. `entrypoints` — Detect framework entry points
96
+ ### 7. `brief` — One-screen "before-I-touch-this" summary
97
+
98
+ AST-only summary of a function: typed signature, first sentence of docstring,
99
+ side-effect classification (fs/network/process/global_mutation), and complexity
100
+ metrics (branches, depth, line count). Lighter than `about`, more useful than
101
+ `fn` when you don't need the body.
102
+
103
+ ```bash
104
+ ucn brief fetch_user
105
+ # fetch_user(user_id: int): dict
106
+ # svc.py:4-8 (5 lines)
107
+ # "Fetch a user from the API."
108
+ # async: no | side_effects: [fs, network, process] | complexity: branches=2, depth=2
109
+ ```
110
+
111
+ ### 8. `doctor` — Project trust report
112
+
113
+ One command that tells you how much UCN trusts the index for this project:
114
+ file/symbol counts, language breakdown, dynamic-import / eval / reflection
115
+ blind spots, parse failures, and a verdict (HIGH/MEDIUM/LOW). Add `--deep` to
116
+ sample resolution coverage and bucket edges by confidence.
117
+
118
+ ```bash
119
+ ucn doctor # fast: counts + blind spots + verdict
120
+ ucn doctor --deep # also samples resolution coverage
121
+ ucn doctor --in=src/core # scope to a subtree
122
+ ```
123
+
124
+ ### 9. `check` — Pre-commit summary
125
+
126
+ Composes `diff-impact` + `verify` + `affected-tests` into one output. Lists
127
+ changed/added/deleted functions, flags signature drift across call sites,
128
+ calls out new functions with no callers, and recommends which tests to run.
129
+
130
+ ```bash
131
+ ucn check # vs HEAD
132
+ ucn check --base=main # vs main branch
133
+ ucn check --staged # only staged changes
134
+ ```
135
+
136
+ ### 10. `entrypoints` — Detect framework entry points
95
137
 
96
138
  Lists functions registered as framework handlers (HTTP routes, DI beans, job schedulers, etc.). Detects patterns across Express, FastAPI, Flask, Spring, Gin, Actix, Celery, pytest, and more.
97
139
 
98
140
  ```bash
99
- ucn entrypoints # All detected entry points
141
+ ucn entrypoints # All detected entry points (tests included by default)
100
142
  ucn entrypoints --type=http # HTTP routes only
101
143
  ucn entrypoints --framework=express # Specific framework
102
144
  ucn entrypoints --file=routes/ # Scoped to files
145
+ ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pytest, Rust #[test], etc.)
103
146
  ```
104
147
 
105
148
  ## When to Use the Other Commands
@@ -117,10 +160,10 @@ ucn entrypoints --file=routes/ # Scoped to files
117
160
  | Understanding who depends on a file | `ucn exporters <file>` | Which files import it |
118
161
  | See what a file exports | `ucn file-exports <file>` | All exported functions, classes, variables with signatures |
119
162
  | Quick project overview | `ucn toc` | Every file with function/class counts and line counts |
120
- | Project complexity stats | `ucn stats` | File counts, symbol counts, lines by language. `--functions` for per-function line counts |
163
+ | 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) |
121
164
  | Find by glob pattern | `ucn find "handle*"` | Locate definitions matching a glob (supports * and ?) |
122
165
  | Text search with context | `ucn search term --context=3` | Like grep -C 3, shows surrounding lines |
123
- | Regex search (default) | `ucn search '\d+'` | Search supports regex by default (alternation, character classes, etc.) |
166
+ | Regex search (default) | `ucn search '\d+'` | JavaScript regex (V8 engine). See "Regex notes" below for syntax — alternation is `a|b`, not grep-style |
124
167
  | Text search filtered | `ucn search term --exclude=test` | Search only in matching files |
125
168
  | Structural search (index) | `ucn search --type=function --param=Request` | Query the symbol table, not text. Finds functions by param, return type, decorator, etc. |
126
169
  | Find all db.* calls | `ucn search --type=call --receiver=db` | Search call sites by receiver — something grep can't do |
@@ -133,13 +176,72 @@ ucn entrypoints --file=routes/ # Scoped to files
133
176
  | File-level dependency tree | `ucn graph <file> --depth=1` | Visual import tree. Setting `--depth=N` expands all children. Can be noisy — use depth=1 for large projects. For function-level flow, use `trace` instead |
134
177
  | Are there circular dependencies? | `ucn circular-deps` | Detect circular import chains. `--file=<pattern>` filters to cycles involving a file. `--exclude=test` skips test files |
135
178
  | What are the framework entry points? | `ucn entrypoints` | Lists all detected routes, DI beans, tasks, etc. Filter: `--type=http`, `--framework=express` |
179
+ | Polyglot route ↔ request matching | `ucn endpoints --bridge` | Server routes (Express/Fastify/Koa/NestJS/Flask/FastAPI/Spring/JAX-RS/Gin/Echo/Chi/Fiber/axum/actix/Next.js) ↔ client requests (fetch/axios/requests/httpx/RestTemplate/WebClient/reqwest). Match confidence: EXACT, PARTIAL, UNCERTAIN. Filter with `--method`, `--prefix`, `--server-only`, `--client-only`, `--unmatched`, `--hide-uncertain` |
136
180
  | Find which tests cover a function | `ucn tests <name>` | Test files and test function names. Scope with `--file`, `--class-name`, `--exclude`, `--calls-only` |
137
- | Extract specific lines from a file | `ucn lines --file=<file> --range=10-20` | Pull a line range without reading the whole file |
181
+ | Extract specific lines from a file | `ucn lines 10-20 --file=<file>` | Pull a line range without reading the whole file |
138
182
  | Find type definitions | `ucn typedef <name>` | Interfaces, enums, structs, traits, type aliases |
139
183
  | See a project's public API | `ucn api` or `ucn api --file=<file>` | All exported/public symbols with signatures |
140
184
  | Drill into context results | `ucn expand <N>` | Show source code for item N from a previous `context` call |
141
185
  | Best usage example of a function | `ucn example <name>` | Finds and scores the best call site with surrounding context |
142
186
  | Debug a stack trace | `ucn stacktrace --stack="<trace>"` | Parses stack frames and shows source context per frame |
187
+ | Quick look before touching a function | `ucn brief <name>` | Signature + docstring + side effects + complexity, one screen |
188
+ | Project trust report | `ucn doctor [--deep]` | Index coverage, blind spots, parse failures, verdict |
189
+ | Pre-commit summary | `ucn check [--base=main]` | Changed funcs + signature drift + affected tests in one shot |
190
+ | Find missing-await bugs | `ucn audit-async` | Lists async calls inside async functions that lack `await`. JS/TS/Python only. Filter with `--file`, `--exclude`, `--limit` |
191
+
192
+ ## Regex Notes (`search` command)
193
+
194
+ `search` uses **JavaScript regex** (the V8 engine), not grep BRE/ERE. Common gotchas:
195
+
196
+ - Alternation is `a|b`, **not** `a\|b`. `ucn search "flask|fastapi|django"` works; `ucn search "flask\|fastapi\|django"` matches the literal string.
197
+ - `(`, `[`, `{` outside character classes do **not** need escaping for literal match in most cases — but normal JS regex semantics apply (you can still escape them for clarity).
198
+ - Wrap the pattern in single quotes so the shell does not interpret special characters (`*`, `?`, `\`, `$`, etc.).
199
+ - Default is case-insensitive; pass `--case-sensitive` to flip.
200
+ - `--no-regex` forces literal-string search if you need to match regex metacharacters as text without escaping.
201
+
202
+ ## Reading Call-Site Patterns
203
+
204
+ `verify`, `impact`, and `about` annotate call sites with structural classification flags. Watch for these in summary lines (`Patterns: 4 in try, 4 in callback`) and per-call-site entries:
205
+
206
+ | Flag | What it means | Why it matters |
207
+ |------|--------------|---------------|
208
+ | `inLoop` | Call is inside a `for`/`while`/comprehension | N+1 query risk, repeated work, performance hot path |
209
+ | `inTry` | Call is wrapped in try/catch (or equivalent) | Errors are handled — different from "must fix" code paths |
210
+ | `inCallback` | Call sits inside a callback/lambda/closure that's not the enclosing function | Async deferred work, may run on a different stack frame |
211
+ | `inTestCase` | Call originates from inside a test function | Isolate production callers from test setup |
212
+ | `awaited` | Call's parent is `await` / `Promise.then` (JS/TS/Python) | Confirms async coordination — its absence on async callees signals a missing-await bug |
213
+
214
+ `audit-async` is the focused tool for the `awaited=false` case across an entire async function body.
215
+
216
+ ## Confidence Scores
217
+
218
+ `about` and `context` show confidence per caller/callee edge by default (e.g. `confidence: 0.65 (scope-match)`). Resolution labels (high to low):
219
+
220
+ | Label | Score | Meaning |
221
+ |-------|-------|---------|
222
+ | `exact-binding` | 0.98 | Import or binding evidence — direct call |
223
+ | `same-class` | 0.92 | Method call resolved within the enclosing class |
224
+ | `receiver-hint` | 0.80 | Receiver type inferred (Go/Java/Rust) — e.g. `f.run()` where `f: Filter` |
225
+ | `scope-match` | 0.65 | Symbol resolved by name within a file/package scope |
226
+ | `name-only` | 0.40 | Name match only, no binding/scope evidence — review before trusting |
227
+ | `uncertain` | 0.25 | Ambiguous — multiple candidates, hidden unless `--include-uncertain` |
228
+
229
+ Filter or hide:
230
+ - `--min-confidence=0.7` — keep only high-confidence edges (≥ same-class)
231
+ - `--hide-confidence` — silence the scores (legacy `--no-confidence` is a silent alias)
232
+ - `--include-uncertain` — include otherwise-filtered low-confidence matches
233
+
234
+ ## Symbol Handles (stable IDs)
235
+
236
+ Every result that lists a symbol emits a **handle** in the form `relativePath:line:name` (e.g. `core/api.ts:42:handler`). Pass it back to any name-accepting command and resolution is pinned to that exact definition — no name disambiguation, no `--file` needed.
237
+
238
+ ```bash
239
+ ucn find handler # → emits src/api.ts:42:handler
240
+ ucn brief src/api.ts:42:handler # pins to that exact one
241
+ ucn impact src/api.ts:42:handler # same
242
+ ```
243
+
244
+ The shorter `relativePath:line` form (no `:name`) also works — UCN looks up the symbol by location. Plain names (`handler`) still work for the fuzzy/heuristic path.
143
245
 
144
246
  ## Command Format
145
247
 
@@ -157,14 +259,15 @@ ucn [target] <command> [name] [--flags]
157
259
 
158
260
  | Flag | When to use it |
159
261
  |------|---------------|
160
- | `--class-name=X` | Scope to specific class (e.g., `--class-name=Repository` for method `save`). Works with `fn`, `about`, `context`, `impact`, `tests`, `example`, `typedef`, `verify`, `plan` |
262
+ | `--class-name=X` | Scope to specific class (e.g., `--class-name=Repository` for method `save`). Works with `about`, `context`, `impact`, `blast`, `smart`, `trace`, `reverse-trace`, `example`, `related`, `brief`, `find`, `usages`, `tests`, `affected-tests`, `fn`, `verify`, `plan`, `typedef` |
161
263
  | `--file=<pattern>` | Disambiguate when a name exists in multiple files (e.g., `--file=api`) |
162
264
  | `--exclude=test,mock` | Focus on production code only |
163
265
  | `--in=src/core` | Limit search to a subdirectory |
164
266
  | `--depth=N` | Control tree depth for `trace`, `graph`, and detail level for `find` (default 3). Also expands all children — no breadth limit |
165
- | `--all` | Expand truncated sections in `about`, `trace`, `graph`, `related` |
267
+ | `--all` | Expand truncated sections. Applies to `about`, `blast`, `trace`, `reverse-trace`, `related`, `find`, `toc`, `fn`, `class`, `graph`, `diff-impact` |
166
268
  | `--include-tests` | Include test files in usage counts (`about`) and results (`find`, `usages`, `deadcode`). Callers always include tests. |
167
- | `--include-methods` | Include `obj.method()` calls in `context`/`smart` (only direct calls shown by default) |
269
+ | `--exclude-tests` | Exclude test entries from `entrypoints` (tests are included by default since they ARE entry points). |
270
+ | `--include-methods` | Include `obj.method()` calls in caller/callee analysis. `impact` defaults to true (show all callable sites); other commands default to false (use `--no-include-methods` to opt out). Applies to `about`, `context`, `impact`, `verify`, `blast`, `smart`, `trace`, `reverse-trace`, `affected-tests` |
168
271
  | `--base=<ref>` | Git ref for diff-impact (default: HEAD) |
169
272
  | `--staged` | Analyze staged changes (diff-impact) |
170
273
  | `--no-cache` | Force re-index after editing files |
@@ -172,19 +275,22 @@ ucn [target] <command> [name] [--flags]
172
275
  | `--context=N` | Lines of surrounding context in `usages`/`search` output |
173
276
  | `--no-regex` | Force plain text search (regex is default) |
174
277
  | `--functions` | Show per-function line counts in `stats` (complexity audit) |
175
- | `--json` | Machine-readable JSON output (wrapped in `{meta, data}`) |
278
+ | `--hot` | List top N most-called functions in `stats` (use with `--top=N`, default 10). Best orientation primitive when entering a new repo |
279
+ | `--diverse` | Cluster `example` call sites by argument shape and return one representative per cluster (use with `--top=N`, default 3) |
280
+ | `--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 |
281
+ | `--json` | Machine-readable JSON output. Some commands wrap in `{meta, data}` (e.g., `find`, `deadcode`); others return flat objects (e.g., `about`, `impact`, `verify`, `plan`, `imports`) — check each command's output shape |
176
282
  | `--code-only` | Exclude matches in comments and strings (`search`/`usages`) |
177
283
  | `--with-types` | Include related type definitions in `smart`/`about` output |
178
284
  | `--detailed` | Show full symbol listing per file in `toc` |
179
285
  | `--top-level` | Show only top-level functions in `toc` (exclude nested/indented) |
180
286
  | `--top=N` | Limit result count (default: 10 for most commands) |
181
- | `--limit=N` | Limit result count for `find`, `usages`, `search`, `deadcode`, `api`, `toc`, `entrypoints`, `diff-impact` |
287
+ | `--limit=N` | Limit result count for `find`, `usages`, `toc`, `search`, `deadcode`, `entrypoints`, `endpoints`, `diff-impact`, `check`, `api`, `doctor`, `audit-async` |
182
288
  | `--max-files=N` | Max files to index (for large projects with 10K+ files) |
183
289
  | `--max-lines=N` | Max source lines for `class` (large classes show summary by default) |
184
290
  | `--case-sensitive` | Case-sensitive text search (default: case-insensitive) |
185
291
  | `--exact` | Exact name match only in `find`/`typedef` (no substring) |
186
- | `--include-uncertain` | Include ambiguous/uncertain matches in `context`/`smart`/`about` |
187
- | `--no-confidence` | Hide confidence scores (shown by default) in `context`/`about` |
292
+ | `--include-uncertain` | Include ambiguous/uncertain matches. Applies to `about`, `context`, `blast`, `smart`, `trace`, `reverse-trace`, `affected-tests` |
293
+ | `--hide-confidence` | Hide confidence scores (shown by default) in `context`/`about` |
188
294
  | `--min-confidence=N` | Filter edges below confidence threshold (e.g., `--min-confidence=0.7` keeps only high-confidence edges) |
189
295
  | `--calls-only` | Only show call/test-case matches in `tests` (skip file-level results) |
190
296
  | `--add-param=<name>` | Add a parameter (`plan` command). Combine with `--default=<value>` |
@@ -193,6 +299,13 @@ ucn [target] <command> [name] [--flags]
193
299
  | `--include-exported` | Include exported symbols in `deadcode` results |
194
300
  | `--include-decorated` | Include decorated/annotated symbols in `deadcode` results |
195
301
  | `--framework=X` | Filter `entrypoints` by framework (e.g., `express`, `spring`, `celery`) |
302
+ | `--bridge` | Match server routes to client requests (`endpoints`). Confidence tiers: EXACT, PARTIAL, UNCERTAIN |
303
+ | `--server-only` | Only list server routes (`endpoints`) |
304
+ | `--client-only` | Only list client requests (`endpoints`) |
305
+ | `--unmatched` | Only show routes/requests with no match (`endpoints`, pair with `--bridge`) |
306
+ | `--method=GET` | Filter by HTTP method (`endpoints`) |
307
+ | `--prefix=/api` | Filter routes/requests by path prefix (`endpoints`) |
308
+ | `--hide-uncertain` | Hide UNCERTAIN-confidence bridges (`endpoints`) |
196
309
  | `--type=<kind>` | Structural search: `function`, `class`, `call`, `method`, `type`. Triggers index query instead of text grep |
197
310
  | `--param=<name>` | Structural search: filter by parameter name or type (e.g., `--param=Request`) |
198
311
  | `--receiver=<name>` | Structural search: filter calls by receiver (e.g., `--receiver=db` for all db.* calls) |
@@ -202,6 +315,8 @@ ucn [target] <command> [name] [--flags]
202
315
  | `--unused` | Structural search: only symbols with zero callers |
203
316
  | `--no-follow-symlinks` | Don't follow symbolic links during file discovery |
204
317
  | `--workers=N` | Parallel build workers (auto-detect by default; `0` to disable; env: `UCN_WORKERS`) |
318
+ | `--deep` | `doctor` only: sample resolution coverage. Slower but produces confidence histogram. |
319
+ | `--compact` | One-line-per-item output for `about`/`context`/`find`/`usages`/`impact`. Halves token cost; same info. |
205
320
 
206
321
  ## Workflow Integration
207
322
 
package/README.md CHANGED
@@ -51,21 +51,21 @@ ucn deadcode --exclude=test # unused code, AST-verified
51
51
  $ ucn trace build --depth=2
52
52
 
53
53
  build
54
- ├── detectProjectPattern (core/discovery.js:399) 1x
55
- ├── checkDir (core/discovery.js:403) 2x
56
- │ └── shouldIgnore (core/discovery.js:347) 1x
57
- ├── parseGitignore (core/discovery.js:130) 1x
58
- ├── expandGlob (core/discovery.js:190) 1x
59
- ├── parseGlobPattern (core/discovery.js:226) 1x
60
- ├── walkDir (core/discovery.js:283) 1x
61
- │ └── compareNames (core/discovery.js:169) 1x
62
- ├── indexFile (core/project.js:273) 1x
63
- │ ├── addSymbol (core/project.js:343) 4x
64
- │ ├── detectLanguage (languages/index.js:157) 1x
54
+ ├── detectProjectPattern (core/discovery.js:431) 1x
55
+ ├── parseGitignore (core/discovery.js:131) 1x
56
+ ├── expandGlob (core/discovery.js:191) 1x
57
+ ├── parseGlobPattern (core/discovery.js:227) 1x
58
+ ├── walkDir (core/discovery.js:284) 1x
59
+ └── compareNames (core/discovery.js:170) 1x
60
+ ├── parallelBuild (core/parallel-build.js:25) 1x
61
+ ├── indexFile (core/project.js:310) 1x
62
+ ├── addSymbol (core/project.js:398) 4x
63
+ │ ├── detectLanguage (languages/index.js:209) 1x
65
64
  │ ├── parse (core/parser.js:69) 1x
66
- └── extractImports (core/imports.js:19) 1x
67
- ├── buildImportGraph (core/project.js:549) 1x
68
- └── buildInheritanceGraph (core/project.js:627) 1x
65
+ ├── extractImports (core/imports.js:19) 1x
66
+ │ └── extractExports (core/imports.js:44) 1x
67
+ ├── buildImportGraph (core/project.js:631) 1x
68
+ └── buildInheritanceGraph (core/project.js:636) 1x
69
69
  ```
70
70
 
71
71
  One command. No files opened. Every function located by file and line.
@@ -81,26 +81,28 @@ $ ucn about expandGlob
81
81
 
82
82
  expandGlob (function)
83
83
  ════════════════════════════════════════════════════════════
84
- core/discovery.js:190-221
85
- expandGlob (pattern, options = {})
84
+ core/discovery.js:191-222 → core/discovery.js:191:expandGlob
85
+ expandGlob (pattern: string, options: number = {}) : string[]
86
86
 
87
- CALLERS (3):
88
- cli/index.js:859 [runGlobCommand]
87
+ CALLERS (7):
88
+ confidence: 0 high (>0.8), 7 medium (0.5-0.8), 0 low (<0.5)
89
+ cli/index.js:1190 [runGlobCommand]
89
90
  const files = expandGlob(pattern);
90
- core/cache.js:274 [isCacheStale]
91
+ confidence: 0.65 (scope-match)
92
+ core/cache.js:417 [isCacheStale]
91
93
  const currentFiles = expandGlob(pattern, globOpts);
92
- core/project.js:195 [build]
93
- const files = expandGlob(pattern, globOpts);
94
+ confidence: 0.65 (scope-match)
95
+ ... (5 more)
94
96
 
95
97
  CALLEES (3):
96
- parseGlobPattern [utility] - core/discovery.js:226
97
- walkDir [utility] - core/discovery.js:283
98
- compareNames [utility] - core/discovery.js:169
98
+ parseGlobPattern [utility] - core/discovery.js:227
99
+ walkDir [utility] {fs} - core/discovery.js:284
100
+ compareNames [utility] - core/discovery.js:170
99
101
 
100
- TESTS: 6 matches in 2 file(s)
102
+ TESTS: 5 matches in 1 file(s)
101
103
  ```
102
104
 
103
- Need to trace execution upward instead? `ucn reverse-trace fn` walks the caller chain back to entry points.
105
+ Each caller comes with a confidence score (`exact-binding`, `same-class`, `receiver-hint`, `scope-match`, `name-only`) so you can tell direct calls from name-only matches. Add `--hide-confidence` to silence the scores, or `--min-confidence=0.7` to drop everything below `same-class`. Add `--git` to see who last touched the function. Need to trace execution upward instead? `ucn reverse-trace fn` walks the caller chain back to entry points.
104
106
 
105
107
  ## Change code without breaking things
106
108
 
@@ -109,38 +111,100 @@ Before touching a function, check if all existing call sites match its signature
109
111
  ```
110
112
  $ ucn verify expandGlob
111
113
 
112
- expandGlob (pattern, options = {})
114
+ Verification: expandGlob
115
+ ════════════════════════════════════════════════════════════
116
+ core/discovery.js:191
117
+ expandGlob (pattern: string, options: number = {}) : string[]
118
+
113
119
  Expected arguments: 1-2
114
120
 
115
- STATUS: ✓ All calls valid (7 calls, 0 mismatches)
121
+ STATUS: ✓ All calls valid
122
+ Total calls: 7
123
+ Valid: 7
124
+ Mismatches: 0
125
+ Uncertain: 0
126
+ Patterns: 4 in try, 4 in callback
116
127
  ```
117
128
 
129
+ The `Patterns:` line surfaces structural classification of each call site — `inLoop`, `inTry`, `inCallback`, `inTestCase`, `awaited` — so you can spot risky call sites (e.g., calls inside loops, missing `await`) at a glance. Same line appears on `impact` and inside `about`.
130
+
118
131
  Then preview the refactoring. UCN shows exactly what needs to change and where:
119
132
 
120
133
  ```
121
134
  $ ucn plan expandGlob --rename-to=expandGlobPattern
122
135
 
136
+ Refactoring plan: rename
137
+ ════════════════════════════════════════════════════════════
138
+ core/discovery.js:191
139
+
123
140
  SIGNATURE CHANGE:
124
- Before: expandGlob (pattern, options = {})
125
- After: expandGlobPattern (pattern, options = {})
141
+ Before: expandGlob (pattern: string, options: number = {}) : string[]
142
+ After: expandGlobPattern (pattern: string, options: number = {}) : string[]
126
143
 
127
- CHANGES NEEDED: 7 across 4 files
144
+ CHANGES NEEDED: 11
145
+ Files affected: 4
128
146
 
129
- cli/index.js :859
130
- const files = expandGlob(pattern);
131
- → const files = expandGlobPattern(pattern);
147
+ BY FILE:
132
148
 
133
- core/cache.js :274
134
- const currentFiles = expandGlob(pattern, globOpts);
135
- const currentFiles = expandGlobPattern(pattern, globOpts);
149
+ cli/index.js (2 changes)
150
+ :1190
151
+ const files = expandGlob(pattern);
152
+ → Rename to: const files = expandGlobPattern(pattern);
153
+ :15
154
+ const { expandGlob, findProjectRoot } = require('../core/discovery');
155
+ → Update import: const { expandGlobPattern, findProjectRoot } = require('../core/discovery');
136
156
 
137
- core/project.js :195
138
- const files = expandGlob(pattern, globOpts);
139
- → const files = expandGlobPattern(pattern, globOpts);
157
+ ... (more changes in core/cache.js, core/project.js, test/integration.test.js)
140
158
  ```
141
159
 
142
160
  Run `ucn diff-impact --staged` before committing to see what you changed and who calls it.
143
161
 
162
+ Or wrap the same checks in a single command:
163
+
164
+ ```
165
+ $ ucn check --staged
166
+
167
+ Pre-commit Check vs HEAD
168
+ ════════════════════════════════════════════════════════════
169
+ Changed: 3 functions
170
+ parseFlags (cli/index.js:165) [MODIFIED] 2 callers
171
+ ...
172
+ ```
173
+
174
+ `ucn check` composes `diff-impact` + `verify` + `affected-tests` in one shot — flags ADDED functions with no callers, signature drift across call sites, and recommends which tests to run.
175
+
176
+ ## Get the lay of the land in a new repo
177
+
178
+ ```
179
+ $ ucn brief fetch_user
180
+ fetch_user(user_id: int): dict
181
+ svc.py:4-8 (5 lines)
182
+ "Fetch a user from the API."
183
+ async: no | side_effects: [fs, network, process] | complexity: branches=2, depth=2
184
+ ```
185
+
186
+ `brief` is the lighter alternative to `about` — typed signature, first sentence of the docstring, side-effect classification, and complexity, all in one screen. Pair with `--git` to see who last touched it and how often.
187
+
188
+ ```
189
+ $ ucn doctor
190
+
191
+ UCN Trust Report — /path/to/project
192
+ Index: 144 files, 1569 symbols
193
+ Languages: javascript (74%), typescript (13%), java (4%), python (3%), rust (3%), go (3%)
194
+ Cache: fresh, 221ms build
195
+ ...
196
+ Trust level: HIGH
197
+ ```
198
+
199
+ `doctor` reports how much UCN trusts the index — file/symbol counts, blind spots (dynamic imports, eval, reflection), parse failures, and a verdict. Use `--deep` to also sample resolution coverage.
200
+
201
+ `entrypoints` lists detected framework handlers (HTTP routes, DI beans, jobs, tests):
202
+
203
+ ```
204
+ ucn entrypoints --type=http --framework=spring # narrow to one framework
205
+ ucn entrypoints --exclude-tests # tests are included by default
206
+ ```
207
+
144
208
  ## Find what to clean up
145
209
 
146
210
  Which tests should you run after a change? `affected-tests` walks the blast radius and finds every test that touches the affected functions:
@@ -148,11 +212,22 @@ Which tests should you run after a change? `affected-tests` walks the blast radi
148
212
  ```
149
213
  $ ucn affected-tests expandGlob
150
214
 
151
- 1 function changed → 18 functions affected (depth 3)
152
- Summary: 18 affected → 12 test files, 11/18 functions covered (61%)
215
+ affected-tests: expandGlob
216
+ ════════════════════════════════════════════════════════════
217
+ core/discovery.js:191
218
+ 1 function changed → 15 functions affected (depth 3)
219
+
220
+ Test files to run (19):
153
221
 
154
- Uncovered (7): runGlobCommand, runProjectCommand, ...
222
+ test/integration.test.js (covers: expandGlob, build, idx, setupProject)
223
+ L47: index.build(null, { quiet: true }); [call]
224
+ L167: const files = expandGlob('**/*.go', { root: tmpDir }); [call]
225
+ ...
226
+
227
+ Uncovered (10): runGlobCommand, main, runProjectCommand, ...
155
228
  ⚠ These affected functions have no test references
229
+
230
+ Summary: 15 affected → 19 test files, 5/15 functions covered (33%)
156
231
  ```
157
232
 
158
233
  ## Find unused code
@@ -160,19 +235,47 @@ Uncovered (7): runGlobCommand, runProjectCommand, ...
160
235
  ```
161
236
  $ ucn deadcode --exclude=test
162
237
 
163
- Dead code: 1 unused symbol(s)
238
+ Dead code: 3 unused symbol(s)
239
+
240
+ core/bridge.js
241
+ [ 90- 92] endsWithWildcard (function)
242
+ [ 258- 265] parsePythonDecorator (function)
243
+ core/search.js
244
+ [1409-1445] _testBodyReferencesClass (function)
245
+
246
+ 325 exported symbol(s) excluded (all have callers). Use --include-exported to audit them.
247
+ ```
248
+
249
+ Find missing-await bugs:
164
250
 
165
- core/discovery.js
166
- [ 162- 166] legacyResolve (function)
167
251
  ```
252
+ ucn audit-async
253
+ ```
254
+
255
+ Lists async calls inside async functions that lack `await` (JS/TS/Python).
256
+
257
+ ## Map your API surface across languages
258
+
259
+ UCN can match server routes to client requests across the supported languages — Express/Fastify/Koa/NestJS/Next.js, Flask/FastAPI, Spring/JAX-RS, Go net/http (Gin/Echo/Chi/Fiber), axum/actix-web on the server side; fetch/axios, requests/httpx, RestTemplate/WebClient, reqwest on the client side.
260
+
261
+ ```bash
262
+ ucn endpoints --bridge
263
+
264
+ # Filters
265
+ ucn endpoints --bridge --unmatched # routes with no client / clients with no server
266
+ ucn endpoints --bridge --method=POST
267
+ ucn endpoints --bridge --prefix=/api
268
+ ```
269
+
270
+ Match confidence: `EXACT` (literal-literal), `PARTIAL` (server param ↔ client literal), `UNCERTAIN` (template-literal client). Use `--hide-uncertain` to drop the noisy tier.
168
271
 
169
272
  ## Extract without reading the whole file
170
273
 
171
274
  ```
172
275
  $ ucn fn compareNames
173
276
 
174
- core/discovery.js:169
175
- [ 169- 177] compareNames(a, b)
277
+ core/discovery.js:170
278
+ [ 170- 178] compareNames(a, b)
176
279
  ────────────────────────────────────────────────────────────
177
280
  function compareNames(a, b) {
178
281
  const aLower = a.toLowerCase();
@@ -258,114 +361,7 @@ cp -r "$(npm root -g)/ucn/.claude/skills/ucn" ~/.agents/skills/
258
361
 
259
362
  ## Full help
260
363
 
261
- ```text
262
- UCN - Universal Code Navigator
263
-
264
- Supported: JavaScript, TypeScript, Python, Go, Rust, Java, HTML
265
-
266
- Usage:
267
- ucn [command] [args] Project mode (current directory)
268
- ucn <file> [command] [args] Single file mode
269
- ucn <dir> [command] [args] Project mode (specific directory)
270
- ucn "pattern" [command] [args] Glob pattern mode
271
- (Default output is text; add --json for machine-readable JSON)
272
-
273
- ═══════════════════════════════════════════════════════════════════════════════
274
- UNDERSTAND CODE
275
- ═══════════════════════════════════════════════════════════════════════════════
276
- about <name> Full picture (definition, callers, callees, tests, code)
277
- context <name> Who calls this + what it calls (numbered for expand)
278
- smart <name> Function + all dependencies inline
279
- impact <name> What breaks if changed (call sites grouped by file)
280
- blast <name> Transitive blast radius (callers of callers, --depth=N)
281
- trace <name> Call tree visualization (--depth=N expands all children)
282
- reverse-trace <name> Upward call chain to entry points (--depth=N, default 5)
283
- related <name> Find similar functions (same file, shared deps)
284
- example <name> Best usage example with context
285
-
286
- ═══════════════════════════════════════════════════════════════════════════════
287
- FIND CODE
288
- ═══════════════════════════════════════════════════════════════════════════════
289
- find <name> Find symbol definitions (supports glob: find "handle*")
290
- usages <name> All usages grouped: definitions, calls, imports, references
291
- toc Table of contents (compact; --detailed lists all symbols)
292
- search <term> Text search (regex default, --context=N, --exclude=, --in=)
293
- Structural: --type=function|class|call --param= --returns= --decorator= --exported --unused
294
- tests <name> Find test files for a function
295
- affected-tests <n> Tests affected by a change (blast + test detection, --depth=N)
296
-
297
- ═══════════════════════════════════════════════════════════════════════════════
298
- EXTRACT CODE
299
- ═══════════════════════════════════════════════════════════════════════════════
300
- fn <name>[,n2,...] Extract function(s) (comma-separated for bulk, --file)
301
- class <name> Extract class
302
- lines <range> Extract line range (e.g., lines 50-100)
303
- expand <N> Show code for item N from context output
304
-
305
- ═══════════════════════════════════════════════════════════════════════════════
306
- FILE DEPENDENCIES
307
- ═══════════════════════════════════════════════════════════════════════════════
308
- imports <file> What does file import
309
- exporters <file> Who imports this file
310
- file-exports <file> What does file export
311
- graph <file> Full dependency tree (--depth=N, --direction=imports|importers|both)
312
- circular-deps Detect circular import chains (--file=, --exclude=)
313
-
314
- ═══════════════════════════════════════════════════════════════════════════════
315
- REFACTORING HELPERS
316
- ═══════════════════════════════════════════════════════════════════════════════
317
- plan <name> Preview refactoring (--add-param, --remove-param, --rename-to)
318
- verify <name> Check all call sites match signature
319
- diff-impact What changed in git diff and who calls it (--base, --staged)
320
- deadcode Find unused functions/classes
321
- entrypoints Detect framework entry points (routes, DI, tasks)
322
-
323
- ═══════════════════════════════════════════════════════════════════════════════
324
- OTHER
325
- ═══════════════════════════════════════════════════════════════════════════════
326
- api Show exported/public symbols
327
- typedef <name> Find type definitions
328
- stats Project statistics (--functions for per-function line counts)
329
- stacktrace <text> Parse stack trace, show code at each frame (alias: stack)
330
-
331
- Common Flags:
332
- --file <pattern> Filter by file path (e.g., --file=routes)
333
- --exclude=a,b Exclude patterns (e.g., --exclude=test,mock)
334
- --in=<path> Only in path (e.g., --in=src/core)
335
- --depth=N Trace/graph depth (default: 3, also expands all children)
336
- --direction=X Graph direction: imports, importers, or both (default: both)
337
- --all Expand truncated sections (about, trace, graph, related)
338
- --top=N Limit results (find, deadcode)
339
- --limit=N Limit result count (find, usages, search, deadcode, api, toc)
340
- --max-files=N Max files to index (large projects)
341
- --context=N Lines of context around matches
342
- --json Machine-readable output
343
- --code-only Filter out comments and strings
344
- --with-types Include type definitions
345
- --include-tests Include test files
346
- --class-name=X Scope to specific class (e.g., --class-name=Repository)
347
- --include-methods Include method calls (obj.fn) in caller/callee analysis
348
- --include-uncertain Include ambiguous/uncertain matches
349
- --no-confidence Hide confidence scores (shown by default)
350
- --min-confidence=N Filter edges below confidence threshold (0.0-1.0)
351
- --include-exported Include exported symbols in deadcode
352
- --no-regex Force plain text search (regex is default)
353
- --functions Show per-function line counts (stats command)
354
- --include-decorated Include decorated/annotated symbols in deadcode
355
- --framework=X Filter entrypoints by framework (e.g., --framework=express,spring)
356
- --exact Exact name match only (find)
357
- --calls-only Only show call/test-case matches (tests)
358
- --case-sensitive Case-sensitive text search (search)
359
- --detailed List all symbols in toc (compact by default)
360
- --top-level Show only top-level functions in toc
361
- --max-lines=N Max source lines for class (large classes show summary)
362
- --no-cache Disable caching
363
- --clear-cache Clear cache before running
364
- --base=<ref> Git ref for diff-impact (default: HEAD)
365
- --staged Analyze staged changes (diff-impact)
366
- --no-follow-symlinks Don't follow symbolic links
367
- -i, --interactive Keep index in memory for multiple queries
368
- ```
364
+ Run `ucn --help` for the full command list and flags.
369
365
 
370
366
  ---
371
367