sigmap 3.5.0 → 3.5.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 +48 -38
- package/README.md +16 -14
- package/gen-context.js +277 -3
- package/package.json +2 -1
- package/packages/adapters/llm-full.js +25 -0
- package/src/extractors/generic.js +26 -0
- package/src/format/llm-txt.js +28 -0
- package/src/format/llms-txt.js +70 -0
package/AGENTS.md
CHANGED
|
@@ -12,46 +12,33 @@ 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 v3.
|
|
15
|
+
Below are the code signatures extracted by SigMap v3.5.0 on 2026-04-14T21:58:46.968Z.
|
|
16
16
|
|
|
17
17
|
Use these signatures to answer questions about the code accurately.
|
|
18
18
|
|
|
19
19
|
## Code Signatures
|
|
20
20
|
|
|
21
|
-
<!-- Generated by SigMap gen-context.js v3.
|
|
21
|
+
<!-- Generated by SigMap gen-context.js v3.5.0 -->
|
|
22
22
|
<!-- DO NOT EDIT below the marker line — run gen-context.js to regenerate -->
|
|
23
23
|
|
|
24
24
|
# Code signatures
|
|
25
25
|
|
|
26
|
-
## changes (last 5 commits —
|
|
26
|
+
## changes (last 5 commits — 19 minutes ago)
|
|
27
27
|
```
|
|
28
28
|
src/config/loader.js ~detectAutoSrcDirs
|
|
29
29
|
src/eval/analyzer.js ~isDockerfile
|
|
30
30
|
src/extractors/markdown.js +extract
|
|
31
|
+
src/extractors/patterns.js +extract +implementing
|
|
31
32
|
src/extractors/properties.js +extract
|
|
33
|
+
src/extractors/python_dataclass.js +extract +definitions
|
|
32
34
|
src/extractors/toml.js +extract
|
|
35
|
+
src/extractors/typescript_react.js +extract +declarations
|
|
36
|
+
src/extractors/vue_sfc.js +extract
|
|
33
37
|
src/extractors/xml.js +attributes +extract
|
|
34
38
|
```
|
|
35
39
|
|
|
36
40
|
## packages
|
|
37
41
|
|
|
38
|
-
### packages/adapters/codex.js
|
|
39
|
-
```
|
|
40
|
-
module.exports = { name, format, outputPath, write }
|
|
41
|
-
function format(context, opts = {}) → string
|
|
42
|
-
function outputPath(cwd) → string
|
|
43
|
-
function write(context, cwd, opts = {})
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### packages/adapters/index.js
|
|
47
|
-
```
|
|
48
|
-
module.exports = { getAdapter, listAdapters, adapt, outputsToAdapters }
|
|
49
|
-
function getAdapter(name) → { name: string, format: F
|
|
50
|
-
function listAdapters() → string[]
|
|
51
|
-
function adapt(context, adapterName, opts = {}) → string
|
|
52
|
-
function outputsToAdapters(outputs) → string[]
|
|
53
|
-
```
|
|
54
|
-
|
|
55
42
|
### packages/core/index.js
|
|
56
43
|
```
|
|
57
44
|
module.exports = { extract, rank, buildSigIndex, scan, score, adapt }
|
|
@@ -72,6 +59,14 @@ function outputPath(cwd) → string
|
|
|
72
59
|
function write(context, cwd, opts = {})
|
|
73
60
|
```
|
|
74
61
|
|
|
62
|
+
### packages/adapters/codex.js
|
|
63
|
+
```
|
|
64
|
+
module.exports = { name, format, outputPath, write }
|
|
65
|
+
function format(context, opts = {}) → string
|
|
66
|
+
function outputPath(cwd) → string
|
|
67
|
+
function write(context, cwd, opts = {})
|
|
68
|
+
```
|
|
69
|
+
|
|
75
70
|
### packages/adapters/copilot.js
|
|
76
71
|
```
|
|
77
72
|
module.exports = { name, format, outputPath, write }
|
|
@@ -95,6 +90,15 @@ function outputPath(cwd) → string
|
|
|
95
90
|
function write(context, cwd, opts = {})
|
|
96
91
|
```
|
|
97
92
|
|
|
93
|
+
### packages/adapters/index.js
|
|
94
|
+
```
|
|
95
|
+
module.exports = { getAdapter, listAdapters, adapt, outputsToAdapters }
|
|
96
|
+
function getAdapter(name) → { name: string, format: F
|
|
97
|
+
function listAdapters() → string[]
|
|
98
|
+
function adapt(context, adapterName, opts = {}) → string
|
|
99
|
+
function outputsToAdapters(outputs) → string[]
|
|
100
|
+
```
|
|
101
|
+
|
|
98
102
|
### packages/adapters/openai.js
|
|
99
103
|
```
|
|
100
104
|
module.exports = { name, format, outputPath }
|
|
@@ -175,6 +179,12 @@ module.exports = { extract }
|
|
|
175
179
|
function extract(src) → string[]
|
|
176
180
|
```
|
|
177
181
|
|
|
182
|
+
### src/extractors/patterns.js
|
|
183
|
+
```
|
|
184
|
+
module.exports = { extract }
|
|
185
|
+
function extract(src) → string[]
|
|
186
|
+
```
|
|
187
|
+
|
|
178
188
|
### src/extractors/properties.js
|
|
179
189
|
```
|
|
180
190
|
module.exports = { extract }
|
|
@@ -187,6 +197,12 @@ module.exports = { extract }
|
|
|
187
197
|
function extract(src) → string[]
|
|
188
198
|
```
|
|
189
199
|
|
|
200
|
+
### src/extractors/python_dataclass.js
|
|
201
|
+
```
|
|
202
|
+
module.exports = { extract }
|
|
203
|
+
function extract(src) → string[]
|
|
204
|
+
```
|
|
205
|
+
|
|
190
206
|
### src/extractors/sql.js
|
|
191
207
|
```
|
|
192
208
|
module.exports = { extract }
|
|
@@ -207,6 +223,18 @@ module.exports = { extract }
|
|
|
207
223
|
function extract(src) → string[]
|
|
208
224
|
```
|
|
209
225
|
|
|
226
|
+
### src/extractors/typescript_react.js
|
|
227
|
+
```
|
|
228
|
+
module.exports = { extract }
|
|
229
|
+
function extract(src) → string[]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### src/extractors/vue_sfc.js
|
|
233
|
+
```
|
|
234
|
+
module.exports = { extract }
|
|
235
|
+
function extract(src) → string[]
|
|
236
|
+
```
|
|
237
|
+
|
|
210
238
|
### src/extractors/xml.js
|
|
211
239
|
```
|
|
212
240
|
module.exports = { extract }
|
|
@@ -381,12 +409,6 @@ function normalizeParams(params)
|
|
|
381
409
|
function extractDocHint(src, fnName, fnSigLine)
|
|
382
410
|
```
|
|
383
411
|
|
|
384
|
-
### src/extractors/python_dataclass.js
|
|
385
|
-
```
|
|
386
|
-
module.exports = { extract }
|
|
387
|
-
function extract(src) → string[]
|
|
388
|
-
```
|
|
389
|
-
|
|
390
412
|
### src/extractors/ruby.js
|
|
391
413
|
```
|
|
392
414
|
module.exports = { extract }
|
|
@@ -455,12 +477,6 @@ function extractClassMembers(block)
|
|
|
455
477
|
function normalizeParams(params)
|
|
456
478
|
```
|
|
457
479
|
|
|
458
|
-
### src/extractors/typescript_react.js
|
|
459
|
-
```
|
|
460
|
-
module.exports = { extract }
|
|
461
|
-
function extract(src) → string[]
|
|
462
|
-
```
|
|
463
|
-
|
|
464
480
|
### src/extractors/vue.js
|
|
465
481
|
```
|
|
466
482
|
module.exports = { extract }
|
|
@@ -469,12 +485,6 @@ function normalizeParams(params)
|
|
|
469
485
|
function normalizeType(type)
|
|
470
486
|
```
|
|
471
487
|
|
|
472
|
-
### src/extractors/vue_sfc.js
|
|
473
|
-
```
|
|
474
|
-
module.exports = { extract }
|
|
475
|
-
function extract(src) → string[]
|
|
476
|
-
```
|
|
477
|
-
|
|
478
488
|
### src/extractors/yaml.js
|
|
479
489
|
```
|
|
480
490
|
module.exports = { extract }
|
package/README.md
CHANGED
|
@@ -50,15 +50,15 @@ npx sigmap # 10 seconds. zero config. your AI never reads the wrong file again
|
|
|
50
50
|
|
|
51
51
|
<div align="center">
|
|
52
52
|
<img src="docs/comparison-chart.svg" alt="SigMap benchmark — before vs after across 3 RAG quality metrics" width="700" />
|
|
53
|
-
<br/><sub><a href="https://manojmallick.github.io/sigmap/guide/task-benchmark.html">
|
|
53
|
+
<br/><sub><a href="https://manojmallick.github.io/sigmap/guide/task-benchmark.html">90 tasks · 18 real repos · no LLM API · <strong>full methodology →</strong></a></sub>
|
|
54
54
|
</div>
|
|
55
55
|
|
|
56
56
|
| | Without SigMap | With SigMap |
|
|
57
57
|
|---|:---:|:---:|
|
|
58
58
|
| Task success | 10% | **59%** |
|
|
59
|
-
| Prompts per task | 2.84 | **1.
|
|
59
|
+
| Prompts per task | 2.84 | **1.78** |
|
|
60
60
|
| Tokens per session | ~80,000 | **~2,000** |
|
|
61
|
-
| Right file found | 13.
|
|
61
|
+
| Right file found | 13.6% | **84.4%** |
|
|
62
62
|
| Hallucination risk | 92% | **0%** |
|
|
63
63
|
|
|
64
64
|
</details>
|
|
@@ -126,24 +126,26 @@ Reproduced with `node scripts/run-benchmark.mjs` on public repos:
|
|
|
126
126
|
|
|
127
127
|
| Repo | Language | Raw tokens | After SigMap | Reduction |
|
|
128
128
|
|------|----------|------------|--------------|-----------|
|
|
129
|
-
| express | JavaScript |
|
|
130
|
-
| flask | Python |
|
|
131
|
-
| gin | Go |
|
|
132
|
-
| spring-petclinic | Java |
|
|
129
|
+
| express | JavaScript | 70.6K | 911 | **98.7%** |
|
|
130
|
+
| flask | Python | 147.9K | 6.7K | **95.4%** |
|
|
131
|
+
| gin | Go | 216.4K | 6.0K | **97.2%** |
|
|
132
|
+
| spring-petclinic | Java | 97.9K | 3.4K | **96.5%** |
|
|
133
133
|
| rails | Ruby | 1.5M | 7.1K | **99.5%** |
|
|
134
|
-
| axios | TypeScript |
|
|
135
|
-
| rust-analyzer | Rust | 3.5M |
|
|
134
|
+
| axios | TypeScript | 105.7K | 6.1K | **94.3%** |
|
|
135
|
+
| rust-analyzer | Rust | 3.5M | 6.3K | **99.8%** |
|
|
136
136
|
| abseil-cpp | C++ | 2.3M | 6.3K | **99.7%** |
|
|
137
|
-
| serilog | C# |
|
|
138
|
-
| riverpod | Dart |
|
|
137
|
+
| serilog | C# | 195.5K | 6.9K | **96.4%** |
|
|
138
|
+
| riverpod | Dart | 747.2K | 6.5K | **99.1%** |
|
|
139
139
|
| okhttp | Kotlin | 31.3K | 1.4K | **95.5%** |
|
|
140
140
|
| laravel | PHP | 1.7M | 7.2K | **99.6%** |
|
|
141
141
|
| akka | Scala | 790.5K | 7.1K | **99.1%** |
|
|
142
|
-
| vapor | Swift | 171.
|
|
143
|
-
| vue-core | Vue |
|
|
142
|
+
| vapor | Swift | 171.4K | 6.4K | **96.2%** |
|
|
143
|
+
| vue-core | Vue | 414.4K | 8.6K | **97.9%** |
|
|
144
144
|
| svelte | Svelte | 438.2K | 8.0K | **98.2%** |
|
|
145
|
+
| fastify | JavaScript | 54.4K | 2.6K | **95.3%** |
|
|
146
|
+
| fastapi | Python | 178.4K | 5.2K | **97.1%** |
|
|
145
147
|
|
|
146
|
-
**Average:
|
|
148
|
+
**Average: 97.5% 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`.
|
|
147
149
|
|
|
148
150
|
---
|
|
149
151
|
|
package/gen-context.js
CHANGED
|
@@ -5881,6 +5881,153 @@ __factories["./packages/adapters/index"] = function(module, exports) {
|
|
|
5881
5881
|
module.exports = { getAdapter, listAdapters, adapt, outputsToAdapters };
|
|
5882
5882
|
};
|
|
5883
5883
|
|
|
5884
|
+
// ── ./src/extractors/generic ──
|
|
5885
|
+
__factories["./src/extractors/generic"] = function(module, exports) {
|
|
5886
|
+
'use strict';
|
|
5887
|
+
const PATTERNS = [
|
|
5888
|
+
/^(?:pub\s+)?(?:async\s+)?function\s+\w+\s*\(/,
|
|
5889
|
+
/^(?:pub\s+)?(?:async\s+)?fn\s+\w+[\s(<]/,
|
|
5890
|
+
/^def\s+\w+[\s(|:]/,
|
|
5891
|
+
/^(?:pub\s+)?func\s+\w+\s*\(/,
|
|
5892
|
+
/^(?:let|let\s+rec)\s+\w+\s*[=(]/,
|
|
5893
|
+
/^class\s+\w+/,
|
|
5894
|
+
/^(?:proc|sub|method)\s+\w+\s*\(/,
|
|
5895
|
+
];
|
|
5896
|
+
function extract(src) {
|
|
5897
|
+
if (!src || typeof src !== 'string') return [];
|
|
5898
|
+
const results = [];
|
|
5899
|
+
for (const raw of src.split('\n')) {
|
|
5900
|
+
const line = raw.trim();
|
|
5901
|
+
if (!line || /^[#\-]/.test(line) || /^\/\//.test(line) || line.includes('\0')) continue;
|
|
5902
|
+
for (const pat of PATTERNS) {
|
|
5903
|
+
if (pat.test(line)) { results.push(line.slice(0, 120)); break; }
|
|
5904
|
+
}
|
|
5905
|
+
if (results.length >= 15) break;
|
|
5906
|
+
}
|
|
5907
|
+
return results;
|
|
5908
|
+
}
|
|
5909
|
+
module.exports = { extract };
|
|
5910
|
+
};
|
|
5911
|
+
|
|
5912
|
+
// ── ./src/format/llm-txt ──
|
|
5913
|
+
__factories["./src/format/llm-txt"] = function(module, exports) {
|
|
5914
|
+
'use strict';
|
|
5915
|
+
const path = require('path');
|
|
5916
|
+
function outputPath(cwd) { return path.join(cwd, 'llm.txt'); }
|
|
5917
|
+
function format(context, cwd, version) {
|
|
5918
|
+
const name = context.projectName || path.basename(cwd);
|
|
5919
|
+
const langs = [...new Set((context.fileEntries || []).map(f => f.language).filter(Boolean))];
|
|
5920
|
+
const mods = context.srcDirs || [];
|
|
5921
|
+
return [
|
|
5922
|
+
`# Project: ${name}`,
|
|
5923
|
+
`Languages: ${langs.join(', ') || 'unknown'}`,
|
|
5924
|
+
`Root: ${mods[0] || 'src/'}`,
|
|
5925
|
+
'',
|
|
5926
|
+
'## Modules',
|
|
5927
|
+
...mods.map(m => `- ${m}/`),
|
|
5928
|
+
'',
|
|
5929
|
+
'## Key flows',
|
|
5930
|
+
'- <!-- describe your main user flows here -->',
|
|
5931
|
+
'',
|
|
5932
|
+
'## Rules',
|
|
5933
|
+
'- <!-- describe your team conventions here -->',
|
|
5934
|
+
'',
|
|
5935
|
+
`Generated: ${new Date().toISOString()} | SigMap v${version}`,
|
|
5936
|
+
].join('\n');
|
|
5937
|
+
}
|
|
5938
|
+
module.exports = { format, outputPath };
|
|
5939
|
+
};
|
|
5940
|
+
|
|
5941
|
+
// ── ./src/format/llms-txt ──
|
|
5942
|
+
__factories["./src/format/llms-txt"] = function(module, exports) {
|
|
5943
|
+
'use strict';
|
|
5944
|
+
const path = require('path');
|
|
5945
|
+
const fs = require('fs');
|
|
5946
|
+
const { execSync } = require('child_process');
|
|
5947
|
+
function outputPath(cwd) { return path.join(cwd, 'llms.txt'); }
|
|
5948
|
+
function getShortCommit(cwd) {
|
|
5949
|
+
try { return execSync('git rev-parse --short HEAD', { cwd, timeout: 2000 }).toString().trim(); }
|
|
5950
|
+
catch (_) { return ''; }
|
|
5951
|
+
}
|
|
5952
|
+
function detectVersion(cwd) {
|
|
5953
|
+
try {
|
|
5954
|
+
const pkg = path.join(cwd, 'package.json');
|
|
5955
|
+
if (fs.existsSync(pkg)) return JSON.parse(fs.readFileSync(pkg, 'utf8')).version || '';
|
|
5956
|
+
} catch (_) {}
|
|
5957
|
+
return '';
|
|
5958
|
+
}
|
|
5959
|
+
function format(context, cwd, writtenFiles, sigmapVersion) {
|
|
5960
|
+
writtenFiles = writtenFiles || [];
|
|
5961
|
+
sigmapVersion = sigmapVersion || '';
|
|
5962
|
+
const name = context.projectName || path.basename(cwd);
|
|
5963
|
+
const ver = detectVersion(cwd);
|
|
5964
|
+
const commit = getShortCommit(cwd);
|
|
5965
|
+
const langs = [...new Set((context.fileEntries || []).map(f => f.language).filter(Boolean))];
|
|
5966
|
+
const lines = [
|
|
5967
|
+
'# SigMap Context Index',
|
|
5968
|
+
`> Generated by SigMap v${sigmapVersion} — zero-dependency AI context engine`,
|
|
5969
|
+
'',
|
|
5970
|
+
'## Project',
|
|
5971
|
+
`- Name: ${name}`,
|
|
5972
|
+
];
|
|
5973
|
+
if (ver) lines.push(`- Version: ${ver}`);
|
|
5974
|
+
if (langs.length) lines.push(`- Language: ${langs.join(', ')}`);
|
|
5975
|
+
if (commit) lines.push(`- Commit: ${commit}`);
|
|
5976
|
+
if (writtenFiles.length) {
|
|
5977
|
+
lines.push('', '## Context Files');
|
|
5978
|
+
for (const f of writtenFiles) {
|
|
5979
|
+
const rel = path.relative(cwd, f.path);
|
|
5980
|
+
const extra = f.tokens ? `: ${f.tokens} tokens` : '';
|
|
5981
|
+
lines.push(`- [${f.label || rel}](${rel})${extra}`);
|
|
5982
|
+
}
|
|
5983
|
+
}
|
|
5984
|
+
const mods = context.srcDirs || [];
|
|
5985
|
+
if (mods.length) {
|
|
5986
|
+
lines.push('', '## Source Modules');
|
|
5987
|
+
for (const m of mods) lines.push(`- [${m}/](${m}/)`);
|
|
5988
|
+
}
|
|
5989
|
+
const top5 = (context.fileEntries || [])
|
|
5990
|
+
.sort((a, b) => (b.sigs || []).length - (a.sigs || []).length)
|
|
5991
|
+
.slice(0, 5);
|
|
5992
|
+
if (top5.length) {
|
|
5993
|
+
lines.push('', '## Key Files');
|
|
5994
|
+
for (const f of top5) {
|
|
5995
|
+
const rel = path.relative(cwd, f.filePath);
|
|
5996
|
+
const preview = (f.sigs || []).slice(0, 3).join(', ');
|
|
5997
|
+
lines.push(`- ${rel}: ${preview}`);
|
|
5998
|
+
}
|
|
5999
|
+
}
|
|
6000
|
+
return lines.join('\n');
|
|
6001
|
+
}
|
|
6002
|
+
module.exports = { format, outputPath };
|
|
6003
|
+
};
|
|
6004
|
+
|
|
6005
|
+
// ── ./packages/adapters/llm-full ──
|
|
6006
|
+
__factories["./packages/adapters/llm-full"] = function(module, exports) {
|
|
6007
|
+
'use strict';
|
|
6008
|
+
const path = require('path');
|
|
6009
|
+
const fs = require('fs');
|
|
6010
|
+
function outputPath(cwd) { return path.join(cwd, 'llm-full.txt'); }
|
|
6011
|
+
function format(context, opts) {
|
|
6012
|
+
opts = opts || {};
|
|
6013
|
+
const lines = [
|
|
6014
|
+
`# ${context.projectName || 'Project'} — SigMap Context`,
|
|
6015
|
+
`Generated: ${new Date().toISOString()} | SigMap v${opts.version || ''}`,
|
|
6016
|
+
'',
|
|
6017
|
+
];
|
|
6018
|
+
for (const entry of (context.fileEntries || [])) {
|
|
6019
|
+
const rel = path.relative(opts.cwd || '', entry.filePath);
|
|
6020
|
+
lines.push(`## ${rel}`, '```', ...(entry.sigs || []), '```', '');
|
|
6021
|
+
}
|
|
6022
|
+
return lines.join('\n');
|
|
6023
|
+
}
|
|
6024
|
+
function write(context, cwd, opts) {
|
|
6025
|
+
opts = opts || {};
|
|
6026
|
+
fs.writeFileSync(outputPath(cwd), format(context, { ...opts, cwd }));
|
|
6027
|
+
}
|
|
6028
|
+
module.exports = { name: 'llm-full', format, outputPath, write };
|
|
6029
|
+
};
|
|
6030
|
+
|
|
5884
6031
|
/**
|
|
5885
6032
|
* SigMap — gen-context.js v1.2.0
|
|
5886
6033
|
* Zero-dependency AI context engine.
|
|
@@ -5893,7 +6040,7 @@ const path = require('path');
|
|
|
5893
6040
|
const os = require('os');
|
|
5894
6041
|
const { execSync } = require('child_process');
|
|
5895
6042
|
|
|
5896
|
-
const VERSION = '3.5.
|
|
6043
|
+
const VERSION = '3.5.1';
|
|
5897
6044
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
5898
6045
|
|
|
5899
6046
|
function requireSourceOrBundled(key) {
|
|
@@ -6042,7 +6189,8 @@ function detectAndExtract(filePath, content, maxSigsPerFile) {
|
|
|
6042
6189
|
const ext = path.extname(base).toLowerCase();
|
|
6043
6190
|
let extractorName = EXT_MAP[ext] || null;
|
|
6044
6191
|
if (!extractorName && isDockerfile(base)) extractorName = 'dockerfile';
|
|
6045
|
-
|
|
6192
|
+
// Feature 7: generic fallback — catches Nix, Elixir, Gleam, Zig, Go templates, etc.
|
|
6193
|
+
if (!extractorName) extractorName = 'generic';
|
|
6046
6194
|
|
|
6047
6195
|
const extractor = getExtractor(extractorName);
|
|
6048
6196
|
if (!extractor) return [];
|
|
@@ -6980,7 +7128,37 @@ function runGenerate(cwd, config, reportMode, reportJson = false) {
|
|
|
6980
7128
|
const finalTokens = estimateTokens(content);
|
|
6981
7129
|
const formatIdx = process.argv.indexOf('--format');
|
|
6982
7130
|
const formatValue = formatIdx >= 0 ? process.argv[formatIdx + 1] : (config.format || 'default');
|
|
6983
|
-
|
|
7131
|
+
// Feature 2: --mode write matrix
|
|
7132
|
+
const activeMode = process.argv.indexOf('--mode') >= 0
|
|
7133
|
+
? process.argv[process.argv.indexOf('--mode') + 1]
|
|
7134
|
+
: (config.mode || 'default');
|
|
7135
|
+
if (activeMode === 'fast') {
|
|
7136
|
+
const llmTxtMod = requireSourceOrBundled('./src/format/llm-txt');
|
|
7137
|
+
const syncContext = { projectName: path.basename(cwd), fileEntries, srcDirs: config.srcDirs || [] };
|
|
7138
|
+
fs.writeFileSync(llmTxtMod.outputPath(cwd), llmTxtMod.format(syncContext, cwd, VERSION));
|
|
7139
|
+
console.warn(`[sigmap] --mode fast → llm.txt`);
|
|
7140
|
+
} else if (activeMode === 'full') {
|
|
7141
|
+
const llmFullMod = requireSourceOrBundled('./packages/adapters/llm-full');
|
|
7142
|
+
const syncContext = { projectName: path.basename(cwd), fileEntries, srcDirs: config.srcDirs || [] };
|
|
7143
|
+
llmFullMod.write(syncContext, cwd, { version: VERSION });
|
|
7144
|
+
console.warn(`[sigmap] --mode full → llm-full.txt`);
|
|
7145
|
+
} else if (activeMode === 'both') {
|
|
7146
|
+
const llmTxtMod = requireSourceOrBundled('./src/format/llm-txt');
|
|
7147
|
+
const llmFullMod = requireSourceOrBundled('./packages/adapters/llm-full');
|
|
7148
|
+
const llmsMod = requireSourceOrBundled('./src/format/llms-txt');
|
|
7149
|
+
const syncContext = { projectName: path.basename(cwd), fileEntries, srcDirs: config.srcDirs || [] };
|
|
7150
|
+
fs.writeFileSync(llmTxtMod.outputPath(cwd), llmTxtMod.format(syncContext, cwd, VERSION));
|
|
7151
|
+
llmFullMod.write(syncContext, cwd, { version: VERSION });
|
|
7152
|
+
writeOutputs(content, config.outputs, cwd, config);
|
|
7153
|
+
const llmsContent = llmsMod.format(syncContext, cwd, [
|
|
7154
|
+
{ path: llmTxtMod.outputPath(cwd), label: 'llm.txt' },
|
|
7155
|
+
{ path: llmFullMod.outputPath(cwd), label: 'llm-full.txt' },
|
|
7156
|
+
], VERSION);
|
|
7157
|
+
fs.writeFileSync(llmsMod.outputPath(cwd), llmsContent);
|
|
7158
|
+
console.warn(`[sigmap] --mode both → copilot-instructions.md + llm.txt + llm-full.txt + llms.txt`);
|
|
7159
|
+
} else {
|
|
7160
|
+
writeOutputs(content, config.outputs, cwd, config);
|
|
7161
|
+
}
|
|
6984
7162
|
if (formatValue === 'cache') writeCacheOutput(content, cwd);
|
|
6985
7163
|
result = { inputTokenTotal, finalTokens, fileCount: beforeCount, droppedCount };
|
|
6986
7164
|
}
|
|
@@ -7016,6 +7194,29 @@ function runGenerate(cwd, config, reportMode, reportJson = false) {
|
|
|
7016
7194
|
}
|
|
7017
7195
|
}
|
|
7018
7196
|
|
|
7197
|
+
// Feature 8: post-run summary — 6-line stdout after every normal run
|
|
7198
|
+
if (!reportMode
|
|
7199
|
+
&& !process.argv.includes('--json')
|
|
7200
|
+
&& !process.argv.includes('--report')
|
|
7201
|
+
&& !process.argv.includes('--quiet')) {
|
|
7202
|
+
const bar = '\u2500'.repeat(43);
|
|
7203
|
+
const syms = fileEntries.reduce((n, f) => n + (f.sigs ? f.sigs.length : 0), 0);
|
|
7204
|
+
const pct = result.inputTokenTotal > 0
|
|
7205
|
+
? Math.round((1 - result.finalTokens / result.inputTokenTotal) * 100)
|
|
7206
|
+
: 0;
|
|
7207
|
+
process.stderr.write([
|
|
7208
|
+
bar,
|
|
7209
|
+
` SigMap v${VERSION}`,
|
|
7210
|
+
` Files scanned : ${result.fileCount}`,
|
|
7211
|
+
` Symbols found : ${syms.toLocaleString()}`,
|
|
7212
|
+
` Token reduction: ${pct}% (${result.inputTokenTotal.toLocaleString()} \u2192 ${result.finalTokens.toLocaleString()})`,
|
|
7213
|
+
` Output : .github/copilot-instructions.md`,
|
|
7214
|
+
bar,
|
|
7215
|
+
` Try: "explain the architecture" \u00b7 "find the auth module"`,
|
|
7216
|
+
bar, '',
|
|
7217
|
+
].join('\n'));
|
|
7218
|
+
}
|
|
7219
|
+
|
|
7019
7220
|
return result;
|
|
7020
7221
|
}
|
|
7021
7222
|
|
|
@@ -7327,6 +7528,12 @@ function registerMcp(cwd, scriptPath) {
|
|
|
7327
7528
|
|
|
7328
7529
|
function main() {
|
|
7329
7530
|
const args = process.argv.slice(2);
|
|
7531
|
+
|
|
7532
|
+
// Feature 1: `sigmap run` alias — strip positional 'run' so existing logic handles it
|
|
7533
|
+
if (args[0] === 'run' && !args[0].startsWith('--')) {
|
|
7534
|
+
args.shift();
|
|
7535
|
+
}
|
|
7536
|
+
|
|
7330
7537
|
const invokedFrom = process.cwd();
|
|
7331
7538
|
const cwd = resolveProjectRoot(invokedFrom);
|
|
7332
7539
|
const scriptPath = process.argv[1] || path.join(invokedFrom, 'gen-context.js');
|
|
@@ -7354,6 +7561,73 @@ function main() {
|
|
|
7354
7561
|
|
|
7355
7562
|
const config = loadConfig(cwd);
|
|
7356
7563
|
|
|
7564
|
+
// Feature 2: `--mode fast|full|both`
|
|
7565
|
+
const modeIdx = args.indexOf('--mode');
|
|
7566
|
+
const mode = modeIdx !== -1
|
|
7567
|
+
? args[modeIdx + 1]
|
|
7568
|
+
: (config.mode || 'default');
|
|
7569
|
+
const VALID_MODES = ['default', 'fast', 'full', 'both'];
|
|
7570
|
+
if (mode && !VALID_MODES.includes(mode)) {
|
|
7571
|
+
console.error(`[sigmap] unknown --mode "${mode}". Valid: ${VALID_MODES.join(', ')}`);
|
|
7572
|
+
process.exit(1);
|
|
7573
|
+
}
|
|
7574
|
+
|
|
7575
|
+
// Feature 6: `sigmap sync` — write all outputs + llms.txt + print compact diff
|
|
7576
|
+
if (args[0] === 'sync') {
|
|
7577
|
+
try {
|
|
7578
|
+
// Generate copilot-instructions.md first (existing output)
|
|
7579
|
+
runGenerate(cwd, config, false);
|
|
7580
|
+
const llmTxt = requireSourceOrBundled('./src/format/llm-txt');
|
|
7581
|
+
const llmsGen = requireSourceOrBundled('./src/format/llms-txt');
|
|
7582
|
+
const llmFullMod = requireSourceOrBundled('./packages/adapters/llm-full');
|
|
7583
|
+
|
|
7584
|
+
// Gather file entries for llm.txt / llm-full.txt
|
|
7585
|
+
const ignorePatterns = loadIgnorePatterns(cwd);
|
|
7586
|
+
let syncFiles = buildFileList(cwd, config).filter((f) => {
|
|
7587
|
+
const rel = path.relative(cwd, f).replace(/\\/g, '/');
|
|
7588
|
+
return !matchesIgnore(rel, ignorePatterns);
|
|
7589
|
+
});
|
|
7590
|
+
const syncEntries = [];
|
|
7591
|
+
for (const fp of syncFiles) {
|
|
7592
|
+
let content = '';
|
|
7593
|
+
try { content = fs.readFileSync(fp, 'utf8'); } catch (_) { continue; }
|
|
7594
|
+
const sigs = detectAndExtract(fp, content, config.maxSigsPerFile || 25);
|
|
7595
|
+
if (sigs.length === 0) continue;
|
|
7596
|
+
syncEntries.push({ filePath: fp, sigs, language: null });
|
|
7597
|
+
}
|
|
7598
|
+
const syncContext = {
|
|
7599
|
+
projectName: path.basename(cwd),
|
|
7600
|
+
fileEntries: syncEntries,
|
|
7601
|
+
srcDirs: config.srcDirs || [],
|
|
7602
|
+
};
|
|
7603
|
+
|
|
7604
|
+
const llmTxtPath = llmTxt.outputPath(cwd);
|
|
7605
|
+
const llmFullPath = llmFullMod.outputPath(cwd);
|
|
7606
|
+
const llmsTxtPath = llmsGen.outputPath(cwd);
|
|
7607
|
+
|
|
7608
|
+
fs.writeFileSync(llmTxtPath, llmTxt.format(syncContext, cwd, VERSION));
|
|
7609
|
+
llmFullMod.write(syncContext, cwd, { version: VERSION });
|
|
7610
|
+
|
|
7611
|
+
const prev = fs.existsSync(llmsTxtPath) ? fs.readFileSync(llmsTxtPath, 'utf8') : '';
|
|
7612
|
+
const next = llmsGen.format(syncContext, cwd, [
|
|
7613
|
+
{ path: llmTxtPath, label: 'llm.txt' },
|
|
7614
|
+
{ path: llmFullPath, label: 'llm-full.txt' },
|
|
7615
|
+
], VERSION);
|
|
7616
|
+
const changed = prev !== next ? 'updated' : 'no change';
|
|
7617
|
+
fs.writeFileSync(llmsTxtPath, next);
|
|
7618
|
+
|
|
7619
|
+
console.log('[sigmap] sync complete');
|
|
7620
|
+
console.log(` .github/copilot-instructions.md updated`);
|
|
7621
|
+
console.log(` llm.txt updated`);
|
|
7622
|
+
console.log(` llm-full.txt updated`);
|
|
7623
|
+
console.log(` llms.txt ${changed}`);
|
|
7624
|
+
} catch (err) {
|
|
7625
|
+
console.error(`[sigmap] sync error: ${err.message}`);
|
|
7626
|
+
process.exit(1);
|
|
7627
|
+
}
|
|
7628
|
+
process.exit(0);
|
|
7629
|
+
}
|
|
7630
|
+
|
|
7357
7631
|
if (args.includes('--init')) {
|
|
7358
7632
|
writeInitConfig(cwd);
|
|
7359
7633
|
process.exit(0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
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": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"init": "node gen-context.js --init",
|
|
25
25
|
"report": "node gen-context.js --report",
|
|
26
26
|
"audit:strategies": "node scripts/run-strategy-audit.mjs",
|
|
27
|
+
"benchmark:matrix": "node scripts/run-benchmark-matrix.mjs --save --skip-clone",
|
|
27
28
|
"health": "node gen-context.js --health",
|
|
28
29
|
"map": "node gen-project-map.js",
|
|
29
30
|
"mcp": "node gen-context.js --mcp",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
module.exports = { name: 'llm-full', format, outputPath, write };
|
|
5
|
+
|
|
6
|
+
function outputPath(cwd) { return path.join(cwd, 'llm-full.txt'); }
|
|
7
|
+
|
|
8
|
+
function format(context, opts) {
|
|
9
|
+
opts = opts || {};
|
|
10
|
+
const lines = [
|
|
11
|
+
`# ${context.projectName || 'Project'} — SigMap Context`,
|
|
12
|
+
`Generated: ${new Date().toISOString()} | SigMap v${opts.version || ''}`,
|
|
13
|
+
'',
|
|
14
|
+
];
|
|
15
|
+
for (const entry of (context.fileEntries || [])) {
|
|
16
|
+
const rel = path.relative(opts.cwd || '', entry.filePath);
|
|
17
|
+
lines.push(`## ${rel}`, '```', ...(entry.sigs || []), '```', '');
|
|
18
|
+
}
|
|
19
|
+
return lines.join('\n');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function write(context, cwd, opts) {
|
|
23
|
+
opts = opts || {};
|
|
24
|
+
fs.writeFileSync(outputPath(cwd), format(context, { ...opts, cwd }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
module.exports = { extract };
|
|
3
|
+
|
|
4
|
+
const PATTERNS = [
|
|
5
|
+
/^(?:pub\s+)?(?:async\s+)?function\s+\w+\s*\(/,
|
|
6
|
+
/^(?:pub\s+)?(?:async\s+)?fn\s+\w+[\s(<]/,
|
|
7
|
+
/^def\s+\w+[\s(|:]/,
|
|
8
|
+
/^(?:pub\s+)?func\s+\w+\s*\(/,
|
|
9
|
+
/^(?:let|let\s+rec)\s+\w+\s*[=(]/,
|
|
10
|
+
/^class\s+\w+/,
|
|
11
|
+
/^(?:proc|sub|method)\s+\w+\s*\(/,
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
function extract(src) {
|
|
15
|
+
if (!src || typeof src !== 'string') return [];
|
|
16
|
+
const results = [];
|
|
17
|
+
for (const raw of src.split('\n')) {
|
|
18
|
+
const line = raw.trim();
|
|
19
|
+
if (!line || /^[#\-]/.test(line) || /^\/\//.test(line) || line.includes('\0')) continue;
|
|
20
|
+
for (const pat of PATTERNS) {
|
|
21
|
+
if (pat.test(line)) { results.push(line.slice(0, 120)); break; }
|
|
22
|
+
}
|
|
23
|
+
if (results.length >= 15) break;
|
|
24
|
+
}
|
|
25
|
+
return results;
|
|
26
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const path = require('path');
|
|
3
|
+
module.exports = { format, outputPath };
|
|
4
|
+
|
|
5
|
+
function outputPath(cwd) { return path.join(cwd, 'llm.txt'); }
|
|
6
|
+
|
|
7
|
+
function format(context, cwd, version) {
|
|
8
|
+
const name = context.projectName || path.basename(cwd);
|
|
9
|
+
const langs = [...new Set((context.fileEntries || []).map(f => f.language).filter(Boolean))];
|
|
10
|
+
const mods = context.srcDirs || [];
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
`# Project: ${name}`,
|
|
14
|
+
`Languages: ${langs.join(', ') || 'unknown'}`,
|
|
15
|
+
`Root: ${mods[0] || 'src/'}`,
|
|
16
|
+
'',
|
|
17
|
+
'## Modules',
|
|
18
|
+
...mods.map(m => `- ${m}/`),
|
|
19
|
+
'',
|
|
20
|
+
'## Key flows',
|
|
21
|
+
'- <!-- describe your main user flows here -->',
|
|
22
|
+
'',
|
|
23
|
+
'## Rules',
|
|
24
|
+
'- <!-- describe your team conventions here -->',
|
|
25
|
+
'',
|
|
26
|
+
`Generated: ${new Date().toISOString()} | SigMap v${version}`,
|
|
27
|
+
].join('\n');
|
|
28
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
module.exports = { format, outputPath };
|
|
6
|
+
|
|
7
|
+
function outputPath(cwd) { return path.join(cwd, 'llms.txt'); }
|
|
8
|
+
|
|
9
|
+
function getShortCommit(cwd) {
|
|
10
|
+
try { return execSync('git rev-parse --short HEAD', { cwd, timeout: 2000 }).toString().trim(); }
|
|
11
|
+
catch (_) { return ''; }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function detectVersion(cwd) {
|
|
15
|
+
try {
|
|
16
|
+
const pkg = path.join(cwd, 'package.json');
|
|
17
|
+
if (fs.existsSync(pkg)) return JSON.parse(fs.readFileSync(pkg, 'utf8')).version || '';
|
|
18
|
+
} catch (_) {}
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function format(context, cwd, writtenFiles, sigmapVersion) {
|
|
23
|
+
writtenFiles = writtenFiles || [];
|
|
24
|
+
sigmapVersion = sigmapVersion || '';
|
|
25
|
+
|
|
26
|
+
const name = context.projectName || path.basename(cwd);
|
|
27
|
+
const ver = detectVersion(cwd);
|
|
28
|
+
const commit = getShortCommit(cwd);
|
|
29
|
+
const langs = [...new Set((context.fileEntries || []).map(f => f.language).filter(Boolean))];
|
|
30
|
+
|
|
31
|
+
const lines = [
|
|
32
|
+
'# SigMap Context Index',
|
|
33
|
+
`> Generated by SigMap v${sigmapVersion} — zero-dependency AI context engine`,
|
|
34
|
+
'',
|
|
35
|
+
'## Project',
|
|
36
|
+
`- Name: ${name}`,
|
|
37
|
+
];
|
|
38
|
+
if (ver) lines.push(`- Version: ${ver}`);
|
|
39
|
+
if (langs.length) lines.push(`- Language: ${langs.join(', ')}`);
|
|
40
|
+
if (commit) lines.push(`- Commit: ${commit}`);
|
|
41
|
+
|
|
42
|
+
if (writtenFiles.length) {
|
|
43
|
+
lines.push('', '## Context Files');
|
|
44
|
+
for (const f of writtenFiles) {
|
|
45
|
+
const rel = path.relative(cwd, f.path);
|
|
46
|
+
const extra = f.tokens ? `: ${f.tokens} tokens` : '';
|
|
47
|
+
lines.push(`- [${f.label || rel}](${rel})${extra}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const mods = context.srcDirs || [];
|
|
52
|
+
if (mods.length) {
|
|
53
|
+
lines.push('', '## Source Modules');
|
|
54
|
+
for (const m of mods) lines.push(`- [${m}/](${m}/)`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const top5 = (context.fileEntries || [])
|
|
58
|
+
.sort((a, b) => (b.sigs || []).length - (a.sigs || []).length)
|
|
59
|
+
.slice(0, 5);
|
|
60
|
+
if (top5.length) {
|
|
61
|
+
lines.push('', '## Key Files');
|
|
62
|
+
for (const f of top5) {
|
|
63
|
+
const rel = path.relative(cwd, f.filePath);
|
|
64
|
+
const preview = (f.sigs || []).slice(0, 3).join(', ');
|
|
65
|
+
lines.push(`- ${rel}: ${preview}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return lines.join('\n');
|
|
70
|
+
}
|