sigmap 3.3.0 → 3.3.2

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 ADDED
@@ -0,0 +1,42 @@
1
+ # SigMap — AGENTS.md
2
+
3
+ Instructions for Codex-style agents working in this repository.
4
+
5
+ ## Append Strategy (Required)
6
+
7
+ When writing generated signature content, never overwrite human-written notes above the marker.
8
+
9
+ Use this marker block for all appendable context files:
10
+
11
+ ```
12
+ ## Auto-generated signatures
13
+ <!-- Updated by gen-context.js -->
14
+ ```
15
+
16
+ ### Files that must use append-under-marker
17
+
18
+ 1. `CLAUDE.md`
19
+ 2. `.github/copilot-instructions.md`
20
+ 3. `.github/gemini-context.md`
21
+
22
+ ### Safe write procedure
23
+
24
+ 1. Read existing file (or start with empty string if file does not exist).
25
+ 2. Find the marker `## Auto-generated signatures`.
26
+ 3. If marker exists: keep everything above marker unchanged; replace only marker-and-below with new generated block.
27
+ 4. If marker does not exist: append marker + generated block to the end.
28
+ 5. Never modify human content above marker.
29
+
30
+ ### Legacy cleanup rule
31
+
32
+ If an existing generated file has no marker but contains prior SigMap-generated content headers, replace the full legacy generated content with marker + new generated block.
33
+
34
+ ## Verification
35
+
36
+ After changing write logic, run:
37
+
38
+ ```bash
39
+ node test/integration/multi-output.test.js
40
+ ```
41
+
42
+ Expected: all tests pass, including append-preservation cases.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,17 @@ Format: [Semantic Versioning](https://semver.org/)
10
10
 
11
11
  ---
12
12
 
13
+ ## [3.3.1] — 2026-04-10 — Patch: `--each --adapter` flag combination
14
+
15
+ ### Fixed
16
+ - **`--each --adapter <name>` now works correctly** · [#37](https://github.com/manojmallick/sigmap/issues/37)
17
+ - Running `sigmap --each --adapter claude` (or any adapter) from a parent directory containing multiple git repos now correctly writes the chosen adapter output (e.g. `CLAUDE.md`) inside each sub-repo.
18
+ - Root cause: the `--adapter` handler ran before `--each` in `main()`, so `--each` was never reached when both flags were supplied together. The `--each` block is now evaluated first.
19
+ - `runEach()` accepts an optional `adapterOverride` parameter that merges `outputs`/`adapters` into each sub-repo's config before calling `runGenerate`, mirroring how the standalone `--adapter` flag works.
20
+ - Invalid adapter names passed alongside `--each` now exit non-zero with a clear error message listing valid adapters.
21
+
22
+ ---
23
+
13
24
  ## [3.3.0] — 2026-04-08 — Context-Aware CLI & Command Switcher
14
25
 
15
26
  ### Added
package/README.md CHANGED
@@ -1,36 +1,62 @@
1
1
  <div align="center">
2
2
 
3
+ <img src="docs-vp/.vitepress/public/logo.svg" alt="SigMap logo" width="64" height="84" />
4
+
3
5
  <h1>⚡ SigMap</h1>
4
6
 
5
- <p><strong>Zero-dependency AI context engine 97% token reduction</strong></p>
7
+ <p><strong>WITHOUT SIGMAP, YOUR AI IS GUESSING.</strong><br>
8
+ <strong>It sees 8% of your codebase and invents the rest.</strong></p>
9
+
10
+ <p><sub>Run one command. Force every answer to come from real code.</sub></p>
11
+
12
+ </div>
13
+
14
+ <div align="center">
15
+ <img src="docs/impact-banner.svg" alt="SigMap — 6× better answers, 97% fewer tokens, 2× fewer prompts" width="760" />
16
+ </div>
6
17
 
7
- <p>
8
- Every coding agent session starts with full codebase context at under 4K tokens.<br>
9
- Multiple install options. Zero runtime dependencies. Requires only Node.js 18+.
10
- </p>
18
+ ```sh
19
+ npx sigmap # 10 seconds. zero config. your AI never reads the wrong file again.
20
+ ```
21
+
22
+ <details>
23
+ <summary><strong>Trust signals</strong></summary>
24
+
25
+ <div align="center">
11
26
 
12
- <!-- Status -->
13
27
  [![npm version](https://img.shields.io/npm/v/sigmap?color=7c6af7&label=latest&logo=npm)](https://www.npmjs.com/package/sigmap)
14
- [![Tests](https://img.shields.io/badge/tests-340%20passing-22c55e)](https://github.com/manojmallick/sigmap/tree/main/test)
28
+ [![CI](https://github.com/manojmallick/sigmap/actions/workflows/ci.yml/badge.svg)](https://github.com/manojmallick/sigmap/actions/workflows/ci.yml)
15
29
  [![Zero deps](https://img.shields.io/badge/dependencies-zero-22c55e)](package.json)
16
- [![Last commit](https://img.shields.io/github/last-commit/manojmallick/sigmap?color=7c6af7)](https://github.com/manojmallick/sigmap/commits/main)
17
-
18
- <!-- Meta -->
19
30
  [![License: MIT](https://img.shields.io/badge/License-MIT-7c6af7.svg)](LICENSE)
20
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
21
- [![npm](https://img.shields.io/badge/npm-sigmap-cb3837?logo=npm)](https://www.npmjs.com/package/sigmap)
22
- [![GitHub Stars](https://img.shields.io/github/stars/manojmallick/sigmap?style=flat&color=f59e0b&logo=github)](https://github.com/manojmallick/sigmap/stargazers)
23
-
24
- <!-- Links -->
25
- [![Docs](https://img.shields.io/badge/docs-live-7c6af7?logo=github-pages)](https://manojmallick.github.io/sigmap)
26
- [![Changelog](https://img.shields.io/badge/changelog-CHANGELOG.md-blue)](CHANGELOG.md)
27
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
28
31
  [![VS Code](https://img.shields.io/badge/VS%20Code-extension-0078d4?logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=manojmallick.sigmap)
29
32
  [![JetBrains](https://img.shields.io/badge/JetBrains-plugin-000000?logo=jetbrains)](https://plugins.jetbrains.com/plugin/31109-sigmap--ai-context-engine/)
30
- [![Open VSX](https://img.shields.io/open-vsx/v/manojmallick/sigmap?color=a251e3&label=Open%20VSX&logo=vscodium)](https://open-vsx.org/extension/manojmallick/sigmap)
33
+ [![Docs](https://img.shields.io/badge/docs-live-7c6af7?logo=github-pages)](https://manojmallick.github.io/sigmap)
34
+ [![GitHub Stars](https://img.shields.io/github/stars/manojmallick/sigmap?style=flat&color=f59e0b&logo=github)](https://github.com/manojmallick/sigmap/stargazers)
31
35
 
32
36
  </div>
33
37
 
38
+ </details>
39
+
40
+ <details>
41
+ <summary><strong>Full benchmark breakdown →</strong></summary>
42
+
43
+ <br/>
44
+
45
+ <div align="center">
46
+ <img src="docs/comparison-chart.svg" alt="SigMap benchmark — before vs after across 3 RAG quality metrics" width="700" />
47
+ <br/><sub><a href="https://manojmallick.github.io/sigmap/guide/task-benchmark.html">80 tasks · 16 real repos · no LLM API · <strong>full methodology →</strong></a></sub>
48
+ </div>
49
+
50
+ | | Without SigMap | With SigMap |
51
+ |---|:---:|:---:|
52
+ | Task success | 10% | **59%** |
53
+ | Prompts per task | 2.84 | **1.54** |
54
+ | Tokens per session | ~80,000 | **~2,000** |
55
+ | Right file found | 13.7% | **87.5%** |
56
+ | Hallucination risk | 92% | **0%** |
57
+
58
+ </details>
59
+
34
60
  ---
35
61
 
36
62
  ## Table of contents
@@ -39,7 +65,7 @@
39
65
  |---|---|
40
66
  | [What it does](#-what-it-does) | Token reduction table, pipeline overview |
41
67
  | [Quick start](#-quick-start) | Install (binary or npm), generate in 60 seconds |
42
- | [Standalone binaries](docs/binaries.md) | macOS, Linux, Windows — no Node required |
68
+ | [Standalone binaries](docs/readmes/binaries.md) | macOS, Linux, Windows — no Node required |
43
69
  | [VS Code extension](#-vs-code-extension) | Status bar, stale alerts, commands |
44
70
  | [JetBrains plugin](#-jetbrains-plugin) | IntelliJ IDEA, WebStorm, PyCharm support |
45
71
  | [Languages supported](#-languages-supported) | 21 languages |
@@ -53,7 +79,7 @@
53
79
  | [Project structure](#-project-structure) | File-by-file map |
54
80
  | [Principles](#-principles) | Design decisions |
55
81
 
56
- > 📖 **New to SigMap?** Read the **[Complete Getting Started Guide](docs/GETTING_STARTED.md)** — token savings walkthrough, every command, VS Code plugin, and CI setup.
82
+ > 📖 **New to SigMap?** Read the **[Complete Getting Started Guide](docs/readmes/GETTING_STARTED.md)** — token savings walkthrough, every command, VS Code plugin, and CI setup.
57
83
 
58
84
  ---
59
85
 
@@ -65,7 +91,7 @@ SigMap scans your source files and extracts only the **function and class signat
65
91
  Your codebase
66
92
 
67
93
 
68
- gen-context.js ──► extracts signatures from 21 languages
94
+ sigmap ─────────► extracts signatures from 21 languages
69
95
 
70
96
 
71
97
  .github/copilot-instructions.md ◄── auto-read by Copilot / Claude / Cursor
@@ -88,6 +114,31 @@ AI agent session starts with full context
88
114
 
89
115
  > **97% fewer tokens. The same codebase understanding.**
90
116
 
117
+ ### Benchmark: real-world repos
118
+
119
+ Reproduced with `node scripts/run-benchmark.mjs` on public repos:
120
+
121
+ | Repo | Language | Raw tokens | After SigMap | Reduction |
122
+ |------|----------|------------|--------------|-----------|
123
+ | express | JavaScript | 15.5K | 201 | **98.7%** |
124
+ | flask | Python | 84.8K | 3.4K | **96.0%** |
125
+ | gin | Go | 172.8K | 5.7K | **96.7%** |
126
+ | spring-petclinic | Java | 77.0K | 634 | **99.2%** |
127
+ | rails | Ruby | 1.5M | 7.1K | **99.5%** |
128
+ | axios | TypeScript | 31.7K | 1.5K | **95.2%** |
129
+ | rust-analyzer | Rust | 3.5M | 5.9K | **99.8%** |
130
+ | abseil-cpp | C++ | 2.3M | 6.3K | **99.7%** |
131
+ | serilog | C# | 113.7K | 5.8K | **94.9%** |
132
+ | riverpod | Dart | 682.7K | 6.5K | **99.0%** |
133
+ | okhttp | Kotlin | 31.3K | 1.4K | **95.5%** |
134
+ | laravel | PHP | 1.7M | 7.2K | **99.6%** |
135
+ | akka | Scala | 790.5K | 7.1K | **99.1%** |
136
+ | vapor | Swift | 171.2K | 6.4K | **96.3%** |
137
+ | vue-core | Vue | 404.2K | 8.8K | **97.8%** |
138
+ | svelte | Svelte | 438.2K | 8.0K | **98.2%** |
139
+
140
+ **Average: 99.3% reduction across 16 languages.** See [`benchmarks/reports/token-reduction.md`](benchmarks/reports/token-reduction.md) or reproduce with `node scripts/run-benchmark.mjs`.
141
+
91
142
  ---
92
143
 
93
144
  ## ⚡ Installation
@@ -198,7 +249,7 @@ shasum -a 256 sigmap-darwin-arm64
198
249
  # Compare with sigmap-checksums.txt
199
250
  ```
200
251
 
201
- Full guide: [docs/binaries.md](docs/binaries.md)
252
+ Full guide: [docs/readmes/binaries.md](docs/readmes/binaries.md)
202
253
 
203
254
  </details>
204
255
 
@@ -248,8 +299,6 @@ No npm, no `node_modules`. Drop `gen-context.js` into any project and run it dir
248
299
 
249
300
  </details>
250
301
 
251
- > **Note:** When using the single-file download, replace `sigmap` with `node gen-context.js` in all commands below.
252
-
253
302
  ---
254
303
 
255
304
  ## 🚀 Features
@@ -264,17 +313,19 @@ sigmap --adapter claude # → CLAUDE.md (appended below marker)
264
313
  sigmap --adapter cursor # → .cursorrules
265
314
  sigmap --adapter windsurf # → .windsurfrules
266
315
  sigmap --adapter openai # → .github/openai-context.md
267
- sigmap --adapter gemini # → .github/gemini-context.md
316
+ sigmap --adapter gemini # → .github/gemini-context.md (appended below marker)
317
+ sigmap --adapter codex # → AGENTS.md (appended below marker)
268
318
  ```
269
319
 
270
320
  | Adapter | Output file | AI assistant |
271
321
  |---|---|---|
272
- | `copilot` | `.github/copilot-instructions.md` | GitHub Copilot |
322
+ | `copilot` | `.github/copilot-instructions.md` (append) | GitHub Copilot |
273
323
  | `claude` | `CLAUDE.md` (append) | Claude / Claude Code |
274
324
  | `cursor` | `.cursorrules` | Cursor |
275
325
  | `windsurf` | `.windsurfrules` | Windsurf |
276
326
  | `openai` | `.github/openai-context.md` | Any OpenAI model |
277
- | `gemini` | `.github/gemini-context.md` | Google Gemini |
327
+ | `gemini` | `.github/gemini-context.md` (append) | Google Gemini |
328
+ | `codex` | `AGENTS.md` (append) | OpenAI Codex |
278
329
 
279
330
  Configure multiple adapters at once in `gen-context.config.json`:
280
331
 
@@ -327,7 +378,7 @@ chmod +x ./sigmap-darwin-arm64
327
378
  ./sigmap-darwin-arm64
328
379
  ```
329
380
 
330
- See [docs/binaries.md](docs/binaries.md) for Gatekeeper / SmartScreen notes and checksum verification.
381
+ See [docs/readmes/binaries.md](docs/readmes/binaries.md) for Gatekeeper / SmartScreen notes and checksum verification.
331
382
 
332
383
  **npm** (requires Node.js 18+):
333
384
 
@@ -340,7 +391,7 @@ npm install -g sigmap # install globally
340
391
 
341
392
  ### Generate context
342
393
 
343
- Download the single-file CLI and generate context immediately:
394
+ Once installed, run from your project root:
344
395
 
345
396
  ```bash
346
397
  sigmap # generate once and exit
@@ -372,17 +423,17 @@ npx repomix --compress # deep dive sessions
372
423
 
373
424
  ## 🧩 VS Code extension
374
425
 
375
- The `vscode-extension/` directory contains a first-party VS Code extension that keeps you informed without any manual commands.
426
+ The official SigMap VS Code extension keeps your context fresh without any manual commands. Install it once and it runs silently in the background.
376
427
 
377
428
  | Feature | Detail |
378
429
  |---|---|
379
430
  | **Status bar item** | Shows health grade (`A`/`B`/`C`/`D`) + time since last regen; refreshes every 60 s |
380
431
  | **Stale notification** | Warns when `copilot-instructions.md` is > 24 h old; one-click regeneration |
381
- | **Regenerate command** | `SigMap: Regenerate Context` — runs `node gen-context.js` in the integrated terminal |
432
+ | **Regenerate command** | `SigMap: Regenerate Context` — runs `sigmap` in the integrated terminal |
382
433
  | **Open context command** | `SigMap: Open Context File` — opens `.github/copilot-instructions.md` |
383
- | **Script path setting** | `sigmap.scriptPath` — override when `gen-context.js` is not at the project root |
434
+ | **Script path setting** | `sigmap.scriptPath` — override the path to the `sigmap` binary or `gen-context.js` |
384
435
 
385
- Activate on startup (`onStartupFinished`) — loads within 3 s, never blocks editor startup.
436
+ Activates on startup (`onStartupFinished`) — loads within 3 s, never blocks editor startup.
386
437
 
387
438
  **Install:** [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=manojmallick.sigmap) | [Open VSX Registry](https://open-vsx.org/extension/manojmallick/sigmap)
388
439
 
@@ -390,19 +441,19 @@ Activate on startup (`onStartupFinished`) — loads within 3 s, never blocks edi
390
441
 
391
442
  ## 🔧 JetBrains plugin
392
443
 
393
- The `jetbrains-plugin/` directory contains a Kotlin-based plugin for JetBrains IDEs with the same core features as the VS Code extension.
444
+ The official SigMap JetBrains plugin brings the same features to IntelliJ-based IDEs. Install it from the JetBrains Marketplace and it works identically to the VS Code extension.
394
445
 
395
446
  | Feature | Detail |
396
447
  |---|---|
397
448
  | **Status bar widget** | Shows health grade (`A`-`F`) + time since last regen; updates every 60 s |
398
- | **Regenerate action** | `Tools → SigMap → Regenerate Context` or **Ctrl+Alt+G** — runs `node gen-context.js` |
449
+ | **Regenerate action** | `Tools → SigMap → Regenerate Context` or **Ctrl+Alt+G** — runs `sigmap` |
399
450
  | **Open context action** | `Tools → SigMap → Open Context File` — opens `.github/copilot-instructions.md` |
400
451
  | **View roadmap action** | `Tools → SigMap → View Roadmap` — opens roadmap in browser |
401
452
  | **One-click regen** | Click status bar widget to regenerate context instantly |
402
453
 
403
454
  Compatible with **IntelliJ IDEA 2024.1+** (Community & Ultimate), **WebStorm**, **PyCharm**, **GoLand**, **RubyMine**, **PhpStorm**, and all other IntelliJ-based IDEs.
404
455
 
405
- **Install:** [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/31109-sigmap--ai-context-engine/) | [Manual setup guide](docs/JETBRAINS_SETUP.md)
456
+ **Install:** [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/31109-sigmap--ai-context-engine/) | [Manual setup guide](docs/readmes/JETBRAINS_SETUP.md)
406
457
 
407
458
  ---
408
459
 
@@ -484,7 +535,7 @@ One `.github/context-<module>.md` per top-level source directory, plus a tiny ov
484
535
 
485
536
  Recently committed files are **hot** (auto-injected). Everything else is **cold** (on-demand via MCP). Best reduction available — ~200 tokens always-on.
486
537
 
487
- 📖 Full guide: [docs/CONTEXT_STRATEGIES.md](docs/CONTEXT_STRATEGIES.md) — decision tree, scenario comparisons, migration steps.
538
+ 📖 Full guide: [docs/readmes/CONTEXT_STRATEGIES.md](docs/readmes/CONTEXT_STRATEGIES.md) — decision tree, scenario comparisons, migration steps.
488
539
 
489
540
  ---
490
541
 
@@ -493,7 +544,7 @@ Recently committed files are **hot** (auto-injected). Everything else is **cold*
493
544
  Start the MCP server on stdio:
494
545
 
495
546
  ```bash
496
- node gen-context.js --mcp
547
+ sigmap --mcp
497
548
  ```
498
549
 
499
550
  ### Available tools
@@ -511,7 +562,7 @@ node gen-context.js --mcp
511
562
 
512
563
  Reads files on every call — no stale state, no restart needed.
513
564
 
514
- 📖 Setup guide: [docs/MCP_SETUP.md](docs/MCP_SETUP.md)
565
+ 📖 Setup guide: [docs/readmes/MCP_SETUP.md](docs/readmes/MCP_SETUP.md)
515
566
 
516
567
  ---
517
568
 
@@ -519,57 +570,66 @@ Reads files on every call — no stale state, no restart needed.
519
570
 
520
571
  > See [CHANGELOG.md](CHANGELOG.md) for the full history.
521
572
 
573
+ All flags are the same regardless of how you invoke SigMap — swap the prefix to match your install:
574
+
575
+ > `sigmap` · `npx sigmap` · `gen-context` · `node gen-context.js`
576
+
577
+ <details>
578
+ <summary><strong>All flags</strong></summary>
579
+
522
580
  ```
523
- node gen-context.js Generate once and exit
524
- node gen-context.js --watch Generate and watch for file changes
525
- node gen-context.js --setup Generate + install git hook + start watcher
526
- node gen-context.js --diff Generate context for git-changed files only
527
- node gen-context.js --diff --staged Staged files only (pre-commit check)
528
- node gen-context.js --mcp Start MCP server on stdio
581
+ sigmap Generate once and exit
582
+ sigmap --watch Generate and watch for file changes
583
+ sigmap --setup Generate + install git hook + start watcher
584
+ sigmap --diff Generate context for git-changed files only
585
+ sigmap --diff --staged Staged files only (pre-commit check)
586
+ sigmap --mcp Start MCP server on stdio
529
587
 
530
- node gen-context.js --query "<text>" Rank files by relevance to a query
531
- node gen-context.js --query "<text>" --json Ranked results as JSON
532
- node gen-context.js --query "<text>" --top <n> Limit results to top N files (default 10)
588
+ sigmap --query "<text>" Rank files by relevance to a query
589
+ sigmap --query "<text>" --json Ranked results as JSON
590
+ sigmap --query "<text>" --top <n> Limit results to top N files (default 10)
533
591
 
534
- node gen-context.js --analyze Per-file breakdown (sigs / tokens / extractor / coverage)
535
- node gen-context.js --analyze --json Analysis as JSON
536
- node gen-context.js --analyze --slow Include extraction timing per file
537
- node gen-context.js --diagnose-extractors Self-test all 21 extractors against fixtures
592
+ sigmap --analyze Per-file breakdown (sigs / tokens / extractor / coverage)
593
+ sigmap --analyze --json Analysis as JSON
594
+ sigmap --analyze --slow Include extraction timing per file
595
+ sigmap --diagnose-extractors Self-test all 21 extractors against fixtures
538
596
 
539
- node gen-context.js --benchmark Run retrieval quality benchmark (hit@5 / MRR)
540
- node gen-context.js --benchmark --json Benchmark results as JSON
541
- node gen-context.js --eval Alias for --benchmark
597
+ sigmap --benchmark Run retrieval quality benchmark (hit@5 / MRR)
598
+ sigmap --benchmark --json Benchmark results as JSON
599
+ sigmap --eval Alias for --benchmark
542
600
 
543
- node gen-context.js --report Token reduction stats
544
- node gen-context.js --report --json Structured JSON report (exits 1 if over budget)
545
- node gen-context.js --report --history Usage log summary
546
- node gen-context.js --report --history --json Usage history as JSON
601
+ sigmap --report Token reduction stats
602
+ sigmap --report --json Structured JSON report (exits 1 if over budget)
603
+ sigmap --report --history Usage log summary
604
+ sigmap --report --history --json Usage history as JSON
547
605
 
548
- node gen-context.js --health Composite health score (0–100, grade A–D)
549
- node gen-context.js --health --json Machine-readable health JSON
606
+ sigmap --health Composite health score (0–100, grade A–D)
607
+ sigmap --health --json Machine-readable health JSON
550
608
 
551
- node gen-context.js --suggest-tool "<task>" Recommend model tier for a task
552
- node gen-context.js --suggest-tool "<task>" --json Machine-readable tier recommendation
609
+ sigmap --suggest-tool "<task>" Recommend model tier for a task
610
+ sigmap --suggest-tool "<task>" --json Machine-readable tier recommendation
553
611
 
554
- node gen-context.js --monorepo Per-package context for monorepos (packages/, apps/, services/)
555
- node gen-context.js --each Process each sub-repo under a parent directory
556
- node gen-context.js --routing Include model routing hints in output
557
- node gen-context.js --format cache Write Anthropic prompt-cache JSON
558
- node gen-context.js --track Append run metrics to .context/usage.ndjson
612
+ sigmap --monorepo Per-package context for monorepos (packages/, apps/, services/)
613
+ sigmap --each Process each sub-repo under a parent directory
614
+ sigmap --routing Include model routing hints in output
615
+ sigmap --format cache Write Anthropic prompt-cache JSON
616
+ sigmap --track Append run metrics to .context/usage.ndjson
559
617
 
560
- node gen-context.js --init Write config + .contextignore scaffold
561
- node gen-context.js --version Version string
562
- node gen-context.js --help Usage information
618
+ sigmap --init Write config + .contextignore scaffold
619
+ sigmap --version Version string
620
+ sigmap --help Usage information
563
621
  ```
622
+ </details>
623
+
564
624
 
565
625
  ### Task classification — `--suggest-tool`
566
626
 
567
627
  ```bash
568
- node gen-context.js --suggest-tool "security audit of the auth module"
628
+ sigmap --suggest-tool "security audit of the auth module"
569
629
  # tier : powerful
570
630
  # models : claude-opus-4-6, gpt-5-4, gemini-2-5-pro
571
631
 
572
- node gen-context.js --suggest-tool "fix a typo in the yaml config" --json
632
+ sigmap --suggest-tool "fix a typo in the yaml config" --json
573
633
  # {"tier":"fast","label":"Fast (low-cost)","models":"claude-haiku-4-5, ...","costHint":"~$0.0008 / 1K tokens"}
574
634
  ```
575
635
 
@@ -635,7 +695,7 @@ build/
635
695
  test/fixtures/
636
696
  ```
637
697
 
638
- Run `node gen-context.js --init` to scaffold both files in one step.
698
+ Run `sigmap --init` to scaffold both files in one step.
639
699
 
640
700
  ### Output targets
641
701
 
@@ -665,14 +725,14 @@ If `output` is omitted, the default `.github/copilot-instructions.md` is used.
665
725
 
666
726
  ```bash
667
727
  # Append run metrics to .context/usage.ndjson
668
- node gen-context.js --track
728
+ sigmap --track
669
729
 
670
730
  # Structured JSON report for CI (exits 1 if over budget)
671
- node gen-context.js --report --json
731
+ sigmap --report --json
672
732
  # { "version": "2.0.0", "finalTokens": 3200, "reductionPct": 92.4, "overBudget": false }
673
733
 
674
734
  # Composite health score
675
- node gen-context.js --health
735
+ sigmap --health
676
736
  # score: 95/100 (grade A) | reduction: 91.2% | 1 day since regen | 47 runs
677
737
  ```
678
738
 
@@ -684,22 +744,22 @@ Copy `examples/self-healing-github-action.yml` to `.github/workflows/` to auto-r
684
744
 
685
745
  ```yaml
686
746
  - name: SigMap health check
687
- run: node gen-context.js --health --json
747
+ run: sigmap --health --json
688
748
  - name: Regenerate context
689
- run: node gen-context.js
749
+ run: sigmap
690
750
  ```
691
751
 
692
- 📖 Full guide: [docs/ENTERPRISE_SETUP.md](docs/ENTERPRISE_SETUP.md)
752
+ 📖 Full guide: [docs/readmes/ENTERPRISE_SETUP.md](docs/readmes/ENTERPRISE_SETUP.md)
693
753
 
694
754
  ### Prompt caching — 60% API cost reduction
695
755
 
696
756
  ```bash
697
- node gen-context.js --format cache
757
+ sigmap --format cache
698
758
  # Writes: .github/copilot-instructions.cache.json
699
759
  # Format: { type: 'text', text: '...', cache_control: { type: 'ephemeral' } }
700
760
  ```
701
761
 
702
- 📖 Full guide: [docs/REPOMIX_CACHE.md](docs/REPOMIX_CACHE.md)
762
+ 📖 Full guide: [docs/readmes/REPOMIX_CACHE.md](docs/readmes/REPOMIX_CACHE.md)
703
763
 
704
764
  ---
705
765
 
@@ -829,7 +889,7 @@ sigmap/
829
889
 
830
890
  | Principle | Implementation |
831
891
  |---|---|
832
- | **Zero npm dependencies** | `node gen-context.js` on a blank machine with Node 18+ nothing else required |
892
+ | **Zero npm dependencies** | `npx sigmap` on any machine no install required. Or use the standalone binary for zero Node.js dependency. |
833
893
  | **Never throw** | All extractors return `[]` on any error — the run always completes |
834
894
  | **Deterministic** | No AI or LLM involved in extraction — only regex + Node built-ins |
835
895
  | **Repomix is a companion** | Use both tools; SigMap never replaces Repomix |
@@ -3,7 +3,7 @@
3
3
 
4
4
  "output": ".github/copilot-instructions.md",
5
5
 
6
- "outputs": ["copilot"],
6
+ "outputs": ["copilot", "codex"],
7
7
 
8
8
  "srcDirs": ["src", "app", "lib", "packages", "services", "api"],
9
9
 
package/gen-context.js CHANGED
@@ -34,7 +34,7 @@ __factories["./src/config/defaults"] = function(module, exports) {
34
34
  // Output targets: 'copilot' | 'claude' | 'cursor' | 'windsurf'
35
35
  outputs: ['copilot'],
36
36
 
37
- // Adapter targets (v3.0+): replaces 'outputs'. Same names, adds 'openai' | 'gemini'.
37
+ // Adapter targets (v3.0+): replaces 'outputs'. Same names, adds 'openai' | 'gemini' | 'codex'.
38
38
  // Old 'outputs' config key is still accepted and silently maps to 'adapters'.
39
39
  adapters: null, // null means: use 'outputs' for backward compat
40
40
 
@@ -173,7 +173,7 @@ __factories["./src/config/loader"] = function(module, exports) {
173
173
  if (!merged.adapters && Array.isArray(merged.outputs)) {
174
174
  merged.adapters = merged.outputs.slice();
175
175
  } else if (Array.isArray(merged.adapters) && !userConfig.outputs) {
176
- merged.outputs = merged.adapters.filter((a) => ['copilot','claude','cursor','windsurf'].includes(a));
176
+ merged.outputs = merged.adapters.filter((a) => ['copilot','claude','cursor','windsurf','codex'].includes(a));
177
177
  }
178
178
  return merged;
179
179
  }
@@ -3700,7 +3700,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
3700
3700
 
3701
3701
  const SERVER_INFO = {
3702
3702
  name: 'sigmap',
3703
- version: '3.2.1',
3703
+ version: '3.3.2',
3704
3704
  description: 'SigMap MCP server — code signatures on demand',
3705
3705
  };
3706
3706
 
@@ -4888,7 +4888,9 @@ __factories["./src/eval/runner"] = function(module, exports) {
4888
4888
  // ── ./packages/adapters/copilot (bundled) ──
4889
4889
  __factories["./packages/adapters/copilot"] = function(module, exports) {
4890
4890
  const path = require('path');
4891
+ const fs = require('fs');
4891
4892
  const name = 'copilot';
4893
+ const COPILOT_MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
4892
4894
  function format(context, opts = {}) {
4893
4895
  if (!context || typeof context !== 'string') return '';
4894
4896
  const version = (opts && opts.version) || 'unknown';
@@ -4904,7 +4906,20 @@ __factories["./packages/adapters/copilot"] = function(module, exports) {
4904
4906
  ].join('\n');
4905
4907
  }
4906
4908
  function outputPath(cwd) { return path.join(cwd, '.github', 'copilot-instructions.md'); }
4907
- module.exports = { name, format, outputPath };
4909
+ function write(context, cwd, opts = {}) {
4910
+ const filePath = outputPath(cwd);
4911
+ let existing = '';
4912
+ if (fs.existsSync(filePath)) existing = fs.readFileSync(filePath, 'utf8');
4913
+ const formatted = format(context, opts);
4914
+ const markerIdx = existing.indexOf('## Auto-generated signatures');
4915
+ const isLegacyGenerated = existing.includes('<!-- Generated by SigMap gen-context.js') || existing.includes('# Code signatures');
4916
+ const newContent = markerIdx !== -1
4917
+ ? existing.slice(0, markerIdx) + COPILOT_MARKER.trimStart() + formatted
4918
+ : (isLegacyGenerated ? COPILOT_MARKER.trimStart() + formatted : existing + COPILOT_MARKER + formatted);
4919
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
4920
+ fs.writeFileSync(filePath, newContent, 'utf8');
4921
+ }
4922
+ module.exports = { name, format, outputPath, write };
4908
4923
  };
4909
4924
 
4910
4925
  // ── ./packages/adapters/claude (bundled) ──
@@ -4989,7 +5004,9 @@ __factories["./packages/adapters/openai"] = function(module, exports) {
4989
5004
  // ── ./packages/adapters/gemini (bundled) ──
4990
5005
  __factories["./packages/adapters/gemini"] = function(module, exports) {
4991
5006
  const path = require('path');
5007
+ const fs = require('fs');
4992
5008
  const name = 'gemini';
5009
+ const GEMINI_MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
4993
5010
  function format(context, opts = {}) {
4994
5011
  if (!context || typeof context !== 'string') return '';
4995
5012
  const version = (opts && opts.version) || 'unknown';
@@ -5007,12 +5024,51 @@ __factories["./packages/adapters/gemini"] = function(module, exports) {
5007
5024
  ].join('\n');
5008
5025
  }
5009
5026
  function outputPath(cwd) { return path.join(cwd, '.github', 'gemini-context.md'); }
5010
- module.exports = { name, format, outputPath };
5027
+ function write(context, cwd, opts = {}) {
5028
+ const filePath = outputPath(cwd);
5029
+ let existing = '';
5030
+ if (fs.existsSync(filePath)) existing = fs.readFileSync(filePath, 'utf8');
5031
+ const formatted = format(context, opts);
5032
+ const markerIdx = existing.indexOf('## Auto-generated signatures');
5033
+ const isLegacyGenerated = existing.includes('<!-- Generated by SigMap gen-context.js') || existing.includes('## Code Signatures');
5034
+ const newContent = markerIdx !== -1
5035
+ ? existing.slice(0, markerIdx) + GEMINI_MARKER.trimStart() + formatted
5036
+ : (isLegacyGenerated ? GEMINI_MARKER.trimStart() + formatted : existing + GEMINI_MARKER + formatted);
5037
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
5038
+ fs.writeFileSync(filePath, newContent, 'utf8');
5039
+ }
5040
+ module.exports = { name, format, outputPath, write };
5041
+ };
5042
+
5043
+ // ── ./packages/adapters/codex (bundled) ──
5044
+ __factories["./packages/adapters/codex"] = function(module, exports) {
5045
+ const path = require('path');
5046
+ const fs = require('fs');
5047
+ const openai = __require('./packages/adapters/openai');
5048
+ const name = 'codex';
5049
+ const CODEX_MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
5050
+ function format(context, opts = {}) {
5051
+ return openai.format(context, opts);
5052
+ }
5053
+ function outputPath(cwd) { return path.join(cwd, 'AGENTS.md'); }
5054
+ function write(context, cwd, opts = {}) {
5055
+ const filePath = outputPath(cwd);
5056
+ let existing = '';
5057
+ if (fs.existsSync(filePath)) existing = fs.readFileSync(filePath, 'utf8');
5058
+ const formatted = format(context, opts);
5059
+ const markerIdx = existing.indexOf('## Auto-generated signatures');
5060
+ const isLegacyGenerated = existing.includes('<!-- Generated by SigMap gen-context.js') || existing.includes('## Code Signatures') || existing.includes('# Code signatures');
5061
+ const newContent = markerIdx !== -1
5062
+ ? existing.slice(0, markerIdx) + CODEX_MARKER.trimStart() + formatted
5063
+ : (isLegacyGenerated ? CODEX_MARKER.trimStart() + formatted : existing + CODEX_MARKER + formatted);
5064
+ fs.writeFileSync(filePath, newContent, 'utf8');
5065
+ }
5066
+ module.exports = { name, format, outputPath, write };
5011
5067
  };
5012
5068
 
5013
5069
  // ── ./packages/adapters/index (bundled) ──
5014
5070
  __factories["./packages/adapters/index"] = function(module, exports) {
5015
- const ADAPTER_NAMES = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini'];
5071
+ const ADAPTER_NAMES = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
5016
5072
  const _adapterCache = {};
5017
5073
  function getAdapter(name) {
5018
5074
  if (!name || typeof name !== 'string') return null;
@@ -5049,7 +5105,7 @@ const path = require('path');
5049
5105
  const os = require('os');
5050
5106
  const { execSync } = require('child_process');
5051
5107
 
5052
- const VERSION = '3.3.0';
5108
+ const VERSION = '3.3.2';
5053
5109
  const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
5054
5110
 
5055
5111
  function requireSourceOrBundled(key) {
@@ -5619,6 +5675,7 @@ function resolveAdapterPath(adapter, cwd, config) {
5619
5675
  if (adapter === 'claude') return path.join(cwd, 'CLAUDE.md');
5620
5676
  if (adapter === 'cursor') return path.join(cwd, '.cursorrules');
5621
5677
  if (adapter === 'windsurf') return path.join(cwd, '.windsurfrules');
5678
+ if (adapter === 'codex') return path.join(cwd, 'AGENTS.md');
5622
5679
 
5623
5680
  return null;
5624
5681
  }
@@ -5641,7 +5698,7 @@ function writeCacheOutput(content, cwd) {
5641
5698
  function writeOutputs(content, targets, cwd, config) {
5642
5699
  config = config || {};
5643
5700
  // v3.0+: adapter-aware output targets
5644
- const ADAPTER_TARGETS = new Set(['openai', 'gemini']);
5701
+ const ADAPTER_TARGETS = new Set(['copilot', 'openai', 'gemini', 'codex']);
5645
5702
 
5646
5703
  const targetMap = {
5647
5704
  copilot: resolveAdapterPath('copilot', cwd, config),
@@ -5654,15 +5711,21 @@ function writeOutputs(content, targets, cwd, config) {
5654
5711
  writeClaude(content, cwd);
5655
5712
  continue;
5656
5713
  }
5657
- // v3.0+ adapter targets (openai, gemini) — use bundled adapter to format + write
5714
+ // v3.0+ adapter targets (copilot, openai, gemini, codex) — use bundled adapter to format + write
5658
5715
  if (ADAPTER_TARGETS.has(target)) {
5659
5716
  try {
5660
5717
  const adapterMod = __require('./packages/adapters/' + target);
5661
- const formatted = adapterMod.format(content, { version: VERSION });
5662
- const outPath = adapterMod.outputPath(cwd);
5663
- ensureDir(outPath);
5664
- fs.writeFileSync(outPath, formatted, 'utf8');
5665
- console.warn(`[sigmap] wrote ${path.relative(cwd, outPath)}`);
5718
+ if (typeof adapterMod.write === 'function') {
5719
+ adapterMod.write(content, cwd, { version: VERSION });
5720
+ const outPath = adapterMod.outputPath(cwd);
5721
+ console.warn(`[sigmap] wrote ${path.relative(cwd, outPath)} (appended signatures)`);
5722
+ } else {
5723
+ const formatted = adapterMod.format(content, { version: VERSION });
5724
+ const outPath = adapterMod.outputPath(cwd);
5725
+ ensureDir(outPath);
5726
+ fs.writeFileSync(outPath, formatted, 'utf8');
5727
+ console.warn(`[sigmap] wrote ${path.relative(cwd, outPath)}`);
5728
+ }
5666
5729
  } catch (err) {
5667
5730
  console.warn(`[sigmap] adapter "${target}" failed: ${err.message}`);
5668
5731
  }
@@ -6257,7 +6320,7 @@ function detectRepoDirs(cwd) {
6257
6320
  return repos;
6258
6321
  }
6259
6322
 
6260
- function runEach(cwd, baseConfig) {
6323
+ function runEach(cwd, baseConfig, adapterOverride) {
6261
6324
  const repos = detectRepoDirs(cwd);
6262
6325
  if (repos.length === 0) {
6263
6326
  console.warn('[sigmap] --each: no project subdirectories found');
@@ -6276,6 +6339,13 @@ function runEach(cwd, baseConfig) {
6276
6339
  } catch (_) {
6277
6340
  repoConfig = { ...baseConfig };
6278
6341
  }
6342
+ // --adapter override: apply on top of per-repo config
6343
+ if (adapterOverride) {
6344
+ repoConfig = Object.assign({}, repoConfig, {
6345
+ outputs: adapterOverride === 'claude' ? ['claude'] : [adapterOverride],
6346
+ adapters: [adapterOverride],
6347
+ });
6348
+ }
6279
6349
  console.warn(`[sigmap] --each: processing ${name} …`);
6280
6350
  try {
6281
6351
  runGenerate(repoDir, repoConfig, false);
@@ -6413,8 +6483,8 @@ Strategies (set via config "strategy" key):
6413
6483
  ~90% fewer tokens. Best with MCP (Claude Code, Cursor).
6414
6484
  Set "hotCommits": N to control how many commits count as hot (default 10).
6415
6485
 
6416
- Adapters (v3.0+): copilot | claude | cursor | windsurf | openai | gemini
6417
- Set "adapters": ["copilot","openai"] in config to write multiple adapter outputs.
6486
+ Adapters (v3.0+): copilot | claude | cursor | windsurf | openai | gemini | codex
6487
+ Set "adapters": ["copilot","openai","codex"] in config to write multiple adapter outputs.
6418
6488
  Old "outputs" config key is still accepted (maps to adapters automatically).
6419
6489
 
6420
6490
  Config: gen-context.config.json
@@ -6748,12 +6818,29 @@ function main() {
6748
6818
  process.exit(0);
6749
6819
  }
6750
6820
 
6821
+ // ── --each [--adapter <name>] ────────────────────────────────────────────
6822
+ // Must be checked before --adapter so that --each --adapter <name> is
6823
+ // handled here (per-repo) rather than running a single generate on the
6824
+ // parent directory.
6825
+ if (args.includes('--each')) {
6826
+ const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
6827
+ const adpIdx = args.indexOf('--adapter');
6828
+ const adapterOverride = adpIdx >= 0 ? (args[adpIdx + 1] || '').trim().toLowerCase() : null;
6829
+ if (adapterOverride && !VALID_ADAPTERS.includes(adapterOverride)) {
6830
+ console.error(`[sigmap] --each: unknown adapter "${adapterOverride}"`);
6831
+ console.error(` Valid adapters: ${VALID_ADAPTERS.join(', ')}`);
6832
+ process.exit(1);
6833
+ }
6834
+ runEach(cwd, config, adapterOverride || null);
6835
+ process.exit(0);
6836
+ }
6837
+
6751
6838
  // ── --adapter <name> ───────────────────────────────────────────────────────
6752
6839
  if (args.includes('--adapter')) {
6753
6840
  try {
6754
6841
  const adpIdx = args.indexOf('--adapter');
6755
6842
  const adapterName = (args[adpIdx + 1] || '').trim().toLowerCase();
6756
- const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini'];
6843
+ const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
6757
6844
  if (!adapterName || adapterName.startsWith('--')) {
6758
6845
  console.error('[sigmap] --adapter requires an adapter name');
6759
6846
  console.error(` Valid adapters: ${VALID_ADAPTERS.join(', ')}`);
@@ -6867,11 +6954,6 @@ function main() {
6867
6954
  process.exit(0);
6868
6955
  }
6869
6956
 
6870
- if (args.includes('--each')) {
6871
- runEach(cwd, config);
6872
- process.exit(0);
6873
- }
6874
-
6875
6957
  if (args.includes('--setup')) {
6876
6958
  runGenerate(cwd, config, false);
6877
6959
  installHook(cwd, scriptPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
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": {
@@ -36,6 +36,7 @@
36
36
  "src/",
37
37
  "packages/",
38
38
  "README.md",
39
+ "AGENTS.md",
39
40
  "LICENSE",
40
41
  "CHANGELOG.md",
41
42
  ".contextignore.example",
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Codex adapter — writes OpenAI-style context to AGENTS.md.
5
+ *
6
+ * This adapter reuses the same prompt format as the OpenAI adapter,
7
+ * but targets AGENTS.md so Codex-style agents can read repository guidance.
8
+ *
9
+ * Contract:
10
+ * format(context, opts?) → string
11
+ * outputPath(cwd) → string
12
+ * write(context, cwd, opts?) → void
13
+ */
14
+
15
+ const path = require('path');
16
+ const fs = require('fs');
17
+ const openai = require('./openai');
18
+
19
+ const name = 'codex';
20
+ const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
21
+
22
+ /**
23
+ * Format context using the OpenAI adapter format.
24
+ * @param {string} context - Raw signature context string
25
+ * @param {object} [opts]
26
+ * @returns {string}
27
+ */
28
+ function format(context, opts = {}) {
29
+ return openai.format(context, opts);
30
+ }
31
+
32
+ /**
33
+ * Return the output file path for this adapter.
34
+ * @param {string} cwd - Project root
35
+ * @returns {string}
36
+ */
37
+ function outputPath(cwd) {
38
+ return path.join(cwd, 'AGENTS.md');
39
+ }
40
+
41
+ /**
42
+ * Write signatures into AGENTS.md using append-under-marker.
43
+ * If marker exists, content above marker is preserved.
44
+ * If legacy generated content exists without marker, replace it cleanly.
45
+ * @param {string} context - Raw signature context string
46
+ * @param {string} cwd - Project root
47
+ * @param {object} [opts]
48
+ */
49
+ function write(context, cwd, opts = {}) {
50
+ const filePath = outputPath(cwd);
51
+ let existing = '';
52
+ if (fs.existsSync(filePath)) {
53
+ existing = fs.readFileSync(filePath, 'utf8');
54
+ }
55
+
56
+ const formatted = format(context, opts);
57
+ const markerIdx = existing.indexOf('## Auto-generated signatures');
58
+
59
+ let newContent;
60
+ if (markerIdx !== -1) {
61
+ newContent = existing.slice(0, markerIdx) + MARKER.trimStart() + formatted;
62
+ } else {
63
+ const isLegacyGenerated = existing.includes('<!-- Generated by SigMap gen-context.js')
64
+ || existing.includes('## Code Signatures')
65
+ || existing.includes('# Code signatures');
66
+ newContent = isLegacyGenerated
67
+ ? MARKER.trimStart() + formatted
68
+ : existing + MARKER + formatted;
69
+ }
70
+
71
+ fs.writeFileSync(filePath, newContent, 'utf8');
72
+ }
73
+
74
+ module.exports = { name, format, outputPath, write };
@@ -10,8 +10,10 @@
10
10
  */
11
11
 
12
12
  const path = require('path');
13
+ const fs = require('fs');
13
14
 
14
15
  const name = 'copilot';
16
+ const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
15
17
 
16
18
  /**
17
19
  * Format context for GitHub Copilot instructions.
@@ -44,4 +46,37 @@ function outputPath(cwd) {
44
46
  return path.join(cwd, '.github', 'copilot-instructions.md');
45
47
  }
46
48
 
47
- module.exports = { name, format, outputPath };
49
+ /**
50
+ * Write signatures into copilot-instructions.md using append-under-marker.
51
+ * If marker exists, content above marker is preserved.
52
+ * If legacy generated content exists without marker, replace it cleanly.
53
+ * @param {string} context - Raw signature context string
54
+ * @param {string} cwd - Project root
55
+ * @param {object} [opts]
56
+ */
57
+ function write(context, cwd, opts = {}) {
58
+ const filePath = outputPath(cwd);
59
+ let existing = '';
60
+ if (fs.existsSync(filePath)) {
61
+ existing = fs.readFileSync(filePath, 'utf8');
62
+ }
63
+
64
+ const formatted = format(context, opts);
65
+ const markerIdx = existing.indexOf('## Auto-generated signatures');
66
+
67
+ let newContent;
68
+ if (markerIdx !== -1) {
69
+ newContent = existing.slice(0, markerIdx) + MARKER.trimStart() + formatted;
70
+ } else {
71
+ const isLegacyGenerated = existing.includes('<!-- Generated by SigMap gen-context.js')
72
+ || existing.includes('# Code signatures');
73
+ newContent = isLegacyGenerated
74
+ ? MARKER.trimStart() + formatted
75
+ : existing + MARKER + formatted;
76
+ }
77
+
78
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
79
+ fs.writeFileSync(filePath, newContent, 'utf8');
80
+ }
81
+
82
+ module.exports = { name, format, outputPath, write };
@@ -15,8 +15,10 @@
15
15
  */
16
16
 
17
17
  const path = require('path');
18
+ const fs = require('fs');
18
19
 
19
20
  const name = 'gemini';
21
+ const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
20
22
 
21
23
  /**
22
24
  * Format context as a Gemini system instruction.
@@ -56,4 +58,37 @@ function outputPath(cwd) {
56
58
  return path.join(cwd, '.github', 'gemini-context.md');
57
59
  }
58
60
 
59
- module.exports = { name, format, outputPath };
61
+ /**
62
+ * Write signatures into gemini-context.md using append-under-marker.
63
+ * If marker exists, content above marker is preserved.
64
+ * If legacy generated content exists without marker, replace it cleanly.
65
+ * @param {string} context - Raw signature context string
66
+ * @param {string} cwd - Project root
67
+ * @param {object} [opts]
68
+ */
69
+ function write(context, cwd, opts = {}) {
70
+ const filePath = outputPath(cwd);
71
+ let existing = '';
72
+ if (fs.existsSync(filePath)) {
73
+ existing = fs.readFileSync(filePath, 'utf8');
74
+ }
75
+
76
+ const formatted = format(context, opts);
77
+ const markerIdx = existing.indexOf('## Auto-generated signatures');
78
+
79
+ let newContent;
80
+ if (markerIdx !== -1) {
81
+ newContent = existing.slice(0, markerIdx) + MARKER.trimStart() + formatted;
82
+ } else {
83
+ const isLegacyGenerated = existing.includes('<!-- Generated by SigMap gen-context.js')
84
+ || existing.includes('## Code Signatures');
85
+ newContent = isLegacyGenerated
86
+ ? MARKER.trimStart() + formatted
87
+ : existing + MARKER + formatted;
88
+ }
89
+
90
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
91
+ fs.writeFileSync(filePath, newContent, 'utf8');
92
+ }
93
+
94
+ module.exports = { name, format, outputPath, write };
@@ -11,14 +11,14 @@
11
11
 
12
12
  const path = require('path');
13
13
 
14
- const ADAPTER_NAMES = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini'];
14
+ const ADAPTER_NAMES = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
15
15
 
16
16
  // Lazy-load adapters so unused ones don't pay any require() cost
17
17
  const _cache = {};
18
18
 
19
19
  /**
20
20
  * Load and return an adapter module by name.
21
- * @param {string} name - Adapter name (copilot|claude|cursor|windsurf|openai|gemini)
21
+ * @param {string} name - Adapter name (copilot|claude|cursor|windsurf|openai|gemini|codex)
22
22
  * @returns {{ name: string, format: Function, outputPath: Function }|null}
23
23
  */
24
24
  function getAdapter(name) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-cli",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "description": "SigMap CLI wrapper — thin adapter for programmatic CLI invocation",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap-core",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "description": "SigMap core library — zero-dependency code signature extraction, retrieval, and security scanning",
5
5
  "main": "index.js",
6
6
  "keywords": [
package/src/mcp/server.js CHANGED
@@ -18,7 +18,7 @@ const { readContext, searchSignatures, getMap, createCheckpoint, getRouting, exp
18
18
 
19
19
  const SERVER_INFO = {
20
20
  name: 'sigmap',
21
- version: '3.2.1',
21
+ version: '3.3.2',
22
22
  description: 'SigMap MCP server — code signatures on demand',
23
23
  };
24
24