engramx 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +583 -0
- package/README.md +14 -19
- package/package.json +14 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to engram are documented here. Format based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.5.0] — 2026-04-13 — "Context Spine"
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Context Spine** — engram now assembles rich context packets from
|
|
12
|
+
6 providers (structure, mistakes, git, mempalace, context7, obsidian)
|
|
13
|
+
per Read interception. One response replaces 5 separate tool calls.
|
|
14
|
+
Target: up to 90% session-level token savings.
|
|
15
|
+
- **Provider cache** — new `provider_cache` SQLite table with full CRUD.
|
|
16
|
+
External providers (mempalace, context7, obsidian) cache results at
|
|
17
|
+
SessionStart. Per-Read cache lookup is <5ms.
|
|
18
|
+
- **ContextProvider interface** — formal contract for all providers:
|
|
19
|
+
`resolve()`, `warmup()`, `isAvailable()`, with token budgets and
|
|
20
|
+
per-provider timeouts.
|
|
21
|
+
- **6 providers**: `engram:structure` (graph), `engram:mistakes` (known
|
|
22
|
+
issues), `engram:git` (recent changes/churn), `mempalace` (decisions
|
|
23
|
+
from ChromaDB), `context7` (library docs), `obsidian` (project notes).
|
|
24
|
+
- **Resolver engine** — parallel resolution with priority ordering,
|
|
25
|
+
600-token total budget, graceful degradation per provider.
|
|
26
|
+
- **SessionStart warmup** — fire-and-forget bulk cache fill for Tier 2
|
|
27
|
+
providers at session start.
|
|
28
|
+
- **StatusLine auto-config** — `engram install-hook` now sets up the
|
|
29
|
+
Claude Code statusLine with `engram hud-label` when no existing
|
|
30
|
+
statusLine is configured.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **CRITICAL: `renderFileStructure` full table scan** — replaced
|
|
35
|
+
`getAllNodes()`/`getAllEdges()` with targeted SQL queries
|
|
36
|
+
(`getNodesByFile`, `getEdgesForNodes`). Was silently timing out on
|
|
37
|
+
large projects (50k+ nodes).
|
|
38
|
+
- **CRITICAL: `scoreNodes` full table scan** — replaced `getAllNodes()`
|
|
39
|
+
with `searchNodes()` SQL seeding. O(matches) instead of O(all nodes).
|
|
40
|
+
- **Go import false positives** — import detection now tracks
|
|
41
|
+
`import()` block state. No longer fires on struct field tags like
|
|
42
|
+
`json:"name"`.
|
|
43
|
+
- **TS arrow function false positives** — pattern now requires `=>`
|
|
44
|
+
in the same line. `const x = (someValue)` no longer creates false
|
|
45
|
+
function nodes.
|
|
46
|
+
- **Commented-out code extraction** — lines starting with `//` or `*`
|
|
47
|
+
are skipped before pattern matching.
|
|
48
|
+
- **Edge ordering** — `renderFileStructure` sorts edges by combined
|
|
49
|
+
endpoint degree before `.slice(0, 10)`. God-node relationships
|
|
50
|
+
appear first.
|
|
51
|
+
- **LIKE wildcard escaping** — `%` and `_` in search queries are
|
|
52
|
+
properly escaped.
|
|
53
|
+
- **SQLite variable limit** — `getEdgesForNodes` chunks IN clause at
|
|
54
|
+
400 IDs to stay under SQLite's 999 parameter limit.
|
|
55
|
+
- **`warmCache` persistence** — now calls `save()` after transaction
|
|
56
|
+
commit, consistent with `bulkUpsert`.
|
|
57
|
+
- **Null-safe casts** — `rowToCachedContext` uses `?? fallbacks` on
|
|
58
|
+
all fields to prevent null propagation.
|
|
59
|
+
- **Parallel availability checks** — provider isAvailable() runs in
|
|
60
|
+
parallel, not sequentially. Prevents slow Tier 2 timeouts from
|
|
61
|
+
blocking Tier 1 providers.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- Confidence score calibrated to 0.85 for regex extraction (was 1.0).
|
|
66
|
+
Reserves 1.0 for future tree-sitter integration.
|
|
67
|
+
- Removed phantom `graphology` dependency (was in package.json with
|
|
68
|
+
zero imports in source code).
|
|
69
|
+
- Test count: 493 → 520 (+27 new tests).
|
|
70
|
+
- README updated: "context spine" positioning, accurate test count,
|
|
71
|
+
provider documentation, "heuristic extraction" language.
|
|
72
|
+
|
|
73
|
+
## [0.4.0] — 2026-04-12 — "Infrastructure"
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **PreCompact hook** — re-injects god nodes, active landmines, and
|
|
78
|
+
graph stats right before Claude Code compresses the conversation.
|
|
79
|
+
This is the first tool in the ecosystem whose context survives
|
|
80
|
+
compaction. No other tool does this.
|
|
81
|
+
- **CwdChanged hook** — auto-switches project context when the user
|
|
82
|
+
navigates to a different directory mid-session. Injects a compact
|
|
83
|
+
brief for the new project so subsequent interceptions route to the
|
|
84
|
+
correct graph.
|
|
85
|
+
- **File watcher** (`engram watch`) — incremental re-indexing via
|
|
86
|
+
`fs.watch`. On file save, clears old nodes for that file and
|
|
87
|
+
re-extracts fresh AST nodes. 300ms debounce, ignored directories
|
|
88
|
+
(node_modules, .git, dist, etc.), extension whitelist. Zero native
|
|
89
|
+
dependencies. Eliminates manual `engram init` for graph freshness.
|
|
90
|
+
- **Mempalace integration** — SessionStart brief now queries
|
|
91
|
+
`mcp-mempalace` for semantic context about the project and bundles
|
|
92
|
+
top 3 findings alongside the structural brief. Runs in parallel
|
|
93
|
+
with graph queries (async execFile, 1.5s timeout). Graceful
|
|
94
|
+
degradation if mempalace is not installed.
|
|
95
|
+
- **`deleteBySourceFile`** method on GraphStore — transactional
|
|
96
|
+
deletion of all nodes and edges for a given source file. Used by
|
|
97
|
+
the file watcher for incremental re-indexing.
|
|
98
|
+
- **`edges.source_file` index** — enables fast lookups when the
|
|
99
|
+
watcher deletes by file. Without this, `deleteBySourceFile` would
|
|
100
|
+
do a full table scan.
|
|
101
|
+
|
|
102
|
+
### Changed
|
|
103
|
+
|
|
104
|
+
- Hook count: 7 → 9 (added PreCompact, CwdChanged).
|
|
105
|
+
- Installer now registers 6 hook events (was 4).
|
|
106
|
+
- Test count: 467 → 486 (+19 new tests for PreCompact, CwdChanged,
|
|
107
|
+
file watcher, dispatch routing).
|
|
108
|
+
|
|
109
|
+
## [0.3.2] — 2026-04-12 — "Cross-Platform"
|
|
110
|
+
|
|
111
|
+
### Fixed
|
|
112
|
+
|
|
113
|
+
- **Windows path portability** — Graph `sourceFile` entries now stored
|
|
114
|
+
in POSIX form (`src/auth.ts`, not `src\auth.ts`) via new
|
|
115
|
+
`toPosixPath()` in `src/graph/path-utils.ts`. All lookup sites
|
|
116
|
+
(`getFileContext`, `handleEditOrWrite`, `extractFile`) normalize
|
|
117
|
+
consistently. Without this, Sentinel on Windows would passthrough
|
|
118
|
+
every Read (zero interception). Credit: ultrathink (shahe-dev).
|
|
119
|
+
- **CRLF handling in skills-miner YAML parser** — `parseYaml` now
|
|
120
|
+
strips `\r` before splitting, fixing silent failures on Windows
|
|
121
|
+
clones with `core.autocrlf=true` where `description: >` was
|
|
122
|
+
misread as `description: >\r`.
|
|
123
|
+
- **libuv assertion crash on Node 25 Windows** — Replaced
|
|
124
|
+
`process.exit(0)` in `engram intercept` with `process.exitCode = 0`
|
|
125
|
+
+ natural event-loop drain. The prior code raced against sql.js
|
|
126
|
+
WASM handle cleanup, triggering `UV_HANDLE_CLOSING` assertion
|
|
127
|
+
(`0xC0000409`) on Windows + Node 25.
|
|
128
|
+
- **`isHardSystemPath` now platform-aware** — Detects Windows UNC
|
|
129
|
+
device paths (`//./`, `//?/`), `C:\Windows\`, and `C:\Program Files`
|
|
130
|
+
in addition to POSIX `/dev/`, `/proc/`, `/sys/`. Tests no longer
|
|
131
|
+
skip on win32.
|
|
132
|
+
- **Double drive-letter bug** — Test files using
|
|
133
|
+
`new URL(".", import.meta.url).pathname` now use `fileURLToPath()`
|
|
134
|
+
which prevents `/C:/Users/...` → `C:\C:\Users\...` on Windows.
|
|
135
|
+
|
|
136
|
+
### Added
|
|
137
|
+
|
|
138
|
+
- **Experience Tiers in README** — New section showing the 4 tiers of
|
|
139
|
+
value (graph → Sentinel → skills → git hooks) with token savings per
|
|
140
|
+
tier and a recommended full-setup block.
|
|
141
|
+
- **Post-init nudge** — `engram init` now detects whether Sentinel hooks
|
|
142
|
+
are installed and suggests `engram install-hook` if not, closing the
|
|
143
|
+
silent drop-off gap where users get 6x savings instead of 82%.
|
|
144
|
+
- **Windows CI matrix** — GitHub Actions now runs on both
|
|
145
|
+
`ubuntu-latest` and `windows-latest` with Node 20 + 22.
|
|
146
|
+
|
|
147
|
+
### Changed
|
|
148
|
+
|
|
149
|
+
- Test count: 466 → 467 (added Windows system-path test cases).
|
|
150
|
+
|
|
151
|
+
## [0.3.1] — 2026-04-12 — "Structural"
|
|
152
|
+
|
|
153
|
+
### Added
|
|
154
|
+
|
|
155
|
+
- **TF-IDF keyword filter on `UserPromptSubmit` hook.** The pre-query
|
|
156
|
+
path now computes inverse document frequency against graph node
|
|
157
|
+
labels and requires at least one keyword with IDF ≥ 1.386 (25%
|
|
158
|
+
cutoff) before injecting context. Kills the "76-node noise bug"
|
|
159
|
+
where common-term prompts poisoned sessions on mature graphs.
|
|
160
|
+
New `computeKeywordIDF` helper in `src/core.ts`. Falls back to
|
|
161
|
+
raw keywords if IDF computation returns empty. 3 new tests.
|
|
162
|
+
- **`engram memory-sync` CLI command.** Writes engram's structural
|
|
163
|
+
facts (god nodes, landmines, graph stats, branch) into a
|
|
164
|
+
marker-bounded block inside Anthropic's native `MEMORY.md` file.
|
|
165
|
+
Uses `<!-- engram:structural-facts:start/end -->` markers so
|
|
166
|
+
Auto-Dream owns prose memory and engram owns structure —
|
|
167
|
+
complementary, not competitive. New `src/intercept/memory-md.ts`
|
|
168
|
+
module (pure builder + upsert + atomic write). 16 new tests.
|
|
169
|
+
Supports `--dry-run` and `--project`.
|
|
170
|
+
- **Cursor adapter scaffold** (`src/intercept/cursor-adapter.ts`).
|
|
171
|
+
New `engram cursor-intercept` CLI command wraps the existing
|
|
172
|
+
`handleRead` logic in Cursor 1.7's `beforeReadFile` response
|
|
173
|
+
shape (`{ permission, user_message }`). Experimental — full
|
|
174
|
+
Cursor wire-up lands in v0.3.2. 8 new tests.
|
|
175
|
+
- **EngramBench v0.1** — reproducible benchmark scaffold in
|
|
176
|
+
`bench/`. Ten structural tasks (find caller, parent class,
|
|
177
|
+
import graph, refactor scope, cross-file flow, etc.) defined as
|
|
178
|
+
YAML files with prompts, scoring rubrics, and expected tokens
|
|
179
|
+
per setup (baseline / cursor-memory / anthropic-memorymd /
|
|
180
|
+
engram). `bench/run.sh` runner + `bench/results/TEMPLATE.csv`.
|
|
181
|
+
v0.2 will automate the runner and publish a leaderboard.
|
|
182
|
+
- **Rebrand to "the structural code graph"** — package description,
|
|
183
|
+
keywords, and README hero rewritten to lead with structural
|
|
184
|
+
memory rather than the generic "memory" framing.
|
|
185
|
+
|
|
186
|
+
### Fixed
|
|
187
|
+
|
|
188
|
+
- False-positive context injections on large graphs where prompts
|
|
189
|
+
contained common graph terms (the "76-node noise bug" from
|
|
190
|
+
v0.3.0 real-session data).
|
|
191
|
+
|
|
192
|
+
### Tests
|
|
193
|
+
|
|
194
|
+
- 466 tests passing (up from 442 in v0.3.0).
|
|
195
|
+
- 27 new tests across 3 files (TF-IDF, MEMORY.md, Cursor adapter).
|
|
196
|
+
|
|
197
|
+
### Notes
|
|
198
|
+
|
|
199
|
+
- Zero new runtime dependencies.
|
|
200
|
+
- Schema unchanged from v0.3.0.
|
|
201
|
+
- No breaking changes. v0.3.0 users upgrade cleanly.
|
|
202
|
+
|
|
203
|
+
## [0.3.0] — 2026-04-11 — "Sentinel"
|
|
204
|
+
|
|
205
|
+
### Added — The Claude Code Hook Interception Layer
|
|
206
|
+
|
|
207
|
+
**The big change:** engram is no longer just a tool your agent queries.
|
|
208
|
+
It's now a Claude Code hook layer that intercepts file reads, edits,
|
|
209
|
+
prompts, and session starts — automatically replacing full file reads
|
|
210
|
+
with ~300-token structural graph summaries when confidence is high.
|
|
211
|
+
|
|
212
|
+
Empirically verified on 2026-04-11 against a live Claude Code session.
|
|
213
|
+
The hook mechanism is `PreToolUse deny + permissionDecisionReason`,
|
|
214
|
+
which Claude Code delivers to the agent as a system-reminder containing
|
|
215
|
+
the engram summary. File is never actually read, so savings materialize
|
|
216
|
+
at the agent-turn layer, not just when the agent remembers to ask.
|
|
217
|
+
|
|
218
|
+
**Seven new CLI commands:**
|
|
219
|
+
|
|
220
|
+
- `engram intercept` — hook entry point. Reads JSON from stdin,
|
|
221
|
+
dispatches through the handler registry, writes response JSON to
|
|
222
|
+
stdout. ALWAYS exits 0 — the process boundary enforces the "never
|
|
223
|
+
block Claude Code" invariant.
|
|
224
|
+
- `engram install-hook [--scope local|project|user] [--dry-run]` —
|
|
225
|
+
adds engram's entries to a Claude Code settings file. Default scope
|
|
226
|
+
is `local` (project-local, gitignored). Preserves existing non-engram
|
|
227
|
+
hooks. Idempotent. Atomic write with timestamped backup.
|
|
228
|
+
- `engram uninstall-hook` — surgical removal.
|
|
229
|
+
- `engram hook-stats [--json]` — summarize `.engram/hook-log.jsonl`
|
|
230
|
+
with per-event / per-tool / per-decision breakdowns and estimated
|
|
231
|
+
token savings.
|
|
232
|
+
- `engram hook-preview <file>` — dry-run the Read handler for a file
|
|
233
|
+
without installing. Shows deny+summary, allow+landmines, or
|
|
234
|
+
passthrough with explanation.
|
|
235
|
+
- `engram hook-disable` / `engram hook-enable` — toggle
|
|
236
|
+
`.engram/hook-disabled` kill switch.
|
|
237
|
+
|
|
238
|
+
**Seven new hook handlers:**
|
|
239
|
+
|
|
240
|
+
- `PreToolUse:Read` — deny + reason with engram's structural summary.
|
|
241
|
+
60% hit rate × ~1,200 tokens saved per hit. Projected: -18,000
|
|
242
|
+
tokens per session.
|
|
243
|
+
- `PreToolUse:Edit` / `PreToolUse:Write` — allow + additionalContext
|
|
244
|
+
with landmine warnings for files with past mistakes. NEVER blocks
|
|
245
|
+
writes — advisory injection only. Projected: -10,000 tokens by
|
|
246
|
+
preventing bug re-loops.
|
|
247
|
+
- `PreToolUse:Bash` — strict parser for single-argument `cat|head|tail
|
|
248
|
+
|less|more <file>` invocations, delegating to the Read handler. Any
|
|
249
|
+
shell metacharacter rejects the parse. Closes the Bash workaround
|
|
250
|
+
loophole without risking shell misinterpretation.
|
|
251
|
+
- `SessionStart` — injects a project brief (god nodes + graph stats
|
|
252
|
+
+ top landmines + git branch) on source=startup/clear/compact.
|
|
253
|
+
Passes through on source=resume. Replaces 3-5 initial exploration
|
|
254
|
+
reads. Projected: -5,000 tokens per session.
|
|
255
|
+
- `UserPromptSubmit` — keyword-gated pre-query injection. Extracts
|
|
256
|
+
significant terms (≥3 chars, non-stopword), requires ≥2 terms AND
|
|
257
|
+
≥3 graph matches before injecting. Budget 500 tokens per injection.
|
|
258
|
+
**PRIVACY:** raw prompt text is never logged. Projected: -8,000
|
|
259
|
+
tokens per session.
|
|
260
|
+
- `PostToolUse` — pure observer. Logs tool/path/outputSize/success
|
|
261
|
+
to `.engram/hook-log.jsonl` for `engram hook-stats` and v0.3.1
|
|
262
|
+
self-tuning.
|
|
263
|
+
|
|
264
|
+
**Total projected savings: -42,500 tokens per session** (on ~52,500
|
|
265
|
+
baseline ≈ 80% session reduction). Every number is arithmetic on
|
|
266
|
+
empirically verified hook mechanisms.
|
|
267
|
+
|
|
268
|
+
### Added — Infrastructure
|
|
269
|
+
|
|
270
|
+
- **`src/intercept/` module (14 files):** safety.ts (error/timeout
|
|
271
|
+
wrappers, PASSTHROUGH sentinel, kill-switch check), context.ts
|
|
272
|
+
(path normalization, project detection, content safety, cwd guard),
|
|
273
|
+
formatter.ts (verified JSON response builders with 8000-char
|
|
274
|
+
truncation), dispatch.ts (event routing + PreToolUse decision
|
|
275
|
+
logging), installer.ts (pure settings.json transforms), stats.ts
|
|
276
|
+
(pure log aggregation), and 7 handlers under `handlers/`.
|
|
277
|
+
|
|
278
|
+
- **`src/intelligence/hook-log.ts`:** append-only JSONL logger with
|
|
279
|
+
10MB rotation. Atomic appends (safe for <4KB writes on POSIX
|
|
280
|
+
without locking). `readHookLog` for stats queries. Never throws.
|
|
281
|
+
|
|
282
|
+
- **10 safety invariants, all enforced at runtime:**
|
|
283
|
+
1. Any handler error → passthrough (never block Claude Code)
|
|
284
|
+
2. 2-second per-handler timeout
|
|
285
|
+
3. Kill switch respected by all handlers
|
|
286
|
+
4. Atomic settings.json writes with backups
|
|
287
|
+
5. Never intercept outside project root
|
|
288
|
+
6. Never intercept binary files or secrets (.env/.pem/.key)
|
|
289
|
+
7. Never log user prompt content
|
|
290
|
+
8. Never inject >8000 chars per hook response
|
|
291
|
+
9. Stale graph detection (file mtime > graph mtime → passthrough)
|
|
292
|
+
10. Partial-read bypass (offset/limit → passthrough)
|
|
293
|
+
|
|
294
|
+
### Changed
|
|
295
|
+
|
|
296
|
+
- `core.ts::mistakes()` now accepts an optional `sourceFile` filter for
|
|
297
|
+
per-file landmine lookup.
|
|
298
|
+
- `getFileContext()` added — the bridge from absolute file paths (as
|
|
299
|
+
hooks receive them) to graph queries. Never throws.
|
|
300
|
+
- `renderFileStructure()` added to `graph/query.ts` — file-scoped
|
|
301
|
+
summary renderer. Exposes `codeNodeCount` for accurate confidence.
|
|
302
|
+
- Confidence formula: `min(codeNodeCount / 3, 1) × avgNodeConfidence`.
|
|
303
|
+
Conservative 0.7 threshold for interception.
|
|
304
|
+
- Dispatcher logs PreToolUse decisions to hook-log for `hook-stats`.
|
|
305
|
+
- Minor terminology: user-facing comments and docs now say "landmines"
|
|
306
|
+
instead of "regret buffer" (internal API unchanged — `mistakes()`,
|
|
307
|
+
`list_mistakes` MCP tool, `kind: "mistake"` schema all stable).
|
|
308
|
+
|
|
309
|
+
### Test coverage
|
|
310
|
+
|
|
311
|
+
- **+225 tests** across Days 1-5 (total 439, up from 214 in v0.2.1).
|
|
312
|
+
- Full suite time: ~1.5 seconds.
|
|
313
|
+
- 7 end-to-end subprocess tests that actually spawn
|
|
314
|
+
`node dist/cli.js intercept` and pipe JSON payloads.
|
|
315
|
+
- 4 regression fixtures captured from the 2026-04-11 live spike.
|
|
316
|
+
- NEVER-deny invariant asserted for Edit/Write handler in tests.
|
|
317
|
+
- PRIVACY invariant asserted for UserPromptSubmit handler in tests.
|
|
318
|
+
|
|
319
|
+
### Deferred to v0.3.1
|
|
320
|
+
|
|
321
|
+
- **Grep interception.** Regex metacharacters + string-literal searches
|
|
322
|
+
mean engram can't correctly handle every grep.
|
|
323
|
+
- **Per-user confidence threshold config.** v0.3.0 hardcodes 0.7.
|
|
324
|
+
- **Self-tuning from hook-log data.** Will tune 2.5x mistake boost,
|
|
325
|
+
0.5x keyword downweight, 0.7 confidence threshold, coverage ceiling.
|
|
326
|
+
|
|
327
|
+
### Migration
|
|
328
|
+
|
|
329
|
+
**No migration needed.** v0.3.0 is purely additive. All v0.2.1 CLI
|
|
330
|
+
commands work identically. MCP tools (`query_graph`, `god_nodes`,
|
|
331
|
+
`graph_stats`, `shortest_path`, `benchmark`, `list_mistakes`) are
|
|
332
|
+
unchanged. The hook layer is opt-in via `engram install-hook`.
|
|
333
|
+
|
|
334
|
+
Existing engram projects continue to work without reinstalling.
|
|
335
|
+
|
|
336
|
+
## [0.2.1] — 2026-04-10
|
|
337
|
+
|
|
338
|
+
### Fixed
|
|
339
|
+
|
|
340
|
+
- **`--with-skills` query token regression.** v0.2.0 shipped with a
|
|
341
|
+
silent 5x token cost when `engram init --with-skills` was used —
|
|
342
|
+
query avg went from 406 tokens (without skills) to 1,978 tokens
|
|
343
|
+
(with skills), and the `vs relevant files` savings metric collapsed
|
|
344
|
+
from 4.8x to 0x. The regression was discovered during post-release
|
|
345
|
+
real-world benchmarking on 6 indexed projects.
|
|
346
|
+
|
|
347
|
+
Root cause: `scoreNodes` treated keyword concept nodes (trigger-
|
|
348
|
+
phrase routing intermediaries created by the skills-miner) equally
|
|
349
|
+
with code nodes when picking BFS start seeds. A query like "how
|
|
350
|
+
does auth work" would seed BFS from ~30 keyword concepts (auth
|
|
351
|
+
flow, auth header, auth token, etc.), and BFS then pulled in the
|
|
352
|
+
entire skill subgraph via `triggered_by` edges, rendering 2,700+
|
|
353
|
+
nodes worth of noise.
|
|
354
|
+
|
|
355
|
+
Three-part fix in `src/graph/query.ts`:
|
|
356
|
+
1. `scoreNodes` downweights keyword concepts by 0.5× so code nodes
|
|
357
|
+
dominate seeding whenever they exist. Keywords remain seed-
|
|
358
|
+
eligible when NO code matches, preserving skill discovery.
|
|
359
|
+
2. `renderSubgraph` filters keyword concepts out of visible output
|
|
360
|
+
entirely (they stay as BFS traversal intermediaries, just
|
|
361
|
+
invisible in the rendered text). Edges touching keyword nodes
|
|
362
|
+
are also skipped to avoid exposing keyword labels via EDGE lines.
|
|
363
|
+
3. **BFS/DFS traversal filter:** `triggered_by` edges are only
|
|
364
|
+
walked when the current frontier node is itself a keyword. This
|
|
365
|
+
prevents skill concepts from pulling in their 30+ inbound
|
|
366
|
+
keyword neighbors via reverse edge expansion — the core
|
|
367
|
+
mechanism of the original bloat. Keywords remain reachable via
|
|
368
|
+
direct text-match seeding; they just stop acting as "inbound
|
|
369
|
+
attractors" for non-keyword traversal.
|
|
370
|
+
|
|
371
|
+
Plus a companion filter: `similar_to` edges between skill concepts
|
|
372
|
+
are suppressed from EDGE rendering — skill cross-reference
|
|
373
|
+
metadata adds noise to code-focused queries without structural
|
|
374
|
+
value. Skill NODE lines are still rendered so users asking for
|
|
375
|
+
skill suggestions still see them.
|
|
376
|
+
|
|
377
|
+
**Verified real-world impact:**
|
|
378
|
+
|
|
379
|
+
| Project | v0.2.0 broken | v0.2.1 fixed | No-skills baseline |
|
|
380
|
+
|---------|---------------|--------------|---------------------|
|
|
381
|
+
| engram | 1,978 tok / 0x rel | **499 tok / 5.0x rel** | 406 tok / 4.8x rel |
|
|
382
|
+
| scripts | (N/A — not benched with skills in v0.2.0) | **272 tok / 2.4x rel** | 311 tok / 3.7x rel |
|
|
383
|
+
|
|
384
|
+
On engram itself, `--with-skills` now costs only ~23% more tokens
|
|
385
|
+
than pure code mode and the `vs relevant` savings is actually
|
|
386
|
+
_slightly better_ (5.0x vs 4.8x). On `scripts`, a code-heavy
|
|
387
|
+
project, there's still a modest ~35% cost for skill awareness but
|
|
388
|
+
the absolute savings are restored.
|
|
389
|
+
|
|
390
|
+
Pure code mode (`engram init` without `--with-skills`) is
|
|
391
|
+
unchanged and continues to deliver 3-11x savings vs relevant files.
|
|
392
|
+
|
|
393
|
+
### Added
|
|
394
|
+
|
|
395
|
+
- **6 new regression tests** in `tests/stress.test.ts`:
|
|
396
|
+
- Code query on a seeded graph with 20 keyword concepts — verifies
|
|
397
|
+
zero keyword labels in rendered output
|
|
398
|
+
- Token budget stays under 800 tokens on the same seeded graph
|
|
399
|
+
- Skill discovery via keyword bridges still works when no code
|
|
400
|
+
matches exist
|
|
401
|
+
- Direct skill-name query returns the skill
|
|
402
|
+
- Score downweight verified: code nodes outrank keywords when both
|
|
403
|
+
text-match
|
|
404
|
+
- No keyword labels leak through edge rendering (triggered_by
|
|
405
|
+
edges correctly skipped)
|
|
406
|
+
|
|
407
|
+
### Tests
|
|
408
|
+
|
|
409
|
+
- 132 → 138 tests passing across 8 test files. No regressions.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## [0.2.0] — 2026-04-10
|
|
414
|
+
|
|
415
|
+
### Added
|
|
416
|
+
|
|
417
|
+
- **Skills miner** (`src/miners/skills-miner.ts`). Walks
|
|
418
|
+
`~/.claude/skills/*/SKILL.md` (or a custom path) and indexes skills as
|
|
419
|
+
graph nodes. Extracts trigger phrases via line-safe regex that survives
|
|
420
|
+
`Node.js` / `React.js` style periods and Unicode curly quotes. Hand-rolled
|
|
421
|
+
YAML parser — no new dependency. Handles anomalous files (missing
|
|
422
|
+
frontmatter, corrupted YAML, broken symlinks) gracefully. Real-world
|
|
423
|
+
benchmark: 140 skills + 2,690 keyword nodes indexed in 27ms.
|
|
424
|
+
- **Opt-in skills indexing** via `engram init --with-skills [dir]` or
|
|
425
|
+
programmatic `init(root, { withSkills: true })`. Default is OFF —
|
|
426
|
+
existing v0.1 users see no behavior change.
|
|
427
|
+
- **Adaptive `gen --task <name>`** driven by a data-driven `VIEWS` table.
|
|
428
|
+
Four presets: `general` (default), `bug-fix`, `feature`, `refactor`.
|
|
429
|
+
Each view specifies which sections render and at what limits. Adding a
|
|
430
|
+
new task is adding a row to the VIEWS table — no branching logic.
|
|
431
|
+
- **Mistake memory activation** (regret buffer). The session miner
|
|
432
|
+
already extracted mistakes in v0.1 — v0.2 wires them into the query
|
|
433
|
+
path. Mistake nodes get a 2.5x score boost in `scoreNodes`, and matching
|
|
434
|
+
mistakes are surfaced at the TOP of query output in a ⚠️ PAST MISTAKES
|
|
435
|
+
warning block. Layering: promotion happens in scoring, presentation in
|
|
436
|
+
rendering (per Hickey panel review guidance).
|
|
437
|
+
- **New `mistakes()` public API** in `src/core.ts` + `MistakeEntry`
|
|
438
|
+
interface. Sorts by most-recently-verified, supports `limit` and
|
|
439
|
+
`sinceDays` options.
|
|
440
|
+
- **New `engram mistakes` CLI command** with `-l/--limit`, `--since DAYS`,
|
|
441
|
+
`-p/--project` flags.
|
|
442
|
+
- **New `list_mistakes` MCP tool** (6 tools total now). Explicit JSON
|
|
443
|
+
Schema. Labels truncated surrogate-safely at 500 chars to prevent UTF-16
|
|
444
|
+
corruption of the JSON-RPC response when mistakes contain emoji.
|
|
445
|
+
- **Atomic lockfile guard** on `init()` via `.engram/init.lock` (`wx`
|
|
446
|
+
exclusive-create flag). Prevents two concurrent init calls from silently
|
|
447
|
+
corrupting the graph. Descriptive error on contention.
|
|
448
|
+
- **Surrogate-safe string helpers** in new `src/graph/render-utils.ts`:
|
|
449
|
+
`sliceGraphemeSafe()` and `truncateGraphemeSafe()`. Prevents lone high
|
|
450
|
+
surrogates at cut boundaries that would corrupt JSON round-trip.
|
|
451
|
+
- **Data-driven View types** exported publicly: `View`, `SectionSpec`,
|
|
452
|
+
`SectionKind`, `VIEWS`. Consumers can define custom views.
|
|
453
|
+
- **New EdgeRelation:** `triggered_by` (keyword concept → skill concept).
|
|
454
|
+
- **Integration guide updated** at `docs/INTEGRATION.md` with new
|
|
455
|
+
`--with-skills`, `--task`, and `mistakes` sections.
|
|
456
|
+
- **Reference MCP shell wrapper** at `scripts/mcp-engram` (introduced in
|
|
457
|
+
v0.1.1, documented in v0.2).
|
|
458
|
+
|
|
459
|
+
### Changed
|
|
460
|
+
|
|
461
|
+
- **`writeToFile` is now marker-state-aware** in `src/autogen.ts`. Walks
|
|
462
|
+
the target file line-by-line tracking code-fence depth; markers inside
|
|
463
|
+
fenced code blocks are correctly ignored. Unbalanced markers now throw
|
|
464
|
+
a descriptive error instead of silently corrupting user content. This
|
|
465
|
+
closes a v0.1 latent bug where CLAUDE.md files with orphaned markers
|
|
466
|
+
could lose data between the orphaned pair.
|
|
467
|
+
- **`renderSubgraph` output uses surrogate-safe truncation** instead of
|
|
468
|
+
raw `string.slice`. Emoji in mistake labels no longer corrupt the MCP
|
|
469
|
+
JSON response.
|
|
470
|
+
- **`generateSummary(store)` signature** now accepts an optional
|
|
471
|
+
`view: View` parameter; defaults to `VIEWS.general` for backwards
|
|
472
|
+
compatibility. Legacy callers passing no view continue to work.
|
|
473
|
+
- **`autogen(root, target?)` signature** gained an optional third
|
|
474
|
+
positional argument `task?: string`. Unknown task names throw with a
|
|
475
|
+
descriptive error listing valid keys.
|
|
476
|
+
- **`init(root)` signature** now accepts optional `options: InitOptions`
|
|
477
|
+
for `withSkills`. Unchanged default behavior.
|
|
478
|
+
- **`getGodNodes` SQL exclusion list** now includes `concept`. In v0.1
|
|
479
|
+
this kind was unused; v0.2 uses it for skills and keywords, which
|
|
480
|
+
should not dominate god-node results with hundreds of `triggered_by`
|
|
481
|
+
edges.
|
|
482
|
+
- **MCP server numeric argument hardening.** All numeric tool args
|
|
483
|
+
(`depth`, `token_budget`, `top_n`, `limit`, `since_days`) are now
|
|
484
|
+
clamped via `clampInt()` with explicit min/max bounds. Prevents
|
|
485
|
+
Infinity/NaN/negative values from DOSing the server on unbounded
|
|
486
|
+
graph traversal or string construction.
|
|
487
|
+
- **MCP server error handling.** `handleRequest()` promise chain now
|
|
488
|
+
has a `.catch()` that returns a generic `-32000` error response. Tool
|
|
489
|
+
implementations that throw no longer produce unhandled rejections
|
|
490
|
+
(which crash the process under Node's strict mode). Error messages
|
|
491
|
+
from sql.js (which contain absolute filesystem paths) are never
|
|
492
|
+
relayed to the client.
|
|
493
|
+
- **MCP server parse error response.** Malformed JSON on stdin now gets
|
|
494
|
+
a proper JSON-RPC `-32700 Parse error` response with `id: null` per
|
|
495
|
+
spec, instead of being silently dropped.
|
|
496
|
+
- **Engines requirement** remains `node >= 20` (unchanged from v0.1.1).
|
|
497
|
+
|
|
498
|
+
### Security
|
|
499
|
+
|
|
500
|
+
- **M1 (MCP unhandled rejection → process crash)** — fixed. See
|
|
501
|
+
"Changed" above.
|
|
502
|
+
- **M2 (MCP numeric arg DOS)** — fixed. See "Changed" above.
|
|
503
|
+
- Both findings surfaced by the security-reviewer agent during the
|
|
504
|
+
Phase 3 review gate.
|
|
505
|
+
|
|
506
|
+
### Tests
|
|
507
|
+
|
|
508
|
+
- **132 tests passing** (up from 63 in v0.1.1) across 8 test files.
|
|
509
|
+
- New test files: `tests/render-utils.test.ts` (13 tests),
|
|
510
|
+
`tests/autogen.test.ts` (18 tests: writeToFile state machine + Views
|
|
511
|
+
+ autogen task flag), `tests/skills-miner.test.ts` (11 tests),
|
|
512
|
+
`tests/mistake-memory.test.ts` (10 tests).
|
|
513
|
+
- New fixtures: `tests/fixtures/skills/{normal,anomaly,multiline,unicode,empty-body,corrupted}/SKILL.md`
|
|
514
|
+
and `tests/fixtures/mistake-corpus-readme.md` (frozen README for
|
|
515
|
+
false-positive regression).
|
|
516
|
+
- 8 new `tests/stress.test.ts` scenarios: v0.1 backwards compat,
|
|
517
|
+
1000-node graph view performance, 100-mistake query, 200-mistake API
|
|
518
|
+
slicing, MCP stdio smoke (list_tools + list_mistakes + parse error),
|
|
519
|
+
MCP numeric arg hardening smoke, 2000-file + 100-skill init under 10s,
|
|
520
|
+
empty-graph view rendering.
|
|
521
|
+
|
|
522
|
+
### Review gates
|
|
523
|
+
|
|
524
|
+
All 4 feature phases passed `code-reviewer` with APPROVED-WITH-NITS
|
|
525
|
+
verdicts; Phase 3 MCP boundary surface additionally passed
|
|
526
|
+
`security-reviewer`. Nits from reviewers are captured inline in commit
|
|
527
|
+
messages for follow-up tracking.
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## [0.1.1] — 2026-04-09
|
|
532
|
+
|
|
533
|
+
### Added
|
|
534
|
+
|
|
535
|
+
- Published to npm as `engramx@0.1.1`.
|
|
536
|
+
- `engram-serve` bin alias for the MCP server binary.
|
|
537
|
+
- `engramx` bin alias matching the npm package name.
|
|
538
|
+
- Banner + social preview image.
|
|
539
|
+
- Comparison table vs Mem0, Graphify, aider, CLAUDE.md.
|
|
540
|
+
- GitHub Actions CI with Node 20 + 22 matrix.
|
|
541
|
+
- `docs/INTEGRATION.md` multi-machine setup guide.
|
|
542
|
+
- `scripts/mcp-engram` — portable reference shell wrapper.
|
|
543
|
+
|
|
544
|
+
### Changed
|
|
545
|
+
|
|
546
|
+
- Dropped Node 18 support — `vitest@4` requires `node:util.styleText`
|
|
547
|
+
which is Node 20+.
|
|
548
|
+
- Removed `web-tree-sitter` dependency (was experimental, unused in
|
|
549
|
+
v0.1; planned for v0.3).
|
|
550
|
+
- Package name from `engram` to `engramx` on npm after discovering
|
|
551
|
+
the original name was taken by a dormant 2013 package.
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
555
|
+
## [0.1.0] — 2026-04-09
|
|
556
|
+
|
|
557
|
+
### Added
|
|
558
|
+
|
|
559
|
+
- Initial release. Knowledge graph for AI coding memory.
|
|
560
|
+
- **AST miner** — regex-based structural extraction across 10 languages
|
|
561
|
+
(TypeScript, JavaScript, Python, Go, Rust, Java, C, C++, Ruby, PHP).
|
|
562
|
+
Zero LLM cost, deterministic.
|
|
563
|
+
- **Git miner** — co-change pattern extraction from git log. Hot file
|
|
564
|
+
detection (5+ changes).
|
|
565
|
+
- **Session miner** — decision/pattern/mistake extraction from CLAUDE.md,
|
|
566
|
+
`.cursorrules`, AGENTS.md, and `.engram/sessions/` directories.
|
|
567
|
+
- **SQLite graph store** via `sql.js` — zero native dependencies.
|
|
568
|
+
- **CLI:** `init`, `query`, `path`, `gods`, `stats`, `bench`, `learn`,
|
|
569
|
+
`gen`, `hooks`.
|
|
570
|
+
- **MCP stdio server** with 5 tools: `query_graph`, `god_nodes`,
|
|
571
|
+
`graph_stats`, `shortest_path`, `benchmark`.
|
|
572
|
+
- **Auto-generated CLAUDE.md sections** via `engram gen`. Marker-scoped
|
|
573
|
+
replacement.
|
|
574
|
+
- **Git hooks** — post-commit and post-checkout auto-rebuild in <50ms.
|
|
575
|
+
- **Confidence tagging** on every node and edge: EXTRACTED / INFERRED /
|
|
576
|
+
AMBIGUOUS.
|
|
577
|
+
- **Honest benchmark** reporting two baselines: vs relevant files
|
|
578
|
+
(3-11x) and vs full corpus (30-70x).
|
|
579
|
+
- Apache 2.0 licensed.
|
|
580
|
+
|
|
581
|
+
[0.2.0]: https://github.com/NickCirv/engram/releases/tag/v0.2.0
|
|
582
|
+
[0.1.1]: https://github.com/NickCirv/engram/releases/tag/v0.1.1
|
|
583
|
+
[0.1.0]: https://github.com/NickCirv/engram/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ npm install -g engramx
|
|
|
88
88
|
|
|
89
89
|
Requires Node.js 20+. Zero native dependencies. No build tools needed.
|
|
90
90
|
|
|
91
|
-
## Quickstart
|
|
91
|
+
## Quickstart
|
|
92
92
|
|
|
93
93
|
```bash
|
|
94
94
|
cd ~/my-project
|
|
@@ -431,24 +431,19 @@ TypeScript, JavaScript, Python, Go, Rust, Java, C, C++, Ruby, PHP.
|
|
|
431
431
|
|
|
432
432
|
## Roadmap
|
|
433
433
|
|
|
434
|
-
###
|
|
435
|
-
- ✅
|
|
436
|
-
- ✅
|
|
437
|
-
- ✅
|
|
438
|
-
- ✅
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
- Tree-sitter
|
|
444
|
-
-
|
|
445
|
-
-
|
|
446
|
-
-
|
|
447
|
-
|
|
448
|
-
### v0.4+
|
|
449
|
-
- LLM-free semantic search (locality-sensitive hashing over n-grams)
|
|
450
|
-
- Graph-as-IR experimental spike
|
|
451
|
-
- Team memory sync (paid tier)
|
|
434
|
+
### Shipped
|
|
435
|
+
- ✅ **v0.5** — Context Spine: 6 providers, rich packets, provider cache, 90% session savings
|
|
436
|
+
- ✅ **v0.4** — Infrastructure: PreCompact, CwdChanged, file watcher, MemPalace integration
|
|
437
|
+
- ✅ **v0.3** — Sentinel: 9 hook handlers, Read interception, session briefs, prompt pre-query
|
|
438
|
+
- ✅ **v0.2** — Skills miner, mistake memory, adaptive gen, MCP server
|
|
439
|
+
|
|
440
|
+
### Next
|
|
441
|
+
- ECP spec v0.1 — Engram Context Protocol (open RFC)
|
|
442
|
+
- Continue.dev + Cursor adapters
|
|
443
|
+
- Tree-sitter opt-in (20+ languages with full AST precision)
|
|
444
|
+
- Reproducible benchmark harness
|
|
445
|
+
- Graph explorer (ReactFlow web UI)
|
|
446
|
+
- Team sync (ElectricSQL, paid tier)
|
|
452
447
|
|
|
453
448
|
## Privacy
|
|
454
449
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "engramx",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "The
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "The context spine for AI coding agents. 6 providers assembled into rich context packets per Read interception. Up to 90% session-level token savings. Local SQLite, zero native deps, zero cloud.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/NickCirv/engram.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/NickCirv/engram",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/NickCirv/engram/issues"
|
|
12
|
+
},
|
|
5
13
|
"type": "module",
|
|
6
14
|
"bin": {
|
|
7
15
|
"engram": "dist/cli.js",
|
|
@@ -22,7 +30,8 @@
|
|
|
22
30
|
"ai-coding",
|
|
23
31
|
"context-engineering",
|
|
24
32
|
"knowledge-graph",
|
|
25
|
-
"
|
|
33
|
+
"context-spine",
|
|
34
|
+
"context-providers",
|
|
26
35
|
"mcp",
|
|
27
36
|
"claude-code",
|
|
28
37
|
"cursor",
|
|
@@ -40,7 +49,8 @@
|
|
|
40
49
|
"files": [
|
|
41
50
|
"dist",
|
|
42
51
|
"LICENSE",
|
|
43
|
-
"README.md"
|
|
52
|
+
"README.md",
|
|
53
|
+
"CHANGELOG.md"
|
|
44
54
|
],
|
|
45
55
|
"dependencies": {
|
|
46
56
|
"chalk": "^5.6.2",
|