sigmap 3.3.1 → 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/README.md CHANGED
@@ -1,38 +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>
6
13
 
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>
14
+ <div align="center">
15
+ <img src="docs/impact-banner.svg" alt="SigMap better answers, 97% fewer tokens, fewer prompts" width="760" />
16
+ </div>
11
17
 
12
- <img src="docs/sigmap-banner.png" alt="SigMap — AI context engine" width="700">
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">
13
26
 
14
- <!-- Status -->
15
27
  [![npm version](https://img.shields.io/npm/v/sigmap?color=7c6af7&label=latest&logo=npm)](https://www.npmjs.com/package/sigmap)
16
28
  [![CI](https://github.com/manojmallick/sigmap/actions/workflows/ci.yml/badge.svg)](https://github.com/manojmallick/sigmap/actions/workflows/ci.yml)
17
29
  [![Zero deps](https://img.shields.io/badge/dependencies-zero-22c55e)](package.json)
18
- [![Last commit](https://img.shields.io/github/last-commit/manojmallick/sigmap?color=7c6af7)](https://github.com/manojmallick/sigmap/commits/main)
19
-
20
- <!-- Meta -->
21
30
  [![License: MIT](https://img.shields.io/badge/License-MIT-7c6af7.svg)](LICENSE)
22
- [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
23
- [![npm](https://img.shields.io/badge/npm-sigmap-cb3837?logo=npm)](https://www.npmjs.com/package/sigmap)
24
- [![GitHub Stars](https://img.shields.io/github/stars/manojmallick/sigmap?style=flat&color=f59e0b&logo=github)](https://github.com/manojmallick/sigmap/stargazers)
25
-
26
- <!-- Links -->
27
- [![Docs](https://img.shields.io/badge/docs-live-7c6af7?logo=github-pages)](https://manojmallick.github.io/sigmap)
28
- [![Changelog](https://img.shields.io/badge/changelog-CHANGELOG.md-blue)](CHANGELOG.md)
29
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
30
31
  [![VS Code](https://img.shields.io/badge/VS%20Code-extension-0078d4?logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=manojmallick.sigmap)
31
32
  [![JetBrains](https://img.shields.io/badge/JetBrains-plugin-000000?logo=jetbrains)](https://plugins.jetbrains.com/plugin/31109-sigmap--ai-context-engine/)
32
- [![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)
33
35
 
34
36
  </div>
35
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
+
36
60
  ---
37
61
 
38
62
  ## Table of contents
@@ -67,7 +91,7 @@ SigMap scans your source files and extracts only the **function and class signat
67
91
  Your codebase
68
92
 
69
93
 
70
- gen-context.js ──► extracts signatures from 21 languages
94
+ sigmap ─────────► extracts signatures from 21 languages
71
95
 
72
96
 
73
97
  .github/copilot-instructions.md ◄── auto-read by Copilot / Claude / Cursor
@@ -90,6 +114,31 @@ AI agent session starts with full context
90
114
 
91
115
  > **97% fewer tokens. The same codebase understanding.**
92
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
+
93
142
  ---
94
143
 
95
144
  ## ⚡ Installation
@@ -250,8 +299,6 @@ No npm, no `node_modules`. Drop `gen-context.js` into any project and run it dir
250
299
 
251
300
  </details>
252
301
 
253
- > **Note:** When using the single-file download, replace `sigmap` with `node gen-context.js` in all commands below.
254
-
255
302
  ---
256
303
 
257
304
  ## 🚀 Features
@@ -266,17 +313,19 @@ sigmap --adapter claude # → CLAUDE.md (appended below marker)
266
313
  sigmap --adapter cursor # → .cursorrules
267
314
  sigmap --adapter windsurf # → .windsurfrules
268
315
  sigmap --adapter openai # → .github/openai-context.md
269
- 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)
270
318
  ```
271
319
 
272
320
  | Adapter | Output file | AI assistant |
273
321
  |---|---|---|
274
- | `copilot` | `.github/copilot-instructions.md` | GitHub Copilot |
322
+ | `copilot` | `.github/copilot-instructions.md` (append) | GitHub Copilot |
275
323
  | `claude` | `CLAUDE.md` (append) | Claude / Claude Code |
276
324
  | `cursor` | `.cursorrules` | Cursor |
277
325
  | `windsurf` | `.windsurfrules` | Windsurf |
278
326
  | `openai` | `.github/openai-context.md` | Any OpenAI model |
279
- | `gemini` | `.github/gemini-context.md` | Google Gemini |
327
+ | `gemini` | `.github/gemini-context.md` (append) | Google Gemini |
328
+ | `codex` | `AGENTS.md` (append) | OpenAI Codex |
280
329
 
281
330
  Configure multiple adapters at once in `gen-context.config.json`:
282
331
 
@@ -342,7 +391,7 @@ npm install -g sigmap # install globally
342
391
 
343
392
  ### Generate context
344
393
 
345
- Download the single-file CLI and generate context immediately:
394
+ Once installed, run from your project root:
346
395
 
347
396
  ```bash
348
397
  sigmap # generate once and exit
@@ -374,17 +423,17 @@ npx repomix --compress # deep dive sessions
374
423
 
375
424
  ## 🧩 VS Code extension
376
425
 
377
- 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.
378
427
 
379
428
  | Feature | Detail |
380
429
  |---|---|
381
430
  | **Status bar item** | Shows health grade (`A`/`B`/`C`/`D`) + time since last regen; refreshes every 60 s |
382
431
  | **Stale notification** | Warns when `copilot-instructions.md` is > 24 h old; one-click regeneration |
383
- | **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 |
384
433
  | **Open context command** | `SigMap: Open Context File` — opens `.github/copilot-instructions.md` |
385
- | **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` |
386
435
 
387
- 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.
388
437
 
389
438
  **Install:** [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=manojmallick.sigmap) | [Open VSX Registry](https://open-vsx.org/extension/manojmallick/sigmap)
390
439
 
@@ -392,12 +441,12 @@ Activate on startup (`onStartupFinished`) — loads within 3 s, never blocks edi
392
441
 
393
442
  ## 🔧 JetBrains plugin
394
443
 
395
- 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.
396
445
 
397
446
  | Feature | Detail |
398
447
  |---|---|
399
448
  | **Status bar widget** | Shows health grade (`A`-`F`) + time since last regen; updates every 60 s |
400
- | **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` |
401
450
  | **Open context action** | `Tools → SigMap → Open Context File` — opens `.github/copilot-instructions.md` |
402
451
  | **View roadmap action** | `Tools → SigMap → View Roadmap` — opens roadmap in browser |
403
452
  | **One-click regen** | Click status bar widget to regenerate context instantly |
@@ -495,7 +544,7 @@ Recently committed files are **hot** (auto-injected). Everything else is **cold*
495
544
  Start the MCP server on stdio:
496
545
 
497
546
  ```bash
498
- node gen-context.js --mcp
547
+ sigmap --mcp
499
548
  ```
500
549
 
501
550
  ### Available tools
@@ -576,11 +625,11 @@ sigmap --help Usage information
576
625
  ### Task classification — `--suggest-tool`
577
626
 
578
627
  ```bash
579
- node gen-context.js --suggest-tool "security audit of the auth module"
628
+ sigmap --suggest-tool "security audit of the auth module"
580
629
  # tier : powerful
581
630
  # models : claude-opus-4-6, gpt-5-4, gemini-2-5-pro
582
631
 
583
- 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
584
633
  # {"tier":"fast","label":"Fast (low-cost)","models":"claude-haiku-4-5, ...","costHint":"~$0.0008 / 1K tokens"}
585
634
  ```
586
635
 
@@ -646,7 +695,7 @@ build/
646
695
  test/fixtures/
647
696
  ```
648
697
 
649
- Run `node gen-context.js --init` to scaffold both files in one step.
698
+ Run `sigmap --init` to scaffold both files in one step.
650
699
 
651
700
  ### Output targets
652
701
 
@@ -676,14 +725,14 @@ If `output` is omitted, the default `.github/copilot-instructions.md` is used.
676
725
 
677
726
  ```bash
678
727
  # Append run metrics to .context/usage.ndjson
679
- node gen-context.js --track
728
+ sigmap --track
680
729
 
681
730
  # Structured JSON report for CI (exits 1 if over budget)
682
- node gen-context.js --report --json
731
+ sigmap --report --json
683
732
  # { "version": "2.0.0", "finalTokens": 3200, "reductionPct": 92.4, "overBudget": false }
684
733
 
685
734
  # Composite health score
686
- node gen-context.js --health
735
+ sigmap --health
687
736
  # score: 95/100 (grade A) | reduction: 91.2% | 1 day since regen | 47 runs
688
737
  ```
689
738
 
@@ -695,9 +744,9 @@ Copy `examples/self-healing-github-action.yml` to `.github/workflows/` to auto-r
695
744
 
696
745
  ```yaml
697
746
  - name: SigMap health check
698
- run: node gen-context.js --health --json
747
+ run: sigmap --health --json
699
748
  - name: Regenerate context
700
- run: node gen-context.js
749
+ run: sigmap
701
750
  ```
702
751
 
703
752
  📖 Full guide: [docs/readmes/ENTERPRISE_SETUP.md](docs/readmes/ENTERPRISE_SETUP.md)
@@ -705,7 +754,7 @@ Copy `examples/self-healing-github-action.yml` to `.github/workflows/` to auto-r
705
754
  ### Prompt caching — 60% API cost reduction
706
755
 
707
756
  ```bash
708
- node gen-context.js --format cache
757
+ sigmap --format cache
709
758
  # Writes: .github/copilot-instructions.cache.json
710
759
  # Format: { type: 'text', text: '...', cache_control: { type: 'ephemeral' } }
711
760
  ```
@@ -840,7 +889,7 @@ sigmap/
840
889
 
841
890
  | Principle | Implementation |
842
891
  |---|---|
843
- | **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. |
844
893
  | **Never throw** | All extractors return `[]` on any error — the run always completes |
845
894
  | **Deterministic** | No AI or LLM involved in extraction — only regex + Node built-ins |
846
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.1';
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
  }
@@ -6420,8 +6483,8 @@ Strategies (set via config "strategy" key):
6420
6483
  ~90% fewer tokens. Best with MCP (Claude Code, Cursor).
6421
6484
  Set "hotCommits": N to control how many commits count as hot (default 10).
6422
6485
 
6423
- Adapters (v3.0+): copilot | claude | cursor | windsurf | openai | gemini
6424
- 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.
6425
6488
  Old "outputs" config key is still accepted (maps to adapters automatically).
6426
6489
 
6427
6490
  Config: gen-context.config.json
@@ -6760,7 +6823,7 @@ function main() {
6760
6823
  // handled here (per-repo) rather than running a single generate on the
6761
6824
  // parent directory.
6762
6825
  if (args.includes('--each')) {
6763
- const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini'];
6826
+ const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
6764
6827
  const adpIdx = args.indexOf('--adapter');
6765
6828
  const adapterOverride = adpIdx >= 0 ? (args[adpIdx + 1] || '').trim().toLowerCase() : null;
6766
6829
  if (adapterOverride && !VALID_ADAPTERS.includes(adapterOverride)) {
@@ -6777,7 +6840,7 @@ function main() {
6777
6840
  try {
6778
6841
  const adpIdx = args.indexOf('--adapter');
6779
6842
  const adapterName = (args[adpIdx + 1] || '').trim().toLowerCase();
6780
- const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini'];
6843
+ const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
6781
6844
  if (!adapterName || adapterName.startsWith('--')) {
6782
6845
  console.error('[sigmap] --adapter requires an adapter name');
6783
6846
  console.error(` Valid adapters: ${VALID_ADAPTERS.join(', ')}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigmap",
3
- "version": "3.3.1",
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.1",
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.1",
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