Status: Adversarial Layer: Runtime
§Scope
No purpose statement is recorded for this subsystem; the scope below states what it covers.
mcp-server/src/*.ts and schema.sql — the server root modules, the storage lifecycle, the invariants
§Start here
mcp-server/src/index.ts; src/db.ts; src/schema.sql; src/invariants.ts
§Structure
What the survey recorded as claims about this subsystem, grouped by what each one states. Every claim is bound to the revision it was asserted at and to the evidence attached to it; a superseded claim is not shown here.
§Other claims
| Claim | Subject | Statement | Epistemic kind | Asserted at |
|---|---|---|---|---|
B-02/identity/binding-is-re-derived-per-call | B-02 | Scope identity is re-derived and re-asserted on every tool call rather than trusted from process start: assertProjectBinding recomputes the project descriptor, compares it against the receipt minted at resolveProject, and requires the bound storage path to remain inside the storage root. Two worktrees of one repository therefore share a projectKey but hold distinct worktree-local stores with distinct workspaceInstanceId values, which is the ordinary case here rather than the exotic one. | Observation | c0734040022f |
B-02/recoverability/checkpoint-is-a-caller-obligation | B-02 | The WAL checkpoint that makes a storage commit recoverable is a caller obligation, not a property of the function that publishes the commit. commitStorage stages and commits without checkpointing; both call sites — end_session and commit_phase_gate — call checkpointDatabaseForStorageCommit immediately before it, and that function treats a busy or partial checkpoint as a hard failure. A third caller added without the checkpoint would reintroduce archived finding B02-1 with nothing in storage-git.ts to stop it. | Inference | c0734040022f |
B-02/storage-lifecycle/open-is-the-only-migration-path | B-02 | openDatabase is the only path by which a store's schema changes: it runs additive column/index migrations, re-execs the whole of schema.sql (546 of 547 CREATE statements carry IF NOT EXISTS), mints the store identity if absent, and then refuses the open when any declared object is missing or present as the wrong kind, or when either required view is absent. No table arrives, and no store is left partially upgraded, outside that sequence. | Observation | c0734040022f |
B-05/contracts/generate-or-assert-every-duplicated-fact | B-05 | The checker set in mcp-server/scripts/ is organized around one rule: a fact published twice is either generated from one source or asserted against it. gen-vocabulary.mjs generates two enum modules and asserts the schema's CHECKs; gen-tool-inventory.mjs generates DEVELOPMENT.md's block and --check refuses a divergence; check-refusal-parity.mjs cannot generate prose so it generates the candidate refusal set and compares that against a register; check-concern-checklist.mjs holds the calibrated checklist to its contract. Where a duplicated fact has neither a generator nor an assertion, it drifts — which is what B05-2 is. | Inference | c0734040022f |
§Vocabulary
- independent storage mode — The .storage-mode marker that makes a project-local .amanuensis/ its own nested git repository and forbids it from ever falling through to the surveyed repository's git.
- store generation — The random 32-hex identity a store mints once, at the open that creates store_identity, and never recomputes — the name a carried record calls the conspectus it came out of.
§Known defects here
1 defect here is open or awaiting verification. Each one's full record, with its evidence, is on Open findings.
- A durable write can block the server indefinitely. Every add_evidence, add_finding, add_claim and set_disposition shells out to
git rev-parsesynchronously with no timeout, so an unresponsive git — a network-mounted worktree, a credential helper waiting on input, a filesystem that has stopped answering — hangs the whole stdio server with no diagnostic, because spawnSync blocks the event loop and the transport is single-threaded. — B02-R1 · Medium · Open
1 further defect here reached a terminal state; it is recorded on Resolved findings.
§Standing
Adversarial — Candidate conclusions are being challenged; treat them as provisional. It cannot justify that the challenge pass has finished.
- Files read
- 13 of 13 ledger rows
- Files in scope, not yet read
- 0 of 13
- Files excluded from the survey obligation
- 0 of 13
- Ledger rows the repository has changed under
- 0 of 13
- Active concerns with a disposition recorded here
- 12 of 12 — 8 confirmed-acceptable, 3 ruled-out, 1 out-of-scope
- Findings by resolution state
- 1 open, 1 verified fixed
- Seams assessable from both sides
- no seam names this subsystem
§Survey record
§File ledger
| Path | Classification | Why in scope | Examined at |
|---|---|---|---|
mcp-server/src/cli.ts | examined | The installer and doctor: registration planning for Claude, VS Code and Codex, the managed config blocks, and the repair plans. | c0734040 |
mcp-server/src/codebase-brief-contract.ts | examined | The codebase-brief schema, its canonical JSON hashing, and the compile/validate pair the brief tools call. | c0734040 |
mcp-server/src/codex-host.ts | examined | Codex parent-workspace discovery, with the 5s probe timeout that finding B02-2 is about. | a521e28 |
mcp-server/src/db.ts | examined | Storage lifecycle: openDatabase runs migrations, re-execs schema.sql, mints store identity, then refuses the open when a declared object or required view is absent. | c0734040 |
mcp-server/src/helpers.ts | examined | The shared ingress guards: resolveWorkspaceCommit, the batched resolveWorkspaceCommits, path and citation validation, and the response envelope every budget is measured on. | c0734040 |
mcp-server/src/index.ts | examined | Server root: workspace selection, tool assembly, Ajv validation, annotation derivation, and the single dispatcher that enforces each tool's compact flag. | a521e28 |
mcp-server/src/invariants.ts | examined | Every status-advance refusal: phase prerequisites, attached-evidence, vocabulary discharge, reconciliation standing, archived store identity, and the carried accounting. | c0734040 |
mcp-server/src/project.ts | examined | Project identity, the binding receipt, the storage root containment check, and the staged atomic publish of a new store. | a521e28 |
mcp-server/src/schema.sql | examined | The durable substrate: 547 CREATE statements, 546 of them IF NOT EXISTS, and 176 immutability trigger lines that make the append-only tables append-only. | c0734040 |
mcp-server/src/session.ts | examined | The session table's three operations; the smallest module in the subsystem and the one every write's session_id comes from. | c0734040 |
mcp-server/src/standing.ts | examined | The reader-lens standing model: locus resolution, the standing ladder, the authority ceiling, and the revision and measured blocks describe_locus answers from. | c0734040 |
mcp-server/src/storage-git.ts | examined | The storage repository: repoState's six starting states, ensureStorageRepo, and commitStorage, which stages and commits without checkpointing the WAL itself. | c0734040 |
mcp-server/src/vocabulary.ts | examined | Generated from contracts/conspectus-vocabulary.json — the single source for every enum, the obligation-bearing split, and the SQL CHECK bindings. | c0734040 |
§Concern review
AT-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
Rationale
AT-2
- Verdict
- Accepted behavior
- Evidence
- Code verified
- Linchpin dependency
- 🔗
Rationale
CC-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
- Linchpin dependency
- 🔗
Rationale
CR-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
- Linchpin dependency
- 🔗
Rationale
EP-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
Rationale
IF-1
- Verdict
- Out of scope
- Evidence
- Code verified
Rationale
RL-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
- Linchpin dependency
- 🔗
Rationale
SC-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
- Linchpin dependency
- 🔗
Rationale
SI-1
- Verdict
- Ruled out
- Evidence
- Code verified
Rationale
SI-2
- Verdict
- Ruled out
- Evidence
- Code verified
Rationale
TB-1
- Verdict
- Accepted behavior
- Evidence
- Code verified
- Linchpin dependency
- 🔗
Rationale
TR-1
- Verdict
- Ruled out
- Evidence
- Code verified
Rationale
§Survey artifact
§B-02 — MCP core, persistence, and lifecycle
Structural account, read at c073404. Scope: mcp-server/src/*.ts and src/schema.sql — the server root, the storage lifecycle, the invariants.
§Observed
One open, five steps. openDatabase (db.ts:66-79) runs runMigrations, then initializeSchema, then mintStoreIdentity, then requireSchemaObjects, then requireViews. Migrations are additive column and index changes guarded by hasTable/hasColumn probes, so they are no-ops on a fresh store; initializeSchema re-execs the whole of schema.sql, which is written with CREATE ... IF NOT EXISTS throughout (546 of 547 statements). requireSchemaObjects then parses the schema's own CREATE statements and refuses the open when a declared object is absent or present as another kind — the guard that turns a silent CREATE TABLE IF NOT EXISTS no-op over a name already held by a view into a refused open rather than a downstream read failure.
Identity is minted, not derived. store_identity holds one row with a random 32-hex store_generation, written INSERT OR IGNORE so the mint happens once and an existing populated store gains one the first time it is opened under this schema. The immutability trigger is on UPDATE and DELETE, so re-opening is a no-op rather than a refusal.
Recoverability is a caller obligation. commitStorage (storage-git.ts:228) stages -A . and commits with -F -, scoped to the storage directory so two concurrent surveys sharing an outer repository cannot entangle. It does not checkpoint. checkpointDatabaseForStorageCommit (db.ts:492) runs wal_checkpoint(TRUNCATE) and throws on a busy or partial result. Both callers — end_session (tools/project.ts:98) and commit_phase_gate (tools/storage-history.ts:32) — call it immediately before the commit.
Every durable write resolves its revision live. resolveWorkspaceCommit (helpers.ts:127) shells git rev-parse --verify <sha>^{commit} in the bound workspace on every call and stores the resolved 40-character name. Nothing is memoized, because the only check that distinguishes a live commit from a collected one is the call the cache would avoid. resolveWorkspaceCommits is the batched form for writers that read a whole recorded set — one git cat-file --batch-check rather than N subprocesses.
The trust boundary is at ingress. requireWorkspaceSourcePath refuses absolute paths, .. traversal, and any path whose first segment is .amanuensis, so the conspectus cannot become evidence about itself.
§Concurrency model
Single-process, synchronous better-sqlite3 over a WAL database; there is no async inside a tool handler. Cross-process concurrency is real and is handled outside this subsystem (the lock table, and the storage git repository's own index). Sibling worktrees on this machine run lanes concurrently against distinct stores, which the worktree-local storage policy is what makes safe.
§Seam contracts from this side
- memory.db — written here, read
mode=roby the materializer (B-04). This side owns the schema;REQUIRED_VIEWSnames the two views the reader depends on and asserts them on every open. - contracts/conspectus-vocabulary.json — read by the generator that writes
src/vocabulary.tsand the Python twin. This side consumes the generated module; it never re-declares an enum. - the storage git repository — written here by
commitStorage, read byget_storage_historyand by anything that clones a phase gate.
§Open
Nothing in storage-git.ts obliges a future caller of commitStorage to checkpoint first; the invariant lives in two call sites. Recorded as claim B02-C2 and disposed under AT-2.