- README: shipped concurrency/HTTP/WebSockets sat in the roadmap as "not yet available"; "no package manager" contradicted [deps]; the deps example would not have compiled (the key IS the module name) - runtime/README: leads with wovm, wo-rt.c demoted to a historical section; dropped 2 nonexistent recipes, crates/rt, @gc refcounting, 13 suites -> 18 - employee + log-watcher READMEs claimed "does not compile"; both are gates - error catalog: +10 emitted codes incl WO-E250, the only diagnostic the shipped query surface raises; recorded why the sweep rotted - language-surface: group-by parses, then the typechecker refuses it - 00-code-review + 00-link-audit re-run; history kept, not rewritten - 48 dead Rust-era exploration links de-linked rather than re-pointed (their prose names the retired plan by number); successor map -> discarded.md - 08-project-structure: compiler/plan/ never existed; corpus has 9 dirs, 5 empty - releasing.md: dropped a --draft step the workflow never had - new docs/00-doc-audit.md: findings + disposition, incl one row where the audit was wrong and the doc it accused was right - status folders removed: 34 stories flat, status only in frontmatter; 252 links recomputed from resolved paths; board/board-views/structure retaught - story 24 -> in-progress, since frontmatter is now the only truth - new iteration 38: fs mutation verbs + net.connect, the two capability families no iteration owned - new iteration 39: gofiber/fiber v3.5.0 parity study. The ledger called CSRF/sessions unblocked by iteration 34's HMAC, but the runtime has no source of randomness at all - linkcheck skips .dev/.superpowers: 0 broken paths, 0 bad anchors Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3.2 KiB
3.2 KiB
| iteration | status |
|---|---|
| 33 | refine |
Iteration 33 — WO_DATA=<path>.db: the persistent store as one file
Format:
product/story-iteration-template. Part of Story — one language, one runtime, one database, one binary.Inserted 2026-08-22 (developer ask: "can the persistent db be in file.db form?"). The truth is already almost there:
WO_DATA=<dir>holds exactly ONE file (shard-0.wal) — the entire persistent state, since RAM is authoritative and no data pages exist. This iteration makes the surface say so: pointWO_DATAat a file and THAT file is the store. Small, driver-only, independent of the concurrency chain.
Goals
WO_DATA=<path>accepts a file path. A path that is not an existing directory is treated as THE wal file (app.db,store.wo.db— the name is the operator's). The directory form stays and keeps meaning<dir>/shard-0.wal— every existing deployment and gate is byte-identical.- One file remains the whole truth at any core count — stage 3 made the WAL owner-shard-only (shard 0 is the sole writer), so nothing multi-shard ever adds a second file.
- The contract says it out loud:
04-db-binding.mddocuments the file form, and documents honestly that the file is an append-only log that grows until iteration 32 lands.
Acceptance Criteria
- Given
WO_DATA=/tmp/app.db(no such directory), when a program seeds, restarts, and verifies, then replay is byte-true and/tmp/app.dbis the only artifact on disk. - Given
WO_DATA=<dir>(existing directory), when the same program runs, then behavior is byte-identical to today —<dir>/shard-0.wal, every standing gate unchanged. - Given the db-bench durability legs pointed at the file form, when the restart proof and kill -9 battery run, then every guarantee holds identically (the file IS the same WAL, only named by the operator).
Out Of Scope
- A paged database file (SQLite's shape) — RAM is authoritative; the disk story is the WAL, full stop.
- Checkpoint/compaction — iteration 32's; its
rename-swap (write snapshot+tail to a NEW file, fsync,
rename()over the old) is exactly what keeps the single-file promise crash-safe when it lands. 33 before or after 32 works; landing 33 first means 32's spec inherits the file form as a stated constraint. - Multiple stores per process, attach-by-file — held iteration 20's territory.
Info
- The whole change is
runtime/src/main.c's hardcodedsnprintf("%s/shard-0.wal", dir)growing a stat-based fork (directory → today's path; otherwise → the path itself), plus a gate check and the binding-doc note. No engine, no WAL format, no compiler. - Fork for the (tiny) spec: what does a NONEXISTENT path mean? Leaning:
a path whose parent exists and that does not end in
/is a file to create; a trailing/or existing directory keeps the directory form. Refusing ambiguity loudly (WO exit 2) beats guessing.
Proposed Solution
Small enough for a bounded slice: brainstorm the one fork in chat, implement driver + db-bench file-form leg + docs in one pass, gates green. No plan document needed unless it grows.