유대선
프로젝트로
·트러블슈팅·2

Five months of write-only memory: 81 writes, 2 reads — and the defaults that caused it

Capture and partitioning worked; consumption was structurally dead (read:write 2:81). Root: global-by-default search, no startup identity in panes, pull-only recall, 220K-char responses. Fix: scoped-by-default reads, boot-time auto recall, compact responses with an out-of-scope note, and read-side metering.

A sibling project measured its five months of Dalkkak sessions: 81 memory writes, 2 reads. The write path was machine-enforced (directives require emission every turn; hooks verify; an entire capability gate audits record integrity). The read path was one sentence in a prompt.

The trigger incident: one unscoped graph_search matched 871 nodes across every startup, the truncated top-10 were all from the most-written project, and the agent concluded "no records exist" for the current one — then spent 1.34M tokens re-mining transcripts for facts that were sitting in the graph.

Five structural causes, five mechanical fixes (commit 869b7f0b):

  1. Search defaulted to global. Now the pane's startup is the default scope — the pane spawn persists its owning startup and exports DALKKAK_STARTUP_ID; the MCP server (the agent's child process) inherits it. scope:"all" escapes.
  2. "0 in scope" could masquerade as "0 anywhere". Scoped responses now lead with a scope note: total matches, how many were excluded, and an explicit "0 here ≠ 0 anywhere".
  3. Reading cost 220K chars at limit 5. Compact one-line 200-char summaries by default; detail:"full" stays bounded.
  4. Recall was pull-only. At pane boot the app writes boot-context/<startup>.md (open issues + recent decisions/identity/structure, streaming only that startup's jsonl) and the managed wrappers inject it into the system prompt — memory the founder never has to ask for. Claude via bash/PowerShell interpolation; Codex via env + instructions (both agents, both platforms).
  5. Nothing measured consumption. Every read-tool call now appends to graph/.metrics/memory-reads.jsonl, so the read:write ratio is finally observable.

The meta-lesson matches the same-day capability-gate incident: we prove one direction and ship. Writes were tested; reads weren't even counted. Defaults are the product — a scope that is optional, a recall that must be requested, and a compact mode nobody turns on are indistinguishable from not existing.

Deferred: pre-command risk surfacing (hook), trial-and-error narrative capture, and the ratio dashboard UI.