sigmap 4.0.0 → 4.0.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/AGENTS.md +58 -50
- package/CHANGELOG.md +56 -0
- package/README.md +80 -8
- package/gen-context.config.json.example +6 -3
- package/gen-context.js +111 -14
- 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/AGENTS.md
CHANGED
|
@@ -12,7 +12,7 @@ Use this marker block for all appendable context files:
|
|
|
12
12
|
## Auto-generated signatures
|
|
13
13
|
<!-- Updated by gen-context.js -->
|
|
14
14
|
You are a coding assistant with full knowledge of this codebase.
|
|
15
|
-
Below are the code signatures extracted by SigMap v4.0.0 on 2026-04-
|
|
15
|
+
Below are the code signatures extracted by SigMap v4.0.0 on 2026-04-15T06:03:22.464Z.
|
|
16
16
|
|
|
17
17
|
Use these signatures to answer questions about the code accurately.
|
|
18
18
|
|
|
@@ -23,24 +23,24 @@ Use these signatures to answer questions about the code accurately.
|
|
|
23
23
|
|
|
24
24
|
# Code signatures
|
|
25
25
|
|
|
26
|
-
## changes (last 5 commits —
|
|
26
|
+
## changes (last 5 commits — 7 minutes ago)
|
|
27
27
|
```
|
|
28
|
+
src/analysis/coverage-score.js +coverageScore +_walk
|
|
29
|
+
src/eval/analyzer.js ~analyzeFiles
|
|
28
30
|
src/extractors/generic.js +extract
|
|
29
31
|
src/format/llm-txt.js +outputPath +format
|
|
30
32
|
src/format/llms-txt.js +outputPath +getShortCommit +detectVersion +format
|
|
33
|
+
packages/adapters/claude.js +_confidenceMeta ~format
|
|
34
|
+
packages/adapters/copilot.js +_confidenceMeta ~format
|
|
35
|
+
packages/adapters/cursor.js +_confidenceMeta ~format
|
|
36
|
+
packages/adapters/gemini.js +_confidenceMeta ~format ~write
|
|
31
37
|
packages/adapters/llm-full.js +outputPath +format +write
|
|
38
|
+
packages/adapters/openai.js +_confidenceMeta ~format ~outputPath
|
|
39
|
+
packages/adapters/windsurf.js +_confidenceMeta ~format
|
|
32
40
|
```
|
|
33
41
|
|
|
34
42
|
## packages
|
|
35
43
|
|
|
36
|
-
### packages/adapters/llm-full.js
|
|
37
|
-
```
|
|
38
|
-
module.exports = { name: 'llm-full', format, outputPath, write }
|
|
39
|
-
function outputPath(cwd)
|
|
40
|
-
function format(context, opts)
|
|
41
|
-
function write(context, cwd, opts)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
44
|
### packages/adapters/claude.js
|
|
45
45
|
```
|
|
46
46
|
module.exports = { name, format, outputPath, write }
|
|
@@ -50,14 +50,6 @@ function outputPath(cwd) → string
|
|
|
50
50
|
function write(context, cwd, opts = {})
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
### packages/adapters/codex.js
|
|
54
|
-
```
|
|
55
|
-
module.exports = { name, format, outputPath, write }
|
|
56
|
-
function format(context, opts = {}) → string
|
|
57
|
-
function outputPath(cwd) → string
|
|
58
|
-
function write(context, cwd, opts = {})
|
|
59
|
-
```
|
|
60
|
-
|
|
61
53
|
### packages/adapters/copilot.js
|
|
62
54
|
```
|
|
63
55
|
module.exports = { name, format, outputPath, write }
|
|
@@ -84,13 +76,12 @@ function write(context, cwd, opts = {})
|
|
|
84
76
|
function _confidenceMeta(opts)
|
|
85
77
|
```
|
|
86
78
|
|
|
87
|
-
### packages/adapters/
|
|
79
|
+
### packages/adapters/llm-full.js
|
|
88
80
|
```
|
|
89
|
-
module.exports = {
|
|
90
|
-
function
|
|
91
|
-
function
|
|
92
|
-
function
|
|
93
|
-
function outputsToAdapters(outputs) → string[]
|
|
81
|
+
module.exports = { name: 'llm-full', format, outputPath, write }
|
|
82
|
+
function outputPath(cwd)
|
|
83
|
+
function format(context, opts)
|
|
84
|
+
function write(context, cwd, opts)
|
|
94
85
|
```
|
|
95
86
|
|
|
96
87
|
### packages/adapters/openai.js
|
|
@@ -109,6 +100,23 @@ function _confidenceMeta(opts)
|
|
|
109
100
|
function outputPath(cwd) → string
|
|
110
101
|
```
|
|
111
102
|
|
|
103
|
+
### packages/adapters/codex.js
|
|
104
|
+
```
|
|
105
|
+
module.exports = { name, format, outputPath, write }
|
|
106
|
+
function format(context, opts = {}) → string
|
|
107
|
+
function outputPath(cwd) → string
|
|
108
|
+
function write(context, cwd, opts = {})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### packages/adapters/index.js
|
|
112
|
+
```
|
|
113
|
+
module.exports = { getAdapter, listAdapters, adapt, outputsToAdapters }
|
|
114
|
+
function getAdapter(name) → { name: string, format: F
|
|
115
|
+
function listAdapters() → string[]
|
|
116
|
+
function adapt(context, adapterName, opts = {}) → string
|
|
117
|
+
function outputsToAdapters(outputs) → string[]
|
|
118
|
+
```
|
|
119
|
+
|
|
112
120
|
### packages/cli/index.js
|
|
113
121
|
```
|
|
114
122
|
module.exports = { CLI_ENTRY, run }
|
|
@@ -149,6 +157,26 @@ function adapt(context, adapterName, opts = {}) → string
|
|
|
149
157
|
|
|
150
158
|
## src
|
|
151
159
|
|
|
160
|
+
### src/analysis/coverage-score.js
|
|
161
|
+
```
|
|
162
|
+
module.exports = { coverageScore }
|
|
163
|
+
function coverageScore(cwd, fileEntries, config) → { * score: number, * grad
|
|
164
|
+
function _walk(dir, excludeSet, out)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### src/eval/analyzer.js
|
|
168
|
+
```
|
|
169
|
+
module.exports = { analyzeFiles, formatAnalysisTable, formatAnalysisJSON }
|
|
170
|
+
function isDockerfile(name)
|
|
171
|
+
function getExtractorName(filePath)
|
|
172
|
+
function tokenCount(sigs)
|
|
173
|
+
function hasCoverage(filePath, cwd)
|
|
174
|
+
function loadExtractor(name, cwd)
|
|
175
|
+
function analyzeFiles(files, cwd, opts) → object[]
|
|
176
|
+
function formatAnalysisTable(stats, showSlow) → string
|
|
177
|
+
function formatAnalysisJSON(stats) → object
|
|
178
|
+
```
|
|
179
|
+
|
|
152
180
|
### src/extractors/generic.js
|
|
153
181
|
```
|
|
154
182
|
module.exports = { extract }
|
|
@@ -171,11 +199,13 @@ function detectVersion(cwd)
|
|
|
171
199
|
function format(context, cwd, writtenFiles, sigmapVersion)
|
|
172
200
|
```
|
|
173
201
|
|
|
174
|
-
### src/
|
|
202
|
+
### src/mcp/server.js
|
|
175
203
|
```
|
|
176
|
-
module.exports = {
|
|
177
|
-
function
|
|
178
|
-
function
|
|
204
|
+
module.exports = { start }
|
|
205
|
+
function respond(id, result)
|
|
206
|
+
function respondError(id, code, message)
|
|
207
|
+
function dispatch(msg, cwd)
|
|
208
|
+
function start(cwd)
|
|
179
209
|
```
|
|
180
210
|
|
|
181
211
|
### src/config/defaults.js
|
|
@@ -191,19 +221,6 @@ function loadConfig(cwd) → object
|
|
|
191
221
|
function deepClone(obj)
|
|
192
222
|
```
|
|
193
223
|
|
|
194
|
-
### src/eval/analyzer.js
|
|
195
|
-
```
|
|
196
|
-
module.exports = { analyzeFiles, formatAnalysisTable, formatAnalysisJSON }
|
|
197
|
-
function isDockerfile(name)
|
|
198
|
-
function getExtractorName(filePath)
|
|
199
|
-
function tokenCount(sigs)
|
|
200
|
-
function hasCoverage(filePath, cwd)
|
|
201
|
-
function loadExtractor(name, cwd)
|
|
202
|
-
function analyzeFiles(files, cwd, opts) → object[]
|
|
203
|
-
function formatAnalysisTable(stats, showSlow) → string
|
|
204
|
-
function formatAnalysisJSON(stats) → object
|
|
205
|
-
```
|
|
206
|
-
|
|
207
224
|
### src/eval/runner.js
|
|
208
225
|
```
|
|
209
226
|
module.exports = { run, rank, loadTasks, buildSigIndex, formatTable, formatMetrics, tokenize }
|
|
@@ -609,15 +626,6 @@ function queryContext(args, cwd)
|
|
|
609
626
|
function getImpact(args, cwd)
|
|
610
627
|
```
|
|
611
628
|
|
|
612
|
-
### src/mcp/server.js
|
|
613
|
-
```
|
|
614
|
-
module.exports = { start }
|
|
615
|
-
function respond(id, result)
|
|
616
|
-
function respondError(id, code, message)
|
|
617
|
-
function dispatch(msg, cwd)
|
|
618
|
-
function start(cwd)
|
|
619
|
-
```
|
|
620
|
-
|
|
621
629
|
### src/mcp/tools.js
|
|
622
630
|
```
|
|
623
631
|
module.exports = { TOOLS }
|
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,62 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [4.0.1] — 2026-04-15 — Config auto-detection fix
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **Bundled `loadConfig` lacked `detectAutoSrcDirs`**: the inline `__factories["./src/config/loader"]` copy inside `gen-context.js` was a stripped-down version that returned raw `DEFAULTS` without filesystem auto-detection. After `--init` wrote a config with 6 hardcoded `srcDirs`, auto-detection was bypassed and custom project directories were missed — causing coverage to drop for any project whose source lives outside those 6 dirs. The bundled loader is now fully in sync with `src/config/loader.js`.
|
|
17
|
+
- **`--init` config hardcoded `srcDirs`**: `gen-context.config.json.example` had `"srcDirs": ["src","app","lib","packages","services","api"]` as a plain value. Any project that ran `--init` would lock into those 6 dirs and lose auto-detection. The example now omits `srcDirs` entirely and uses `_comment` keys to explain that auto-detection runs automatically. Users who need custom dirs can add `srcDirs` manually.
|
|
18
|
+
- **`gen-context.config.json` (SigMap repo)**: restored explicit `"srcDirs": ["src","packages"]` so the repo's own context generation is not affected by auto-detection picking up `docs-vp/`, `scripts/`, `test/`, and `vscode-extension/`.
|
|
19
|
+
- **Example `outputs` updated**: `gen-context.config.json.example` now lists all four standard adapters — `["copilot","codex","claude","gemini"]` — matching the recommended setup.
|
|
20
|
+
|
|
21
|
+
### Benchmarks (v4.0.1)
|
|
22
|
+
- Token reduction: **97.6% average** across 18 repos ✅
|
|
23
|
+
- Retrieval hit@5: **84.4%** (up from 83.3% in v4.0.0)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## [4.0.0] — 2026-04-15 — Intelligence Layer
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- **Coverage score** (`src/analysis/coverage-score.js`): measures what fraction of source files made it into context after token-budget application.
|
|
31
|
+
- Grade scale: A ≥ 90% · B ≥ 75% · C ≥ 50% · D < 50%
|
|
32
|
+
- Confidence indicator: HIGH / MEDIUM / LOW
|
|
33
|
+
- Per-module breakdown per srcDir via `perModule` Map
|
|
34
|
+
- **Confidence indicators in all output writers**: every generated file now includes a metadata comment:
|
|
35
|
+
```
|
|
36
|
+
<!-- sigmap: version=4.0.0 confidence=HIGH coverage=94% dropped=9 commit=abc1234 -->
|
|
37
|
+
```
|
|
38
|
+
Applies to: `copilot`, `claude`, `cursor`, `windsurf`, `openai`, `gemini` adapters.
|
|
39
|
+
- **`--report` module heatmap**: ASCII bar chart per srcDir showing coverage percentage:
|
|
40
|
+
```
|
|
41
|
+
Module Coverage:
|
|
42
|
+
src ████████████████ 100% (64/64 files)
|
|
43
|
+
packages ██████████████░░ 86% (12/14 files)
|
|
44
|
+
```
|
|
45
|
+
`--report --json` gains a `coverage` object with `score`, `grade`, `confidence`, `totalFiles`, `includedFiles`, `droppedFiles`, and `perModule`.
|
|
46
|
+
- **`--diff` risk score**: each changed file is now classified LOW / MEDIUM / HIGH based on reverse-dependency BFS, public API exports, route status, and config-file status:
|
|
47
|
+
```
|
|
48
|
+
[sigmap] Risk: Changed files (3):
|
|
49
|
+
src/auth/service.ts [HIGH] — exports public API, 5 downstream dependents
|
|
50
|
+
src/config/database.ts [MEDIUM] — config file
|
|
51
|
+
src/utils/format.ts [LOW] — no dependents, internal utility
|
|
52
|
+
```
|
|
53
|
+
- **Coverage in post-run summary**: every normal run now prints a `Coverage` line:
|
|
54
|
+
```
|
|
55
|
+
Coverage : A (97%) — 76 of 78 source files included
|
|
56
|
+
```
|
|
57
|
+
- **Coverage in `--health` and `--health --json`**: coverage grade, score, and file counts are included in both text and JSON health output. `--health --json` adds `coverage`, `coverageGrade`, `coverageConfidence`, `coverageTotalFiles`, `coverageIncludedFiles`.
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
- **Token budget drop order step 5**: now uses `signalQuality = sigs / linesOfCode` (least-informative files dropped first) instead of the previous "fewest sigs" heuristic.
|
|
61
|
+
- **`src/eval/analyzer.js` `analyzeFiles()` output**: each file stat now includes `linesOfCode` and `signalQuality` fields.
|
|
62
|
+
|
|
63
|
+
### Benchmark (v4.0.0)
|
|
64
|
+
- Token reduction: **97.6% average** across 18 repos (target ≥ 97.0%) ✅
|
|
65
|
+
- Retrieval hit@5: 83.3% (retrieval improvement targeted in v4.5 with adaptive query)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
13
69
|
## [3.5.0] — 2026-04-14 — Phase C/D Intelligence Expansion
|
|
14
70
|
|
|
15
71
|
### Added
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
npx sigmap # 10 seconds. zero config. your AI never reads the wrong file again.
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
> Latest: **
|
|
22
|
+
> Latest: **v4.0.0** — Intelligence Layer. Coverage score, confidence indicators in every output file, `--report` module heatmap, `--diff` risk scoring, and extractor quality-based drop order.
|
|
23
23
|
|
|
24
24
|
<div align="center">
|
|
25
25
|
<img src="demo.gif" alt="SigMap demo — reducing 80K tokens to 4K in under 10 seconds" width="760" />
|
|
@@ -145,7 +145,7 @@ Reproduced with `node scripts/run-benchmark.mjs` on public repos:
|
|
|
145
145
|
| fastify | JavaScript | 54.4K | 2.6K | **95.3%** |
|
|
146
146
|
| fastapi | Python | 178.4K | 5.2K | **97.1%** |
|
|
147
147
|
|
|
148
|
-
**Average: 97.
|
|
148
|
+
**Average: 97.6% reduction across 18 repos (16 languages).** See [`benchmarks/reports/token-reduction.md`](benchmarks/reports/token-reduction.md) or reproduce with `node scripts/run-benchmark.mjs`.
|
|
149
149
|
|
|
150
150
|
---
|
|
151
151
|
|
|
@@ -746,17 +746,89 @@ If `output` is omitted, the default `.github/copilot-instructions.md` is used.
|
|
|
746
746
|
|
|
747
747
|
## 📊 Observability
|
|
748
748
|
|
|
749
|
+
### Coverage score (v4.0)
|
|
750
|
+
|
|
751
|
+
Every run now prints a coverage line alongside token reduction:
|
|
752
|
+
|
|
753
|
+
```
|
|
754
|
+
───────────────────────────────────────────
|
|
755
|
+
SigMap v4.0.0
|
|
756
|
+
Files scanned : 76
|
|
757
|
+
Symbols found : 332
|
|
758
|
+
Token reduction: 94% (65,227 → 4,103)
|
|
759
|
+
Coverage : A (97%) — 76 of 78 source files included
|
|
760
|
+
Output : .github/copilot-instructions.md
|
|
761
|
+
───────────────────────────────────────────
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
The **coverage score** answers _how much of your codebase is represented in context_ after the token budget is applied. Grade scale: A ≥ 90% · B ≥ 75% · C ≥ 50% · D < 50%.
|
|
765
|
+
|
|
766
|
+
### Module heatmap in `--report`
|
|
767
|
+
|
|
749
768
|
```bash
|
|
750
|
-
|
|
751
|
-
|
|
769
|
+
sigmap --report
|
|
770
|
+
```
|
|
752
771
|
|
|
753
|
-
|
|
772
|
+
```
|
|
773
|
+
[sigmap] report:
|
|
774
|
+
version : 4.0.0
|
|
775
|
+
files processed : 76
|
|
776
|
+
reduction : 93.7%
|
|
777
|
+
coverage : A (97%) — 76 of 78 source files included
|
|
778
|
+
confidence : HIGH
|
|
779
|
+
|
|
780
|
+
Module Coverage:
|
|
781
|
+
src ████████████████ 100% (64/64 files)
|
|
782
|
+
packages ██████████████░░ 86% (12/14 files)
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
Machine-readable JSON (suitable for CI dashboards):
|
|
786
|
+
|
|
787
|
+
```bash
|
|
754
788
|
sigmap --report --json
|
|
755
|
-
# { "version": "
|
|
789
|
+
# { "version": "4.0.0", "finalTokens": 4103, "reductionPct": 93.7,
|
|
790
|
+
# "coverage": { "score": 97, "grade": "A", "confidence": "HIGH", ... } }
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### Composite health score
|
|
756
794
|
|
|
757
|
-
|
|
795
|
+
```bash
|
|
758
796
|
sigmap --health
|
|
759
|
-
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
```
|
|
800
|
+
[sigmap] health:
|
|
801
|
+
score : 80/100 (grade B)
|
|
802
|
+
coverage : A (97%) — 76 of 78 source files
|
|
803
|
+
strategy : full
|
|
804
|
+
...
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
sigmap --health --json
|
|
809
|
+
# { "score": 80, "grade": "B", "coverage": 97, "coverageGrade": "A",
|
|
810
|
+
# "tokens": 4103, "reduction": 93.7, ... }
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Confidence indicators in generated files
|
|
814
|
+
|
|
815
|
+
Every output file now carries a metadata line so you can inspect freshness at a glance:
|
|
816
|
+
|
|
817
|
+
```
|
|
818
|
+
<!-- sigmap: version=4.0.0 confidence=HIGH coverage=97% dropped=2 commit=8540612 -->
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
### Diff risk score
|
|
822
|
+
|
|
823
|
+
```bash
|
|
824
|
+
sigmap --diff HEAD~3
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
```
|
|
828
|
+
[sigmap] Risk: Changed files (4):
|
|
829
|
+
src/auth/service.ts [HIGH] — exports public API, 5 downstream dependents
|
|
830
|
+
src/config/database.ts [MEDIUM] — config file
|
|
831
|
+
src/utils/format.ts [LOW] — no dependents, internal utility
|
|
760
832
|
```
|
|
761
833
|
|
|
762
834
|
### Self-healing CI
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "SigMap configuration — all keys are optional (defaults shown)",
|
|
2
|
+
"_comment": "SigMap configuration — all keys are optional (defaults shown). Copy to gen-context.config.json.",
|
|
3
3
|
|
|
4
4
|
"output": ".github/copilot-instructions.md",
|
|
5
5
|
|
|
6
|
-
"outputs": ["copilot", "codex"],
|
|
6
|
+
"outputs": ["copilot", "codex", "claude", "gemini"],
|
|
7
7
|
|
|
8
|
-
"
|
|
8
|
+
"_srcDirs_comment": "Source directories to scan. OMIT this key to use auto-detection (recommended).",
|
|
9
|
+
"_srcDirs_comment2": "Auto-detection reads package.json/go.mod/Cargo.toml and scans top-level dirs automatically.",
|
|
10
|
+
"_srcDirs_comment3": "Only set this explicitly if auto-detection misses part of your project layout.",
|
|
11
|
+
"_srcDirs_example": ["src", "app", "lib", "packages", "services", "api"],
|
|
9
12
|
|
|
10
13
|
"exclude": [
|
|
11
14
|
"node_modules", ".git", "dist", "build", "out",
|
package/gen-context.js
CHANGED
|
@@ -116,14 +116,98 @@ __factories["./src/config/defaults"] = function(module, exports) {
|
|
|
116
116
|
|
|
117
117
|
// ── ./src/config/loader ──
|
|
118
118
|
__factories["./src/config/loader"] = function(module, exports) {
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
const fs = require('fs');
|
|
121
121
|
const path = require('path');
|
|
122
122
|
const { DEFAULTS } = __require('./src/config/defaults');
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
// Keys that are valid in gen-context.config.json
|
|
125
125
|
const KNOWN_KEYS = new Set(Object.keys(DEFAULTS));
|
|
126
|
-
|
|
126
|
+
|
|
127
|
+
// Common top-level folder names that reliably hold source code
|
|
128
|
+
const COMMON_CODE_DIRS = new Set([
|
|
129
|
+
'src', 'app', 'lib', 'packages', 'services', 'api', 'core', 'cmd',
|
|
130
|
+
'internal', 'pkg', 'handlers', 'controllers', 'models', 'views',
|
|
131
|
+
'components', 'pages', 'routes', 'middleware', 'utils', 'helpers',
|
|
132
|
+
'modules', 'plugins', 'extensions', 'adapters', 'drivers',
|
|
133
|
+
'hooks', 'composables', 'stores', 'features', 'domain', 'infra',
|
|
134
|
+
'infrastructure', 'application', 'data', 'Sources', 'Tests',
|
|
135
|
+
]);
|
|
136
|
+
|
|
137
|
+
const SUPPORTED_CODE_EXTS = new Set([
|
|
138
|
+
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
|
|
139
|
+
'.py', '.pyw', '.java', '.kt', '.kts', '.go', '.rs', '.cs',
|
|
140
|
+
'.cpp', '.c', '.h', '.hpp', '.cc', '.rb', '.rake', '.php',
|
|
141
|
+
'.swift', '.dart', '.scala', '.sc', '.vue', '.svelte',
|
|
142
|
+
'.html', '.htm', '.css', '.scss', '.sass', '.less',
|
|
143
|
+
'.yml', '.yaml', '.sh', '.bash', '.zsh', '.fish',
|
|
144
|
+
'.sql', '.graphql', '.gql', '.tf', '.tfvars', '.proto',
|
|
145
|
+
'.toml', '.properties', '.xml', '.md',
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
function detectAutoSrcDirs(cwd, excludeList) {
|
|
149
|
+
const excludeSet = new Set(excludeList || []);
|
|
150
|
+
const candidates = new Set(DEFAULTS.srcDirs);
|
|
151
|
+
|
|
152
|
+
// Manifest-based detection
|
|
153
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
154
|
+
if (fs.existsSync(pkgPath)) {
|
|
155
|
+
try {
|
|
156
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
157
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies, ...pkg.peerDependencies };
|
|
158
|
+
if (allDeps.react || allDeps.next)
|
|
159
|
+
for (const d of ['src', 'app', 'pages', 'components', 'hooks', 'lib', 'utils']) candidates.add(d);
|
|
160
|
+
if (allDeps['@angular/core'])
|
|
161
|
+
for (const d of ['src', 'projects', 'apps', 'libs']) candidates.add(d);
|
|
162
|
+
if (allDeps['@nestjs/core'])
|
|
163
|
+
for (const d of ['src', 'libs', 'apps']) candidates.add(d);
|
|
164
|
+
if (allDeps.vue)
|
|
165
|
+
for (const d of ['src', 'components', 'views', 'stores', 'composables', 'plugins']) candidates.add(d);
|
|
166
|
+
if (allDeps.svelte || allDeps['@sveltejs/kit'])
|
|
167
|
+
for (const d of ['src', 'lib', 'routes']) candidates.add(d);
|
|
168
|
+
if (allDeps.nx || allDeps.turbo || allDeps.lerna || pkg.workspaces)
|
|
169
|
+
for (const d of ['packages', 'apps', 'libs', 'services']) candidates.add(d);
|
|
170
|
+
} catch (_) {}
|
|
171
|
+
}
|
|
172
|
+
if (fs.existsSync(path.join(cwd, 'pyproject.toml')) || fs.existsSync(path.join(cwd, 'requirements.txt')) || fs.existsSync(path.join(cwd, 'setup.py')))
|
|
173
|
+
for (const d of ['src', 'app', 'apps', 'tests', 'examples', 'instance', 'blueprints']) candidates.add(d);
|
|
174
|
+
if (fs.existsSync(path.join(cwd, 'Gemfile')))
|
|
175
|
+
for (const d of ['app', 'lib', 'config', 'db', 'spec', 'test']) candidates.add(d);
|
|
176
|
+
if (fs.existsSync(path.join(cwd, 'composer.json')))
|
|
177
|
+
for (const d of ['app', 'resources', 'routes', 'database', 'tests']) candidates.add(d);
|
|
178
|
+
if (fs.existsSync(path.join(cwd, 'go.mod')))
|
|
179
|
+
for (const d of ['cmd', 'internal', 'pkg', 'api', 'handler', 'handlers', 'middleware', 'service']) candidates.add(d);
|
|
180
|
+
if (fs.existsSync(path.join(cwd, 'Cargo.toml')))
|
|
181
|
+
for (const d of ['src', 'crates', 'examples', 'tests', 'benches']) candidates.add(d);
|
|
182
|
+
if (fs.existsSync(path.join(cwd, 'pubspec.yaml')))
|
|
183
|
+
for (const d of ['lib', 'test', 'integration_test', 'example', 'bin']) candidates.add(d);
|
|
184
|
+
if (fs.existsSync(path.join(cwd, 'Package.swift')))
|
|
185
|
+
for (const d of ['Sources', 'Tests']) candidates.add(d);
|
|
186
|
+
|
|
187
|
+
// Top-level directory scan
|
|
188
|
+
try {
|
|
189
|
+
const entries = fs.readdirSync(cwd, { withFileTypes: true });
|
|
190
|
+
for (const entry of entries) {
|
|
191
|
+
if (!entry.isDirectory() || entry.name.startsWith('.') || excludeSet.has(entry.name)) continue;
|
|
192
|
+
const lname = entry.name.toLowerCase();
|
|
193
|
+
if (COMMON_CODE_DIRS.has(entry.name) || COMMON_CODE_DIRS.has(lname)) { candidates.add(entry.name); continue; }
|
|
194
|
+
const dirPath = path.join(cwd, entry.name);
|
|
195
|
+
try {
|
|
196
|
+
const subs = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
197
|
+
if (subs.some(s => s.isFile() && (SUPPORTED_CODE_EXTS.has(path.extname(s.name).toLowerCase()) || s.name === 'Dockerfile'))) {
|
|
198
|
+
candidates.add(entry.name); continue;
|
|
199
|
+
}
|
|
200
|
+
if (subs.some(s => s.isDirectory() && ['src', 'lib', 'main', 'java', 'kotlin', 'scala', 'python'].includes(s.name)))
|
|
201
|
+
candidates.add(entry.name);
|
|
202
|
+
} catch (_) {}
|
|
203
|
+
}
|
|
204
|
+
} catch (_) {}
|
|
205
|
+
|
|
206
|
+
return Array.from(candidates).filter(d => {
|
|
207
|
+
try { return fs.statSync(path.join(cwd, d)).isDirectory(); } catch (_) { return false; }
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
127
211
|
/**
|
|
128
212
|
* Load and merge configuration for a given working directory.
|
|
129
213
|
*
|
|
@@ -133,18 +217,24 @@ __factories["./src/config/loader"] = function(module, exports) {
|
|
|
133
217
|
function loadConfig(cwd) {
|
|
134
218
|
const configPath = path.join(cwd, 'gen-context.config.json');
|
|
135
219
|
if (!fs.existsSync(configPath)) {
|
|
136
|
-
|
|
220
|
+
const cfg = deepClone(DEFAULTS);
|
|
221
|
+
const detected = detectAutoSrcDirs(cwd, cfg.exclude);
|
|
222
|
+
if (detected.length > 0) cfg.srcDirs = detected;
|
|
223
|
+
return cfg;
|
|
137
224
|
}
|
|
138
|
-
|
|
225
|
+
|
|
139
226
|
let userConfig;
|
|
140
227
|
try {
|
|
141
228
|
const raw = fs.readFileSync(configPath, 'utf8');
|
|
142
229
|
userConfig = JSON.parse(raw);
|
|
143
230
|
} catch (err) {
|
|
144
231
|
console.warn(`[sigmap] config parse error in ${configPath}: ${err.message}`);
|
|
145
|
-
|
|
232
|
+
const cfg = deepClone(DEFAULTS);
|
|
233
|
+
const detected = detectAutoSrcDirs(cwd, cfg.exclude);
|
|
234
|
+
if (detected.length > 0) cfg.srcDirs = detected;
|
|
235
|
+
return cfg;
|
|
146
236
|
}
|
|
147
|
-
|
|
237
|
+
|
|
148
238
|
// Warn on unknown keys (helps catch typos)
|
|
149
239
|
for (const key of Object.keys(userConfig)) {
|
|
150
240
|
if (key.startsWith('_')) continue; // allow _comment etc.
|
|
@@ -152,7 +242,7 @@ __factories["./src/config/loader"] = function(module, exports) {
|
|
|
152
242
|
console.warn(`[sigmap] unknown config key: "${key}" (ignored)`);
|
|
153
243
|
}
|
|
154
244
|
}
|
|
155
|
-
|
|
245
|
+
|
|
156
246
|
// Deep merge: top-level known keys from user override defaults
|
|
157
247
|
// For object values (e.g. mcp), merge one level deep
|
|
158
248
|
const merged = deepClone(DEFAULTS);
|
|
@@ -167,6 +257,13 @@ __factories["./src/config/loader"] = function(module, exports) {
|
|
|
167
257
|
merged[key] = val;
|
|
168
258
|
}
|
|
169
259
|
}
|
|
260
|
+
|
|
261
|
+
// If user didn't specify srcDirs, auto-detect; fall back to DEFAULTS if nothing found
|
|
262
|
+
if (!Array.isArray(userConfig.srcDirs)) {
|
|
263
|
+
const detected = detectAutoSrcDirs(cwd, merged.exclude);
|
|
264
|
+
merged.srcDirs = detected.length > 0 ? detected : deepClone(DEFAULTS.srcDirs);
|
|
265
|
+
}
|
|
266
|
+
|
|
170
267
|
// Backward compat (v3.0+): if user specified 'adapters', use it as 'outputs' too.
|
|
171
268
|
// If user specified only 'outputs' (old configs), mirror to 'adapters'.
|
|
172
269
|
if (merged.adapters && !Array.isArray(merged.adapters)) merged.adapters = null;
|
|
@@ -177,13 +274,13 @@ __factories["./src/config/loader"] = function(module, exports) {
|
|
|
177
274
|
}
|
|
178
275
|
return merged;
|
|
179
276
|
}
|
|
180
|
-
|
|
277
|
+
|
|
181
278
|
function deepClone(obj) {
|
|
182
279
|
return JSON.parse(JSON.stringify(obj));
|
|
183
280
|
}
|
|
184
|
-
|
|
185
|
-
module.exports = { loadConfig };
|
|
186
|
-
|
|
281
|
+
|
|
282
|
+
module.exports = { loadConfig, detectAutoSrcDirs };
|
|
283
|
+
|
|
187
284
|
};
|
|
188
285
|
|
|
189
286
|
// ── ./src/extractors/cpp ──
|
|
@@ -4478,7 +4575,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
4478
4575
|
|
|
4479
4576
|
const SERVER_INFO = {
|
|
4480
4577
|
name: 'sigmap',
|
|
4481
|
-
version: '4.0.
|
|
4578
|
+
version: '4.0.1',
|
|
4482
4579
|
description: 'SigMap MCP server — code signatures on demand',
|
|
4483
4580
|
};
|
|
4484
4581
|
|
|
@@ -6040,7 +6137,7 @@ const path = require('path');
|
|
|
6040
6137
|
const os = require('os');
|
|
6041
6138
|
const { execSync } = require('child_process');
|
|
6042
6139
|
|
|
6043
|
-
const VERSION = '4.0.
|
|
6140
|
+
const VERSION = '4.0.1';
|
|
6044
6141
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
6045
6142
|
|
|
6046
6143
|
function requireSourceOrBundled(key) {
|
package/package.json
CHANGED
package/src/mcp/server.js
CHANGED