sigmap 4.2.0 → 4.3.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 CHANGED
@@ -10,6 +10,20 @@ Format: [Semantic Versioning](https://semver.org/)
10
10
 
11
11
  ---
12
12
 
13
+ ## [4.3.0] — 2026-04-16
14
+
15
+ ### Added
16
+
17
+ - **`sigmap validate`** — validates config (srcDirs exist, exclude patterns, maxTokens range), computes coverage as sig-index size / total source files, warns when coverage < 70%, exits 1 on hard errors. Optional `--query "<q>"` checks that PascalCase/camelCase symbols in the query appear in top-5 ranked context. Supports `--json`.
18
+ - **`sigmap --ci [--min-coverage N] [--json]`** — GitHub Actions exit gate: exits 0 when coverage ≥ threshold (default 80%), exits 1 otherwise. Uses sig-index vs source file count for a budget-aware coverage metric. Ready for `npx sigmap --ci` in CI workflows.
19
+ - **`extractQuerySymbols(query)`** — internal helper that extracts PascalCase and camelCase identifiers from a query string for symbol-level coverage checks in `sigmap validate`.
20
+
21
+ ### Changed
22
+
23
+ - **`sigmap ask`** — now emits a stderr warning when coverage < 70%, pointing users to `sigmap validate` for diagnosis.
24
+
25
+ ---
26
+
13
27
  ## [4.2.0] — 2026-04-16
14
28
 
15
29
  ### Added
package/gen-context.js CHANGED
@@ -4654,7 +4654,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
4654
4654
 
4655
4655
  const SERVER_INFO = {
4656
4656
  name: 'sigmap',
4657
- version: '4.2.0',
4657
+ version: '4.3.0',
4658
4658
  description: 'SigMap MCP server — code signatures on demand',
4659
4659
  };
4660
4660
 
@@ -6262,7 +6262,7 @@ const path = require('path');
6262
6262
  const os = require('os');
6263
6263
  const { execSync } = require('child_process');
6264
6264
 
6265
- const VERSION = '4.2.0';
6265
+ const VERSION = '4.3.0';
6266
6266
  const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
6267
6267
 
6268
6268
  function requireSourceOrBundled(key) {
@@ -8004,6 +8004,10 @@ function getIntentWeights(intent) {
8004
8004
  return base;
8005
8005
  }
8006
8006
 
8007
+ function extractQuerySymbols(query) {
8008
+ return (query.match(/\b[A-Z][a-zA-Z]+|[a-z]+(?:[A-Z][a-z]+)+\b/g) || []);
8009
+ }
8010
+
8007
8011
  function main() {
8008
8012
  const args = process.argv.slice(2);
8009
8013
 
@@ -8132,6 +8136,9 @@ function main() {
8132
8136
  riskLevel, contextPath: path.relative(cwd, outPath),
8133
8137
  }) + '\n');
8134
8138
  } else {
8139
+ if (coveragePct < 70) {
8140
+ process.stderr.write(`[sigmap] ⚠ coverage ${coveragePct}% — consider running: sigmap validate\n`);
8141
+ }
8135
8142
  const bar = '─'.repeat(44);
8136
8143
  console.log([
8137
8144
  bar,
@@ -8247,6 +8254,65 @@ function main() {
8247
8254
  process.exit(0);
8248
8255
  }
8249
8256
 
8257
+ // v4.3: `sigmap validate` — config + coverage + optional query symbol check
8258
+ if (args[0] === 'validate') {
8259
+ const issues = [];
8260
+ const warnings = [];
8261
+
8262
+ // Config checks
8263
+ for (const d of (config.srcDirs || [])) {
8264
+ if (!fs.existsSync(path.join(cwd, d)))
8265
+ issues.push(`srcDir '${d}' does not exist`);
8266
+ }
8267
+ if ((config.exclude || []).some((p) => p === 'src/**'))
8268
+ issues.push(`exclude pattern 'src/**' will exclude all source files`);
8269
+ if ((config.maxTokens || 0) < 1000)
8270
+ warnings.push(`maxTokens ${config.maxTokens} is very low — consider ≥ 4000`);
8271
+ if ((config.maxTokens || 0) > 50000)
8272
+ warnings.push(`maxTokens ${config.maxTokens} is very high — may exceed LLM context windows`);
8273
+
8274
+ // Coverage check: files actually in context vs total source files
8275
+ const { buildSigIndex: valBuildSigIndex } = requireSourceOrBundled('./src/retrieval/ranker');
8276
+ const valSigIndex = valBuildSigIndex(cwd);
8277
+ const valTotal = buildFileList(cwd, config).length;
8278
+ const coveragePct = valTotal > 0 ? Math.round((valSigIndex.size / valTotal) * 100) : 0;
8279
+ if (coveragePct < 70)
8280
+ warnings.push(`coverage ${coveragePct}% is below recommended 70% — increase maxTokens or expand srcDirs`);
8281
+
8282
+ // Optional query symbol check
8283
+ const valQueryIdx = args.indexOf('--query');
8284
+ if (valQueryIdx !== -1) {
8285
+ const q = (args[valQueryIdx + 1] || '').trim();
8286
+ if (q && !q.startsWith('--')) {
8287
+ try {
8288
+ const { rank, buildSigIndex } = requireSourceOrBundled('./src/retrieval/ranker');
8289
+ const ranked = rank(q, buildSigIndex(cwd), { topK: 5 });
8290
+ const symbols = extractQuerySymbols(q);
8291
+ const missing = symbols.filter((sym) =>
8292
+ !ranked.some((r) => r.sigs && r.sigs.some((s) => s.toLowerCase().includes(sym.toLowerCase())))
8293
+ );
8294
+ if (missing.length > 0)
8295
+ warnings.push(`query "${q}" references symbols not in top-5 context: ${missing.join(', ')}`);
8296
+ else if (symbols.length > 0)
8297
+ console.log(`[sigmap] ✓ query coverage OK — all ${symbols.length} symbols found`);
8298
+ } catch (_) {}
8299
+ }
8300
+ }
8301
+
8302
+ if (args.includes('--json')) {
8303
+ process.stdout.write(JSON.stringify({ valid: issues.length === 0, issues, warnings, coverage: coveragePct }) + '\n');
8304
+ } else {
8305
+ for (const w of warnings) console.warn(`[sigmap] ⚠ ${w}`);
8306
+ if (issues.length === 0) {
8307
+ console.log(`[sigmap] ✓ config valid coverage: ${coveragePct}%`);
8308
+ } else {
8309
+ for (const iss of issues) console.error(`[sigmap] ✗ ${iss}`);
8310
+ process.exit(1);
8311
+ }
8312
+ }
8313
+ process.exit(0);
8314
+ }
8315
+
8250
8316
  // Feature 6: `sigmap sync` — write all outputs + llms.txt + print compact diff
8251
8317
  if (args[0] === 'sync') {
8252
8318
  try {
@@ -8912,6 +8978,30 @@ function main() {
8912
8978
  process.exit(0);
8913
8979
  }
8914
8980
 
8981
+ // v4.3: `--ci [--min-coverage N] [--json]` — GitHub Actions exit gate
8982
+ if (args.includes('--ci')) {
8983
+ const minCovIdx = args.indexOf('--min-coverage');
8984
+ const minCoverage = minCovIdx !== -1 ? Math.max(0, Math.min(100, parseInt(args[minCovIdx + 1], 10) || 80)) : 80;
8985
+
8986
+ // Coverage = files actually in context / total source files
8987
+ const { buildSigIndex: ciBuildSigIndex } = requireSourceOrBundled('./src/retrieval/ranker');
8988
+ const ciSigIndex = ciBuildSigIndex(cwd);
8989
+ const ciTotal = buildFileList(cwd, config).length;
8990
+ const coveragePct = ciTotal > 0 ? Math.round((ciSigIndex.size / ciTotal) * 100) : 0;
8991
+
8992
+ const pass = coveragePct >= minCoverage;
8993
+
8994
+ if (args.includes('--json')) {
8995
+ process.stdout.write(JSON.stringify({ pass, coverage: coveragePct, threshold: minCoverage }) + '\n');
8996
+ } else if (pass) {
8997
+ console.log(`[sigmap] ✓ CI gate passed — coverage ${coveragePct}% ≥ ${minCoverage}%`);
8998
+ } else {
8999
+ console.error(`[sigmap] ✗ CI gate FAILED — coverage ${coveragePct}% < ${minCoverage}%`);
9000
+ console.error(` Fix: increase maxTokens or expand srcDirs in gen-context.config.json`);
9001
+ }
9002
+ process.exit(pass ? 0 : 1);
9003
+ }
9004
+
8915
9005
  // Default: generate once
8916
9006
  runGenerate(cwd, config, false);
8917
9007
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "Zero-dependency AI context engine — 97% token reduction. No npm install. Runs on Node 18+.",
5
5
  "main": "gen-context.js",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-cli",
3
- "version": "4.2.0",
3
+ "version": "4.3.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": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "SigMap core library — zero-dependency code signature extraction, retrieval, and security scanning",
5
5
  "main": "index.js",
6
6
  "keywords": [
package/src/mcp/server.js CHANGED
@@ -18,7 +18,7 @@ const { readContext, searchSignatures, getMap, createCheckpoint, getRouting, exp
18
18
 
19
19
  const SERVER_INFO = {
20
20
  name: 'sigmap',
21
- version: '4.2.0',
21
+ version: '4.3.0',
22
22
  description: 'SigMap MCP server — code signatures on demand',
23
23
  };
24
24