Skip to content

Commit 2a56fbb

Browse files
NickCirvclaude
andcommitted
chore: honesty + hygiene cleanup pass (3-agent audit findings)
A 3-agent audit (code cleanliness · feature-interaction · fresh-clone health) verified the session's work is 100% on build/tests/install (fresh clone: 1097/1097 green, all features smoke-verified, clean tarball) and surfaced three real honesty/cleanliness issues, now fixed: - Grep handler claimed its caller list was 'ranked' — but findCallers returns an alphabetical sort, not an importance ranking. Dropped 'ranked' from the agent-facing packet + the header comment + ADR-0001 + CHANGELOG (the *real* PageRank query-ranking in README/query.ts is untouched — only the false grep-caller claim). Matches the v4.1 honesty discipline. - Read dedup pointer said 'its contents are already in your context' — overstated when the first read returned a structural packet (the agent has the summary, not the contents). Softened to 'what you saw then is still in your context' (true whether the first read served a packet or passed the raw file through). - served-reads.ts: corrected a comment that described the timestamp refresh backwards. Also: up to date, audited 188 packages in 931ms 50 packages are looking for funding run `npm fund` for details found 0 vulnerabilities (non-breaking) cleared all 6 transitive vulns (1 high fast-uri via the MCP SDK → ajv, 5 moderate) → 0 vulnerabilities, production + dev. Only package-lock.json changed. No code-behaviour change. Audit: tsc clean; full suite 1097/1097; build clean; npm audit 0 vulns; leak-scan 0 hits. Feature-interaction audit verdict SHIP (landmine not reintroduced, opt-outs independent, no state collisions). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 61cb39e commit 2a56fbb

6 files changed

Lines changed: 35 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ All notable changes to engram are documented here. Format based on
2222
`PreToolUse:Grep` handler answers symbol-usage searches from the `calls`
2323
reference graph instead of letting a raw match dump flood the context window.
2424
When the agent greps a bare identifier that's a known symbol with references,
25-
engram denies the grep and returns the ranked list of files that reference it,
25+
engram denies the grep and returns the list of files that reference it,
2626
plus the exact `rg -n "<pattern>"` escalation command. **Recall-safe by
2727
construction:** regex/text/multi-word/stopword patterns and unknown symbols
2828
pass straight through (grep out-recalls the structural graph there), and the

docs/adr/0001-grep-symbol-intercept.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ still runs every `Grep` raw, and a symbol search across a large repo floods the
1111
match lines (often 2–20k tokens). The W1.9 benchmark shows engram already wins exactly on the
1212
explore-heavy workloads (troubleshooting +24.9%, code-understanding +23.3%) and is neutral/negative on
1313
linear edits — i.e. the value is in *exploration elimination*, which this gap leaves on the table. The
14-
`calls` reference graph + `findCallers/findCallees/findImpact` (PageRank-ranked) already exist but are
14+
`calls` reference graph + `findCallers/findCallees/findImpact` (pure traversal, alphabetically sorted) already exist but are
1515
CLI-only — never wired into the hook.
1616

1717
## Decision
1818

1919
Add a `PreToolUse:Grep` handler that intercepts **only** a bare-identifier pattern that matches a known
20-
symbol with references in the `calls` graph, denies the grep, and returns engram's ranked caller list.
20+
symbol with references in the `calls` graph, denies the grep, and returns engram's caller list (the files that reference it).
2121
For anything else — regex/metacharacter patterns, multi-word/text searches, stopword identifiers, or a
2222
symbol the graph doesn't know — it returns PASSTHROUGH so the real grep runs.
2323

@@ -27,7 +27,7 @@ wholesale would blind the agent — a correctness regression. We mitigate by (a)
2727
the pattern is a known symbol with ≥1 caller (high precision), and (b) **always emitting the exact
2828
`rg -n "<pattern>"` escalation command** in the deny reason, so the agent can recover full textual
2929
matches in one step if it needs them. The token win comes from the common case ("where is this symbol
30-
used") being answered from a ranked file list (~tens–hundreds of tokens) instead of a raw match dump,
30+
used") being answered from a caller-file list (~tens–hundreds of tokens) instead of a raw match dump,
3131
while correctness is preserved by the escalation path. The discarded alternative — augment-don't-deny
3232
(let grep run AND add engram's note) — preserves recall perfectly but saves zero tokens (grep still
3333
runs + we add tokens), which defeats the purpose. If the precision gate proves too narrow or too broad

package-lock.json

Lines changed: 24 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/intercept/handlers/grep.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
* real grep runs. Default to doing nothing; act only when provably helpful.
1717
*
1818
* Returns:
19-
* - A deny response whose reason is engram's ranked caller list, when the
20-
* pattern is a known symbol with references.
19+
* - A deny response whose reason is engram's caller list (the files that
20+
* reference the symbol), when the pattern is a known symbol with references.
2121
* - PASSTHROUGH (null) otherwise — caller writes nothing, exits 0, the real
2222
* Grep runs unchanged.
2323
* Never throws. Every error path resolves to PASSTHROUGH via wrapSafely.
@@ -106,7 +106,7 @@ function buildGrepAnswer(pattern: string, callerFiles: string[]): string {
106106
const list = callerFiles.map((f) => ` - ${f}`).join("\n");
107107
return [
108108
`[engram] "${pattern}" is referenced by ${callerFiles.length} file(s) ` +
109-
`in the reference graph (structural \`calls\` edges, ranked):`,
109+
`in the reference graph (structural \`calls\` edges):`,
110110
list,
111111
"",
112112
"This is engram's structural answer — resolved function/class references " +

src/intercept/handlers/read.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export const READ_CONFIDENCE_THRESHOLD = 0.7;
6363
function buildDedupPointer(relPath: string): string {
6464
return (
6565
`[engram] You already read \`${relPath}\` earlier in this session and it ` +
66-
`has not changed since — its contents are already in your context above, ` +
66+
`has not changed since — what you saw then is still in your context above, ` +
6767
`no need to re-read it. (If you believe it changed, read it again: engram ` +
6868
`only dedupes byte-identical files within one session and resets on context ` +
6969
`compaction.)`

src/intercept/served-reads.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,9 @@ export function dedupOrRecord(
136136
}
137137

138138
// First read (or changed, or tiny, or stale): record and continue. `at` is
139-
// refreshed only on a real (re-)serve, so dedup-eligibility ages from when
140-
// the content last entered context, not from the last pointer.
139+
// set here, on a record — never on a dedup hit (which returns above without
140+
// touching it) — so dedup-eligibility ages from when this version of the
141+
// content last entered context, not from the last pointer.
141142
map[key] = { mtimeMs: st.mtimeMs, size: st.size, at: now };
142143
capEntries(map);
143144
try {

0 commit comments

Comments
 (0)