writeonce/docs/superpowers/specs
shoney.arickathil 69c34c9a89 docs(spec): WAL checkpoint — compact by rewrite + atomic rename
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>
2026-08-28 17:39:38 +02:00
..
2026-08-01-oop-compiler-vm-design.md docs: iteration 7b migration — amend the normative docs (Phase 4) 2026-08-19 17:11:35 +02:00
2026-08-01-systems-track-design.md docs: status board at docs/00-status.md; gap-closure spec applied; recover lost doc 2026-08-10 23:42:26 +02:00
2026-08-03-blue-green-vm-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-07-logwatcher-sample-and-principles-design.md docs: compiler front-end specifications and plans (Tasks 2-6) 2026-08-10 09:11:04 +02:00
2026-08-10-logwatcher-gap-closure-design.md docs: status board moved to docs/stories/00-status.md 2026-08-21 10:07:20 +02:00
2026-08-11-inferred-gc-mark-sweep-design.md feat: milestone 1 complete — .wob emitter, conformance corpus, single binary; GC redesign specced 2026-08-11 19:31:26 +02:00
2026-08-15-table-relations-query-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-18-web-framework-design.md docs: sync superpowers specs/plans to hold decision 2026-08-21 05:00:56 +02:00
2026-08-20-library-kind-internal-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-20-memory-db-features-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-20-shard-fiber-arc-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-21-db-bench-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-23-chat-websocket-actor-lifecycle-design.md docs: audit all markdown against the code, fix findings, flatten status folders 2026-08-26 19:20:22 +02:00
2026-08-23-net-seams-park-design.md feat: iteration 35 — net seams + the serving slice (fiber-per-connection) 2026-08-23 08:04:32 +02:00
2026-08-28-wal-checkpoint-design.md docs(spec): WAL checkpoint — compact by rewrite + atomic rename 2026-08-28 17:39:38 +02:00
2026-08-28-wal-group-commit-design.md docs(plan): WAL group commit — 6 tasks, databasev2 4 part A 2026-08-28 09:06:09 +02:00