Skip to content

fix: close four gaps a multi-persona audit pass found - #360

Merged
fstubner merged 2 commits into
mainfrom
fix/audit-findings
Sep 5, 2026
Merged

fix: close four gaps a multi-persona audit pass found#360
fstubner merged 2 commits into
mainfrom
fix/audit-findings

Conversation

@fstubner

@fstubner fstubner commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Six independent auditors read the codebase from different angles — attacker, impatient newcomer, 3am SRE, performance engineer, privacy reviewer, inheriting maintainer. Four findings survived verification and are fixed here. (The memory finding went to #359, where the feature it affects lives.)

1. The store-redirect warning missed its own stated case

.xtctx/config.yaml is committable and can set storePath, resolved with no containment — so a cloned repo can point a scraper at another project's store and have those conversations served back as this project's context. The docstring says exactly that.

The check then asked whether the path was outside the home directory. Every Claude Code project's transcripts live under ~/.claude/projects/, so redirecting at a sibling project names a path inside home and was reported as nothing at all.

The boundary is now the tool's own default store. This doesn't reintroduce the noise the home rule was avoiding: setup no longer writes storePath at all, so any config carrying one is already an override.

2. Literal search blamed the query for a broken store

A store that threw and a pass that hit its limit both set exhausted: false, and that was all the caller got:

The literal pass stopped at its limit or time budget… Narrow the query or raise limit.

Against an unreadable store every narrower query returns the same nothing, and the broken tool is never named. It now gets its own sentence saying which store failed and that this is not a query problem.

3. The retrieval-unit repair ran on every project in the database

selectSessionsMissingUnits was the one query that selected sessions without asking whose they were. One database can hold another project's sessions — a copied .xtctx/, a renamed root — and the repair is capped at a few sessions per scan, so foreign rows don't merely waste the rebuild and the embedding after it: they crowd out the real ones, and this project's own gap never closes.

4. An orphaned docstring

claude-code.ts documented a method that isn't there, against the class's closing brace.

Verification

Each fix is pinned by a test that fails against the old behaviour:

mutation result
neutralise the project_root filter 1 test fails
stop naming the unreadable store 1 test fails
revert to a home-shaped boundary 2 tests fail

694 tests pass, tsc -p tsconfig.test.json clean, lint clean.

One finding rejected

The audit's top-ranked item claimed a comment in cursor.ts lies about array recursion. It doesn't — the comment says arrays are walked into and their elements ignored, which is what the code does. Verified verbatim rather than taken on the auditor's word.

Six independent auditors read the codebase from different angles. Four
findings survived verification.

**The store-redirect warning missed its own stated case.** `.xtctx/config.yaml`
is committable and can set `storePath`, resolved with no containment, so a
cloned repo can point a scraper at another project's store and have those
conversations served back as this project's context. The docstring says
exactly that. The check then asked whether the path was outside the *home
directory* — and every Claude Code project's transcripts live under
`~/.claude/projects/`, so redirecting at a sibling project names a path inside
home and was reported as nothing at all. The boundary is now the tool's own
default store. That does not reintroduce the noise the home rule was avoiding:
setup no longer writes `storePath`, so any config carrying one is already an
override.

**Literal search blamed the query for a broken store.** A store that threw and
a pass that hit its limit both set `exhausted: false`, and that was everything
the caller got — so it told the user the pass "stopped at its limit or time
budget" and advised narrowing the query. Against an unreadable store every
narrower query returns the same nothing, and the broken tool is never
mentioned. The tools that threw are now named, with their own sentence.

**The retrieval-unit repair ran on every project in the database.** It was the
one query that selected sessions without asking whose they were. One database
can hold another project's sessions — a copied `.xtctx/`, a renamed root — and
the repair is capped at a few sessions per scan, so foreign rows do not merely
waste the rebuild and the embedding after it, they crowd out the real ones and
this project's own gap never closes.

**An orphaned docstring** in claude-code.ts documented a method that is not
there, sitting against the class's closing brace.

Each fix is pinned by a test that fails against the old behaviour: neutralising
the project filter, dropping the store name, and reverting to a home-shaped
boundary each turn one red.

One finding was rejected rather than fixed. The audit's top-ranked item claimed
a comment in cursor.ts lies about array recursion; the comment says arrays
*are* walked into and their elements ignored, which is what the code does.
@fstubner
fstubner merged commit 89bd838 into main Sep 5, 2026
5 checks passed
@fstubner
fstubner deleted the fix/audit-findings branch September 5, 2026 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant