sigmap 3.0.1 → 3.1.0-alpha.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/CHANGELOG.md +60 -0
- package/README.md +175 -130
- package/gen-context.js +178 -8
- package/package.json +4 -2
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,66 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## [3.2.0] — Planned — Phase A: Cross-Platform Standalone Binaries
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **Standalone binaries** — macOS (arm64 + x64), Linux x64, Windows x64 built via Node.js SEA
|
|
17
|
+
- No Node.js or npm required to run SigMap
|
|
18
|
+
- Download from GitHub Releases: `sigmap-darwin-arm64`, `sigmap-darwin-x64`, `sigmap-linux-x64`, `sigmap-win32-x64.exe`
|
|
19
|
+
- SHA-256 checksums in `sigmap-checksums.txt` attached to every release
|
|
20
|
+
- **`scripts/build-binary.mjs`** — reproducible local binary build for the current platform
|
|
21
|
+
- **`scripts/verify-binary.mjs`** — smoke tests `--version`, `--help`, `generate`, `health`, `report` against a fixture repo
|
|
22
|
+
- **`.github/workflows/release-binaries.yml`** — GHA matrix builds all 4 targets on tag push; attaches artifacts to the GitHub Release
|
|
23
|
+
- **`test/fixtures/binary-smoke/`** — minimal fixture project used by CI smoke tests
|
|
24
|
+
- **`docs/binaries.md`** — install guide covering download, `chmod +x`, macOS Gatekeeper, Windows SmartScreen, and checksum verification
|
|
25
|
+
|
|
26
|
+
### Technical
|
|
27
|
+
- Uses [Node.js SEA](https://nodejs.org/api/single-executable-applications.html) (Node 20 `--experimental-sea-config` + `postject`)
|
|
28
|
+
- `gen-context.js` required no changes — existing `requireSourceOrBundled()` fallback and DEFAULTS fallback in `writeInitConfig()` are both SEA-compatible
|
|
29
|
+
- Binary builds run natively per OS in GHA (no cross-compilation)
|
|
30
|
+
- `release-attach` job waits for the npm-publish Release to exist before uploading binary assets
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## [3.1.0] — 2026-04-07 — Global Command Detection & VS Code Prerelease Fix
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
- **VS Code extension: global command auto-detection** — extension now finds `gen-context` installed via Volta, nvm, npm, or Homebrew without requiring `gen-context.js` in the project root or a manual `sigmap.scriptPath` setting
|
|
38
|
+
- Probe chain: local `node_modules/.bin` → `~/.volta/bin` → `~/.nvm/versions/node/*/bin` (newest first) → `/usr/local/bin` → `/opt/homebrew/bin` → `~/.npm-global/bin` → login-shell `which`
|
|
39
|
+
- Works on macOS GUI apps that do not inherit shell `PATH`
|
|
40
|
+
- `resolveGlobalCommand()` + unified `resolveRunner()` added to `vscode-extension/src/extension.js`
|
|
41
|
+
- **VS Code extension: actionable error message** — when command is not found, notification offers "Copy install command" (copies `npm install -g sigmap` to clipboard) and "Open settings" buttons instead of a plain warning
|
|
42
|
+
- **Prerelease GitHub Actions workflow** — new `prerelease-publish.yml` for manual alpha/beta/rc releases across all 5 platforms (npm, GitHub Packages, VS Code, Open VSX, JetBrains) without marking as @latest
|
|
43
|
+
- VS Code/Open VSX uses `major.minor.patch` versioning (VSCE prerelease constraint)
|
|
44
|
+
- npm/JetBrains use full semver prerelease suffix (e.g. `3.1.0-beta.1`)
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
- **`output` config key not honored for copilot adapter** · [#30](https://github.com/manojmallick/sigmap/issues/30)
|
|
48
|
+
- Custom `output` path in config now correctly used for copilot adapter instead of hard-wired `.github/copilot-instructions.md`
|
|
49
|
+
- Added `resolveAdapterPath()` helper to centralize adapter path resolution
|
|
50
|
+
- Other adapters (claude, cursor, windsurf) continue to use fixed paths as designed
|
|
51
|
+
- 5 new integration tests ensure custom paths work correctly across all config combinations
|
|
52
|
+
- **JetBrains plugin: global `gen-context` command support** · [#29](https://github.com/manojmallick/sigmap/issues/29)
|
|
53
|
+
- Plugin now resolves command via fallback chain: local `gen-context.js` → `node_modules/.bin/gen-context` → system `PATH`
|
|
54
|
+
- Enables use in Java, Rust, Go and other non-Node projects with `gen-context` installed globally via Volta/nvm/npm
|
|
55
|
+
- **VS Code prerelease versioning** — workflow previously failed publishing because semver-suffixed versions (e.g. `3.1.0-alpha.1`) are rejected by VSCE; fixed by splitting into separate `npm_version` and `vscode_version` outputs
|
|
56
|
+
|
|
57
|
+
### Technical
|
|
58
|
+
- `resolveRunner()` returns `{ type: 'script' | 'command', path }` allowing extension to run either `node "path/gen-context.js"` or `"~/.volta/bin/gen-context"` without modification to the terminal command
|
|
59
|
+
|
|
60
|
+
### How to release (tag triggers automatic publish)
|
|
61
|
+
```bash
|
|
62
|
+
git tag v3.1.0
|
|
63
|
+
git push origin v3.1.0
|
|
64
|
+
# npm-publish.yml auto-triggers and publishes to all 5 platforms
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
9
69
|
## [3.0.0] — 2026-04-06 — Platform: Multi-Adapter Architecture
|
|
10
70
|
|
|
11
71
|
### Added
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p>
|
|
8
8
|
Every coding agent session starts with full codebase context at under 4K tokens.<br>
|
|
9
|
-
|
|
9
|
+
Multiple install options. Zero runtime dependencies. Requires only Node.js 18+.
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
12
|
<!-- Status -->
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
[](CHANGELOG.md)
|
|
27
27
|
[](CONTRIBUTING.md)
|
|
28
28
|
[](https://marketplace.visualstudio.com/items?itemName=manojmallick.sigmap)
|
|
29
|
-
[](https://plugins.jetbrains.com/plugin/sigmap)
|
|
29
|
+
[](https://plugins.jetbrains.com/plugin/31109-sigmap--ai-context-engine/)
|
|
30
30
|
[](https://open-vsx.org/extension/manojmallick/sigmap)
|
|
31
31
|
|
|
32
32
|
</div>
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
| | |
|
|
39
39
|
|---|---|
|
|
40
40
|
| [What it does](#-what-it-does) | Token reduction table, pipeline overview |
|
|
41
|
-
| [Quick start](#-quick-start) |
|
|
41
|
+
| [Quick start](#-quick-start) | Install (binary or npm), generate in 60 seconds |
|
|
42
|
+
| [Standalone binaries](docs/binaries.md) | macOS, Linux, Windows — no Node required |
|
|
42
43
|
| [VS Code extension](#-vs-code-extension) | Status bar, stale alerts, commands |
|
|
43
44
|
| [JetBrains plugin](#-jetbrains-plugin) | IntelliJ IDEA, WebStorm, PyCharm support |
|
|
44
45
|
| [Languages supported](#-languages-supported) | 21 languages |
|
|
@@ -47,6 +48,7 @@
|
|
|
47
48
|
| [CLI reference](#-cli-reference) | All flags |
|
|
48
49
|
| [Configuration](#-configuration) | Config file + .contextignore |
|
|
49
50
|
| [Observability](#-observability) | Health score, reports, CI |
|
|
51
|
+
| [Programmatic API](#-programmatic-api) | Use as a Node.js library |
|
|
50
52
|
| [Testing](#-testing) | Run the test suite |
|
|
51
53
|
| [Project structure](#-project-structure) | File-by-file map |
|
|
52
54
|
| [Principles](#-principles) | Design decisions |
|
|
@@ -88,57 +90,96 @@ AI agent session starts with full context
|
|
|
88
90
|
|
|
89
91
|
---
|
|
90
92
|
|
|
91
|
-
##
|
|
93
|
+
## ⚡ Installation
|
|
92
94
|
|
|
93
|
-
|
|
94
|
-
|---|---|
|
|
95
|
-
| **Programmatic API** | `require('sigmap')` — use `extract`, `rank`, `buildSigIndex`, `scan`, `score` directly, no CLI subprocess |
|
|
96
|
-
| **`packages/core/`** | New `sigmap-core` package with stable API surface for third-party integrations |
|
|
97
|
-
| **`packages/cli/`** | Thin `sigmap-cli` forward-compat shim for the v3.0 adapter architecture |
|
|
98
|
-
| **15 new tests** | `core-api.test.js` covers all exported functions, edge cases, and backward compat |
|
|
95
|
+
Pick the method that fits your workflow — all produce the same output.
|
|
99
96
|
|
|
100
|
-
|
|
97
|
+
<details open>
|
|
98
|
+
<summary><strong>npx — try without installing</strong></summary>
|
|
101
99
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
| **`--query --json`** | Machine-readable ranked results (`{ query, results[], totalResults }`) |
|
|
106
|
-
| **`--query --top <n>`** | Limit results (default 10, configurable via `retrieval.topK`) |
|
|
107
|
-
| **`query_context` MCP tool** | 8th MCP tool — `{ query, topK? }` returns ranked file list, usable live in any MCP session |
|
|
108
|
-
| **`--analyze` / `--diagnose-extractors`** | Per-file breakdown of sigs/tokens/extractor/coverage; self-tests all 21 extractors (v2.2) |
|
|
109
|
-
| **`--benchmark` / `--eval`** | Measure hit@5 and MRR retrieval quality against a JSONL task file (v2.1) |
|
|
100
|
+
```bash
|
|
101
|
+
npx sigmap
|
|
102
|
+
```
|
|
110
103
|
|
|
111
|
-
|
|
104
|
+
Runs the latest version without any permanent install. Great for a quick try.
|
|
112
105
|
|
|
113
|
-
|
|
106
|
+
</details>
|
|
107
|
+
|
|
108
|
+
<details>
|
|
109
|
+
<summary><strong>npm global — install once, run anywhere</strong></summary>
|
|
114
110
|
|
|
115
|
-
|
|
111
|
+
```bash
|
|
112
|
+
npm install -g sigmap
|
|
113
|
+
sigmap
|
|
114
|
+
```
|
|
116
115
|
|
|
117
|
-
|
|
116
|
+
Available from any directory on your machine.
|
|
118
117
|
|
|
119
|
-
|
|
120
|
-
|---|---|
|
|
121
|
-
| **Charts in reports** | Visualize token reduction, signature counts, and budget usage per run |
|
|
122
|
-
| **Advanced retrieval metrics** | Add precision@K, recall@K, MRR trend, and query-level diagnostics |
|
|
123
|
-
| **Evaluation dashboard output** | Generate shareable HTML/JSON benchmark summaries from CLI runs |
|
|
124
|
-
| **CI-friendly metrics export** | Persist machine-readable metrics for release gates and regression tracking |
|
|
125
|
-
| **Release quality gates** | Add pass/fail thresholds for hit@5 and precision before publish |
|
|
126
|
-
## 🔌 v3.0 — Platform: Multi-Adapter Architecture
|
|
118
|
+
</details>
|
|
127
119
|
|
|
128
|
-
|
|
120
|
+
<details>
|
|
121
|
+
<summary><strong>npm local — per-project, version-pinned</strong></summary>
|
|
129
122
|
|
|
130
123
|
```bash
|
|
131
|
-
|
|
132
|
-
node gen-context.js --adapter copilot # → .github/copilot-instructions.md
|
|
133
|
-
node gen-context.js --adapter openai # → .github/openai-context.md
|
|
134
|
-
node gen-context.js --adapter gemini # → .github/gemini-context.md
|
|
135
|
-
node gen-context.js --adapter claude # → CLAUDE.md (append)
|
|
124
|
+
npm install --save-dev sigmap
|
|
136
125
|
```
|
|
137
126
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
127
|
+
Add to `package.json` scripts for team consistency:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"scripts": {
|
|
132
|
+
"context": "sigmap",
|
|
133
|
+
"context:watch": "sigmap --watch"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Run with `npm run context`. Version is pinned per project.
|
|
139
|
+
|
|
140
|
+
</details>
|
|
141
|
+
|
|
142
|
+
<details>
|
|
143
|
+
<summary><strong>Volta — team-friendly, auto-pinned version</strong></summary>
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
volta install sigmap
|
|
147
|
+
sigmap
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
[Volta](https://volta.sh) pins the exact version in `package.json` — every team member runs the same version automatically without configuration.
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
<details>
|
|
155
|
+
<summary><strong>Single-file download — no npm, any machine</strong></summary>
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
curl -O https://raw.githubusercontent.com/manojmallick/sigmap/main/gen-context.js
|
|
159
|
+
node gen-context.js
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
No npm, no `node_modules`. Drop `gen-context.js` into any project and run it directly. Requires only Node.js 18+. Ideal for CI, locked-down environments, or one-off use.
|
|
163
|
+
|
|
164
|
+
</details>
|
|
165
|
+
|
|
166
|
+
> **Note:** When using the single-file download, replace `sigmap` with `node gen-context.js` in all commands below.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 🚀 Features
|
|
171
|
+
|
|
172
|
+
### Multi-adapter output
|
|
173
|
+
|
|
174
|
+
Generate context for any AI assistant from a single run:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
sigmap --adapter copilot # → .github/copilot-instructions.md
|
|
178
|
+
sigmap --adapter claude # → CLAUDE.md (appended below marker)
|
|
179
|
+
sigmap --adapter cursor # → .cursorrules
|
|
180
|
+
sigmap --adapter windsurf # → .windsurfrules
|
|
181
|
+
sigmap --adapter openai # → .github/openai-context.md
|
|
182
|
+
sigmap --adapter gemini # → .github/gemini-context.md
|
|
142
183
|
```
|
|
143
184
|
|
|
144
185
|
| Adapter | Output file | AI assistant |
|
|
@@ -150,38 +191,80 @@ const systemPrompt = adapt(context, 'openai', { version: '3.0.0' });
|
|
|
150
191
|
| `openai` | `.github/openai-context.md` | Any OpenAI model |
|
|
151
192
|
| `gemini` | `.github/gemini-context.md` | Google Gemini |
|
|
152
193
|
|
|
153
|
-
|
|
194
|
+
Configure multiple adapters at once in `gen-context.config.json`:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{ "outputs": ["copilot", "claude", "cursor"] }
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Programmatic API
|
|
201
|
+
|
|
202
|
+
Use SigMap as a Node.js library without spawning a subprocess. See the [full API reference](#-programmatic-api) below.
|
|
203
|
+
|
|
204
|
+
### Query-aware retrieval
|
|
154
205
|
|
|
155
|
-
|
|
206
|
+
Find the most relevant files for any task without reading the whole codebase:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
sigmap --query "authentication middleware" # ranked file list
|
|
210
|
+
sigmap --query "auth" --json # machine-readable output
|
|
211
|
+
sigmap --query "auth" --top 5 # top 5 results only
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Diagnostic and evaluation tools
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
sigmap --analyze # per-file: sigs, tokens, extractor, coverage
|
|
218
|
+
sigmap --analyze --slow # include extraction timing
|
|
219
|
+
sigmap --diagnose-extractors # self-test all 21 extractors against fixtures
|
|
220
|
+
sigmap --benchmark # hit@5 and MRR retrieval quality
|
|
221
|
+
sigmap --benchmark --json # machine-readable benchmark results
|
|
222
|
+
```
|
|
156
223
|
|
|
157
224
|
---
|
|
158
|
-
curl -O https://raw.githubusercontent.com/manojmallick/sigmap/main/gen-context.js
|
|
159
225
|
|
|
160
|
-
|
|
161
|
-
|
|
226
|
+
## ⚡ Quick start
|
|
227
|
+
|
|
228
|
+
### Install
|
|
229
|
+
|
|
230
|
+
**Standalone binary** — no Node.js or npm required:
|
|
162
231
|
|
|
163
|
-
|
|
164
|
-
|
|
232
|
+
| Platform | Download |
|
|
233
|
+
|---|---|
|
|
234
|
+
| macOS Apple Silicon | [`sigmap-darwin-arm64`](https://github.com/manojmallick/sigmap/releases/latest/download/sigmap-darwin-arm64) |
|
|
235
|
+
| macOS Intel | [`sigmap-darwin-x64`](https://github.com/manojmallick/sigmap/releases/latest/download/sigmap-darwin-x64) |
|
|
236
|
+
| Linux x64 | [`sigmap-linux-x64`](https://github.com/manojmallick/sigmap/releases/latest/download/sigmap-linux-x64) |
|
|
237
|
+
| Windows x64 | [`sigmap-win32-x64.exe`](https://github.com/manojmallick/sigmap/releases/latest/download/sigmap-win32-x64.exe) |
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# macOS / Linux
|
|
241
|
+
chmod +x ./sigmap-darwin-arm64
|
|
242
|
+
./sigmap-darwin-arm64 generate
|
|
165
243
|
```
|
|
166
244
|
|
|
167
|
-
|
|
245
|
+
See [docs/binaries.md](docs/binaries.md) for Gatekeeper / SmartScreen notes and checksum verification.
|
|
246
|
+
|
|
247
|
+
**npm** (requires Node.js 18+):
|
|
168
248
|
|
|
169
249
|
```bash
|
|
170
|
-
npx sigmap
|
|
171
|
-
npm install -g sigmap
|
|
172
|
-
sigmap # then use anywhere
|
|
250
|
+
npx sigmap # run once without installing
|
|
251
|
+
npm install -g sigmap # install globally
|
|
173
252
|
```
|
|
174
253
|
|
|
175
|
-
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### Generate context
|
|
257
|
+
|
|
258
|
+
Download the single-file CLI and generate context immediately:
|
|
176
259
|
|
|
177
260
|
```bash
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
261
|
+
sigmap # generate once and exit
|
|
262
|
+
sigmap --watch # regenerate on every file save
|
|
263
|
+
sigmap --setup # generate + install git hook + start watcher
|
|
264
|
+
sigmap --diff # context for git-changed files only (PR mode)
|
|
265
|
+
sigmap --diff --staged # staged files only (pre-commit check)
|
|
266
|
+
sigmap --health # show context health score (grade A–D)
|
|
267
|
+
sigmap --mcp # start MCP server on stdio
|
|
185
268
|
```
|
|
186
269
|
|
|
187
270
|
### Companion tool: Repomix
|
|
@@ -194,8 +277,8 @@ SigMap and [Repomix](https://github.com/yamadashy/repomix) are **complementary,
|
|
|
194
277
|
| **Repomix** | On-demand deep sessions, full file content, broader language support |
|
|
195
278
|
|
|
196
279
|
```bash
|
|
197
|
-
|
|
198
|
-
npx repomix --compress
|
|
280
|
+
sigmap --setup # always-on context
|
|
281
|
+
npx repomix --compress # deep dive sessions
|
|
199
282
|
```
|
|
200
283
|
|
|
201
284
|
*"SigMap for daily always-on context; Repomix for deep one-off sessions — use both."*
|
|
@@ -204,8 +287,6 @@ npx repomix --compress # deep dive sessions
|
|
|
204
287
|
|
|
205
288
|
## 🧩 VS Code extension
|
|
206
289
|
|
|
207
|
-
> Introduced in v1.5 — zero runtime npm dependencies.
|
|
208
|
-
|
|
209
290
|
The `vscode-extension/` directory contains a first-party VS Code extension that keeps you informed without any manual commands.
|
|
210
291
|
|
|
211
292
|
| Feature | Detail |
|
|
@@ -224,8 +305,6 @@ Activate on startup (`onStartupFinished`) — loads within 3 s, never blocks edi
|
|
|
224
305
|
|
|
225
306
|
## 🔧 JetBrains plugin
|
|
226
307
|
|
|
227
|
-
> Introduced in v2.9 — brings SigMap to IntelliJ IDEA, WebStorm, PyCharm, and all JetBrains IDEs.
|
|
228
|
-
|
|
229
308
|
The `jetbrains-plugin/` directory contains a Kotlin-based plugin for JetBrains IDEs with the same core features as the VS Code extension.
|
|
230
309
|
|
|
231
310
|
| Feature | Detail |
|
|
@@ -238,7 +317,7 @@ The `jetbrains-plugin/` directory contains a Kotlin-based plugin for JetBrains I
|
|
|
238
317
|
|
|
239
318
|
Compatible with **IntelliJ IDEA 2024.1+** (Community & Ultimate), **WebStorm**, **PyCharm**, **GoLand**, **RubyMine**, **PhpStorm**, and all other IntelliJ-based IDEs.
|
|
240
319
|
|
|
241
|
-
**Install:** [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/sigmap) | [Manual setup guide](docs/JETBRAINS_SETUP.md)
|
|
320
|
+
**Install:** [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/31109-sigmap--ai-context-engine/) | [Manual setup guide](docs/JETBRAINS_SETUP.md)
|
|
242
321
|
|
|
243
322
|
---
|
|
244
323
|
|
|
@@ -279,7 +358,7 @@ Compatible with **IntelliJ IDEA 2024.1+** (Community & Ultimate), **WebStorm**,
|
|
|
279
358
|
|
|
280
359
|
## 🗂 Context strategies
|
|
281
360
|
|
|
282
|
-
>
|
|
361
|
+
> Reduce always-injected tokens by 70–90%.
|
|
283
362
|
|
|
284
363
|
Set `"strategy"` in `gen-context.config.json`:
|
|
285
364
|
|
|
@@ -326,8 +405,6 @@ Recently committed files are **hot** (auto-injected). Everything else is **cold*
|
|
|
326
405
|
|
|
327
406
|
## 🔌 MCP server
|
|
328
407
|
|
|
329
|
-
> Introduced in v0.3, expanded to 8 tools through v2.3.
|
|
330
|
-
|
|
331
408
|
Start the MCP server on stdio:
|
|
332
409
|
|
|
333
410
|
```bash
|
|
@@ -345,7 +422,7 @@ node gen-context.js --mcp
|
|
|
345
422
|
| `list_modules` | — | Token-count table of all top-level module directories |
|
|
346
423
|
| `create_checkpoint` | `{ summary: string }` | Write a session checkpoint to `.context/` |
|
|
347
424
|
| `get_routing` | — | Full model routing table |
|
|
348
|
-
| `query_context` | `{ query: string, topK?: number }` | Files ranked by relevance to the query
|
|
425
|
+
| `query_context` | `{ query: string, topK?: number }` | Files ranked by relevance to the query |
|
|
349
426
|
|
|
350
427
|
Reads files on every call — no stale state, no restart needed.
|
|
351
428
|
|
|
@@ -355,7 +432,7 @@ Reads files on every call — no stale state, no restart needed.
|
|
|
355
432
|
|
|
356
433
|
## ⚙️ CLI reference
|
|
357
434
|
|
|
358
|
-
>
|
|
435
|
+
> See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
359
436
|
|
|
360
437
|
```
|
|
361
438
|
node gen-context.js Generate once and exit
|
|
@@ -441,6 +518,7 @@ Copy `gen-context.config.json.example` to `gen-context.config.json`:
|
|
|
441
518
|
|
|
442
519
|
```json
|
|
443
520
|
{
|
|
521
|
+
"output": ".github/copilot-instructions.md",
|
|
444
522
|
"srcDirs": ["src", "app", "lib"],
|
|
445
523
|
"maxTokens": 6000,
|
|
446
524
|
"outputs": ["copilot"],
|
|
@@ -451,6 +529,15 @@ Copy `gen-context.config.json.example` to `gen-context.config.json`:
|
|
|
451
529
|
}
|
|
452
530
|
```
|
|
453
531
|
|
|
532
|
+
**Key fields:**
|
|
533
|
+
|
|
534
|
+
- **`output`** — custom path for the primary markdown output file (used by `copilot` adapter). Default: `.github/copilot-instructions.md`
|
|
535
|
+
- **`outputs`** — which adapters to write to: `copilot` | `claude` | `cursor` | `windsurf`
|
|
536
|
+
- **`srcDirs`** — directories to scan (relative to project root)
|
|
537
|
+
- **`maxTokens`** — max tokens in final output before budget enforcement
|
|
538
|
+
- **`secretScan`** — redact secrets (AWS keys, tokens, etc.) from output
|
|
539
|
+
- **`strategy`** — output mode: `full` (default) | `per-module` | `hot-cold`
|
|
540
|
+
|
|
454
541
|
Exclusions go in `.contextignore` (gitignore syntax). Also reads `.repomixignore` if present.
|
|
455
542
|
|
|
456
543
|
```
|
|
@@ -468,12 +555,25 @@ Run `node gen-context.js --init` to scaffold both files in one step.
|
|
|
468
555
|
|
|
469
556
|
| Key | Output file | Read by |
|
|
470
557
|
|---|---|---|
|
|
471
|
-
| `"copilot"` | `.github/copilot-instructions.md` | GitHub Copilot |
|
|
558
|
+
| `"copilot"` | `.github/copilot-instructions.md` *(or custom path via `output`)* | GitHub Copilot |
|
|
472
559
|
| `"claude"` | `CLAUDE.md` (appends below marker) | Claude Code |
|
|
473
560
|
| `"cursor"` | `.cursorrules` | Cursor |
|
|
474
561
|
| `"windsurf"` | `.windsurfrules` | Windsurf |
|
|
475
562
|
|
|
476
|
-
|
|
563
|
+
The **`output`** config key sets the primary output file path. It is used by the `copilot` adapter when enabled. Other adapters always write to their fixed paths.
|
|
564
|
+
|
|
565
|
+
**Example:**
|
|
566
|
+
|
|
567
|
+
```json
|
|
568
|
+
{
|
|
569
|
+
"output": ".context/ai-context.md",
|
|
570
|
+
"outputs": ["copilot"]
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
This writes to `.context/ai-context.md` instead of `.github/copilot-instructions.md`.
|
|
575
|
+
|
|
576
|
+
If `output` is omitted, the default `.github/copilot-instructions.md` is used.
|
|
477
577
|
|
|
478
578
|
## 📊 Observability
|
|
479
579
|
|
|
@@ -517,7 +617,7 @@ node gen-context.js --format cache
|
|
|
517
617
|
|
|
518
618
|
---
|
|
519
619
|
|
|
520
|
-
## 📦 Programmatic API
|
|
620
|
+
## 📦 Programmatic API
|
|
521
621
|
|
|
522
622
|
Use SigMap as a library — no CLI subprocess needed:
|
|
523
623
|
|
|
@@ -652,61 +752,6 @@ sigmap/
|
|
|
652
752
|
|
|
653
753
|
---
|
|
654
754
|
|
|
655
|
-
## 📦 Publishing to npm
|
|
656
|
-
|
|
657
|
-
Releases are published automatically via GitHub Actions whenever a version tag is pushed.
|
|
658
|
-
|
|
659
|
-
### One-time setup
|
|
660
|
-
|
|
661
|
-
1. **Create an npm account** at [npmjs.com](https://www.npmjs.com) (if you haven't already).
|
|
662
|
-
|
|
663
|
-
2. **Generate an npm access token**:
|
|
664
|
-
- npmjs.com → Account → Access Tokens → Generate New Token → **Granular Access Token** (or Classic Automation token)
|
|
665
|
-
- Scope: `sigmap` package, permission: **Read and Write**
|
|
666
|
-
|
|
667
|
-
3. **Add the secret to GitHub**:
|
|
668
|
-
```
|
|
669
|
-
GitHub repo → Settings → Secrets and variables → Actions → New repository secret
|
|
670
|
-
Name: NPM_TOKEN
|
|
671
|
-
Value: <paste token>
|
|
672
|
-
```
|
|
673
|
-
|
|
674
|
-
### Releasing a new version
|
|
675
|
-
|
|
676
|
-
```bash
|
|
677
|
-
# 1. Bump version in package.json
|
|
678
|
-
npm version patch # or minor / major
|
|
679
|
-
|
|
680
|
-
# 2. Push the commit AND the new tag
|
|
681
|
-
git push && git push --tags
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
The [npm-publish workflow](.github/workflows/npm-publish.yml) will:
|
|
685
|
-
1. Run the full test suite
|
|
686
|
-
2. Verify `package.json` version matches the pushed tag
|
|
687
|
-
3. Publish to npm with provenance attestation
|
|
688
|
-
4. Create a GitHub Release with auto-generated notes
|
|
689
|
-
|
|
690
|
-
### Backfilling historical versions
|
|
691
|
-
|
|
692
|
-
Tags that existed before the workflow was set up can be published retroactively:
|
|
693
|
-
|
|
694
|
-
```bash
|
|
695
|
-
# Dry run first — see what would be published
|
|
696
|
-
./scripts/backfill-npm.sh
|
|
697
|
-
|
|
698
|
-
# Actually publish all historical tags
|
|
699
|
-
export NPM_TOKEN=npm_xxxxxxxxxxxx
|
|
700
|
-
./scripts/backfill-npm.sh --publish
|
|
701
|
-
|
|
702
|
-
# Start from a specific tag
|
|
703
|
-
./scripts/backfill-npm.sh --publish --from v0.5.0
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
The script assigns `dist-tag: legacy` to all versions except `v1.5.0` (which gets `latest`), so `npm install sigmap` always resolves to the current release.
|
|
707
|
-
|
|
708
|
-
---
|
|
709
|
-
|
|
710
755
|
## 🤝 Contributing
|
|
711
756
|
|
|
712
757
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for how to add a language extractor or new feature.
|
package/gen-context.js
CHANGED
|
@@ -1892,6 +1892,152 @@ __factories["./src/extractors/yaml"] = function(module, exports) {
|
|
|
1892
1892
|
|
|
1893
1893
|
};
|
|
1894
1894
|
|
|
1895
|
+
// ── ./src/extractors/todos ──
|
|
1896
|
+
__factories["./src/extractors/todos"] = function(module, exports) {
|
|
1897
|
+
|
|
1898
|
+
'use strict';
|
|
1899
|
+
|
|
1900
|
+
/**
|
|
1901
|
+
* Extract TODO/FIXME/HACK/XXX comments from source text.
|
|
1902
|
+
* @param {string} src - Raw file content
|
|
1903
|
+
* @returns {{line:number, tag:string, text:string}[]}
|
|
1904
|
+
*/
|
|
1905
|
+
function extractTodos(src) {
|
|
1906
|
+
if (!src || typeof src !== 'string') return [];
|
|
1907
|
+
const todos = [];
|
|
1908
|
+
const lines = src.split('\n');
|
|
1909
|
+
|
|
1910
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1911
|
+
const m = lines[i].match(/(?:\/\/|#)\s*(TODO|FIXME|HACK|XXX)\s*:?\s*(.+)/i);
|
|
1912
|
+
if (!m) continue;
|
|
1913
|
+
todos.push({
|
|
1914
|
+
line: i + 1,
|
|
1915
|
+
tag: m[1].toUpperCase(),
|
|
1916
|
+
text: m[2].trim().slice(0, 70),
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
return todos;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
module.exports = { extractTodos };
|
|
1924
|
+
|
|
1925
|
+
};
|
|
1926
|
+
|
|
1927
|
+
// ── ./src/extractors/coverage ──
|
|
1928
|
+
__factories["./src/extractors/coverage"] = function(module, exports) {
|
|
1929
|
+
|
|
1930
|
+
'use strict';
|
|
1931
|
+
|
|
1932
|
+
const fs = require('fs');
|
|
1933
|
+
const path = require('path');
|
|
1934
|
+
|
|
1935
|
+
function walkFiles(dir) {
|
|
1936
|
+
let out = [];
|
|
1937
|
+
let entries;
|
|
1938
|
+
try {
|
|
1939
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1940
|
+
} catch (_) {
|
|
1941
|
+
return out;
|
|
1942
|
+
}
|
|
1943
|
+
for (const entry of entries) {
|
|
1944
|
+
const full = path.join(dir, entry.name);
|
|
1945
|
+
if (entry.isDirectory()) out = out.concat(walkFiles(full));
|
|
1946
|
+
else if (entry.isFile()) out.push(full);
|
|
1947
|
+
}
|
|
1948
|
+
return out;
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
function buildTestIndex(cwd, testDirs) {
|
|
1952
|
+
const dirs = Array.isArray(testDirs) && testDirs.length ? testDirs : ['tests', 'test', '__tests__', 'spec'];
|
|
1953
|
+
const names = new Set();
|
|
1954
|
+
|
|
1955
|
+
for (const dir of dirs) {
|
|
1956
|
+
const abs = path.join(cwd, dir);
|
|
1957
|
+
if (!fs.existsSync(abs)) continue;
|
|
1958
|
+
for (const file of walkFiles(abs)) {
|
|
1959
|
+
let src = '';
|
|
1960
|
+
try {
|
|
1961
|
+
src = fs.readFileSync(file, 'utf8');
|
|
1962
|
+
} catch (_) {
|
|
1963
|
+
continue;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
for (const m of src.matchAll(/\b(?:test_|it\(|test\(|describe\()\s*['"`]?([\w_]+)/g)) {
|
|
1967
|
+
if (m[1] && m[1].length >= 3) names.add(m[1].toLowerCase());
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
for (const m of src.matchAll(/\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g)) {
|
|
1971
|
+
if (m[1] && m[1].length >= 4) names.add(m[1].toLowerCase());
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
return names;
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
function isTested(funcName, testIndex) {
|
|
1980
|
+
if (!funcName || funcName.length < 3 || !testIndex || testIndex.size === 0) return false;
|
|
1981
|
+
const lower = funcName.toLowerCase();
|
|
1982
|
+
if (testIndex.has(lower) || testIndex.has(`test_${lower}`)) return true;
|
|
1983
|
+
return false;
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
module.exports = { buildTestIndex, isTested };
|
|
1987
|
+
|
|
1988
|
+
};
|
|
1989
|
+
|
|
1990
|
+
// ── ./src/extractors/prdiff ──
|
|
1991
|
+
__factories["./src/extractors/prdiff"] = function(module, exports) {
|
|
1992
|
+
|
|
1993
|
+
'use strict';
|
|
1994
|
+
|
|
1995
|
+
/**
|
|
1996
|
+
* Compare signature arrays and produce compact diff markers.
|
|
1997
|
+
* @param {string[]} baseSigs
|
|
1998
|
+
* @param {string[]} currentSigs
|
|
1999
|
+
* @returns {{added:string[], removed:string[], modified:string[]}}
|
|
2000
|
+
*/
|
|
2001
|
+
function diffSignatures(baseSigs, currentSigs) {
|
|
2002
|
+
const base = new Set(baseSigs || []);
|
|
2003
|
+
const curr = new Set(currentSigs || []);
|
|
2004
|
+
|
|
2005
|
+
const added = [...curr].filter((s) => !base.has(s));
|
|
2006
|
+
const removed = [...base].filter((s) => !curr.has(s));
|
|
2007
|
+
|
|
2008
|
+
const byName = (arr) => {
|
|
2009
|
+
const m = new Map();
|
|
2010
|
+
for (const s of arr) {
|
|
2011
|
+
const n = extractName(s);
|
|
2012
|
+
if (!n) continue;
|
|
2013
|
+
if (!m.has(n)) m.set(n, []);
|
|
2014
|
+
m.get(n).push(s);
|
|
2015
|
+
}
|
|
2016
|
+
return m;
|
|
2017
|
+
};
|
|
2018
|
+
|
|
2019
|
+
const aBy = byName(added);
|
|
2020
|
+
const rBy = byName(removed);
|
|
2021
|
+
const modified = [];
|
|
2022
|
+
|
|
2023
|
+
for (const [name] of aBy) {
|
|
2024
|
+
if (rBy.has(name)) modified.push(name);
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
return { added, removed, modified };
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
function extractName(sig) {
|
|
2031
|
+
if (!sig) return '';
|
|
2032
|
+
const t = sig.trim();
|
|
2033
|
+
const m = t.match(/(?:def|function|func|class|interface|trait|struct|enum|record)?\s*([A-Za-z_][A-Za-z0-9_]*)\s*(?:\(|$)/);
|
|
2034
|
+
return m ? m[1] : '';
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
module.exports = { diffSignatures, extractName };
|
|
2038
|
+
|
|
2039
|
+
};
|
|
2040
|
+
|
|
1895
2041
|
// ── ./src/format/cache ──
|
|
1896
2042
|
__factories["./src/format/cache"] = function(module, exports) {
|
|
1897
2043
|
|
|
@@ -5445,6 +5591,29 @@ function ensureDir(filePath) {
|
|
|
5445
5591
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
5446
5592
|
}
|
|
5447
5593
|
|
|
5594
|
+
// ---------------------------------------------------------------------------
|
|
5595
|
+
// Resolve output path for a given adapter
|
|
5596
|
+
// ---------------------------------------------------------------------------
|
|
5597
|
+
// Takes config.output into account for the copilot adapter.
|
|
5598
|
+
// Returns the full path where output should be written.
|
|
5599
|
+
function resolveAdapterPath(adapter, cwd, config) {
|
|
5600
|
+
config = config || {};
|
|
5601
|
+
|
|
5602
|
+
// Copilot uses config.output if available, otherwise default
|
|
5603
|
+
if (adapter === 'copilot') {
|
|
5604
|
+
return config.output
|
|
5605
|
+
? path.join(cwd, config.output)
|
|
5606
|
+
: path.join(cwd, '.github', 'copilot-instructions.md');
|
|
5607
|
+
}
|
|
5608
|
+
|
|
5609
|
+
// Fixed paths for other adapters
|
|
5610
|
+
if (adapter === 'claude') return path.join(cwd, 'CLAUDE.md');
|
|
5611
|
+
if (adapter === 'cursor') return path.join(cwd, '.cursorrules');
|
|
5612
|
+
if (adapter === 'windsurf') return path.join(cwd, '.windsurfrules');
|
|
5613
|
+
|
|
5614
|
+
return null;
|
|
5615
|
+
}
|
|
5616
|
+
|
|
5448
5617
|
// ---------------------------------------------------------------------------
|
|
5449
5618
|
// Cache output writer (v0.8)
|
|
5450
5619
|
// ---------------------------------------------------------------------------
|
|
@@ -5460,14 +5629,15 @@ function writeCacheOutput(content, cwd) {
|
|
|
5460
5629
|
}
|
|
5461
5630
|
}
|
|
5462
5631
|
|
|
5463
|
-
function writeOutputs(content, targets, cwd) {
|
|
5632
|
+
function writeOutputs(content, targets, cwd, config) {
|
|
5633
|
+
config = config || {};
|
|
5464
5634
|
// v3.0+: adapter-aware output targets
|
|
5465
5635
|
const ADAPTER_TARGETS = new Set(['openai', 'gemini']);
|
|
5466
5636
|
|
|
5467
5637
|
const targetMap = {
|
|
5468
|
-
copilot:
|
|
5469
|
-
cursor:
|
|
5470
|
-
windsurf:
|
|
5638
|
+
copilot: resolveAdapterPath('copilot', cwd, config),
|
|
5639
|
+
cursor: resolveAdapterPath('cursor', cwd, config),
|
|
5640
|
+
windsurf: resolveAdapterPath('windsurf', cwd, config),
|
|
5471
5641
|
};
|
|
5472
5642
|
|
|
5473
5643
|
for (const target of targets) {
|
|
@@ -5709,7 +5879,7 @@ function runPerModuleStrategy(cwd, config, fileEntries, inputTokenTotal) {
|
|
|
5709
5879
|
overviewLines.push('> For cross-module questions load both files.');
|
|
5710
5880
|
const overviewContent = overviewLines.join('\n') + '\n';
|
|
5711
5881
|
const primaryTargets = (config.outputs || ['copilot']).filter((t) => t !== 'claude');
|
|
5712
|
-
writeOutputs(overviewContent, primaryTargets, cwd);
|
|
5882
|
+
writeOutputs(overviewContent, primaryTargets, cwd, config);
|
|
5713
5883
|
|
|
5714
5884
|
const overviewTokens = estimateTokens(overviewContent);
|
|
5715
5885
|
console.warn(`[sigmap] per-module: overview ~${overviewTokens} tokens (always-on), modules total ~${totalOut} tokens (on-demand)`);
|
|
@@ -5728,7 +5898,7 @@ function runHotColdStrategy(cwd, config, fileEntries, recentFiles, inputTokenTot
|
|
|
5728
5898
|
? formatOutput(hotEntries, cwd, false, config, null)
|
|
5729
5899
|
: '<!-- Generated by SigMap — no recently changed files -->\n';
|
|
5730
5900
|
const primaryTargets = (config.outputs || ['copilot']).filter((t) => t !== 'claude');
|
|
5731
|
-
writeOutputs(hotContent, primaryTargets, cwd);
|
|
5901
|
+
writeOutputs(hotContent, primaryTargets, cwd, config);
|
|
5732
5902
|
const hotTokens = estimateTokens(hotContent);
|
|
5733
5903
|
|
|
5734
5904
|
// Cold → .github/context-cold.md (MCP reads this on demand)
|
|
@@ -5831,7 +6001,7 @@ function runDiff(cwd, config, stagedOnly, baseRef) {
|
|
|
5831
6001
|
const diffSection = baseRef ? buildDiffSectionFromBase(cwd, baseRef, fileEntries, config) : [];
|
|
5832
6002
|
const content = formatOutput(fileEntries, cwd, routingEnabled, config, { diffSection });
|
|
5833
6003
|
const finalTokens = estimateTokens(content);
|
|
5834
|
-
writeOutputs(content, config.outputs, cwd);
|
|
6004
|
+
writeOutputs(content, config.outputs, cwd, config);
|
|
5835
6005
|
|
|
5836
6006
|
const scope = baseRef ? `diff-vs-${baseRef}` : (stagedOnly ? 'staged' : 'diff');
|
|
5837
6007
|
console.warn(`[sigmap] ${scope} files: ${fileEntries.length}, diff tokens: ~${finalTokens}`);
|
|
@@ -5940,7 +6110,7 @@ function runGenerate(cwd, config, reportMode, reportJson = false) {
|
|
|
5940
6110
|
const finalTokens = estimateTokens(content);
|
|
5941
6111
|
const formatIdx = process.argv.indexOf('--format');
|
|
5942
6112
|
const formatValue = formatIdx >= 0 ? process.argv[formatIdx + 1] : (config.format || 'default');
|
|
5943
|
-
writeOutputs(content, config.outputs, cwd);
|
|
6113
|
+
writeOutputs(content, config.outputs, cwd, config);
|
|
5944
6114
|
if (formatValue === 'cache') writeCacheOutput(content, cwd);
|
|
5945
6115
|
result = { inputTokenTotal, finalTokens, fileCount: beforeCount, droppedCount };
|
|
5946
6116
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "3.0.1",
|
|
3
|
+
"version": "3.1.0-alpha.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": {
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"report": "node gen-context.js --report",
|
|
26
26
|
"health": "node gen-context.js --health",
|
|
27
27
|
"map": "node gen-project-map.js",
|
|
28
|
-
"mcp": "node gen-context.js --mcp"
|
|
28
|
+
"mcp": "node gen-context.js --mcp",
|
|
29
|
+
"build:binary": "node scripts/build-binary.mjs",
|
|
30
|
+
"verify:binary": "node scripts/verify-binary.mjs"
|
|
29
31
|
},
|
|
30
32
|
"files": [
|
|
31
33
|
"gen-context.js",
|