# 2026-07-07 ## Version retention rollout — deploy repo merged Closed the retention plan's rollout leg. Chain of merges today/yesterday: monorepo #236 (store core) → #237 (gate binary) → #238 (auto pin bump) → #239 (guidance + tools 0.8.1 repin) → #240 (agent publishes /graph.md and hash indexes with retention=20 — the gap found during rollout prep: the cluster's graph publisher is the crawl agent, not the MCP tools, so #236 alone would never have cleared the backlog). Deploy repo PR bumps worlds to server 0.20.0 (retention core), broker to 0.9.0 (retention tool surface; broker versions now track tools releases), agent to 0.19.0 (agent versions now track client releases — jumped from 0.13.1). Also: em dashes removed from all retention user-facing strings and the rule recorded in /conventions.md (no em dashes in CLI help, errors, prompts, tool descriptions). CodeRabbit round on #240 fixed -publish-retention silently swallowing values below -1 (now fails loudly). Verification baseline before the roll: mark://root/graph.md at 554 versions (agent publishes hourly at :53), chain-valid: true. Expected after ArgoCD syncs and the agent pod rolls: the first hourly publish prunes 534 versions in one write (the designed unbounded backlog prune), VERSIONS shows 21 (newest 20 + the new one), the root world logs a msg=prune audit line with pruned_from=1, and chain-valid stays true for the retained suffix. Check with mark_versions on the knowledge system. ## Prune confirmed in production — retention plan complete Verified end-to-end on knowledge.demarkus.io after the deploy PR merged. The race on the first attempt was instructive: the agent Deployment rolled faster than the root StatefulSet, so the agent's startup crawl published v555 with retention=20 to the OLD server 27 seconds before root-0 came up on 0.20.0 (old servers store the unknown key as inert metadata — graceful). A manual `kubectl rollout restart deploy/demarkus-agent` triggered the crawl-at-startup path against the rolled world: /graph.md went 556 → 20 versions (pruned_from=1 pruned_to=536, token_label=admin, chain-valid true), and the hash indexes pruned in the same cycle (root index 531, soul index 528, servicing/origination 83 each) — ~1,714 version files deleted across five documents, every deletion audit-logged. Note retention keeps the newest N INCLUDING the just-written version (total 20, not 21). Agent scheduling for the record: single-replica Deployment running `demarkus-agent daemon`, crawl at startup + hourly ticker phase-locked to pod start, config rendered from deployment.yaml worlds[]. ## Session wrap-up — version retention, question to production in one session Fritz opened with "there are 545 versions of the graph, can we keep N?" and the session closed with the prune verified in production. The arc: feasibility analysis (store layout makes contiguous-prefix pruning chain-safe) → plan doc → accidental-set guard design (tool-layer confirmation, two-write rule deferred) → implementation → five PRs (#236 store core, #237 gate binary, #238/#239 pin/guidance chain, #240 agent) → deploy rollout → kubectl-verified prune (556 → 20 on /graph.md, ~1,714 files across five docs). Durable takeaways beyond the per-day entries: - Two real bugs were found by building, not reviewing: migrateFlatFile's v1-existence assumption (deletion resurrects a bogus v1) and the agent being the actual graph publisher (the MCP-tool retention default alone would never have cleared the backlog). Both are the same lesson — trace the real producer/consumer, not the surface you happen to be editing. Details in /debugging.md. - Security-on-delete shape that held up through review: no new deletion verb, prune rides existing publish capability, os.Root confines every removal, every deletion audit-logged with token label. Reusable for any future destructive store op. - Review-round judgment calls worth remembering: CodeRabbit's int-case test suggestion would have codified a silent-allow hole (fixed the code instead); its client/internal dedup suggestion was right about the problem, wrong about the home (protocol/store owns the server's rule; tools can't import client internals). - New conventions recorded: no em dashes in user-facing strings (/conventions.md); retention is never set on authored docs without an explicit user ask (plugin session guidance, all four plugins). - Confirmed there is no 1000-version limit anywhere in core — the 1000s are LIST entries, LOOKUP results, mark_index docs, and the agent's crawl cap.