sigmap 7.2.1 → 7.4.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
@@ -9,7 +9,7 @@ the files relevant to the task — cutting tokens ~97% while keeping answers
9
9
  grounded. Deterministic, offline, no embeddings or vector database. Works with
10
10
  Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
11
11
 
12
- # Version: 7.2.1 | Benchmark: sigmap-v7.0-main (2026-06-14)
12
+ # Version: 7.4.0 | Benchmark: sigmap-v7.0-main (2026-06-14)
13
13
  # Source: auto-generated from package.json, version.json, src/mcp/tools.js, src/config/defaults.js
14
14
  # Regenerate: npm run generate:llms | Validate: npm run validate:llms
15
15
 
@@ -24,7 +24,7 @@ Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
24
24
  | Task success proxy | 10% | 52.2% |
25
25
  | Prompts per task | 2.84 | 1.72 (39.4% fewer) |
26
26
  | Supported languages | — | 31 |
27
- | MCP tools | — | 11 |
27
+ | MCP tools | — | 15 |
28
28
  | npm runtime dependencies | — | 0 |
29
29
 
30
30
  ---
@@ -114,7 +114,7 @@ sigmap --version Show version
114
114
 
115
115
  ---
116
116
 
117
- ## MCP server — 11 tools
117
+ ## MCP server — 15 tools
118
118
 
119
119
  Start with `sigmap --mcp` (stdio JSON-RPC). Configure once:
120
120
 
@@ -210,6 +210,38 @@ Recall the project decision log — recent notes left by humans or agents across
210
210
  Input: { limit?: number }
