sigmap 8.30.0 → 8.32.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/llms-full.txt CHANGED
@@ -11,13 +11,13 @@ ranking keeps the relevant context in scope (cutting tokens ~97% as a side
11
11
  effect), with no LLM calls, embeddings, or vector database. Works with Claude,
12
12
  Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
13
13
 
14
- # Version: 8.30.0 | Benchmark: sigmap-v8.30-main (2026-09-07)
14
+ # Version: 8.32.0 | Benchmark: sigmap-v8.32-main (2026-09-12)
15
15
  # Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
16
16
  # Regenerate: npm run generate:llms | Validate: npm run validate:llms
17
17
 
18
18
  ---
19
19
 
20
- ## Core metrics (benchmark: sigmap-v8.30-main, 2026-09-07)
20
+ ## Core metrics (benchmark: sigmap-v8.32-main, 2026-09-12)
21
21
 
22
22
  | Metric | Without SigMap | With SigMap |
23
23
  |--------|----------------|-------------|
@@ -132,6 +132,8 @@ sigmap tune Recommend config from repo detection
132
132
  sigmap tune --apply Write the recommendations into gen-context.config.json (merges; your keys preserved)
133
133
  sigmap skills list List skill clients (Claude/Cursor/Windsurf/Copilot/AGENTS.md) and install state (--json)
134
134
  sigmap skills install Install the SigMap agent playbooks for detected clients (--client <name> | --all)
135
+ sigmap lines <file> <start>-<end> Print an exact line range — CLI twin of get_lines (secrets redacted)
136
+ sigmap lines <file> :<line> --context <n> Window around one signature anchor (default ±10)
135
137
  sigmap note "<text>" Append a note to the cross-session decision log
136
138
  sigmap note List recent notes (also: note --list <N>)
137
139
  sigmap status Show repo state — branch, dirty files, index freshness, notes
package/llms.txt CHANGED
@@ -11,7 +11,7 @@ ranking keeps the relevant context in scope (cutting tokens ~97% as a side
11
11
  effect), with no LLM calls, embeddings, or vector database. Works with Claude,
12
12
  Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
13
13
 
14
- # Version: 8.30.0 | Benchmark: sigmap-v8.30-main (2026-09-07)
14
+ # Version: 8.32.0 | Benchmark: sigmap-v8.32-main (2026-09-12)
15
15
  # Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
16
16
  # Regenerate: npm run generate:llms | Validate: npm run validate:llms
17
17
 
@@ -23,7 +23,7 @@ Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
23
23
  - No blast-radius awareness before editing a hub file — `--impact` shows every file a change touches.
24
24
  - Pasted stack traces, CI logs, and JSON bloat the prompt — `squeeze` minimizes them and enriches the top frame from the symbol index.
25
25
 
26
- ## Core metrics (benchmark: sigmap-v8.30-main, 2026-09-07)
26
+ ## Core metrics (benchmark: sigmap-v8.32-main, 2026-09-12)
27
27
 
28
28
  - hit@5 retrieval: 81.1% vs 44.0% single-shot grep baseline (1.73× lift)
29
29
  - Token reduction: 96.8% average across benchmark repos
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "8.30.0",
3
+ "version": "8.32.0",
4
4
  "description": "The deterministic, verifiable grounding layer for AI code work — a zero-dependency signature-and-evidence map that grounds Claude, Cursor, Copilot, Aider, Windsurf, local LLMs & MCP agents against your real code (repo + installed libraries) so they stop hallucinating files, imports & APIs. Runs offline via npx; byte-stable output; ~97% token reduction as proof.",
5
5
  "main": "packages/core/index.js",
