sigmap 6.10.6 → 6.10.9

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/AGENTS.md CHANGED
@@ -61,10 +61,9 @@ Always run `sigmap ask` or `sigmap --query` before searching for files relevant
61
61
  src/extractors/python_ast.py ← ast
62
62
  ```
63
63
 
64
- ## changes (last 5 commits — 11 minutes ago)
64
+ ## changes (last 5 commits — 7 minutes ago)
65
65
  ```
66
- src/analysis/diagnostics.js +estimateTokens +formatFileDecision +computeFileMetrics +explainInclusion
67
- src/map/import-graph.js +buildReverseGraph ~extractImports ~resolveJsPath ~detectCycles
66
+ src/graph/builder.js ~extractFileDeps
68
67
  ```
69
68
 
70
69
  ## packages
@@ -625,6 +624,15 @@ function buildReverseGraph(graph)
625
624
  function analyze(files, cwd)
626
625
  ```
627
626
 
627
+ ### src/graph/builder.js
628
+ ```
629
+ module.exports = { build, buildFromCwd, extractFileDeps }
630
+ function resolveJsPath(dir, importStr, fileSet) → string|null
631
+ function extractFileDeps(filePath, content, fileSet) → string[]
632
+ function build(files, cwd) → { forward: Map<string,str
633
+ function buildFromCwd(cwd, opts) → { forward: Map<string,str
634
+ ```
635
+
628
636
  ### src/mcp/server.js
629
637
  ```
630
638
  module.exports = { start }
package/CHANGELOG.md CHANGED
@@ -10,6 +10,44 @@ Format: [Semantic Versioning](https://semver.org/)
10
10
 
11
11
  ---
12
12
 
13
+ ## [6.10.9] — 2026-05-12
14
+
15
+ ### Changed
16
+
17
+ - **Documentation updates** — Updated roadmap to reflect v6.10.8 completion with Python import detection in builder.js for get_impact MCP tool.
18
+
19
+ ---
20
+
21
+ ## [6.10.8] — 2026-05-12
22
+
23
+ ### Fixed
24
+
25
+ - **Python absolute imports in builder.js for get_impact** — Added Python absolute import detection to `src/graph/builder.js` used by the `get_impact` MCP tool. Previously only `import-graph.js` had this support, causing `get_impact` to return empty blast radius for Python monorepos. Now both tools correctly detect `from package.module import X` patterns (closes #187).
26
+
27
+ ---
28
+
29
+ ## [6.10.7] — 2026-05-12
30
+
31
+ ### Fixed
32
+
33
+ - **Python absolute imports in bundled gen-context.js** — Added Python absolute import detection (`from package.module import X`) to bundled extractImports function. The source code had this support but it was missing from the bundle, causing MCP tools to show empty import graphs for Python monorepos. Now matches source behavior correctly.
34
+
35
+ ---
36
+
37
+ ## [6.10.6] — 2026-05-11
38
+
39
+ ### Added
40
+
41
+ - **Python absolute import detection** — Detects `from package.module import X` patterns in Python files, fixing empty import graphs for monorepos. Handles nested imports like `from services.auth.oauth import get_token` correctly (closes #181).
42
+ - **Comprehensive import graph diagnostics** — New `sigmap-diagnostics.js` tool and `src/analysis/diagnostics.js` module provide per-file metrics and budget decision explanations. Helps debug why files are included/excluded and why import graphs may be empty (closes #182).
43
+ - **Regression tests for MCP tools** — Added 8 comprehensive tests covering simple projects, monorepos, circular imports, and Python absolute imports. All tests passing to prevent regressions in `explain_file`, `get_impact`, and related tools.
44
+
45
+ ### Fixed
46
+
47
+ - **Import graph edge resolution** — Improved `resolveJsPath` to handle additional extensions (.mjs, .cjs, .tsx) and better fileSet path handling. Import graph now correctly detects cross-file dependencies in complex project structures.
48
+
49
+ ---
50
+
13
51
  ## [6.10.5] — 2026-05-11
14
52
 
15
53
  ### Added
package/README.md CHANGED
@@ -87,10 +87,10 @@ Ask → Rank → Context → Validate → Judge → Learn
87
87
 
88
88
  ```
89
89
  Benchmark : sigmap-v6.10-main
90
- Date : 2026-05-05
90
+ Date : 2026-05-12
91
91
 