211
211
  ```
212
212
 
213
+ ### get_callee_signatures
214
+
215
+ Return the EXACT current signature(s) of named symbols (functions, classes, methods) from the index — so an agent never guesses a callee's parameter types from training memory. Call this before writing code that uses a symbol. Unknown names get a closest-match suggestion.
216
+
217
+ ```
218
+ Input: { symbols: array }
219
+ ```
220
+
221
+ ### sigmap_notify_file_created
222
+
223
+ Tell SigMap a file was created or modified so its signatures are indexed live for the rest of the session. Call this after writing a file — the new symbols become resolvable by search_signatures / get_callee_signatures.
224
+
225
+ ```
226
+ Input: { path: string, content?: string }
227
+ ```
228
+
229
+ ### sigmap_notify_symbol_added
230
+
231
+ Fast path: register a single new symbol signature directly in the live index without re-reading the whole file.
232
+
233
+ ```
234
+ Input: { signature: string, file: string, line?: number }
235
+ ```
236
+
237
+ ### sigmap_notify_file_deleted
238
+
239
+ Tell SigMap a file was deleted so its symbols are dropped from the live index.
240
+
241
+ ```
242
+ Input: { path: string }
243
+ ```
244
+
213
245
  ---
214
246
 
215
247
  ## Configuration (gen-context.config.json)
@@ -253,9 +285,9 @@ impact = {"depth":3,"includeSigs":true}
253
285
 
254
286
  ---
255
287
 
256
- ## Supported languages (34 extractors)
288
+ ## Supported languages (35 extractors)
257
289
 
258
- cpp, csharp, css, dart, dockerfile, gdscript, generic, go, graphql, html, java, javascript, kotlin, markdown, php, properties, protobuf, python, r, ruby, rust, scala, shell, sql, svelte, swift, terraform, toml, typescript, typescript_react, vue, vue_sfc, xml, yaml
290
+ cpp, csharp, css, dart, dispatch, dockerfile, gdscript, generic, go, graphql, html, java, javascript, kotlin, markdown, php, properties, protobuf, python, r, ruby, rust, scala, shell, sql, svelte, swift, terraform, toml, typescript, typescript_react, vue, vue_sfc, xml, yaml
259
291
 
260
292
  ---
261
293
 
package/llms.txt CHANGED
@@ -9,7 +9,7 @@ the files relevant to the task — cutting tokens ~97% while keeping answers
9
9
  grounded. Deterministic, offline, no embeddings or vector database. Works with
10
10
  Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
11
11
 
12
- # Version: 7.2.1 | Benchmark: sigmap-v7.0-main (2026-06-14)
12
+ # Version: 7.4.0 | Benchmark: sigmap-v7.0-main (2026-06-14)
13
13
  # Source: auto-generated from package.json, version.json, src/mcp/tools.js, src/config/defaults.js
14
14
  # Regenerate: npm run generate:llms | Validate: npm run validate:llms
15
15
 
@@ -27,7 +27,7 @@ Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
27
27
  - Token reduction: 97.0% average across benchmark repos
28
28
  - Task success: 52.2% vs 10% without SigMap
29
29
  - Prompts per task: 1.72 vs 2.84 baseline (39.4% fewer)
30
- - Languages: 31 supported · MCP tools: 11
30
+ - Languages: 31 supported · MCP tools: 15
31
31
  - Dependencies: zero npm runtime dependencies · fully offline
32
32
 
33
33
  ## Quick start
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "7.2.1",
3
+ "version": "7.4.0",
4
4
  "description": "97% token reduction for AI coding. Extracts function & class signatures with TF-IDF ranking to feed only the right files to Claude, Cursor, Copilot, Aider, Windsurf, local LLMs & MCP. Zero dependencies, runs offline via npx.",
5
5
  "main": "packages/core/index.js",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-cli",
3
- "version": "7.2.1",
3
+ "version": "7.4.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": "7.2.1",
3
+ "version": "7.4.0",
4
4
  "description": "SigMap core library — zero-dependency code signature extraction, retrieval, and security scanning",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Bundle-safe extractor dispatch.
5
+ *
6
+ * `packages/core`'s extract() resolves extractors via dynamic `require(path.join(…))`,
7
+ * which cannot run inside the standalone bundle (no filesystem `src/`). This module
8
+ * uses STATIC requires so the bundler rewrites them to `__require` and the extractors
9
+ * resolve from the bundled factories. Used by the live-index MCP write hooks.
10
+ */
11
+
12
+ const path = require('path');
13
+
14
+ // Static language → extractor map (every entry is a bundled factory).
15
+ const EXTRACTORS = {
16
+ typescript: require('./typescript'),
17
+ typescript_react: require('./typescript_react'),
18
+ javascript: require('./javascript'),
19
+ python: require('./python'),
20
+ java: require('./java'),
21
+ kotlin: require('./kotlin'),
22
+ go: require('./go'),
23
+ rust: require('./rust'),
24
+ csharp: require('./csharp'),
25
+ cpp: require('./cpp'),
26
+ ruby: require('./ruby'),
27
+ php: require('./php'),
28
+ swift: require('./swift'),
29
+ dart: require('./dart'),
30
+ scala: require('./scala'),
31
+ gdscript: require('./gdscript'),
32
+ r: require('./r'),
33
+ vue: require('./vue'),
34
+ vue_sfc: require('./vue_sfc'),
35
+ svelte: require('./svelte'),
36
+ html: require('./html'),
37
+ css: require('./css'),
38
+ yaml: require('./yaml'),
39
+ shell: require('./shell'),
40
+ sql: require('./sql'),
41
+ graphql: require('./graphql'),
42
+ terraform: require('./terraform'),
43
+ protobuf: require('./protobuf'),
44
+ toml: require('./toml'),
45
+ properties: require('./properties'),
46
+ xml: require('./xml'),
47
+ markdown: require('./markdown'),
48
+ dockerfile: require('./dockerfile'),
49
+ generic: require('./generic'),
50
+ };
51
+
52
+ const EXT_MAP = {
53
+ '.ts': 'typescript', '.tsx': 'typescript_react',
54
+ '.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript',
55
+ '.py': 'python', '.pyw': 'python',
56
+ '.java': 'java',
57
+ '.kt': 'kotlin', '.kts': 'kotlin',
58
+ '.go': 'go',
59
+ '.rs': 'rust',
60
+ '.cs': 'csharp',
61
+ '.cpp': 'cpp', '.c': 'cpp', '.h': 'cpp', '.hpp': 'cpp', '.cc': 'cpp',
62
+ '.rb': 'ruby', '.rake': 'ruby',
63
+ '.php': 'php',
64
+ '.swift': 'swift',
65
+ '.dart': 'dart',
66
+ '.scala': 'scala', '.sc': 'scala',
67
+ '.gd': 'gdscript',
68
+ '.r': 'r', '.R': 'r',
69
+ '.vue': 'vue_sfc',
70
+ '.svelte': 'svelte',
71
+ '.html': 'html', '.htm': 'html',
72
+ '.css': 'css', '.scss': 'css', '.sass': 'css', '.less': 'css',
73
+ '.yml': 'yaml', '.yaml': 'yaml',
74
+ '.sh': 'shell', '.bash': 'shell', '.zsh': 'shell', '.fish': 'shell',
75
+ '.sql': 'sql',
76
+ '.graphql': 'graphql', '.gql': 'graphql',
77
+ '.tf': 'terraform', '.tfvars': 'terraform',
78
+ '.proto': 'protobuf',
79
+ '.toml': 'toml',
80
+ '.properties': 'properties',
81
+ '.xml': 'xml',
82
+ '.md': 'markdown',
83
+ };
84
+
85
+ /** Resolve a language key from a file path/name. */
86
+ function langFor(filePathOrName) {
87
+ const base = path.basename(String(filePathOrName || ''));
88
+ if (base === 'Dockerfile' || base.startsWith('Dockerfile.')) return 'dockerfile';
89
+ const ext = path.extname(base).toLowerCase();
90
+ return EXT_MAP[ext] || null;
91
+ }
92
+
93
+ /**
94
+ * Extract signatures from a file's content using the right extractor.
95
+ * @param {string} filePathOrName - path or name (extension drives the extractor)
96
+ * @param {string} src - file content
97
+ * @returns {string[]}
98
+ */
99
+ function extractFile(filePathOrName, src) {
100
+ if (!src || typeof src !== 'string') return [];
101
+ const lang = langFor(filePathOrName);
102
+ const mod = lang ? EXTRACTORS[lang] : null;
103
+ if (!mod || typeof mod.extract !== 'function') return [];
104
+ try {
105
+ const out = mod.extract(src);
106
+ return Array.isArray(out) ? out : [];
107
+ } catch (_) {
108
+ return [];
109
+ }
110
+ }
111
+
112
+ module.exports = { extractFile, langFor };
@@ -543,4 +543,133 @@ function readMemory(args, cwd) {
543
543
  return out.join('\n');
544
544
  }
545
545
 
546
- module.exports = { readContext, searchSignatures, getMap, createCheckpoint, getRouting, explainFile, listModules, queryContext, getImpact, getLines, readMemory };
546
+ /**
547
+ * get_callee_signatures — return the exact defining signature(s) of named
548
+ * symbols from the index, so an agent never guesses a callee's parameter types.
549
+ * Unknown names get a closest-match suggestion.
550
+ * @param {{symbols:string[]}} args
551
+ * @param {string} cwd
552
+ */
553
+ function getCalleeSignatures(args, cwd) {
554
+ const symbols = args && Array.isArray(args.symbols)
555
+ ? args.symbols.map((s) => String(s).trim()).filter(Boolean)
556
+ : null;
557
+ if (!symbols || symbols.length === 0) {
558
+ return 'Missing required argument: symbols (non-empty string[])';
559
+ }
560
+
561
+ try {
562
+ const { buildSigIndex } = require('../retrieval/ranker');
563
+ const { buildSymbolCandidates, closestMatch, formatSuggestion } = require('../verify/closest-match');
564
+ const index = buildSigIndex(cwd);
565
+ if (index.size === 0) return 'No context file found. Run: node gen-context.js';
566
+
567
+ // Extract the defining symbol name from a signature line (same rules as
568
+ // buildSymbolCandidates) so we match definitions, not param occurrences.
569
+ const defName = (sig) => {
570
+ const cleaned = String(sig).replace(/\s*:\d+(?:-\d+)?\s*$/, '');
571
+ const m = cleaned.match(/\b(?:async\s+function|function|class|def|interface|type|enum|const|let|var)\s+([A-Za-z_$][\w$]*)/)
572
+ || cleaned.match(/([A-Za-z_$][\w$]*)\s*\(/);
573
+ return m ? m[1] : null;
574
+ };
575
+
576
+ const candidates = buildSymbolCandidates(index);
577
+ const blocks = [];
578
+ for (const symbol of symbols) {
579
+ const matches = [];
580
+ for (const [file, sigs] of index.entries()) {
581
+ for (const sig of sigs) {
582
+ if (defName(sig) === symbol) matches.push(`${sig} (${file})`);
583
+ }
584
+ }
585
+ if (matches.length === 0) {
586
+ const cm = closestMatch(symbol, candidates);
587
+ const hint = cm ? ' — ' + formatSuggestion(cm) : '';
588
+ blocks.push(`### ${symbol}\n_not found in index${hint}_`);
589
+ } else {
590
+ blocks.push(`### ${symbol}\n${matches.join('\n')}`);
591
+ }
592
+ }
593
+ return blocks.join('\n\n');
594
+ } catch (err) {
595
+ return `_get_callee_signatures failed: ${err.message}_`;
596
+ }
597
+ }
598
+
599
+ // ── Layer 1: live-index write hooks ────────────────────────────────────────
600
+ // Keep the sig-cache fresh while an agent creates/modifies/deletes files, so
601
+ // new code is discoverable in the same session. buildSigIndex already merges
602
+ // the cache (_buildSigIndexFromCache), so updates are live on the next read.
603
+
604
+ function _pkgVersion(cwd) {
605
+ try { return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).version || '0.0.0'; }
606
+ catch (_) { return '0.0.0'; }
607
+ }
608
+
609
+
610
+ /** notify_file_created — extract a file's signatures and index it live. */
611
+ function notifyFileCreated(args, cwd) {
612
+ const rel = args && args.path;
613
+ if (!rel) return 'Missing required argument: path';
614
+ try {
615
+ const { extractFile } = require('../extractors/dispatch');
616
+ const { loadCache, saveCache } = require('../cache/sig-cache');
617
+ const abs = path.resolve(cwd, rel);
618
+ let content = args.content;
619
+ if (typeof content !== 'string') {
620
+ try { content = fs.readFileSync(abs, 'utf8'); } catch (_) { content = ''; }
621
+ }
622
+ const sigs = extractFile(abs, content);
623
+ const version = _pkgVersion(cwd);
624
+ const cache = loadCache(cwd, version);
625
+ if (sigs.length > 0) {
626
+ cache.set(abs, { mtime: Date.now(), sigs });
627
+ }
628
+ saveCache(cwd, version, cache);
629
+ return `Indexed ${rel}: ${sigs.length} signature(s) now live.`;
630
+ } catch (err) {
631
+ return `_notify_file_created failed: ${err.message}_`;
632
+ }
633
+ }
634
+
635
+ /** notify_symbol_added — append one signature to a file's live cache entry. */
636
+ function notifySymbolAdded(args, cwd) {
637
+ if (!args || !args.signature || !args.file) {
638
+ return 'Missing required arguments: signature, file';
639
+ }
640
+ try {
641
+ const { loadCache, saveCache } = require('../cache/sig-cache');
642
+ const abs = path.resolve(cwd, args.file);
643
+ const version = _pkgVersion(cwd);
644
+ const cache = loadCache(cwd, version);
645
+ const entry = cache.get(abs) || { mtime: Date.now(), sigs: [] };
646
+ const line = Number.isFinite(Number(args.line)) ? ` :${args.line}` : '';
647
+ const sig = String(args.signature) + line;
648
+ if (!entry.sigs.includes(sig)) entry.sigs.push(sig);
649
+ entry.mtime = Date.now();
650
+ cache.set(abs, entry);
651
+ saveCache(cwd, version, cache);
652
+ return `Added signature to ${args.file} (${entry.sigs.length} total).`;
653
+ } catch (err) {
654
+ return `_notify_symbol_added failed: ${err.message}_`;
655
+ }
656
+ }
657
+
658
+ /** notify_file_deleted — drop a file's cache-overlay entry. */
659
+ function notifyFileDeleted(args, cwd) {
660
+ const rel = args && args.path;
661
+ if (!rel) return 'Missing required argument: path';
662
+ try {
663
+ const { loadCache, saveCache } = require('../cache/sig-cache');
664
+ const abs = path.resolve(cwd, rel);
665
+ const version = _pkgVersion(cwd);
666
+ const cache = loadCache(cwd, version);
667
+ const had = cache.delete(abs);
668
+ saveCache(cwd, version, cache);
669
+ return had ? `Removed ${rel} from the live index.` : `${rel} was not in the live cache.`;
670
+ } catch (err) {
671
+ return `_notify_file_deleted failed: ${err.message}_`;
672
+ }
673
+ }
674
+
675
+ module.exports = { readContext, searchSignatures, getMap, createCheckpoint, getRouting, explainFile, listModules, queryContext, getImpact, getLines, readMemory, getCalleeSignatures, notifyFileCreated, notifySymbolAdded, notifyFileDeleted };
package/src/mcp/server.js CHANGED
@@ -14,11 +14,11 @@
14
14
 
