ucn 3.8.25 → 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.
@@ -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.
@@ -161,7 +163,7 @@ ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pyte
161
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) |
162
164
  | Find by glob pattern | `ucn find "handle*"` | Locate definitions matching a glob (supports * and ?) |
163
165
  | Text search with context | `ucn search term --context=3` | Like grep -C 3, shows surrounding lines |
164
- | 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 |
165
167
  | Text search filtered | `ucn search term --exclude=test` | Search only in matching files |
166
168
  | Structural search (index) | `ucn search --type=function --param=Request` | Query the symbol table, not text. Finds functions by param, return type, decorator, etc. |
167
169
  | Find all db.* calls | `ucn search --type=call --receiver=db` | Search call sites by receiver — something grep can't do |
@@ -187,6 +189,16 @@ ucn entrypoints --exclude-tests # Hide test fixtures (JUnit @Test, pyte
187
189
  | Pre-commit summary | `ucn check [--base=main]` | Changed funcs + signature drift + affected tests in one shot |
188
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` |
189
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
+
190
202
  ## Reading Call-Site Patterns
191
203
 
192
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:
package/core/bridge.js CHANGED
@@ -86,11 +86,6 @@ function joinRoutePath(prefix, sub) {
86
86
  return p + '/' + s;
87
87
  }
88
88
 
89
- /** True if `s` ends with the wildcard sentinel from a template literal. */
90
- function endsWithWildcard(s) {
91
- return typeof s === 'string' && s.endsWith('*');
92
- }
93
-
94
89
  // ============================================================================
95
90
  // FRAMEWORK PATTERNS
96
91
  // ============================================================================
@@ -253,17 +248,6 @@ const PREFIX_ANNOTATIONS = new Set([
253
248
  'Path', // JAX-RS class-level @Path("/api")
254
249
  ]);
255
250
 
256
- // Python decorator name patterns (e.g., 'app.route' or 'app.get')
257
- // Returns { method, isPrefix } when matched.
258
- function parsePythonDecorator(name) {
259
- if (typeof name !== 'string') return null;
260
- const m = name.match(/^[A-Za-z_][A-Za-z0-9_]*\.(route|get|post|put|delete|patch|options|head)/i);
261
- if (!m) return null;
262
- const verb = m[1].toLowerCase();
263
- if (verb === 'route') return { method: 'ALL', isRoute: true };
264
- return { method: verb.toUpperCase() };
265
- }
266
-
267
251
  // ============================================================================
268
252
  // EXTRACT SERVER ROUTES
269
253
  // ============================================================================
package/core/search.js CHANGED
@@ -1402,48 +1402,6 @@ function _addTestCaseMatches(index, filePath, fileEntry, searchTerm, className,
1402
1402
  }
1403
1403
  }
1404
1404
 
1405
- /**
1406
- * Check if a test body references the target class (directly or via instance variable).
1407
- * Looks at AST usages of className within the test function's line range.
1408
- */
1409
- function _testBodyReferencesClass(index, filePath, fileEntry, testLine, className, instanceTypeMap) {
1410
- // Find the enclosing test function to get its line range
1411
- const enclosing = index.findEnclosingFunction(filePath, testLine, true);
1412
- let startLine, endLine;
1413
- if (enclosing) {
1414
- startLine = enclosing.startLine;
1415
- endLine = enclosing.endLine;
1416
- } else {
1417
- // No enclosing function found (common for JS/TS it/test callbacks which
1418
- // aren't in the symbol table). Estimate range from file content.
1419
- startLine = testLine;
1420
- endLine = _estimateTestBlockEnd(index, filePath, testLine);
1421
- }
1422
-
1423
- // Check if className appears as AST usage in the range
1424
- const classUsages = index._getCachedUsages(filePath, className);
1425
- if (classUsages) {
1426
- for (const u of classUsages) {
1427
- if (u.line >= startLine && u.line <= endLine) return true;
1428
- }
1429
- }
1430
-
1431
- // Check if any instance variable bound to className is used in the range
1432
- if (instanceTypeMap) {
1433
- for (const [varName, cls] of instanceTypeMap) {
1434
- if (cls !== className) continue;
1435
- const varUsages = index._getCachedUsages(filePath, varName);
1436
- if (varUsages) {
1437
- for (const u of varUsages) {
1438
- if (u.line >= startLine && u.line <= endLine) return true;
1439
- }
1440
- }
1441
- }
1442
- }
1443
-
1444
- return false;
1445
- }
1446
-
1447
1405
  /**
1448
1406
  * Estimate the end line of a test block (it/test/describe callback) by tracking
1449
1407
  * brace nesting from the start line.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ucn",
3
- "version": "3.8.25",
3
+ "version": "3.8.26",
4
4
  "mcpName": "io.github.mleoca/ucn",
5
5
  "description": "Code intelligence toolkit for AI agents — extract functions, trace call chains, find callers, detect dead code without reading entire files. Works as MCP server, CLI, or agent skill. Supports JS/TS, Python, Go, Rust, Java.",
6
6
  "main": "index.js",