6
6
  "exports": {
@@ -31,6 +31,8 @@
31
31
  "benchmark:test-discovery": "node scripts/run-test-discovery-benchmark.mjs --save",
32
32
  "benchmark:terse": "node scripts/run-terse-benchmark.mjs --save",
33
33
  "benchmark:callgraph-boost": "node scripts/run-callgraph-boost-benchmark.mjs --save",
34
+ "benchmark:callgraph-jvm": "node scripts/run-callgraph-jvm-benchmark.mjs",
35
+ "validate:callgraph-jvm": "node scripts/run-callgraph-jvm-benchmark.mjs --gate",
34
36
  "benchmark:centrality-blend": "node scripts/run-centrality-blend-benchmark.mjs --save",
35
37
  "benchmark:surface-enrichment": "node scripts/run-surface-enrichment-benchmark.mjs --save",
36
38
  "validate:squeeze": "node scripts/run-squeeze-benchmark.mjs --gate",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-cli",
3
- "version": "8.30.0",
3
+ "version": "8.32.0",
4
4
  "description": "SigMap CLI wrapper — thin adapter for programmatic CLI invocation",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-core",
3
- "version": "8.30.0",
3
+ "version": "8.32.0",
4
4
  "description": "SigMap core library — zero-dependency code signature extraction, retrieval, and security scanning",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -1,5 +1,13 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
4
+
5
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed
7
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
8
+ const MEMBER_LIMIT = 8;
9
+ const PER_FILE_LIMIT = 25;
10
+
3
11
  /**
4
12
  * Extract signatures from C/C++ source code.
5
13
  * @param {string} src - Raw file content
@@ -30,7 +38,7 @@ function extract(src) {
30
38
  sigs.push(`${m[2]}(${normalizeParams(m[3])})${retStr}`);
31
39
  }
32
40
 
33
- return sigs.slice(0, 25);
41
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
34
42
  }
35
43
 
36
44
  function extractBlock(src, startIndex) {
@@ -53,7 +61,7 @@ function extractMembers(block) {
53
61
  const retStr = ret ? ` → ${ret}` : '';
54
62
  members.push(`${m[2]}(${normalizeParams(m[3])})${retStr}`);
55
63
  }
56
- return members.slice(0, 8);
64
+ return capWithNotice(members, MEMBER_LIMIT, 'members');
57
65
  }
58
66
 
59
67
  function normalizeParams(params) {
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
5
+
6
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed
8
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
9
+ const MEMBER_LIMIT = 8;
10
+ const PER_FILE_LIMIT = 25;
4
11
 
5
12
  /**
6
13
  * Extract signatures from C# source code.
@@ -25,11 +32,12 @@ function extract(src) {
25
32
  const block = extractBlock(stripped, bodyStart);
26
33
  sigs.push(withAnchor(`${m[1]} ${m[2]}`, lineAt(stripped, declIdx), lineAt(stripped, bodyStart + block.length)));
27
34
  for (const meth of extractMembers(block)) {
28
- sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + meth.declIdx), lineAt(stripped, bodyStart + meth.endIdx)));
35
+ // The disclosure marker carries no offsets; anchor it at the class body.
36
+ sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
29
37
  }
30
38
  }
31
39
 
32
- return sigs.slice(0, 25);
40
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
33
41
  }
34
42
 
35
43
  function extractBlock(src, startIndex) {
@@ -55,7 +63,7 @@ function extractMembers(block) {
55
63
  endIdx: m.index + m[0].length,
56
64
  });
57
65
  }
58
- return members.slice(0, 8);
66
+ return capMembersWithNotice(members, MEMBER_LIMIT);
59
67
  }
60
68
 
61
69
  function normalizeParams(params) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from CSS/SCSS/SASS/Less source code.
5
11
  * @param {string} src - Raw file content
@@ -63,7 +69,7 @@ function extract(src) {
63
69
  for (const name of selected) sigs.push(`.${name}`);
64
70
  }
65
71
 
66
- return sigs.slice(0, 25);
72
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
67
73
  }
68
74
 
69
75
  module.exports = { extract };
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
5
+
6
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed
8
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
9
+ const MEMBER_LIMIT = 8;
10
+ const PER_FILE_LIMIT = 25;
4
11
 
5
12
  /**
6
13
  * Extract signatures from Dart source code.
@@ -36,7 +43,8 @@ function extract(src) {
36
43
  const block = extractBlock(stripped, bodyStart);
37
44
  sigs.push(withAnchor(`${abs}class ${m[1]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
38
45
  for (const meth of extractMembers(block)) {
39
- sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + meth.declIdx), lineAt(stripped, bodyStart + meth.endIdx)));
46
+ // The disclosure marker carries no offsets; anchor it at the class body.
47
+ sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
40
48
  }
41
49
  }
42
50
 
@@ -48,7 +56,7 @@ function extract(src) {
48
56
  sigs.push(withAnchor(`${m[2]}(${normalizeParams(m[3])})${retStr}`, s, e));
49
57
  }
50
58
 
51
- return sigs.slice(0, 25);
59
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
52
60
  }
53
61
 
54
62
  function extractBlock(src, startIndex) {
@@ -73,7 +81,7 @@ function extractMembers(block) {
73
81
  endIdx: m.index + m[0].length,
74
82
  });
75
83
  }
76
- return members.slice(0, 8);
84
+ return capMembersWithNotice(members, MEMBER_LIMIT);
77
85
  }
78
86
 
79
87
  function normalizeParams(params) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from Dockerfiles.
5
11
  * @param {string} src - Raw file content
@@ -43,7 +49,7 @@ function extract(src) {
43
49
  if (m) sigs.push(`ARG ${m[1]}`);
44
50
  }
45
51
 
46
- return sigs.slice(0, 25);
52
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
47
53
  }
48
54
 
49
55
  module.exports = { extract };
@@ -1,5 +1,15 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
9
+ // Ceilings disclose what they drop rather than truncating silently (#576).
10
+ const MEMBER_LIMIT = 6;
11
+ const ENUM_LIMIT = 24;
12
+
3
13
  /**
4
14
  * Extract signatures from Godot GDScript source code.
5
15
  * @param {string} src - Raw file content
@@ -44,7 +54,7 @@ function extract(src) {
44
54
  .split(',')
45
55
  .map((s) => s.trim().split(/\s*=/)[0].trim())
46
56
  .filter(Boolean);
47
- sigs.push(`${indent}enum ${m[1]} { ${members.slice(0, 6).join(', ')} }`);
57
+ sigs.push(`${indent}enum ${m[1]} { ${capWithNotice(members, ENUM_LIMIT, 'values').join(', ')} }`);
48
58
  }
49
59
 
50
60
  let constCount = 0;
@@ -92,7 +102,7 @@ function extract(src) {
92
102
  }
93
103
  }
94
104
 
95
- return sigs.slice(0, 25);
105
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
96
106
  }
97
107
 
98
108
  function extractInnerMembers(stripped, startIndex) {
@@ -110,7 +120,7 @@ function extractInnerMembers(stripped, startIndex) {
110
120
  members.push(`${staticKw}func ${fm[2]}(${params})${retStr}`);
111
121
  }
112
122
  }
113
- return members.slice(0, 6);
123
+ return capWithNotice(members, MEMBER_LIMIT, 'members');
114
124
  }
115
125
 
116
126
  function normalizeParams(params) {
@@ -1,6 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice } = require('../util/truncate');
5
+
6
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
8
+ const PER_FILE_LIMIT = 25;
4
9
 
5
10
  /**
6
11
  * Extract signatures from Go source code.
@@ -49,7 +54,7 @@ function extract(src) {
49
54
  sigs.push(hinted(withAnchor(`func ${receiver}${m[2]}(${normalizeParams(m[3])})${retStr}`, lineAt(stripped, m.index), lineAt(stripped, end)), m[2]));
50
55
  }
51
56
 
52
- return sigs.slice(0, 25);
57
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
53
58
  }
54
59
 
55
60
  function extractBlock(src, startIndex) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from HTML files.
5
11
  * Focuses on id/class attributes, forms, and script tags.
@@ -33,7 +39,7 @@ function extract(src) {
33
39
  sigs.push(`data-${m[0].match(/data-(\w[\w-]*)/i)[1]}: ${m[1]}`);
34
40
  }
35
41
 
36
- return sigs.slice(0, 25);
42
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
37
43
  }
38
44
 
39
45
  module.exports = { extract };
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
5
+
6
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed
8
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
9
+ const MEMBER_LIMIT = 8;
10
+ const PER_FILE_LIMIT = 25;
4
11
 
5
12
  /**
6
13
  * Extract signatures from Kotlin source code.
@@ -35,7 +42,8 @@ function extract(src) {
35
42
  const block = extractBlock(stripped, bodyStart);
36
43
  sigs.push(withAnchor(`${m[1]} ${m[2]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
37
44
  for (const meth of extractMembers(block)) {
38
- sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + meth.declIdx), lineAt(stripped, bodyStart + meth.endIdx)));
45
+ // The disclosure marker carries no offsets; anchor it at the class body.
46
+ sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
39
47
  }
40
48
  }
41
49
 
@@ -48,7 +56,7 @@ function extract(src) {
48
56
  sigs.push(withAnchor(`${suspend}fun ${m[1]}(${normalizeParams(m[2])})${retStr}`, s, e));
49
57
  }
50
58
 
51
- return sigs.slice(0, 25);
59
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
52
60
  }
53
61
 
54
62
  function extractBlock(src, startIndex) {
@@ -75,7 +83,7 @@ function extractMembers(block) {
75
83
  endIdx: m.index + m[0].length,
76
84
  });
77
85
  }
78
- return members.slice(0, 8);
86
+ return capMembersWithNotice(members, MEMBER_LIMIT);
79
87
  }
80
88
 
81
89
  function normalizeParams(params) {
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
5
+
6
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed
8
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
9
+ const MEMBER_LIMIT = 8;
10
+ const PER_FILE_LIMIT = 25;
4
11
 
5
12
  /**
6
13
  * Extract signatures from PHP source code.
@@ -40,7 +47,8 @@ function extract(src) {
40
47
  const block = extractBlock(stripped, bodyStart);
41
48
  sigs.push(withAnchor(`${kind} ${m[1]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
42
49
  for (const meth of extractMembers(block)) {
43
- sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + meth.declIdx), lineAt(stripped, bodyStart + meth.endIdx)));
50
+ // The disclosure marker carries no offsets; anchor it at the class body.
51
+ sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
44
52
  }
45
53
  }
46
54
 
@@ -52,7 +60,7 @@ function extract(src) {
52
60
  sigs.push(withAnchor(`function ${m[1]}(${normalizeParams(m[2])})${retStr}`, s, e));
53
61
  }
54
62
 
55
- return sigs.slice(0, 25);
63
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
56
64
  }
57
65
 
58
66
  function extractBlock(src, startIndex) {
@@ -80,7 +88,7 @@ function extractMembers(block) {
80
88
  endIdx: m.index + m[0].length,
81
89
  });
82
90
  }
83
- return members.slice(0, 8);
91
+ return capMembersWithNotice(members, MEMBER_LIMIT);
84
92
  }
85
93
 
86
94
  function normalizeParams(params) {
@@ -2,6 +2,11 @@
2
2
 
3
3
  const path = require('path');
4
4
  const { lineAt } = require('./line-anchor');
5
+ const { capWithNotice } = require('../util/truncate');
6
+
7
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
8
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
9
+ const PER_FILE_LIMIT = 30;
5
10
 
6
11
  /**
7
12
  * 1-based line of the last source line belonging to a top-level (indent 0)
@@ -136,7 +141,7 @@ function extract(src, filePath) {
136
141
  }
137
142
  }
138
143
 
139
- return sigs.slice(0, 30);
144
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
140
145
  }
141
146
 
142
147
  function extractClassMethods(stripped, startIndex) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 30;
8
+
3
9
  /**
4
10
  * Extract signatures from R source code.
5
11
  *
@@ -113,7 +119,7 @@ function extract(src) {
113
119
  sigs.push(`setClass("${sm[1]}")`);
114
120
  }
115
121
 
116
- return sigs.slice(0, 30);
122
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
117
123
  }
118
124
 
119
125
  /**
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from Ruby source code.
5
11
  * @param {string} src - Raw file content
@@ -34,7 +40,7 @@ function extract(src) {
34
40
  sigs.push(`def ${m[1]}${params}${retStr}`);
35
41
  }
36
42
 
37
- return sigs.slice(0, 25);
43
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
38
44
  }
39
45
 
40
46
  function normalizeParams(params) {
@@ -1,6 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice } = require('../util/truncate');
5
+
6
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
8
+ const PER_FILE_LIMIT = 25;
4
9
 
5
10
  /**
6
11
  * Extract signatures from Rust source code.
@@ -70,7 +75,7 @@ function extract(src) {
70
75
  sigs.push(hinted(withAnchor(`pub ${asyncKw}fn ${m[1]}(${normalizeParams(m[2])})${retStr}`, s, e), m[1]));
71
76
  }
72
77
 
73
- return sigs.slice(0, 25);
78
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
74
79
  }
75
80
 
76
81
  function extractBlock(src, startIndex) {
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
5
+
6
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed
8
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
9
+ const MEMBER_LIMIT = 8;
10
+ const PER_FILE_LIMIT = 25;
4
11
 
5
12
  /**
6
13
  * Extract signatures from Scala source code.
@@ -27,7 +34,8 @@ function extract(src) {
27
34
  const block = extractBlock(stripped, bodyStart);
28
35
  sigs.push(withAnchor(`${kind} ${m[1]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
29
36
  for (const fn of extractMembers(block)) {
30
- sigs.push(withAnchor(` ${fn.text}`, lineAt(stripped, bodyStart + fn.declIdx), lineAt(stripped, bodyStart + fn.endIdx)));
37
+ // The disclosure marker carries no offsets; anchor it at the class body.
38
+ sigs.push(withAnchor(` ${fn.text}`, lineAt(stripped, bodyStart + (fn.declIdx || 0)), lineAt(stripped, bodyStart + (fn.endIdx || 0))));
31
39
  }
32
40
  }
33
41
 
@@ -41,7 +49,7 @@ function extract(src) {
41
49
  sigs.push(withAnchor(`def ${m[1]}${params}${retStr}`, line, line));
42
50
  }
43
51
 
44
- return sigs.slice(0, 25);
52
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
45
53
  }
46
54
 
47
55
  function extractBlock(src, startIndex) {
@@ -68,7 +76,7 @@ function extractMembers(block) {
68
76
  endIdx: m.index + m[0].length,
69
77
  });
70
78
  }
71
- return members.slice(0, 8);
79
+ return capMembersWithNotice(members, MEMBER_LIMIT);
72
80
  }
73
81
 
74
82
  function normalizeParams(params) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from shell scripts (bash, zsh, fish).
5
11
  * @param {string} src - Raw file content
@@ -37,7 +43,7 @@ function extract(src) {
37
43
  }
38
44
  }
39
45
 
40
- return sigs.slice(0, 25);
46
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
41
47
  }
42
48
 
43
49
  module.exports = { extract };
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from Svelte components.
5
11
  * @param {string} src - Raw file content
@@ -42,7 +48,7 @@ function extract(src) {
42
48
  sigs.push(`$: ${m[1]}`);
43
49
  }
44
50
 
45
- return sigs.slice(0, 25);
51
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
46
52
  }
47
53
 
48
54
  function normalizeParams(params) {
@@ -1,6 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  const { lineAt, withAnchor } = require('./line-anchor');
4
+ const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
5
+
6
+ // Ceilings sit above the default `maxSigsPerFile` so the configured budget
7
+ // governs output rather than a literal buried here, and omissions are disclosed
8
+ // — an undisclosed cap looks like a class that simply has eight methods (#576).
9
+ const MEMBER_LIMIT = 8;
10
+ const PER_FILE_LIMIT = 25;
4
11
 
5
12
  /**
6
13
  * Extract signatures from Swift source code.
@@ -36,7 +43,8 @@ function extract(src) {
36
43
  const block = extractBlock(stripped, bodyStart);
37
44
  sigs.push(withAnchor(`${m[1]} ${m[2]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
38
45
  for (const fn of extractMembers(block)) {
39
- sigs.push(withAnchor(` ${fn.text}`, lineAt(stripped, bodyStart + fn.declIdx), lineAt(stripped, bodyStart + fn.endIdx)));
46
+ // The disclosure marker carries no offsets; anchor it at the class body.
47
+ sigs.push(withAnchor(` ${fn.text}`, lineAt(stripped, bodyStart + (fn.declIdx || 0)), lineAt(stripped, bodyStart + (fn.endIdx || 0))));
40
48
  }
41
49
  }
42
50
 
@@ -48,7 +56,7 @@ function extract(src) {
48
56
  sigs.push(withAnchor(`${asyncKw}func ${m[1]}(${normalizeParams(m[2])})${retStr}`, s, e));
49
57
  }
50
58
 
51
- return sigs.slice(0, 25);
59
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
52
60
  }
53
61
 
54
62
  function extractBlock(src, startIndex) {
@@ -74,7 +82,7 @@ function extractMembers(block) {
74
82
  endIdx: m.index + m[0].length,
75
83
  });
76
84
  }
77
- return members.slice(0, 8);
85
+ return capMembersWithNotice(members, MEMBER_LIMIT);
78
86
  }
79
87
 
80
88
  function normalizeParams(params) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from Vue single-file components.
5
11
  * @param {string} src - Raw file content
@@ -64,7 +70,7 @@ function extract(src) {
64
70
  const emitsMatch = script.match(/(?:defineEmits|emits)\s*(?::\s*|\(\s*)(\[[\s\S]*?\])/);
65
71
  if (emitsMatch) sigs.push(`emits: ${emitsMatch[1].replace(/\s+/g, ' ')}`);
66
72
 
67
- return sigs.slice(0, 25);
73
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
68
74
  }
69
75
 
70
76
  function normalizeParams(params) {
@@ -1,5 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ const { capWithNotice } = require('../util/truncate');
4
+
5
+ // Ceiling sits above the default `maxSigsPerFile` so the configured budget
6
+ // governs output rather than a literal buried here, and omissions are disclosed (#576).
7
+ const PER_FILE_LIMIT = 25;
8
+
3
9
  /**
4
10
  * Extract signatures from YAML configuration files.
5
11
  * @param {string} src - Raw file content
@@ -53,7 +59,7 @@ function extract(src) {
53
59
  }
54
60
  }
55
61
 
56
- return sigs.slice(0, 25);
62
+ return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
57
63
  }
58
64
 
59
65
  module.exports = { extract };