15
15
  const readline = require('readline');
16
16
  const { TOOLS } = require('./tools');
17
- const { readContext, searchSignatures, getMap, createCheckpoint, getRouting, explainFile, listModules, queryContext, getImpact, getLines, readMemory } = require('./handlers');
17
+ const { readContext, searchSignatures, getMap, createCheckpoint, getRouting, explainFile, listModules, queryContext, getImpact, getLines, readMemory, getCalleeSignatures, notifyFileCreated, notifySymbolAdded, notifyFileDeleted } = require('./handlers');
18
18
 
19
19
  const SERVER_INFO = {
20
20
  name: 'sigmap',
21
- version: '7.2.1',
21
+ version: '7.4.0',
22
22
  description: 'SigMap MCP server — code signatures on demand',
23
23
  };
24
24
 
@@ -77,6 +77,10 @@ function dispatch(msg, cwd) {
77
77
  else if (name === 'get_impact') text = getImpact(args, cwd);
78
78
  else if (name === 'get_lines') text = getLines(args, cwd);
79
79
  else if (name === 'read_memory') text = readMemory(args, cwd);
80
+ else if (name === 'get_callee_signatures') text = getCalleeSignatures(args, cwd);
81
+ else if (name === 'sigmap_notify_file_created') text = notifyFileCreated(args, cwd);
82
+ else if (name === 'sigmap_notify_symbol_added') text = notifySymbolAdded(args, cwd);
83
+ else if (name === 'sigmap_notify_file_deleted') text = notifyFileDeleted(args, cwd);
80
84
  else {
81
85
  respondError(id, -32601, `Unknown tool: ${name}`);
82
86
  return;
package/src/mcp/tools.js CHANGED
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * MCP tool definitions for SigMap (11 tools).
4
+ * MCP tool definitions for SigMap (15 tools).
5
5
  * read_context, search_signatures, get_map, create_checkpoint, get_routing,
6
- * explain_file, list_modules, query_context, get_impact, get_lines, read_memory.
6
+ * explain_file, list_modules, query_context, get_impact, get_lines, read_memory,
7
+ * get_callee_signatures, sigmap_notify_file_created, sigmap_notify_symbol_added,
8
+ * sigmap_notify_file_deleted.
7
9
  */
8
10
 
9
11
  const TOOLS = [
@@ -215,6 +217,67 @@ const TOOLS = [
215
217
  required: [],
216
218
  },
217
219
  },
220
+ {
221
+ name: 'get_callee_signatures',
222
+ description:
223
+ 'Return the EXACT current signature(s) of named symbols (functions, classes, ' +
224
+ "methods) from the index — so an agent never guesses a callee's parameter types " +
225
+ 'from training memory. Call this before writing code that uses a symbol. ' +
226
+ 'Unknown names get a closest-match suggestion.',
227
+ inputSchema: {
228
+ type: 'object',
229
+ properties: {
230
+ symbols: {
231
+ type: 'array',
232
+ items: { type: 'string' },
233
+ description: 'Symbol names to resolve (e.g. ["validateToken", "UserService"]).',
234
+ },
235
+ },
236
+ required: ['symbols'],
237
+ },
238
+ },
239
+ {
240
+ name: 'sigmap_notify_file_created',
241
+ description:
242
+ 'Tell SigMap a file was created or modified so its signatures are indexed ' +
243
+ 'live for the rest of the session. Call this after writing a file — the new ' +
244
+ 'symbols become resolvable by search_signatures / get_callee_signatures.',
245
+ inputSchema: {
246
+ type: 'object',
247
+ properties: {
248
+ path: { type: 'string', description: 'File path relative to the project root.' },
249
+ content: { type: 'string', description: 'Optional file content; read from disk if omitted.' },
250
+ },
251
+ required: ['path'],
252
+ },
253
+ },
254
+ {
255
+ name: 'sigmap_notify_symbol_added',
256
+ description:
257
+ 'Fast path: register a single new symbol signature directly in the live ' +
258
+ 'index without re-reading the whole file.',
259
+ inputSchema: {
260
+ type: 'object',
261
+ properties: {
262
+ signature: { type: 'string', description: 'The signature line (e.g. "function check(key)").' },
263
+ file: { type: 'string', description: 'File path the symbol belongs to (relative to root).' },
264
+ line: { type: 'number', description: 'Optional 1-based line number.' },
265
+ },
266
+ required: ['signature', 'file'],
267
+ },
268
+ },
269
+ {
270
+ name: 'sigmap_notify_file_deleted',
271
+ description:
272
+ 'Tell SigMap a file was deleted so its symbols are dropped from the live index.',
273
+ inputSchema: {
274
+ type: 'object',
275
+ properties: {
276
+ path: { type: 'string', description: 'Deleted file path relative to the project root.' },
277
+ },
278
+ required: ['path'],
279
+ },
280
+ },
218
281
  ];
219
282
 
220
283
  module.exports = { TOOLS };