sigmap 8.10.0 → 8.11.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,18 @@ Format: [Semantic Versioning](https://semver.org/)
10
10
 
11
11
  ---
12
12
 
13
+ ## [8.11.0] — 2026-07-11
14
+
15
+ Minor release — the **terse signature encoder** (D7 from the master plan), shipped under its measure-first gate: the public reduction number comes from a benchmark run on this repo, never borrowed from another tool's prose-compression claims.
16
+
17
+ ### Added
18
+ - **`--terse` — deterministic terse signature encoding (#462, PR #463):** opt-in compaction of the generated signature block (`function `→`fn `, tightened params/arrows/exports). Measured on this repo by `npm run benchmark:terse`: **10,232 → 8,580 sig tokens (−16.1%)** across 143 files / 780 signature lines. The `:start-end` line anchor and any trailing doc hint are preserved byte-exactly, so `get_lines`, evidence packs, `parseAnchor`, and symbol extraction keep working; the ranker parses terse context files (regression-tested). `terse: false` config default — default output is byte-identical when off. New `benchmark:terse` npm script (`scripts/run-terse-benchmark.mjs`) is the only legitimate source for this number.
19
+
20
+ ### Changed
21
+ - **README:** replaced the flaky Star History embed with a reliable link (PR #461); added the 'Verified on MseeP' badge below the MseeP security badge (PR #460).
22
+
23
+ ---
24
+
13
25
  ## [8.10.0] — 2026-07-09
14
26
 
15
27
  Minor release — **honesty fixes** from a brutal code-review audit of the CLI surface: closing the gap between what each command *claims* and what it *does*. All changes are zero-dependency, deterministic, and the bundle stays reproducible from `src/`. ~40 new regression tests.
package/README.md CHANGED
@@ -16,6 +16,7 @@
16
16
  [![Discover on ShyPD](https://img.shields.io/badge/ShyPD-Discover-7c6af7?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij48Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iOCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=&logoColor=7c6af7)](https://shypd.ai/tools/sigmap)
17
17
 
18
18
  [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/manojmallick-sigmap-badge.png)](https://mseep.ai/app/manojmallick-sigmap)
19
+ [![Verified on MseeP](https://mseep.ai/badge.svg)](https://mseep.ai/app/193cd37f-1ef3-43c3-80bc-86e23fd12924)
19
20
 
20
21
  </div>
21
22
 
@@ -121,8 +122,8 @@ Ask → Rank → Context → Validate → Judge → Learn
121
122
 
122
123
  <!--SM:benchmarkBlock-->
123
124
  ```
124
- Benchmark : sigmap-v8.10-main (21 repositories, including R language)
125
- Date : 2026-07-09
125
+ Benchmark : sigmap-v8.11-main (21 repositories, including R language)
126
+ Date : 2026-07-11
126
127
 
127
128
  Hit@5 : 87.8% (baseline 13.6% — 6.5× lift)
128
129
  Token reduction: 97.0% (across 21 repos)
@@ -339,9 +340,7 @@ If SigMap saves you context or API spend, a ⭐ on [GitHub](https://github.com/m
339
340
 
340
341
  🌍 See where SigMap's stargazers are around the world on the **[StarMapper star map →](https://starmapper.bruniaux.com/manojmallick/sigmap)**.
341
342
 
342
- <a href="https://star-history.com/#manojmallick/sigmap&Date">
343
- <img src="https://api.star-history.com/svg?repos=manojmallick/sigmap&type=Date" alt="SigMap Star History Chart" width="600" />
344
- </a>
343
+ 📈 Watch SigMap's growth on the **[Star History chart →](https://star-history.com/#manojmallick/sigmap&Date)**.
345
344
 
346
345
  [Report an issue](https://github.com/manojmallick/sigmap/issues) · [Changelog](CHANGELOG.md)
347
346
 
package/gen-context.js CHANGED
@@ -1501,6 +1501,9 @@ __factories["./src/config/defaults"] = function(module, exports) {
1501
1501
  // Include a compact `name@version` list of installed direct deps (D8)
1502
1502
  versionPins: true,
1503
1503
 
1504
+ // Terse signature encoding — deterministic compaction of sig lines (D7, opt-in)
1505
+ terse: false,
1506
+
1504
1507
  // Include TODO/FIXME/HACK/XXX comments as compact section
1505
1508
  todos: true,
1506
1509
 
@@ -10011,6 +10014,96 @@ __factories["./src/format/llms-txt"] = function(module, exports) {
10011
10014
 
10012
10015
  };
10013
10016
 
10017
+ // ── ./src/format/terse ──
10018
+ __factories["./src/format/terse"] = function(module, exports) {
10019
+
10020
+ /**
10021
+ * Terse signature encoder (D7).
10022
+ *
10023
+ * Deterministic compaction of signature lines for the generated context —
10024
+ * opt-in via `--terse` / `terse: true`. Every transform is a fixed string
10025
+ * rewrite (no heuristics, no LLM), so terse output stays byte-stable.
10026
+ *
10027
+ * The line anchor (` :start-end`) and everything after it (Python/R doc
10028
+ * hints) are preserved byte-exactly: `parseAnchor`, `get_lines`, and the
10029
+ * evidence pack keep working on terse output. Symbol extraction is safe too —
10030
+ * `extractName` in src/extractors/prdiff.js already recognizes `fn <name>`.
10031
+ */
10032
+
10033
+ /** First ` :start[-end]` anchor token (two-space prefix, as emitted by line-anchor.js). */
10034
+ const ANCHOR_RE = /\s{2}:\d+(?:-\d+)?(?=\s|$)/;
10035
+
10036
+ /**
10037
+ * Split a signature into the compactable text and the byte-preserved suffix
10038
+ * (anchor + any trailing doc hint).
10039
+ * @param {string} sig
10040
+ * @returns {{ text: string, suffix: string }}
10041
+ */
10042
+ function splitAnchor(sig) {
10043
+ const s = String(sig);
10044
+ const m = ANCHOR_RE.exec(s);
10045
+ if (!m) return { text: s, suffix: '' };
10046
+ return { text: s.slice(0, m.index), suffix: s.slice(m.index) };
10047
+ }
10048
+
10049
+ /**
10050
+ * Compact one signature line. Leading whitespace (member indentation) is kept.
10051
+ * @param {string} sig
10052
+ * @returns {string}
10053
+ */
10054
+ function encodeTerseSig(sig) {
10055
+ const { text, suffix } = splitAnchor(sig);
10056
+ let t = text
10057
+ .replace(/\basync function\b/g, 'async fn')
10058
+ .replace(/\bfunction\b/g, 'fn')
10059
+ .replace(/\s+→\s+/g, '→')
10060
+ .replace(/,\s+/g, ',')
10061
+ .replace(/\s+=\s+/g, '=')
10062
+ .replace(/\{\s+/g, '{')
10063
+ .replace(/\s+\}/g, '}')
10064
+ .replace(/(\S)\s{2,}(?=\S)/g, '$1 ')
10065
+ .replace(/^module\.exports=/, 'exports=');
10066
+ return t + suffix;
10067
+ }
10068
+
10069
+ /**
10070
+ * Compact an array of signature lines.
10071
+ * @param {string[]} sigs
10072
+ * @returns {string[]}
10073
+ */
10074
+ function encodeTerseSigs(sigs) {
10075
+ return (sigs || []).map(encodeTerseSig);
10076
+ }
10077
+
10078
+ /** Estimated tokens of joined signature lines (same chars/4 rule as elsewhere). */
10079
+ function _tokens(sigs) {
10080
+ return Math.ceil(sigs.join('\n').length / 4);
10081
+ }
10082
+
10083
+ /**
10084
+ * Measure the real reduction terse encoding buys over a set of signature
10085
+ * lists — the D7 "measure first" gate. Never quote a number this didn't produce.
10086
+ * @param {string[][]} sigsList one string[] per file
10087
+ * @returns {{ beforeTokens: number, afterTokens: number, reductionPct: number }}
10088
+ */
10089
+ function measureTerse(sigsList) {
10090
+ let beforeTokens = 0;
10091
+ let afterTokens = 0;
10092
+ for (const sigs of sigsList || []) {
10093
+ if (!sigs || !sigs.length) continue;
10094
+ beforeTokens += _tokens(sigs);
10095
+ afterTokens += _tokens(encodeTerseSigs(sigs));
10096
+ }
10097
+ const reductionPct = beforeTokens > 0
10098
+ ? Math.round(((beforeTokens - afterTokens) / beforeTokens) * 1000) / 10
10099
+ : 0;
10100
+ return { beforeTokens, afterTokens, reductionPct };
10101
+ }
10102
+
10103
+ module.exports = { encodeTerseSig, encodeTerseSigs, measureTerse, splitAnchor };
10104
+
10105
+ };
10106
+
10014
10107
  // ── ./src/format/usage-guidance ──
10015
10108
  __factories["./src/format/usage-guidance"] = function(module, exports) {
10016
10109
 
@@ -13950,7 +14043,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
13950
14043
 
13951
14044
  const SERVER_INFO = {
13952
14045
  name: 'sigmap',
13953
- version: '8.10.0',
14046
+ version: '8.11.0',
13954
14047
  description: 'SigMap MCP server — code signatures on demand',
13955
14048
  };
13956
14049
 
@@ -18640,7 +18733,7 @@ function __tryGit(args, opts = {}) {
18640
18733
  catch (_) { return ''; }
18641
18734
  }
18642
18735
 
18643
- const VERSION = '8.10.0';
18736
+ const VERSION = '8.11.0';
18644
18737
  const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
18645
18738
 
18646
18739
  function requireSourceOrBundled(key) {
@@ -19317,6 +19410,21 @@ function formatOutput(fileEntries, cwd, routingEnabled, config, extras) {
19317
19410
  groups[group].push({ rel, sigs: entry.sigs });
19318
19411
  }
19319
19412
 
19413
+ // D7: terse signature encoding — anchors preserved byte-exactly
19414
+ const terseOn = !!(config && config.terse);
19415
+ let encodeTerseSigs = null;
19416
+ if (terseOn) {
19417
+ try {
19418
+ const terseMod = requireSourceOrBundled('./src/format/terse');
19419
+ encodeTerseSigs = terseMod.encodeTerseSigs;
19420
+ const m = terseMod.measureTerse(fileEntries.map((e) => e.sigs));
19421
+ console.warn(`[sigmap] terse: sig block ${m.beforeTokens} → ${m.afterTokens} tokens (-${m.reductionPct}%)`);
19422
+ } catch (err) {
19423
+ encodeTerseSigs = null;
19424
+ console.warn(`[sigmap] terse encoding skipped: ${err.message}`);
19425
+ }
19426
+ }
19427
+
19320
19428
  for (const [group, entries] of Object.entries(groups).sort()) {
19321
19429
  lines.push(`## ${group}`);
19322
19430
  lines.push('');
@@ -19326,7 +19434,7 @@ function formatOutput(fileEntries, cwd, routingEnabled, config, extras) {
19326
19434
  const usedByStr = usedBy && usedBy.length ? ` (used by: ${usedBy.join(', ')})` : '';
19327
19435
  lines.push(`### ${rel}${usedByStr}`);
19328
19436
  lines.push('```');
19329
- lines.push(...sigs);
19437
+ lines.push(...(encodeTerseSigs ? encodeTerseSigs(sigs) : sigs));
19330
19438
  lines.push('```');
19331
19439
  lines.push('');
19332
19440
  }
@@ -20440,6 +20548,7 @@ Usage:
20440
20548
  ${cmd} --monorepo Generate per-package context (monorepo)
20441
20549
  ${cmd} --each Run for every repo in the current directory
20442
20550
  ${cmd} --routing Include model routing hints in output
20551
+ ${cmd} --terse Compact signature encoding (deterministic; line anchors preserved)
20443
20552
  ${cmd} --format cache Also write Anthropic prompt-cache JSON
20444
20553
  ${cmd} --track Append run metrics to .context/usage.ndjson
20445
20554
  ${cmd} --watch Generate + watch for file changes
@@ -20826,6 +20935,11 @@ function main() {
20826
20935
  config.testCoverage = true;
20827
20936
  }
20828
20937
 
20938
+ // --terse: compact signature encoding without editing config (D7)
20939
+ if (args.includes('--terse')) {
20940
+ config.terse = true;
20941
+ }
20942
+
20829
20943
  // ── --output <file> — parse early so every subsequent block can use it ─────
20830
20944
  // Resolves the custom output path and merges it into config.customOutput.
20831
20945
  // Also persists the resolved relative path to gen-context.config.json so
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.10.0 | Benchmark: sigmap-v8.10-main (2026-07-09)
14
+ # Version: 8.11.0 | Benchmark: sigmap-v8.11-main (2026-07-11)
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.10-main, 2026-07-09)
20
+ ## Core metrics (benchmark: sigmap-v8.11-main, 2026-07-11)
21
21
 
22
22
  | Metric | Without SigMap | With SigMap |
23
23
  |--------|----------------|-------------|
@@ -55,6 +55,7 @@ sigmap Generate context once and exit
55
55
  sigmap --monorepo Generate per-package context (monorepo)
56
56
  sigmap --each Run for every repo in the current directory
57
57
  sigmap --routing Include model routing hints in output
58
+ sigmap --terse Compact signature encoding (deterministic; line anchors preserved)
58
59
  sigmap --format cache Also write Anthropic prompt-cache JSON
59
60
  sigmap --track Append run metrics to .context/usage.ndjson
60
61
  sigmap --watch Generate + watch for file changes
@@ -325,6 +326,7 @@ tracking = false
325
326
  mcp = {"autoRegister":true}
326
327
  depMap = true
327
328
  versionPins = true
329
+ terse = false
328
330
  todos = true
329
331
  changes = true
330
332
  changesCommits = 10
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.10.0 | Benchmark: sigmap-v8.10-main (2026-07-09)
14
+ # Version: 8.11.0 | Benchmark: sigmap-v8.11-main (2026-07-11)
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.10-main, 2026-07-09)
26
+ ## Core metrics (benchmark: sigmap-v8.11-main, 2026-07-11)
27
27
 
28
28
  - hit@5 retrieval: 87.8% vs 13.6% random baseline (6.5× lift)
29
29
  - Token reduction: 97.0% average across benchmark repos
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "8.10.0",
3
+ "version": "8.11.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": {
@@ -29,6 +29,7 @@
29
29
  "benchmark:verify": "node scripts/run-verify-benchmark.mjs",
30
30
  "benchmark:squeeze": "node scripts/run-squeeze-benchmark.mjs --save",
31
31
  "benchmark:test-discovery": "node scripts/run-test-discovery-benchmark.mjs --save",
32
+ "benchmark:terse": "node scripts/run-terse-benchmark.mjs --save",
32
33
  "validate:squeeze": "node scripts/run-squeeze-benchmark.mjs --gate",
33
34
  "health": "node gen-context.js --health",
34
35
  "map": "node gen-project-map.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-cli",
3
- "version": "8.10.0",
3
+ "version": "8.11.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.10.0",
3
+ "version": "8.11.0",
4
4
  "description": "SigMap core library — zero-dependency code signature extraction, retrieval, and security scanning",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -117,6 +117,9 @@ const DEFAULTS = {
117
117
  // Include a compact `name@version` list of installed direct deps (D8)
118
118
  versionPins: true,
119
119
 
120
+ // Terse signature encoding — deterministic compaction of sig lines (D7, opt-in)
121
+ terse: false,
122
+
120
123
  // Include TODO/FIXME/HACK/XXX comments as compact section
121
124
  todos: true,
122
125
 
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Terse signature encoder (D7).
5
+ *
6
+ * Deterministic compaction of signature lines for the generated context —
7
+ * opt-in via `--terse` / `terse: true`. Every transform is a fixed string
8
+ * rewrite (no heuristics, no LLM), so terse output stays byte-stable.
9
+ *
10
+ * The line anchor (` :start-end`) and everything after it (Python/R doc
11
+ * hints) are preserved byte-exactly: `parseAnchor`, `get_lines`, and the
12
+ * evidence pack keep working on terse output. Symbol extraction is safe too —
13
+ * `extractName` in src/extractors/prdiff.js already recognizes `fn <name>`.
14
+ */
15
+
16
+ /** First ` :start[-end]` anchor token (two-space prefix, as emitted by line-anchor.js). */
17
+ const ANCHOR_RE = /\s{2}:\d+(?:-\d+)?(?=\s|$)/;
18
+
19
+ /**
20
+ * Split a signature into the compactable text and the byte-preserved suffix
21
+ * (anchor + any trailing doc hint).
22
+ * @param {string} sig
23
+ * @returns {{ text: string, suffix: string }}
24
+ */
25
+ function splitAnchor(sig) {
26
+ const s = String(sig);
27
+ const m = ANCHOR_RE.exec(s);
28
+ if (!m) return { text: s, suffix: '' };
29
+ return { text: s.slice(0, m.index), suffix: s.slice(m.index) };
30
+ }
31
+
32
+ /**
33
+ * Compact one signature line. Leading whitespace (member indentation) is kept.
34
+ * @param {string} sig
35
+ * @returns {string}
36
+ */
37
+ function encodeTerseSig(sig) {
38
+ const { text, suffix } = splitAnchor(sig);
39
+ let t = text
40
+ .replace(/\basync function\b/g, 'async fn')
41
+ .replace(/\bfunction\b/g, 'fn')
42
+ .replace(/\s+→\s+/g, '→')
43
+ .replace(/,\s+/g, ',')
44
+ .replace(/\s+=\s+/g, '=')
45
+ .replace(/\{\s+/g, '{')
46
+ .replace(/\s+\}/g, '}')
47
+ .replace(/(\S)\s{2,}(?=\S)/g, '$1 ')
48
+ .replace(/^module\.exports=/, 'exports=');
49
+ return t + suffix;
50
+ }
51
+
52
+ /**
53
+ * Compact an array of signature lines.
54
+ * @param {string[]} sigs
55
+ * @returns {string[]}
56
+ */
57
+ function encodeTerseSigs(sigs) {
58
+ return (sigs || []).map(encodeTerseSig);
59
+ }
60
+
61
+ /** Estimated tokens of joined signature lines (same chars/4 rule as elsewhere). */
62
+ function _tokens(sigs) {
63
+ return Math.ceil(sigs.join('\n').length / 4);
64
+ }
65
+
66
+ /**
67
+ * Measure the real reduction terse encoding buys over a set of signature
68
+ * lists — the D7 "measure first" gate. Never quote a number this didn't produce.
69
+ * @param {string[][]} sigsList one string[] per file
70
+ * @returns {{ beforeTokens: number, afterTokens: number, reductionPct: number }}
71
+ */
72
+ function measureTerse(sigsList) {
73
+ let beforeTokens = 0;
74
+ let afterTokens = 0;
75
+ for (const sigs of sigsList || []) {
76
+ if (!sigs || !sigs.length) continue;
77
+ beforeTokens += _tokens(sigs);
78
+ afterTokens += _tokens(encodeTerseSigs(sigs));
79
+ }
80
+ const reductionPct = beforeTokens > 0
81
+ ? Math.round(((beforeTokens - afterTokens) / beforeTokens) * 1000) / 10
82
+ : 0;
83
+ return { beforeTokens, afterTokens, reductionPct };
84
+ }
85
+
86
+ module.exports = { encodeTerseSig, encodeTerseSigs, measureTerse, splitAnchor };
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: '8.10.0',
21
+ version: '8.11.0',
22
22
  description: 'SigMap MCP server — code signatures on demand',
23
23
  };
24
24