sigmap 7.12.0 → 7.14.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/CHANGELOG.md +18 -0
- package/gen-context.js +268 -2
- package/llms-full.txt +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/src/conventions/report.js +75 -0
- package/src/create/orchestrate.js +86 -0
- package/src/mcp/server.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,24 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [7.14.0] — 2026-06-17
|
|
14
|
+
|
|
15
|
+
Minor release — `sigmap conventions --report` (grounded codegen, Layer 3 polish).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- **`sigmap conventions --report` — consistency audit + trend vs last run (#319):** the next `conventions` flag (IMPL.md §4). Reports a per-convention consistency score (file naming, export style) and a single file-count-weighted **overall consistency score**, each with a delta vs the previous run — a trackable "how consistent is our style, and is it improving?" number. New zero-dependency, bundle-safe `src/conventions/report.js` (`scoreReport`, `snapshot`, `overallScore`); the command compares against the last snapshot in `.context/conventions-history.ndjson`, prints the audit with ▲/▼ trend arrows, and appends a fresh snapshot. `--json` for machine output. The remaining `conventions` flags (`--fix`, `--update`, `--ci`) and the §9 LLM A/B benchmark are follow-ups.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [7.13.0] — 2026-06-17
|
|
23
|
+
|
|
24
|
+
Minor release — `sigmap create` (grounded codegen, Gap 2 — the pipeline capstone).
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- **`sigmap create "<task>"` — orchestrate the 4-stage grounded-creation pipeline (#316):** the capstone of the grounded-codegen work. One command sequences the four guard stages — `scaffold` → `verify-plan` → `verify-ai-output` → `review-pr` — with `1/4`…`4/4` numbering and a single pass/fail summary. Each stage runs only when its input is present (`--name` → scaffold, `--plan` → verify-plan, `--answer` → verify-ai-output, the git diff → review-pr); a stage with no input is skipped and does not fail the run. New zero-dependency, bundle-safe `src/create/orchestrate.js` (`orchestrate`) delegates to the real stage modules — no logic duplication. CLI supports `--name`, `--plan`, `--answer`, `--staged`/`--base`, and `--json`, and exits non-zero when a ran stage fails. This completes the grounded-creation loop: every root cause (1–4) is closed and all four guard stages are now sequenced by one command.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
13
31
|
## [7.12.0] — 2026-06-17
|
|
14
32
|
|
|
15
33
|
Minor release — `sigmap review-pr` (grounded codegen, Gap 2 — last guard stage).
|
package/gen-context.js
CHANGED
|
@@ -28,6 +28,175 @@ function __require(key) {
|
|
|
28
28
|
// ── ./src/plan/verify-plan ──
|
|
29
29
|
// ── ./src/cache/freshen ──
|
|
30
30
|
// ── ./src/review/review-pr ──
|
|
31
|
+
// ── ./src/create/orchestrate ──
|
|
32
|
+
// ── ./src/conventions/report ──
|
|
33
|
+
__factories["./src/conventions/report"] = function(module, exports) {
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Convention audit + trend (IMPL.md §4 — `conventions --report`).
|
|
37
|
+
*
|
|
38
|
+
* Turns an `extractConventions` result into an audit: a consistency score per
|
|
39
|
+
* convention plus a single file-count-weighted overall score, each with a delta
|
|
40
|
+
* vs the previous run (the trend). Pure, zero-dependency, bundle-safe.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
const NAMES = { fileNaming: 'file naming', exportStyle: 'export style' };
|
|
44
|
+
|
|
45
|
+
/** File-count-weighted mean of the scored conventions' dominant shares (0–1). */
|
|
46
|
+
function overallScore(result) {
|
|
47
|
+
let num = 0;
|
|
48
|
+
let den = 0;
|
|
49
|
+
for (const key of ['fileNaming', 'exportStyle']) {
|
|
50
|
+
const c = result && result[key];
|
|
51
|
+
if (c && c.total > 0) { num += c.dominantPct * c.total; den += c.total; }
|
|
52
|
+
}
|
|
53
|
+
return den > 0 ? num / den : 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build a consistency report with trend vs a prior snapshot.
|
|
58
|
+
* @param {object} result an `extractConventions` result
|
|
59
|
+
* @param {object|null} [prior] a previous snapshot (this module's `snapshot` shape)
|
|
60
|
+
* @returns {{ conventions: object[], testFramework: string|null,
|
|
61
|
+
* score: number, prevScore: number|null, scoreDelta: number|null }}
|
|
62
|
+
*/
|
|
63
|
+
function scoreReport(result, prior) {
|
|
64
|
+
const conventions = [];
|
|
65
|
+
for (const key of ['fileNaming', 'exportStyle']) {
|
|
66
|
+
const c = (result && result[key]) || { dominant: null, dominantPct: 0, total: 0, tier: 'unknown' };
|
|
67
|
+
const priorPct = prior && prior[key] && typeof prior[key].dominantPct === 'number' ? prior[key].dominantPct : null;
|
|
68
|
+
conventions.push({
|
|
69
|
+
key,
|
|
70
|
+
name: NAMES[key] || key,
|
|
71
|
+
dominant: c.dominant,
|
|
72
|
+
dominantPct: c.dominantPct,
|
|
73
|
+
tier: c.tier,
|
|
74
|
+
total: c.total,
|
|
75
|
+
delta: priorPct == null ? null : c.dominantPct - priorPct,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const score = overallScore(result);
|
|
79
|
+
const prevScore = prior && typeof prior.score === 'number' ? prior.score : null;
|
|
80
|
+
return {
|
|
81
|
+
conventions,
|
|
82
|
+
testFramework: (result && result.testFramework) || null,
|
|
83
|
+
score,
|
|
84
|
+
prevScore,
|
|
85
|
+
scoreDelta: prevScore == null ? null : score - prevScore,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A compact, persistable snapshot of a run (one line in the history log).
|
|
91
|
+
* @param {object} result an `extractConventions` result
|
|
92
|
+
* @param {string} [ts] ISO timestamp (caller supplies — keeps this pure)
|
|
93
|
+
*/
|
|
94
|
+
function snapshot(result, ts) {
|
|
95
|
+
const pick = (c) => (c && c.total > 0
|
|
96
|
+
? { dominant: c.dominant, dominantPct: c.dominantPct, tier: c.tier, total: c.total }
|
|
97
|
+
: { dominant: null, dominantPct: 0, tier: 'unknown', total: 0 });
|
|
98
|
+
return {
|
|
99
|
+
ts: ts || null,
|
|
100
|
+
fileNaming: pick(result && result.fileNaming),
|
|
101
|
+
exportStyle: pick(result && result.exportStyle),
|
|
102
|
+
testFramework: (result && result.testFramework) || null,
|
|
103
|
+
score: overallScore(result),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = { scoreReport, snapshot, overallScore };
|
|
108
|
+
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
__factories["./src/create/orchestrate"] = function(module, exports) {
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* create orchestrator (IMPL.md §6.2 — the capstone of the grounded-creation loop).
|
|
115
|
+
*
|
|
116
|
+
* Sequences the four guard stages — scaffold → verify-plan → verify-ai-output →
|
|
117
|
+
* review-pr — in one pass with `n/4` numbering and a single pass/fail summary.
|
|
118
|
+
* The agent does the LLM writing between stages; `create` runs the deterministic
|
|
119
|
+
* guards it owns. A stage runs only when its input is present (else it is
|
|
120
|
+
* skipped, which does not fail the run). Zero-dependency, bundle-safe; delegates
|
|
121
|
+
* to the real stage modules.
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
const { proposeScaffold } = __require('./src/scaffold/propose');
|
|
125
|
+
const { verifyPlan } = __require('./src/plan/verify-plan');
|
|
126
|
+
const { verify } = __require('./src/verify/hallucination-guard');
|
|
127
|
+
const { reviewPr } = __require('./src/review/review-pr');
|
|
128
|
+
|
|
129
|
+
const TOTAL = 4;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Run the create pipeline over whatever inputs are available.
|
|
133
|
+
* @param {object} ctx
|
|
134
|
+
* @param {string} [ctx.task] free-text task label (echoed back)
|
|
135
|
+
* @param {string} [ctx.name] module name → enables the scaffold stage
|
|
136
|
+
* @param {object} [ctx.conventions] an `extractConventions` result (for scaffold)
|
|
137
|
+
* @param {object} [ctx.scaffoldOpts] options forwarded to `proposeScaffold`
|
|
138
|
+
* @param {string} [ctx.plan] plan markdown → enables verify-plan
|
|
139
|
+
* @param {string} [ctx.answer] AI answer markdown → enables verify-ai-output
|
|
140
|
+
* @param {Array<{path:string,status:string}>} [ctx.changedFiles] → enables review-pr
|
|
141
|
+
* @param {string} cwd repo root
|
|
142
|
+
* @returns {{ task: string|null, steps: object[], summary: object }}
|
|
143
|
+
*/
|
|
144
|
+
function orchestrate(ctx = {}, cwd) {
|
|
145
|
+
const steps = [];
|
|
146
|
+
|
|
147
|
+
// 1/4 — scaffold (needs a name + conventions)
|
|
148
|
+
if (ctx.name && ctx.conventions) {
|
|
149
|
+
const d = proposeScaffold(ctx.name, ctx.conventions, ctx.scaffoldOpts || {});
|
|
150
|
+
steps.push({ n: 1, total: TOTAL, name: 'scaffold', ran: true, ok: !!d.ok, skipped: false, detail: d });
|
|
151
|
+
} else {
|
|
152
|
+
steps.push({ n: 1, total: TOTAL, name: 'scaffold', ran: false, ok: null, skipped: true, reason: 'no --name' });
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 2/4 — verify-plan (needs a plan)
|
|
156
|
+
if (ctx.plan != null && String(ctx.plan).trim() !== '') {
|
|
157
|
+
const r = verifyPlan(ctx.plan, cwd);
|
|
158
|
+
steps.push({ n: 2, total: TOTAL, name: 'verify-plan', ran: true, ok: !!r.summary.ok, skipped: false, detail: r });
|
|
159
|
+
} else {
|
|
160
|
+
steps.push({ n: 2, total: TOTAL, name: 'verify-plan', ran: false, ok: null, skipped: true, reason: 'no --plan' });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 3/4 — verify-ai-output (needs an answer)
|
|
164
|
+
if (ctx.answer != null && String(ctx.answer).trim() !== '') {
|
|
165
|
+
const r = verify(ctx.answer, cwd);
|
|
166
|
+
steps.push({ n: 3, total: TOTAL, name: 'verify-ai-output', ran: true, ok: r.summary.total === 0, skipped: false, detail: r });
|
|
167
|
+
} else {
|
|
168
|
+
steps.push({ n: 3, total: TOTAL, name: 'verify-ai-output', ran: false, ok: null, skipped: true, reason: 'no --answer' });
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 4/4 — review-pr (needs changed files)
|
|
172
|
+
if (Array.isArray(ctx.changedFiles) && ctx.changedFiles.length) {
|
|
173
|
+
const r = reviewPr(ctx.changedFiles, cwd);
|
|
174
|
+
steps.push({ n: 4, total: TOTAL, name: 'review-pr', ran: true, ok: !!r.summary.ok, skipped: false, detail: r });
|
|
175
|
+
} else {
|
|
176
|
+
steps.push({ n: 4, total: TOTAL, name: 'review-pr', ran: false, ok: null, skipped: true, reason: 'no changes' });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const ran = steps.filter((s) => s.ran);
|
|
180
|
+
const passed = ran.filter((s) => s.ok).length;
|
|
181
|
+
const failed = ran.length - passed;
|
|
182
|
+
return {
|
|
183
|
+
task: ctx.task || null,
|
|
184
|
+
steps,
|
|
185
|
+
summary: {
|
|
186
|
+
total: TOTAL,
|
|
187
|
+
ran: ran.length,
|
|
188
|
+
skipped: steps.length - ran.length,
|
|
189
|
+
passed,
|
|
190
|
+
failed,
|
|
191
|
+
ok: failed === 0,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = { orchestrate, TOTAL };
|
|
197
|
+
|
|
198
|
+
};
|
|
199
|
+
|
|
31
200
|
__factories["./src/review/review-pr"] = function(module, exports) {
|
|
32
201
|
|
|
33
202
|
/**
|
|
@@ -7369,7 +7538,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
7369
7538
|
|
|
7370
7539
|
const SERVER_INFO = {
|
|
7371
7540
|
name: 'sigmap',
|
|
7372
|
-
version: '7.
|
|
7541
|
+
version: '7.14.0',
|
|
7373
7542
|
description: 'SigMap MCP server — code signatures on demand',
|
|
7374
7543
|
};
|
|
7375
7544
|
|
|
@@ -13047,7 +13216,7 @@ function __tryGit(args, opts = {}) {
|
|
|
13047
13216
|
catch (_) { return ''; }
|
|
13048
13217
|
}
|
|
13049
13218
|
|
|
13050
|
-
const VERSION = '7.
|
|
13219
|
+
const VERSION = '7.14.0';
|
|
13051
13220
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
13052
13221
|
|
|
13053
13222
|
function requireSourceOrBundled(key) {
|
|
@@ -16242,6 +16411,38 @@ function main() {
|
|
|
16242
16411
|
process.exit(0);
|
|
16243
16412
|
}
|
|
16244
16413
|
|
|
16414
|
+
// `--report`: consistency audit + score + trend vs the last run.
|
|
16415
|
+
if (args.includes('--report')) {
|
|
16416
|
+
const { scoreReport, snapshot } = requireSourceOrBundled('./src/conventions/report');
|
|
16417
|
+
const histPath = path.join(cwd, '.context', 'conventions-history.ndjson');
|
|
16418
|
+
let prior = null;
|
|
16419
|
+
try {
|
|
16420
|
+
const lines = fs.readFileSync(histPath, 'utf8').split('\n').filter(Boolean);
|
|
16421
|
+
if (lines.length) prior = JSON.parse(lines[lines.length - 1]);
|
|
16422
|
+
} catch (_) {}
|
|
16423
|
+
const report = scoreReport(result, prior);
|
|
16424
|
+
// Append the new snapshot to the history log.
|
|
16425
|
+
try {
|
|
16426
|
+
fs.mkdirSync(path.join(cwd, '.context'), { recursive: true });
|
|
16427
|
+
fs.appendFileSync(histPath, JSON.stringify(snapshot(result, new Date().toISOString())) + '\n');
|
|
16428
|
+
} catch (_) {}
|
|
16429
|
+
|
|
16430
|
+
if (jsonOut) {
|
|
16431
|
+
process.stdout.write(JSON.stringify(report) + '\n');
|
|
16432
|
+
process.exit(0);
|
|
16433
|
+
}
|
|
16434
|
+
const pctR = (n) => `${(n * 100).toFixed(0)}%`;
|
|
16435
|
+
const arrow = (d) => (d == null ? '' : d > 0.0005 ? ` ▲${(d * 100).toFixed(0)}pp` : d < -0.0005 ? ` ▼${(Math.abs(d) * 100).toFixed(0)}pp` : ' =');
|
|
16436
|
+
console.log('[sigmap] conventions --report (TS/JS/Python)');
|
|
16437
|
+
console.log(` overall consistency: ${pctR(report.score)}${arrow(report.scoreDelta)}${report.prevScore == null ? ' (first run)' : ''}`);
|
|
16438
|
+
for (const c of report.conventions) {
|
|
16439
|
+
if (c.total === 0) { console.log(` ${c.name.padEnd(14)} n/a (no samples)`); continue; }
|
|
16440
|
+
console.log(` ${c.name.padEnd(14)} ${c.dominant} ${pctR(c.dominantPct)} [${c.tier}]${arrow(c.delta)}`);
|
|
16441
|
+
}
|
|
16442
|
+
console.log(` ${'test framework'.padEnd(14)} ${report.testFramework || 'none detected'}`);
|
|
16443
|
+
process.exit(0);
|
|
16444
|
+
}
|
|
16445
|
+
|
|
16245
16446
|
// `--conflicts`: surface why a convention is mixed (breakdown + rename suggestions).
|
|
16246
16447
|
if (args.includes('--conflicts')) {
|
|
16247
16448
|
const { analyzeConflicts } = requireSourceOrBundled('./src/conventions/conflicts');
|
|
@@ -16553,6 +16754,71 @@ function main() {
|
|
|
16553
16754
|
process.exit(1);
|
|
16554
16755
|
}
|
|
16555
16756
|
|
|
16757
|
+
// Gap 2 (capstone): `sigmap create "<task>"` — orchestrate the 4 guard stages
|
|
16758
|
+
// (scaffold → verify-plan → verify-ai-output → review-pr) with n/4 numbering.
|
|
16759
|
+
if (args[0] === 'create') {
|
|
16760
|
+
const jsonOut = args.includes('--json');
|
|
16761
|
+
const task = args[1] && !args[1].startsWith('--') ? args[1] : null;
|
|
16762
|
+
const flagVal = (flag) => { const i = args.indexOf(flag); return i !== -1 && args[i + 1] && !args[i + 1].startsWith('--') ? args[i + 1] : null; };
|
|
16763
|
+
const nameArg = flagVal('--name');
|
|
16764
|
+
const planFile = flagVal('--plan');
|
|
16765
|
+
const answerFile = flagVal('--answer');
|
|
16766
|
+
const staged = args.includes('--staged');
|
|
16767
|
+
const baseArg = flagVal('--base');
|
|
16768
|
+
|
|
16769
|
+
const ctx = { task };
|
|
16770
|
+
|
|
16771
|
+
if (nameArg) {
|
|
16772
|
+
ctx.name = nameArg;
|
|
16773
|
+
try {
|
|
16774
|
+
const { extractConventions } = requireSourceOrBundled('./src/conventions/extract');
|
|
16775
|
+
ctx.conventions = extractConventions(cwd, buildFileList(cwd, config));
|
|
16776
|
+
} catch (_) {}
|
|
16777
|
+
}
|
|
16778
|
+
for (const [flag, file, key] of [['--plan', planFile, 'plan'], ['--answer', answerFile, 'answer']]) {
|
|
16779
|
+
if (!file) continue;
|
|
16780
|
+
try { ctx[key] = fs.readFileSync(path.resolve(cwd, file), 'utf8'); }
|
|
16781
|
+
catch (e) { console.error(`[sigmap] cannot read ${flag} file: ${e.message}`); process.exit(1); }
|
|
16782
|
+
}
|
|
16783
|
+
|
|
16784
|
+
// review-pr inputs: changed files from git (same collection as review-pr).
|
|
16785
|
+
let nameStatus = '';
|
|
16786
|
+
if (staged) {
|
|
16787
|
+
nameStatus = __tryGit(['diff', '--cached', '--name-status'], { cwd });
|
|
16788
|
+
} else {
|
|
16789
|
+
let base = baseArg;
|
|
16790
|
+
if (!base) {
|
|
16791
|
+
for (const ref of ['main', 'develop']) {
|
|
16792
|
+
if (__tryGit(['rev-parse', '--verify', '--quiet', ref], { cwd })) { base = ref; break; }
|
|
16793
|
+
}
|
|
16794
|
+
}
|
|
16795
|
+
const mb = base ? (__tryGit(['merge-base', 'HEAD', base], { cwd }) || base) : 'HEAD~1';
|
|
16796
|
+
nameStatus = __tryGit(['diff', '--name-status', `${mb}..HEAD`], { cwd });
|
|
16797
|
+
}
|
|
16798
|
+
ctx.changedFiles = nameStatus.split('\n').filter(Boolean).map((line) => {
|
|
16799
|
+
const parts = line.split('\t');
|
|
16800
|
+
return { path: parts[parts.length - 1], status: parts[0][0] };
|
|
16801
|
+
});
|
|
16802
|
+
|
|
16803
|
+
const { orchestrate } = requireSourceOrBundled('./src/create/orchestrate');
|
|
16804
|
+
const result = orchestrate(ctx, cwd);
|
|
16805
|
+
|
|
16806
|
+
if (jsonOut) {
|
|
16807
|
+
process.stdout.write(JSON.stringify(result) + '\n');
|
|
16808
|
+
process.exit(result.summary.ok ? 0 : 1);
|
|
16809
|
+
}
|
|
16810
|
+
|
|
16811
|
+
console.log(`[sigmap] create${result.task ? ` "${result.task}"` : ''} — grounded-creation pipeline`);
|
|
16812
|
+
for (const st of result.steps) {
|
|
16813
|
+
const mark = st.skipped ? '–' : (st.ok ? '✓' : '✗');
|
|
16814
|
+
const status = st.skipped ? `skipped (${st.reason})` : (st.ok ? 'ok' : 'FAILED');
|
|
16815
|
+
console.log(` ${st.n}/${st.total} ${mark} ${st.name.padEnd(16)} ${status}`);
|
|
16816
|
+
}
|
|
16817
|
+
const su = result.summary;
|
|
16818
|
+
console.log(`\n ${su.ran}/${su.total} ran · ${su.passed} passed · ${su.failed} failed · ${su.skipped} skipped`);
|
|
16819
|
+
process.exit(su.ok ? 0 : 1);
|
|
16820
|
+
}
|
|
16821
|
+
|
|
16556
16822
|
// Feature 1: `sigmap explain <file>` — why a file is included or excluded
|
|
16557
16823
|
if (args[0] === 'explain' || args.includes('--explain')) {
|
|
16558
16824
|
const target = args[0] === 'explain'
|
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.
|
|
12
|
+
# Version: 7.14.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
|
|
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.
|
|
12
|
+
# Version: 7.14.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
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.14.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": {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convention audit + trend (IMPL.md §4 — `conventions --report`).
|
|
5
|
+
*
|
|
6
|
+
* Turns an `extractConventions` result into an audit: a consistency score per
|
|
7
|
+
* convention plus a single file-count-weighted overall score, each with a delta
|
|
8
|
+
* vs the previous run (the trend). Pure, zero-dependency, bundle-safe.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const NAMES = { fileNaming: 'file naming', exportStyle: 'export style' };
|
|
12
|
+
|
|
13
|
+
/** File-count-weighted mean of the scored conventions' dominant shares (0–1). */
|
|
14
|
+
function overallScore(result) {
|
|
15
|
+
let num = 0;
|
|
16
|
+
let den = 0;
|
|
17
|
+
for (const key of ['fileNaming', 'exportStyle']) {
|
|
18
|
+
const c = result && result[key];
|
|
19
|
+
if (c && c.total > 0) { num += c.dominantPct * c.total; den += c.total; }
|
|
20
|
+
}
|
|
21
|
+
return den > 0 ? num / den : 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Build a consistency report with trend vs a prior snapshot.
|
|
26
|
+
* @param {object} result an `extractConventions` result
|
|
27
|
+
* @param {object|null} [prior] a previous snapshot (this module's `snapshot` shape)
|
|
28
|
+
* @returns {{ conventions: object[], testFramework: string|null,
|
|
29
|
+
* score: number, prevScore: number|null, scoreDelta: number|null }}
|
|
30
|
+
*/
|
|
31
|
+
function scoreReport(result, prior) {
|
|
32
|
+
const conventions = [];
|
|
33
|
+
for (const key of ['fileNaming', 'exportStyle']) {
|
|
34
|
+
const c = (result && result[key]) || { dominant: null, dominantPct: 0, total: 0, tier: 'unknown' };
|
|
35
|
+
const priorPct = prior && prior[key] && typeof prior[key].dominantPct === 'number' ? prior[key].dominantPct : null;
|
|
36
|
+
conventions.push({
|
|
37
|
+
key,
|
|
38
|
+
name: NAMES[key] || key,
|
|
39
|
+
dominant: c.dominant,
|
|
40
|
+
dominantPct: c.dominantPct,
|
|
41
|
+
tier: c.tier,
|
|
42
|
+
total: c.total,
|
|
43
|
+
delta: priorPct == null ? null : c.dominantPct - priorPct,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const score = overallScore(result);
|
|
47
|
+
const prevScore = prior && typeof prior.score === 'number' ? prior.score : null;
|
|
48
|
+
return {
|
|
49
|
+
conventions,
|
|
50
|
+
testFramework: (result && result.testFramework) || null,
|
|
51
|
+
score,
|
|
52
|
+
prevScore,
|
|
53
|
+
scoreDelta: prevScore == null ? null : score - prevScore,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A compact, persistable snapshot of a run (one line in the history log).
|
|
59
|
+
* @param {object} result an `extractConventions` result
|
|
60
|
+
* @param {string} [ts] ISO timestamp (caller supplies — keeps this pure)
|
|
61
|
+
*/
|
|
62
|
+
function snapshot(result, ts) {
|
|
63
|
+
const pick = (c) => (c && c.total > 0
|
|
64
|
+
? { dominant: c.dominant, dominantPct: c.dominantPct, tier: c.tier, total: c.total }
|
|
65
|
+
: { dominant: null, dominantPct: 0, tier: 'unknown', total: 0 });
|
|
66
|
+
return {
|
|
67
|
+
ts: ts || null,
|
|
68
|
+
fileNaming: pick(result && result.fileNaming),
|
|
69
|
+
exportStyle: pick(result && result.exportStyle),
|
|
70
|
+
testFramework: (result && result.testFramework) || null,
|
|
71
|
+
score: overallScore(result),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { scoreReport, snapshot, overallScore };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create orchestrator (IMPL.md §6.2 — the capstone of the grounded-creation loop).
|
|
5
|
+
*
|
|
6
|
+
* Sequences the four guard stages — scaffold → verify-plan → verify-ai-output →
|
|
7
|
+
* review-pr — in one pass with `n/4` numbering and a single pass/fail summary.
|
|
8
|
+
* The agent does the LLM writing between stages; `create` runs the deterministic
|
|
9
|
+
* guards it owns. A stage runs only when its input is present (else it is
|
|
10
|
+
* skipped, which does not fail the run). Zero-dependency, bundle-safe; delegates
|
|
11
|
+
* to the real stage modules.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { proposeScaffold } = require('../scaffold/propose');
|
|
15
|
+
const { verifyPlan } = require('../plan/verify-plan');
|
|
16
|
+
const { verify } = require('../verify/hallucination-guard');
|
|
17
|
+
const { reviewPr } = require('../review/review-pr');
|
|
18
|
+
|
|
19
|
+
const TOTAL = 4;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Run the create pipeline over whatever inputs are available.
|
|
23
|
+
* @param {object} ctx
|
|
24
|
+
* @param {string} [ctx.task] free-text task label (echoed back)
|
|
25
|
+
* @param {string} [ctx.name] module name → enables the scaffold stage
|
|
26
|
+
* @param {object} [ctx.conventions] an `extractConventions` result (for scaffold)
|
|
27
|
+
* @param {object} [ctx.scaffoldOpts] options forwarded to `proposeScaffold`
|
|
28
|
+
* @param {string} [ctx.plan] plan markdown → enables verify-plan
|
|
29
|
+
* @param {string} [ctx.answer] AI answer markdown → enables verify-ai-output
|
|
30
|
+
* @param {Array<{path:string,status:string}>} [ctx.changedFiles] → enables review-pr
|
|
31
|
+
* @param {string} cwd repo root
|
|
32
|
+
* @returns {{ task: string|null, steps: object[], summary: object }}
|
|
33
|
+
*/
|
|
34
|
+
function orchestrate(ctx = {}, cwd) {
|
|
35
|
+
const steps = [];
|
|
36
|
+
|
|
37
|
+
// 1/4 — scaffold (needs a name + conventions)
|
|
38
|
+
if (ctx.name && ctx.conventions) {
|
|
39
|
+
const d = proposeScaffold(ctx.name, ctx.conventions, ctx.scaffoldOpts || {});
|
|
40
|
+
steps.push({ n: 1, total: TOTAL, name: 'scaffold', ran: true, ok: !!d.ok, skipped: false, detail: d });
|
|
41
|
+
} else {
|
|
42
|
+
steps.push({ n: 1, total: TOTAL, name: 'scaffold', ran: false, ok: null, skipped: true, reason: 'no --name' });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 2/4 — verify-plan (needs a plan)
|
|
46
|
+
if (ctx.plan != null && String(ctx.plan).trim() !== '') {
|
|
47
|
+
const r = verifyPlan(ctx.plan, cwd);
|
|
48
|
+
steps.push({ n: 2, total: TOTAL, name: 'verify-plan', ran: true, ok: !!r.summary.ok, skipped: false, detail: r });
|
|
49
|
+
} else {
|
|
50
|
+
steps.push({ n: 2, total: TOTAL, name: 'verify-plan', ran: false, ok: null, skipped: true, reason: 'no --plan' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 3/4 — verify-ai-output (needs an answer)
|
|
54
|
+
if (ctx.answer != null && String(ctx.answer).trim() !== '') {
|
|
55
|
+
const r = verify(ctx.answer, cwd);
|
|
56
|
+
steps.push({ n: 3, total: TOTAL, name: 'verify-ai-output', ran: true, ok: r.summary.total === 0, skipped: false, detail: r });
|
|
57
|
+
} else {
|
|
58
|
+
steps.push({ n: 3, total: TOTAL, name: 'verify-ai-output', ran: false, ok: null, skipped: true, reason: 'no --answer' });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 4/4 — review-pr (needs changed files)
|
|
62
|
+
if (Array.isArray(ctx.changedFiles) && ctx.changedFiles.length) {
|
|
63
|
+
const r = reviewPr(ctx.changedFiles, cwd);
|
|
64
|
+
steps.push({ n: 4, total: TOTAL, name: 'review-pr', ran: true, ok: !!r.summary.ok, skipped: false, detail: r });
|
|
65
|
+
} else {
|
|
66
|
+
steps.push({ n: 4, total: TOTAL, name: 'review-pr', ran: false, ok: null, skipped: true, reason: 'no changes' });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const ran = steps.filter((s) => s.ran);
|
|
70
|
+
const passed = ran.filter((s) => s.ok).length;
|
|
71
|
+
const failed = ran.length - passed;
|
|
72
|
+
return {
|
|
73
|
+
task: ctx.task || null,
|
|
74
|
+
steps,
|
|
75
|
+
summary: {
|
|
76
|
+
total: TOTAL,
|
|
77
|
+
ran: ran.length,
|
|
78
|
+
skipped: steps.length - ran.length,
|
|
79
|
+
passed,
|
|
80
|
+
failed,
|
|
81
|
+
ok: failed === 0,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = { orchestrate, TOTAL };
|
package/src/mcp/server.js
CHANGED