Defer the heavy curation pass off the hot path — terse log stub + kb:check now, pnpm log:audit later
0061-defer-curation-tier-off-hot-path
- Reversibility
- two-way door
DEC-0061 — Defer the heavy curation pass off the hot path
Reversibility: two-way door — a new off-hot-path script, a pre-commit hook, a soft lint, and a CLAUDE.md rule change; revert any piece and the old discipline returns. The durable commitment is the principle (the curation tier's expensive judgment work belongs off the hot path, like the machine tier's), not this exact wiring.
Context
A DX audit (the same one that produced Fast deterministic KB integrity check (kb:check) — make SSOT cheap to uphold) found the code inner loop fast (cold gate ~18 s; KB parse 0 failures in 575 ms) but the decision-logging/curation tier to be the real DX tax. The standing CLAUDE.md mandate was: "when a consequential decision lands, invoke the log-auditor in the same turn." That runs a heavy synchronous agent pass on every consequential change. Measured cost of the resulting bloat: knowledge/log.md had grown to 233 KB of multi-paragraph essays (each log line a second copy of its ADR's rationale — an SSOT violation), ADRs carried 20–44 [[wiki-links]] each, and one schema tweak cascaded into ~44 rewritten decision files. Dumb-fast trace capture + off-hot-path distill/prune had already solved the mirror-image problem on the machine tier — make the hot-path capture dumb-and-fast, defer the expensive distill to scripts/trace-distill-prune.mjs (claude -p, off the hot path). The curation tier had not had the same treatment. Fast deterministic KB integrity check (kb:check) — make SSOT cheap to uphold then built the missing deterministic primitive (pnpm kb:check, ~600 ms, read-only).
Options considered
- Keep the per-turn agent pass. Rejected: it is the tax — a heavy judgment pass on every change, and the source of the 233 KB / second-copy bloat.
- Apply the DEC-0041 pattern to curation (chosen). Hot path = terse one-line
log.mdstub + a wiki-link ([[id]]) + deterministickb:check(no agent). Deferred =pnpm log:auditat session/PR end runs the log-auditor's expensive work once, over a batch. Sameclaude -psubscription posture as the trace distiller (Subscription-backed extraction is a first-class transport — ClaudeCodeClient (no API keys) / Claude-primitives-first build strategy — the Claude primitive, no new dep, no API key). - Drop the heavy pass entirely. Rejected: that abandons the judgment layer — ADR authoring, contradiction reconciliation, task-filing are real value. We change when/how it runs, not that it runs.
Decision
- Hot path: on a consequential decision, append a terse one-line
knowledge/log.mdentry + a wiki-link ([[id]]) to the atomic ADR (the why lives ONLY in the ADR), and runpnpm kb:check. No agent pass. - Deferred (
pnpm log:audit,scripts/log-audit.mjs): at session/PR end, gatherkb:check --json+ the reduced trace journal + bounded KB context, hand the brief (not raw MBs) toclaude -pwith the log-auditor's mandate (author/expand ADRs, reconcile/dedup, repair cross-refs, surface tasks), and write a gitignored review brief tojournal/audits/. The script is read-only overknowledge/— the model proposes, a human/agent disposes (Establish the learning-loop & audit architecture: SSOT stays human-curated).--dry-run/--no-llmkeep it fully offline-testable. - Continuous integrity:
kb:checkis wired as a pre-commit git hook (.githooks/pre-commit, enabled viacore.hooksPath), fast (<1 s) and failing only on errors (the soft log-length lint and other warnings never block a commit) — so the deferred pass inherits near-zero link rot. - Soft norm (going forward):
kb:checkgains a warn-only log-line-length lint nudging eachlog.mdentry toward a true one-liner. It never fails the gate. The existing 233 KB of essays is not retroactively rewritten here (a separate sweep, filed as an optional follow-up task).
Consequences
- The hot-path curation cost drops from a multi-minute synchronous agent pass to a terse append + a ~600 ms deterministic check — the same win Dumb-fast trace capture + off-hot-path distill/prune delivered for the machine tier, now for the judgment tier.
- The deferred
log:auditwas proven end-to-end this session: a liveclaude -p(haiku) run distilled the real brief, independently caught the DEC-0058 cross-ref drift, and proposed filing the missing task — the heavy judgment work, done off the hot path. log.mdlines become a clean index of pointers; the why lives once, in the atomic ADR — restoring SSOT for new entries.- This ADR + its single log line are themselves the dogfood proof: authored directly under the new rule, no agent pass,
kb:checkclean.
Review
confidence: verified — built and reproduced this session: pnpm log:audit --help/--dry-run/--no-llm all work offline; one live claude -p run distilled the brief (distilled: true) and caught the DEC-0058 drift; pnpm kb:check shows the soft log-length warnings as non-fatal (exit still driven only by real errors) and is clean after this pass; the pre-commit hook fires kb:check and blocks a commit only on an integrity error. Open follow-ups (optional, filed): the retro-shrink of the 233 KB of legacy log.md essays to one-liners (Retro-shrink the legacy knowledge/log.md essays to true one-liners (terse line + wiki-link)).