databasev2 3, chain 6. Brainstormed 2026-08-28 after databasev2 4 part A
landed.
Design: compact the log by rewriting it as one record per live row into a
temp file, fsync, rename over the live WAL, fsync the parent dir, reopen.
Recovery is COMPLETELY UNCHANGED — boot still opens one file and replays
it — and the crash criterion ("the same store as if the checkpoint had
never started") is satisfied by rename, not by code we must get right.
Read .dev/reference/postgresql for this. The finding is that PG's design
is UNAVAILABLE to us, which is what makes the simpler option legitimate:
- PG never compacts its WAL; segments before the redo point are recycled
by rename or unlinked. Its records are page deltas, so a compacted redo
log is not a store — hence heap files, a control file, a redo pointer,
a second recovery source and a separate process
- ours are FULL ROW IMAGES (apply_record implements UPDATE as
remove-then-recreate), so a compacted log IS a complete store. That one
difference deletes all of the above from the design
- what IS worth porting is the ordering discipline: publish the new
"recovery starts here" atomically and LAST, so a crash falls back. PG
needs a start-of-checkpoint redo pointer plus an end-of-checkpoint
control file update; we get the same property from one rename, because
we can swap the whole data set atomically and PG cannot
Forks settled:
- no snapshot format — the compacted log is the snapshot, existing grammar,
so no new encoder or decoder and the dump reuses wo_wal_append_insert
- one source, not two
- volume-only trigger, as a ratio against the LAST compaction's measured
output (the denominator is known exactly; estimating the live set would
mean estimating Text) with an absolute floor. NO TIMER — PG's exists to
bound loss from unflushed buffers and we have none; an idle log does not
grow. Copying the mechanism without the reason was the trap
- stop-the-world, with the pause measured against a stated budget rather
than assumed acceptable; alternatives are bought against a number
- compaction may run ONLY where nothing is staged (right after a barrier),
or a staged record lands in a file about to be replaced. Normative
Recorded before it can be found late: compaction invalidates every WAL
offset iteration 2's `resident: keys` stores, so the compactor rebuilds the
offset map as it writes. Nothing breaks today because that storage half is
unimplemented — it would break later, looking like corruption.
Also corrected exploration/postgresql/buffer-and-checkpoint.md, which was
wrong on two counts: PG does NOT update its control file by rename (in-place
full-block write + CRC32C), and its checkpoint sketch assumes writeonce has
segment files, which it does not and deliberately will not.
Grounding measured on master: seed 20000 leaves a 986614-byte log; 20000
updates take it to 2590262 bytes with the SAME live rows, and boot+verify on
that store is 155ms.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- constraints-and-grammar: gram.y PK/FK productions, pg_constraint,
RI trigger semantics; writeonce direction — @key as unique alias
(id stays THE key), ref actions (@on_delete), backlink-implies-index
(improves on postgres' not-auto-created FK index)
- indexing-and-point-lookup: AM roster + algorithms (Lehman-Yao,
linear hashing), TID = row address; writeonce gap — probe walks
slabs while idx_bucket exists; O(1) slice direction, non-goals
- card index updated; Rust-era plan-10/11/12 links unlinked (rot)
- docs/guides/database-developer-subagent.md: format, paste-ready
agent definition (doctrine/file map/gates), verification, division
of labor
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Board renamed docs/plan/00-kanban.md -> docs/00-status.md and rebuilt: ▶ NEXT
PLAN pointer (iteration 4 — emitter, corpus, `woc build`) then six buckets —
stories, in progress, done, pending, discarded, learnings. It covered only the
Rust runtime before, so the whole OOP track was invisible. All 16 inbound refs
repointed; `Kanban:` banners renamed to `Status:`.
- New discarded.md (settled rejections with reasons: inheritance, `abstract`,
Money/SKU/Float, Dynamic/cast/macro/extern, AOT-to-C, Menhir, shared engine
state) and learnings.md (plumbed≠enforced, vacuous goldens, exit-0-wrong-
output, malloc-path ASan trick, deferred checks that never reach the VM).
- RECOVERED docs/plan/exploration/blue-green-vm/00-vision.md — gone from disk,
never committed (gitignored path), cited by five docs incl. principle 12.
Root cause was broader: all seven forward-roadmap plans in
docs/superpowers/plans/ were untracked and ignored, on one disk only. Dropped
the docs ignore rules with a do-not-re-add note; added __pycache__/*.pyc.
- Repaired broken links across docs/, 270 -> 36: fixes a regression from the
earlier reference/ -> .dev/reference/ move (relative paths at ../../ and
deeper were skipped), plus depth and reorg drift. The 36 residual point at
content that does not exist and need decisions, not paths.
- New spec docs/superpowers/specs/2026-08-10-logwatcher-gap-closure-design.md,
applied: `and`/`or` verdict row; Part 3 gains `env` (six modules), swaps
time.mono for iso/local, adds 22 bare core builtins; throw/time.mono/is cut
(0 uses in the sample). Plan 8: Task 2 gains and/or, Task 5 drops throw,
abstract+`is` task deleted, 8/9 renumber to 7/8. Plan 9 gains core builtins.
Plan 10 gains the 307 -> 0 diagnostic gate. WO-E205 re-filed unreachable-by-
design. types.ml header drops its false satisfaction-set claim. 00-code-
review.md reduced to a stub — its rival Phase 1-4 roadmap retired.