92
92
  Hit@5 : 80.0% (baseline 13.6% — 5.9× lift)
93
- Prompt reduction : 41.0%
93
+ Prompt reduction : 41.4%
94
94
  Task success : 52.2% (baseline 10%)
95
95
  Prompts / task : 1.68 (baseline 2.84)
96
96
  Token reduction: 40–98% (avg 96.8% across 18 real repos)
package/gen-context.js CHANGED
@@ -4091,6 +4091,88 @@ module.exports = { coverageScore };
4091
4091
 
4092
4092
  };
4093
4093
 
4094
+ __factories["./src/analysis/diagnostics"] = function(module, exports) {
4095
+
4096
+ 'use strict';
4097
+
4098
+ const path = require('path');
4099
+
4100
+ function estimateTokens(text) {
4101
+ return Math.ceil(text.length / 4);
4102
+ }
4103
+
4104
+ function formatFileDecision(entry, decision, reason, score = null) {
4105
+ const rel = path.relative(process.cwd(), entry.filePath);
4106
+ const tokens = estimateTokens(entry.sigs.join('\n'));
4107
+ let line = `${decision === 'included' ? '✓' : '✗'} ${rel}`;
4108
+ line += ` [${tokens} tokens]`;
4109
+ if (score !== null) line += ` [score: ${score.toFixed(2)}]`;
4110
+ if (reason) line += ` — ${reason}`;
4111
+ return line;
4112
+ }
4113
+
4114
+ function computeFileMetrics(entry) {
4115
+ const loc = entry.content ? entry.content.split('\n').length : 1;
4116
+ const sigCount = entry.sigs ? entry.sigs.length : 0;
4117
+ const signalQuality = loc > 0 ? sigCount / loc : 0;
4118
+ const tokens = estimateTokens(entry.sigs.join('\n'));
4119
+
4120
+ return {
4121
+ lineOfCode: loc,
4122
+ sigCount: sigCount,
4123
+ signalQuality: signalQuality.toFixed(3),
4124
+ tokens: tokens,
4125
+ relevance: (sigCount / Math.max(loc, 1)).toFixed(3),
4126
+ };
4127
+ }
4128
+
4129
+ function explainInclusion(fileEntries, budgetLimit) {
4130
+ const lines = [];
4131
+
4132
+ lines.push('## File Inclusion Diagnostics\n');
4133
+ lines.push(`Budget: ${budgetLimit} tokens`);
4134
+ lines.push(`Files: ${fileEntries.length} scanned\n`);
4135
+
4136
+ let totalTokens = 0;
4137
+ const withMetrics = fileEntries.map((e) => {
4138
+ const metrics = computeFileMetrics(e);
4139
+ totalTokens += metrics.tokens;
4140
+ return { entry: e, metrics };
4141
+ });
4142
+
4143
+ lines.push(`Total token requirement: ${totalTokens} tokens`);
4144
+ lines.push(`Budget headroom: ${budgetLimit * 0.9} tokens (90% of ${budgetLimit})\n`);
4145
+
4146
+ if (totalTokens > budgetLimit * 0.9) {
4147
+ lines.push('⚠ Over budget — files will be dropped\n');
4148
+ lines.push('### Per-file metrics:');
4149
+ for (const { entry, metrics } of withMetrics) {
4150
+ const rel = path.relative(process.cwd(), entry.filePath);
4151
+ lines.push(`- ${rel}`);
4152
+ lines.push(` - Size: ${metrics.tokens} tokens, ${metrics.lineOfCode} lines`);
4153
+ lines.push(` - Sigs: ${metrics.sigCount}, quality: ${metrics.signalQuality}`);
4154
+ }
4155
+ } else {
4156
+ lines.push('✓ All files fit within budget\n');
4157
+ }
4158
+
4159
+ return lines.join('\n');
4160
+ }
4161
+
4162
+ function explainExclusion(dropped, reason) {
4163
+ return `Excluded ${dropped.length} files: ${reason}`;
4164
+ }
4165
+
4166
+ module.exports = {
4167
+ formatFileDecision,
4168
+ computeFileMetrics,
4169
+ explainInclusion,
4170
+ explainExclusion,
4171
+ estimateTokens,
4172
+ };
4173
+
4174
+ };
4175
+
4094
4176
  __factories["./src/health/scorer"] = function(module, exports) {
4095
4177
 
4096
4178
  /**
@@ -4507,10 +4589,10 @@ __factories["./src/map/import-graph"] = function(module, exports) {
4507
4589
  }
4508
4590
 
4509
4591
  if (PY_EXTS.has(ext)) {
4510
- // from .module import ... / from ..pkg import ...
4511
- const re = /^[ \t]*from\s+(\.+[\w.]*)\s+import/gm;
4592
+ // Relative imports: from .module import ... / from ..pkg import ...
4593
+ const reRel = /^[ \t]*from\s+(\.+[\w.]*)\s+import/gm;
4512
4594
  let m;
4513
- while ((m = re.exec(content)) !== null) {
4595
+ while ((m = reRel.exec(content)) !== null) {
4514
4596
  const dotCount = (m[1].match(/^\.+/) || [''])[0].length;
4515
4597
  const modPart = m[1].slice(dotCount).replace(/\./g, '/');
4516
4598
  let base = dir;
@@ -4518,6 +4600,24 @@ __factories["./src/map/import-graph"] = function(module, exports) {
4518
4600
  const candidate = modPart ? path.join(base, modPart + '.py') : null;
4519
4601
  if (candidate && fileSet.has(candidate)) found.push(candidate);
4520
4602
  }
4603
+
4604
+ // Absolute imports: from package.module import ... (infer from project structure)
4605
+ const reAbs = /^[ \t]*from\s+([\w.]+)\s+import/gm;
4606
+ while ((m = reAbs.exec(content)) !== null) {
4607
+ const modulePath = m[1].replace(/\./g, '/');
4608
+ const candidates = [
4609
+ path.join(dir, modulePath + '.py'),
4610
+ path.join(dir, modulePath, '__init__.py'),
4611
+ path.resolve(dir, '..', modulePath + '.py'),
4612
+ path.resolve(dir, '..', modulePath, '__init__.py'),
4613
+ ];
4614
+ for (const c of candidates) {
4615
+ if (fileSet.has(c)) {
4616
+ found.push(c);
4617
+ break;
4618
+ }
4619
+ }
4620
+ }
4521
4621
  }
4522
4622
 
4523
4623
  return [...new Set(found)];
@@ -5607,7 +5707,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
5607
5707
 
5608
5708
  const SERVER_INFO = {
5609
5709
  name: 'sigmap',
5610
- version: '6.10.6',
5710
+ version: '6.10.9',
5611
5711
  description: 'SigMap MCP server — code signatures on demand',
5612
5712
  };
5613
5713
 
@@ -8234,7 +8334,7 @@ const path = require('path');
8234
8334
  const os = require('os');
8235
8335
  const { execSync } = require('child_process');
8236
8336
 
8237
- const VERSION = '6.10.6';
8337
+ const VERSION = '6.10.9';
8238
8338
  const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
8239
8339
 
8240
8340
  function requireSourceOrBundled(key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "6.10.6",
3
+ "version": "6.10.9",
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": "6.10.6",
3
+ "version": "6.10.9",
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": "6.10.6",
3
+ "version": "6.10.9",
4
4
  "description": "SigMap core library — zero-dependency code signature extraction, retrieval, and security scanning",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -93,6 +93,24 @@ function extractFileDeps(filePath, content, fileSet) {
93
93
  : null;
94
94
  if (candidate && fileSet.has(candidate)) found.push(candidate);
95
95
  }
96
+
97
+ // Absolute imports: from package.module import ... (infer from project structure)
98
+ const reAbs = /^[ \t]*from\s+([\w.]+)\s+import/gm;
99
+ while ((m = reAbs.exec(content)) !== null) {
100
+ const modulePath = m[1].replace(/\./g, '/');
101
+ const candidates = [
102
+ path.join(dir, modulePath + '.py'),
103
+ path.join(dir, modulePath, '__init__.py'),
104
+ path.resolve(dir, '..', modulePath + '.py'),
105
+ path.resolve(dir, '..', modulePath, '__init__.py'),
106
+ ];
107
+ for (const c of candidates) {
108
+ if (fileSet.has(c)) {
109
+ found.push(c);
110
+ break;
111
+ }
112
+ }
113
+ }
96
114
  }
97
115
 
98
116
  // ── Go ────────────────────────────────────────────────────────────────────
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: '6.10.6',
21
+ version: '6.10.9',
22
22
  description: 'SigMap MCP server — code signatures on demand',
23
23
  };
24
24