sigmap 7.22.0 → 7.22.1
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/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/gen-context.js +197 -184
- package/llms-full.txt +2 -2
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/src/mcp/server.js +1 -1
- package/src/verify/parsers.js +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,15 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [7.22.1] — 2026-06-18
|
|
14
|
+
|
|
15
|
+
Patch release — hardens the `verify-ai-output` file-path extractor against the dominant false-positive class.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **`verify-ai-output` no longer flags runtime/library names or placeholder filenames (#347):** `extractFilePaths` now skips well-known `X.js` product names (`node.js`, `next.js`, `vue.js`, `express.js`, `three.js`, `d3.js`, …) and illustrative placeholder basenames (`example`/`sample`/`demo`/`placeholder`, including `minimal-example.js`). Genuine repo-shaped paths (`src/foo/bar.js`, `main.js`, `index.ts`) are still extracted, so real hallucinations are unaffected. This removes the dominant Hallucination Guard false-positive class — in the §9 ablation, 22 of ~34 flags were literally "Node.js" — turning the directional grounding delta into a clean signal. The bundled `src/verify/parsers` factory was regenerated for standalone-binary parity.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
13
22
|
## [7.22.0] — 2026-06-18
|
|
14
23
|
|
|
15
24
|
Minor release — realistic §9 ablation (real-symbol corpus, exact-signature grounding, --verbose) + Gemini model fix.
|
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ Ask → Rank → Context → Validate → Judge → Learn
|
|
|
88
88
|
|
|
89
89
|
```
|
|
90
90
|
Benchmark : sigmap-v7.0-main (21 repositories, including R language)
|
|
91
|
-
Date : 2026-06-
|
|
91
|
+
Date : 2026-06-18
|
|
92
92
|
|
|
93
93
|
Hit@5 : 75.6% (baseline 13.6% — 5.6× lift)
|
|
94
94
|
Token reduction: 97.0% (across 21 repos)
|
package/gen-context.js
CHANGED
|
@@ -7931,7 +7931,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
7931
7931
|
|
|
7932
7932
|
const SERVER_INFO = {
|
|
7933
7933
|
name: 'sigmap',
|
|
7934
|
-
version: '7.22.
|
|
7934
|
+
version: '7.22.1',
|
|
7935
7935
|
description: 'SigMap MCP server — code signatures on demand',
|
|
7936
7936
|
};
|
|
7937
7937
|
|
|
@@ -12756,207 +12756,220 @@ module.exports = { checkStarNudge, readUsage, usagePath, showStarNudge, RUN_THRE
|
|
|
12756
12756
|
|
|
12757
12757
|
// ── ./src/verify/parsers ──
|
|
12758
12758
|
__factories["./src/verify/parsers"] = function(module, exports) {
|
|
12759
|
-
|
|
12759
|
+
|
|
12760
|
+
/**
|
|
12761
|
+
* Parsers for the Hallucination Guard (verify-ai-output).
|
|
12762
|
+
*
|
|
12763
|
+
* Extract the verifiable claims an AI answer makes about a codebase:
|
|
12764
|
+
* - file paths it references
|
|
12765
|
+
* - import / require statements it shows
|
|
12766
|
+
* - function / class symbols it calls
|
|
12767
|
+
* - fenced code blocks (so callers can scope checks to code vs prose)
|
|
12768
|
+
*
|
|
12769
|
+
* Everything here is deterministic and offline — pure string analysis.
|
|
12770
|
+
*/
|
|
12760
12771
|
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
*
|
|
12770
|
-
* Everything here is deterministic and offline — pure string analysis.
|
|
12771
|
-
*/
|
|
12772
|
+
// Extensions we are confident name a source/code/config file (no slash required).
|
|
12773
|
+
const KNOWN_CODE_EXT = new Set([
|
|
12774
|
+
'js', 'jsx', 'mjs', 'cjs', 'ts', 'tsx', 'py', 'pyw', 'rb', 'go', 'rs',
|
|
12775
|
+
'java', 'kt', 'swift', 'c', 'h', 'cpp', 'hpp', 'cs', 'php', 'r',
|
|
12776
|
+
'vue', 'svelte', 'css', 'scss', 'less', 'html', 'json', 'yml', 'yaml',
|
|
12777
|
+
'toml', 'xml', 'sql', 'graphql', 'gql', 'proto', 'tf', 'md', 'sh',
|
|
12778
|
+
'gd', 'gdscript',
|
|
12779
|
+
]);
|
|
12772
12780
|
|
|
12773
|
-
//
|
|
12774
|
-
const
|
|
12775
|
-
|
|
12776
|
-
|
|
12777
|
-
|
|
12778
|
-
|
|
12779
|
-
'gd', 'gdscript',
|
|
12780
|
-
]);
|
|
12781
|
+
// Well-known "X.js" runtime/library product names — never repo files.
|
|
12782
|
+
const LIBRARY_TOKENS = new Set([
|
|
12783
|
+
'node.js', 'next.js', 'nuxt.js', 'vue.js', 'react.js', 'express.js', 'koa.js',
|
|
12784
|
+
'nest.js', 'three.js', 'd3.js', 'chart.js', 'ember.js', 'backbone.js',
|
|
12785
|
+
'angular.js', 'meteor.js', 'moment.js', 'anime.js', 'p5.js', 'next.config.js',
|
|
12786
|
+
]);
|
|
12781
12787
|
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
12799
|
-
|
|
12800
|
-
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12788
|
+
// Illustrative placeholder names the model writes in prose, not repo claims:
|
|
12789
|
+
// e.g. example.js, minimal-example.js, sample.ts, demo.js, placeholder.js.
|
|
12790
|
+
const PLACEHOLDER_RE = /(?:^|[-_.])(?:example|sample|demo|placeholder)(?:[-_.]|$)/i;
|
|
12791
|
+
|
|
12792
|
+
/**
|
|
12793
|
+
* Extract fenced code blocks.
|
|
12794
|
+
* @param {string} text
|
|
12795
|
+
* @returns {{ lang: string, content: string, line: number }[]}
|
|
12796
|
+
*/
|
|
12797
|
+
function extractCodeBlocks(text) {
|
|
12798
|
+
const blocks = [];
|
|
12799
|
+
const lines = text.split('\n');
|
|
12800
|
+
let inBlock = false;
|
|
12801
|
+
let lang = '';
|
|
12802
|
+
let buf = [];
|
|
12803
|
+
let startLine = 0;
|
|
12804
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12805
|
+
const m = lines[i].match(/^```(\w*)/);
|
|
12806
|
+
if (m) {
|
|
12807
|
+
if (!inBlock) {
|
|
12808
|
+
inBlock = true;
|
|
12809
|
+
lang = m[1] || '';
|
|
12810
|
+
buf = [];
|
|
12811
|
+
startLine = i + 2; // first content line (1-based)
|
|
12812
|
+
} else {
|
|
12813
|
+
blocks.push({ lang, content: buf.join('\n'), line: startLine });
|
|
12814
|
+
inBlock = false;
|
|
12815
|
+
}
|
|
12816
|
+
continue;
|
|
12805
12817
|
}
|
|
12806
|
-
|
|
12818
|
+
if (inBlock) buf.push(lines[i]);
|
|
12807
12819
|
}
|
|
12808
|
-
|
|
12820
|
+
return blocks;
|
|
12809
12821
|
}
|
|
12810
|
-
return blocks;
|
|
12811
|
-
}
|
|
12812
12822
|
|
|
12813
|
-
/**
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
function extractFilePaths(text) {
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12823
|
+
/**
|
|
12824
|
+
* Extract file-path references (deduped, first-seen line kept).
|
|
12825
|
+
* A token counts as a path when it has a `.<letter…>` extension AND
|
|
12826
|
+
* either contains a `/` or carries a known code/config extension.
|
|
12827
|
+
* @param {string} text
|
|
12828
|
+
* @returns {{ path: string, line: number }[]}
|
|
12829
|
+
*/
|
|
12830
|
+
function extractFilePaths(text) {
|
|
12831
|
+
const lines = text.split('\n');
|
|
12832
|
+
const seen = new Map();
|
|
12833
|
+
const re = /(?:^|[\s`"'(\[<])([A-Za-z0-9_][\w./-]*\.[A-Za-z][A-Za-z0-9]*)/g;
|
|
12834
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12835
|
+
const line = lines[i];
|
|
12836
|
+
let m;
|
|
12837
|
+
re.lastIndex = 0;
|
|
12838
|
+
while ((m = re.exec(line)) !== null) {
|
|
12839
|
+
const p = m[1];
|
|
12840
|
+
if (/^https?:/i.test(p)) continue;
|
|
12841
|
+
const ext = (p.split('.').pop() || '').toLowerCase();
|
|
12842
|
+
const hasSlash = p.includes('/');
|
|
12843
|
+
if (!hasSlash && !KNOWN_CODE_EXT.has(ext)) continue;
|
|
12844
|
+
if (LIBRARY_TOKENS.has(p.toLowerCase())) continue;
|
|
12845
|
+
const base = p.split('/').pop();
|
|
12846
|
+
if (PLACEHOLDER_RE.test(base)) continue;
|
|
12847
|
+
if (!seen.has(p)) seen.set(p, i + 1);
|
|
12848
|
+
}
|
|
12835
12849
|
}
|
|
12850
|
+
return [...seen.entries()].map(([p, line]) => ({ path: p, line }));
|
|
12836
12851
|
}
|
|
12837
|
-
return [...seen.entries()].map(([p, line]) => ({ path: p, line }));
|
|
12838
|
-
}
|
|
12839
12852
|
|
|
12840
|
-
/**
|
|
12841
|
-
|
|
12842
|
-
|
|
12843
|
-
|
|
12844
|
-
|
|
12845
|
-
function extractImports(text) {
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
|
|
12849
|
-
|
|
12850
|
-
|
|
12851
|
-
|
|
12852
|
-
|
|
12853
|
-
|
|
12854
|
-
|
|
12855
|
-
|
|
12856
|
-
|
|
12857
|
-
|
|
12858
|
-
|
|
12859
|
-
|
|
12860
|
-
|
|
12861
|
-
|
|
12862
|
-
|
|
12863
|
-
|
|
12864
|
-
|
|
12865
|
-
|
|
12866
|
-
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
|
|
12879
|
-
|
|
12880
|
-
|
|
12881
|
-
|
|
12882
|
-
|
|
12883
|
-
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12853
|
+
/**
|
|
12854
|
+
* Extract import / require statements.
|
|
12855
|
+
* @param {string} text
|
|
12856
|
+
* @returns {{ module: string, kind: 'js'|'py', relative: boolean, line: number, raw: string }[]}
|
|
12857
|
+
*/
|
|
12858
|
+
function extractImports(text) {
|
|
12859
|
+
const lines = text.split('\n');
|
|
12860
|
+
const out = [];
|
|
12861
|
+
const push = (module, kind, line, raw) => {
|
|
12862
|
+
if (!module) return;
|
|
12863
|
+
out.push({ module, kind, relative: /^[./]/.test(module), line, raw: raw.trim() });
|
|
12864
|
+
};
|
|
12865
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12866
|
+
const line = lines[i];
|
|
12867
|
+
let m;
|
|
12868
|
+
// JS/TS: import ... from 'x' | export ... from 'x'
|
|
12869
|
+
if ((m = line.match(/\b(?:import|export)\b[^'"]*\bfrom\s*['"]([^'"]+)['"]/))) {
|
|
12870
|
+
push(m[1], 'js', i + 1, line);
|
|
12871
|
+
} else if ((m = line.match(/\bimport\s*['"]([^'"]+)['"]/))) {
|
|
12872
|
+
// side-effect import 'x'
|
|
12873
|
+
push(m[1], 'js', i + 1, line);
|
|
12874
|
+
}
|
|
12875
|
+
// require('x') / dynamic import('x') — may co-occur, scan separately
|
|
12876
|
+
const reqRe = /\b(?:require|import)\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
12877
|
+
let r;
|
|
12878
|
+
while ((r = reqRe.exec(line)) !== null) push(r[1], 'js', i + 1, line);
|
|
12879
|
+
|
|
12880
|
+
// TS: import X = require('mod')
|
|
12881
|
+
if ((m = line.match(/\bimport\s+[A-Za-z_$][\w$]*\s*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\)/))) {
|
|
12882
|
+
push(m[1], 'js', i + 1, line);
|
|
12883
|
+
}
|
|
12884
|
+
|
|
12885
|
+
// Python: from x import y | import x
|
|
12886
|
+
if ((m = line.match(/^\s*from\s+([.\w]+)\s+import\b/))) {
|
|
12887
|
+
push(m[1], 'py', i + 1, line);
|
|
12888
|
+
} else if ((m = line.match(/^\s*import\s+([A-Za-z_][\w.]*)/))) {
|
|
12889
|
+
push(m[1], 'py', i + 1, line);
|
|
12890
|
+
}
|
|
12891
|
+
}
|
|
12892
|
+
|
|
12893
|
+
// Multi-line JS/TS imports, e.g.
|
|
12894
|
+
// import {
|
|
12895
|
+
// A as B,
|
|
12896
|
+
// } from './mod';
|
|
12897
|
+
// The per-line pass above misses these because `from '…'` sits on a later
|
|
12898
|
+
// line. Trigger only when the opening line has no quote and no `from` yet,
|
|
12899
|
+
// then gather forward until the source string appears.
|
|
12900
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12901
|
+
const start = lines[i];
|
|
12902
|
+
if (!/^\s*(?:import|export)\b/.test(start)) continue;
|
|
12903
|
+
if (/['"]/.test(start) || /\bfrom\b/.test(start)) continue; // single-line, already handled
|
|
12904
|
+
let joined = start;
|
|
12905
|
+
for (let j = i + 1; j < Math.min(lines.length, i + 12); j++) {
|
|
12906
|
+
joined += ' ' + lines[j];
|
|
12907
|
+
const fm = joined.match(/\bfrom\s*['"]([^'"]+)['"]/);
|
|
12908
|
+
if (fm) { push(fm[1], 'js', i + 1, start.trim()); break; }
|
|
12909
|
+
if (/['"]/.test(lines[j]) && !/\bfrom\b/.test(joined)) break; // a string that isn't a source — bail
|
|
12910
|
+
}
|
|
12897
12911
|
}
|
|
12912
|
+
return out;
|
|
12898
12913
|
}
|
|
12899
|
-
return out;
|
|
12900
|
-
}
|
|
12901
12914
|
|
|
12902
|
-
/**
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
function extractNpmScripts(text) {
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
|
|
12921
|
-
|
|
12915
|
+
/**
|
|
12916
|
+
* Extract npm/pnpm/yarn script invocations (`npm run <name>`).
|
|
12917
|
+
* Only the explicit `run` form is matched, to avoid confusing package-manager
|
|
12918
|
+
* subcommands (`yarn add`, `pnpm install`) with script names.
|
|
12919
|
+
* @param {string} text
|
|
12920
|
+
* @returns {{ name: string, line: number }[]}
|
|
12921
|
+
*/
|
|
12922
|
+
function extractNpmScripts(text) {
|
|
12923
|
+
const lines = text.split('\n');
|
|
12924
|
+
const out = [];
|
|
12925
|
+
const seen = new Set();
|
|
12926
|
+
const re = /\b(?:npm|pnpm|yarn)\s+run(?:-script)?\s+([A-Za-z0-9:_-]+)/g;
|
|
12927
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12928
|
+
let m;
|
|
12929
|
+
re.lastIndex = 0;
|
|
12930
|
+
while ((m = re.exec(lines[i])) !== null) {
|
|
12931
|
+
const name = m[1];
|
|
12932
|
+
if (seen.has(name)) continue;
|
|
12933
|
+
seen.add(name);
|
|
12934
|
+
out.push({ name, line: i + 1 });
|
|
12935
|
+
}
|
|
12922
12936
|
}
|
|
12937
|
+
return out;
|
|
12923
12938
|
}
|
|
12924
|
-
return out;
|
|
12925
|
-
}
|
|
12926
12939
|
|
|
12927
|
-
/**
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
function extractSymbols(text) {
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12940
|
+
/**
|
|
12941
|
+
* Extract function/class symbol references that look like calls.
|
|
12942
|
+
* Restricted to backtick-wrapped calls (`foo(...)`) for high precision.
|
|
12943
|
+
* @param {string} text
|
|
12944
|
+
* @returns {{ name: string, line: number }[]}
|
|
12945
|
+
*/
|
|
12946
|
+
function extractSymbols(text) {
|
|
12947
|
+
const lines = text.split('\n');
|
|
12948
|
+
const out = [];
|
|
12949
|
+
const seen = new Set();
|
|
12950
|
+
const re = /`([A-Za-z_$][\w$]*)\s*\([^`]*\)`/g;
|
|
12951
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12952
|
+
let m;
|
|
12953
|
+
re.lastIndex = 0;
|
|
12954
|
+
while ((m = re.exec(lines[i])) !== null) {
|
|
12955
|
+
const name = m[1];
|
|
12956
|
+
const key = name + '@' + (i + 1);
|
|
12957
|
+
if (seen.has(key)) continue;
|
|
12958
|
+
seen.add(key);
|
|
12959
|
+
out.push({ name, line: i + 1 });
|
|
12960
|
+
}
|
|
12947
12961
|
}
|
|
12962
|
+
return out;
|
|
12948
12963
|
}
|
|
12949
|
-
return out;
|
|
12950
|
-
}
|
|
12951
|
-
|
|
12952
|
-
module.exports = {
|
|
12953
|
-
extractCodeBlocks,
|
|
12954
|
-
extractFilePaths,
|
|
12955
|
-
extractImports,
|
|
12956
|
-
extractSymbols,
|
|
12957
|
-
extractNpmScripts,
|
|
12958
|
-
};
|
|
12959
12964
|
|
|
12965
|
+
module.exports = {
|
|
12966
|
+
extractCodeBlocks,
|
|
12967
|
+
extractFilePaths,
|
|
12968
|
+
extractImports,
|
|
12969
|
+
extractSymbols,
|
|
12970
|
+
extractNpmScripts,
|
|
12971
|
+
};
|
|
12972
|
+
|
|
12960
12973
|
};
|
|
12961
12974
|
|
|
12962
12975
|
// ── ./src/verify/closest-match ──
|
|
@@ -13609,7 +13622,7 @@ function __tryGit(args, opts = {}) {
|
|
|
13609
13622
|
catch (_) { return ''; }
|
|
13610
13623
|
}
|
|
13611
13624
|
|
|
13612
|
-
const VERSION = '7.22.
|
|
13625
|
+
const VERSION = '7.22.1';
|
|
13613
13626
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
13614
13627
|
|
|
13615
13628
|
function requireSourceOrBundled(key) {
|
package/llms-full.txt
CHANGED
|
@@ -9,13 +9,13 @@ 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.22.
|
|
12
|
+
# Version: 7.22.1 | Benchmark: sigmap-v7.0-main (2026-06-18)
|
|
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
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
## Core metrics (benchmark: sigmap-v7.0-main, 2026-06-
|
|
18
|
+
## Core metrics (benchmark: sigmap-v7.0-main, 2026-06-18)
|
|
19
19
|
|
|
20
20
|
| Metric | Without SigMap | With SigMap |
|
|
21
21
|
|--------|----------------|-------------|
|
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.22.
|
|
12
|
+
# Version: 7.22.1 | Benchmark: sigmap-v7.0-main (2026-06-18)
|
|
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
|
|
|
@@ -21,7 +21,7 @@ Claude, Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
|
21
21
|
- No blast-radius awareness before editing a hub file — `--impact` shows every file a change touches.
|
|
22
22
|
- Pasted stack traces, CI logs, and JSON bloat the prompt — `squeeze` minimizes them and enriches the top frame from the symbol index.
|
|
23
23
|
|
|
24
|
-
## Core metrics (benchmark: sigmap-v7.0-main, 2026-06-
|
|
24
|
+
## Core metrics (benchmark: sigmap-v7.0-main, 2026-06-18)
|
|
25
25
|
|
|
26
26
|
- hit@5 retrieval: 75.6% vs 13.6% random baseline (5.6× lift)
|
|
27
27
|
- Token reduction: 97.0% average across benchmark repos
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "7.22.
|
|
3
|
+
"version": "7.22.1",
|
|
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": {
|
package/src/mcp/server.js
CHANGED
package/src/verify/parsers.js
CHANGED
|
@@ -21,6 +21,17 @@ const KNOWN_CODE_EXT = new Set([
|
|
|
21
21
|
'gd', 'gdscript',
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
|
+
// Well-known "X.js" runtime/library product names — never repo files.
|
|
25
|
+
const LIBRARY_TOKENS = new Set([
|
|
26
|
+
'node.js', 'next.js', 'nuxt.js', 'vue.js', 'react.js', 'express.js', 'koa.js',
|
|
27
|
+
'nest.js', 'three.js', 'd3.js', 'chart.js', 'ember.js', 'backbone.js',
|
|
28
|
+
'angular.js', 'meteor.js', 'moment.js', 'anime.js', 'p5.js', 'next.config.js',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
// Illustrative placeholder names the model writes in prose, not repo claims:
|
|
32
|
+
// e.g. example.js, minimal-example.js, sample.ts, demo.js, placeholder.js.
|
|
33
|
+
const PLACEHOLDER_RE = /(?:^|[-_.])(?:example|sample|demo|placeholder)(?:[-_.]|$)/i;
|
|
34
|
+
|
|
24
35
|
/**
|
|
25
36
|
* Extract fenced code blocks.
|
|
26
37
|
* @param {string} text
|
|
@@ -73,6 +84,9 @@ function extractFilePaths(text) {
|
|
|
73
84
|
const ext = (p.split('.').pop() || '').toLowerCase();
|
|
74
85
|
const hasSlash = p.includes('/');
|
|
75
86
|
if (!hasSlash && !KNOWN_CODE_EXT.has(ext)) continue;
|
|
87
|
+
if (LIBRARY_TOKENS.has(p.toLowerCase())) continue;
|
|
88
|
+
const base = p.split('/').pop();
|
|
89
|
+
if (PLACEHOLDER_RE.test(base)) continue;
|
|
76
90
|
if (!seen.has(p)) seen.set(p, i + 1);
|
|
77
91
|
}
|
|
78
92
|
}
|