ucn 3.7.6 → 3.7.7

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/cli/index.js CHANGED
@@ -983,7 +983,7 @@ function runProjectCommand(rootDir, command, arg) {
983
983
  });
984
984
  printOutput(deadcodeResults,
985
985
  output.formatDeadcodeJson,
986
- r => output.formatDeadcode(r)
986
+ r => output.formatDeadcode(r, { top: flags.top })
987
987
  );
988
988
  break;
989
989
  }
@@ -1720,7 +1720,7 @@ Common Flags:
1720
1720
  --depth=N Trace/graph depth (default: 3, also expands all children)
1721
1721
  --direction=X Graph direction: imports, importers, or both (default: both)
1722
1722
  --all Expand truncated sections (about, trace, graph, related)
1723
- --top=N Limit results (find)
1723
+ --top=N Limit results (find, deadcode)
1724
1724
  --context=N Lines of context around matches
1725
1725
  --json Machine-readable output
1726
1726
  --code-only Filter out comments and strings
@@ -2154,7 +2154,7 @@ function executeInteractiveCommand(index, command, arg, iflags = {}) {
2154
2154
  exclude: iflags.exclude,
2155
2155
  in: iflags.in
2156
2156
  });
2157
- console.log(output.formatDeadcode(deadResult));
2157
+ console.log(output.formatDeadcode(deadResult, { top: iflags.top }));
2158
2158
  break;
2159
2159
  }
2160
2160
 
package/core/output.js CHANGED
@@ -1724,12 +1724,20 @@ function formatDeadcode(results, options = {}) {
1724
1724
  }
1725
1725
 
1726
1726
  const lines = [];
1727
+ const top = options.top > 0 ? options.top : 0;
1728
+ const showing = top > 0 ? results.slice(0, top) : results;
1729
+ const hidden = results.length - showing.length;
1730
+
1727
1731
  if (results.length > 0) {
1728
- lines.push(`Dead code: ${results.length} unused symbol(s)\n`);
1732
+ if (hidden > 0) {
1733
+ lines.push(`Dead code: ${results.length} unused symbol(s) (showing ${showing.length})\n`);
1734
+ } else {
1735
+ lines.push(`Dead code: ${results.length} unused symbol(s)\n`);
1736
+ }
1729
1737
  }
1730
1738
 
1731
1739
  let currentFile = null;
1732
- for (const item of results) {
1740
+ for (const item of showing) {
1733
1741
  if (item.file !== currentFile) {
1734
1742
  currentFile = item.file;
1735
1743
  lines.push(item.file);
@@ -1747,6 +1755,10 @@ function formatDeadcode(results, options = {}) {
1747
1755
  lines.push(` ${lineRange(item.startLine, item.endLine)} ${item.name} (${item.type})${exported}${hintStr}`);
1748
1756
  }
1749
1757
 
1758
+ if (hidden > 0) {
1759
+ lines.push(`\n${hidden} more result(s) not shown. Use --top=${results.length} or --all to see all.`);
1760
+ }
1761
+
1750
1762
  // Show counts of excluded items with expansion hints
1751
1763
  if (results.length === 0) {
1752
1764
  lines.push('No dead code found.');
package/mcp/server.js CHANGED
@@ -451,6 +451,7 @@ server.registerTool(
451
451
  includeTests: include_tests || false
452
452
  });
453
453
  return toolResult(output.formatDeadcode(result, {
454
+ top: top || 0,
454
455
  decoratedHint: !include_decorated && result.excludedDecorated > 0 ? `${result.excludedDecorated} decorated/annotated symbol(s) hidden (framework-registered). Use include_decorated=true to include them.` : undefined,
455
456
  exportedHint: !include_exported && result.excludedExported > 0 ? `${result.excludedExported} exported symbol(s) excluded (all have callers). Use include_exported=true to audit them.` : undefined
456
457
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ucn",
3
- "version": "3.7.6",
3
+ "version": "3.7.7",
4
4
  "description": "Universal Code Navigator — AST-based call graph analysis for AI agents. Find callers, trace impact, detect dead code across JS/TS, Python, Go, Rust, Java, and HTML. CLI, MCP server, and agent skill.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -9647,6 +9647,34 @@ it('formatDeadcode handles zero exclusions without hints', () => {
9647
9647
  assert.ok(text.includes('helper'), 'Should still show the result');
9648
9648
  });
9649
9649
 
9650
+ it('formatDeadcode respects --top option', () => {
9651
+ const { formatDeadcode } = require('../core/output');
9652
+
9653
+ const results = [
9654
+ { name: 'a', type: 'function', file: 'a.js', startLine: 1, endLine: 3, isExported: false },
9655
+ { name: 'b', type: 'function', file: 'b.js', startLine: 1, endLine: 3, isExported: false },
9656
+ { name: 'c', type: 'function', file: 'c.js', startLine: 1, endLine: 3, isExported: false },
9657
+ { name: 'd', type: 'function', file: 'd.js', startLine: 1, endLine: 3, isExported: false },
9658
+ { name: 'e', type: 'function', file: 'e.js', startLine: 1, endLine: 3, isExported: false }
9659
+ ];
9660
+ results.excludedDecorated = 0;
9661
+ results.excludedExported = 0;
9662
+
9663
+ // With top=2, should show only 2 results
9664
+ const text = formatDeadcode(results, { top: 2 });
9665
+ assert.ok(text.includes('(showing 2)'), 'Should indicate showing 2');
9666
+ assert.ok(text.includes('a (function)'), 'Should show first result');
9667
+ assert.ok(text.includes('b (function)'), 'Should show second result');
9668
+ assert.ok(!text.includes('c (function)'), 'Should not show third result');
9669
+ assert.ok(text.includes('3 more result(s) not shown'), 'Should show hidden count');
9670
+
9671
+ // Without top, should show all results
9672
+ const textAll = formatDeadcode(results);
9673
+ assert.ok(!textAll.includes('showing'), 'Should not indicate partial results');
9674
+ assert.ok(textAll.includes('e (function)'), 'Should show all results');
9675
+ assert.ok(!textAll.includes('more result(s) not shown'), 'Should not show hidden hint');
9676
+ });
9677
+
9650
9678
  it('deadcode Python: simple decorators NOT excluded (only attribute access)', () => {
9651
9679
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ucn-dc-simple-deco-'));
9652
9680
  try {