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

decision read as Explain confidence verified status active 2026-06-19 owner forward-deployed-engineer
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

  1. 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.
  2. Apply the DEC-0041 pattern to curation (chosen). Hot path = terse one-line log.md stub + a wiki-link ([[id]]) + deterministic kb:check (no agent). Deferred = pnpm log:audit at session/PR end runs the log-auditor's expensive work once, over a batch. Same claude -p subscription 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).
  3. 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.md entry + a wiki-link ([[id]]) to the atomic ADR (the why lives ONLY in the ADR), and run pnpm kb:check. No agent pass.
  • Deferred (pnpm log:audit, scripts/log-audit.mjs): at session/PR end, gather kb:check --json + the reduced trace journal + bounded KB context, hand the brief (not raw MBs) to claude -p with the log-auditor's mandate (author/expand ADRs, reconcile/dedup, repair cross-refs, surface tasks), and write a gitignored review brief to journal/audits/. The script is read-only over knowledge/ — the model proposes, a human/agent disposes (Establish the learning-loop & audit architecture: SSOT stays human-curated). --dry-run/--no-llm keep it fully offline-testable.
  • Continuous integrity: kb:check is wired as a pre-commit git hook (.githooks/pre-commit, enabled via core.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:check gains a warn-only log-line-length lint nudging each log.md entry 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:audit was proven end-to-end this session: a live claude -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.md lines 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:check clean.

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)).