- `readiness: ready | refine` is a SECOND axis, orthogonal to status.
`ready` = the brainstorm is complete and the decisions are LOCKED (a spec
approved, or the forks explicitly confirmed). `refine` = open forks remain
and it cannot be planned yet
- `status: refine` RETIRED because it carried both meanings at once, so a held
iteration with an approved spec (language 18, 26) was indistinguishable from
one nobody had thought about. status is now purely where the WORK is:
done | in-progress | pending | hold — `pending` was already the board's own
rendering word, so nothing new was invented
- all 47 iterations classified from EVIDENCE in their own text, not by guess:
"the four forks are SETTLED" / "spec + plan approved" / "Approved spec:" for
ready; "Forks the spec must settle" / "no spec exists yet" for refine. Every
shipped iteration is ready by definition. 19 done, 5 in-progress, 15
pending, 8 hold; 27 ready, 20 refine
- two iterations moved refine -> in-progress rather than -> pending: language
31 and 34 are absorbed into 24 and work on them is literally happening, which
the board already showed as 🔄 while their frontmatter said otherwise. That
disagreement is now gone
- board legend, board-views' frontmatter contract, and two new Dataview
queries updated — the useful one being `readiness: ready AND status:
pending`, the startable set
WHAT THE NEW AXIS IMMEDIATELY SURFACED: of 15 pending iterations, exactly ONE
is startable — databasev2 4, io_uring group-commit, whose forks were confirmed
settled 2026-08-20. Everything else pending needs a brainstorm first. That was
invisible while one key carried both meanings, and it is now on the board.
Also caught by the sweep, unrelated to readiness but found by cross-checking
frontmatter against the board: SIX duplicate rows. Every iteration moved into
databasev2 was still listed in the LANGUAGE pending table under its retired id
(23, 32, 33, 20, 21, 27) as well as its new one. Stale copies removed. And two
databasev2 rows made claims the sweep contradicts — iteration 1 was billed
"startable today" while its forks are open, and 6 still called itself the
ceiling-raiser after 2 took that role.
Docs only. linkcheck 0 broken / 0 anchors.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7.1 KiB
| iteration | status | readiness |
|---|---|---|
| 16 | done | ready |
Iteration 16 — the web framework: a .wo library, HTTP/1.1 behind a proxy
Format:
product/story-iteration-template. Part of Story — one language, one runtime, one database, one binary.Inserted 2026-08-18. LANDED 2026-08-19 (branch
web-framework):just web-app14/0 — deps chain, auth middleware, CRUD with @unique 409 / FK-restrict 409 / checked-decode 400, :name captures, 404, pipelined keep-alive, SIGTERM, WAL restart persistence. Two notable as-built facts: (1) connection policy is pipelined-keep-alive/close-when-idle — a probe showed a parked keep-alive connection starves accept on a single-threaded server; (2) the chain exposed and fixed two compiler gaps — owned values stored in containers now MOVE (run/container-owned-move), and a dep's internalusepaths resolve dep-relatively.v1 polish LANDED 2026-08-20 (branch
framework-v1, developer directive: ship routing/middleware/req-resp as a polished micro-framework, nothing MVC-scale): registration helpersget/post/put/delete_(the take-Handler shape, probe-proven — deviation 1 of the 16 plan retired), 405 +Allowon wrong-method path hits, HEAD served as GET with the body suppressed (RFC 9110 §9.3.2), a request-lineLoggingmiddleware,set_header;just web-app16/0. It exposed and fixed a third compiler gap: a Text single-segment interpolation of a place crossedlet/assignment boundaries uncopied —copy_place_textnow sees throughInterp(run/interp-borrowed-field).Auth-in-core LANDED 2026-08-20 (same branch):
http/auth.wo— the MECHANISM per the core doctrine:Authorizationparsing, pure-.wobase64 (RFC 4648), constant-timect_eq,req.principalas the blessed "who is this" slot (Middleware.before now takesmut reqto write it),BearerAuth+BasicAuth(WWW-Authenticate challenge) middlewares. Policy stays app-side. Probe matrix 26/26 incl. RFC vectors, ASan-clean; web-app dogfoodsBearerAuth(its hand-rolled Auth deleted);just web-app17/0. The framework README now carries the core CHECKLIST: what is ✅ (parsing, routing, middleware, types, auth, JSON), what is a candidate slice (form/multipart, error-mapping hook, config record), and what parks behind 8/11 by design (streaming, backpressure, per-request cancellation).Form-encoded bodies LANDED 2026-08-20 (same branch):
media_type(req)(content-type lowercased, parameters stripped) andform_values(req)(nil unless the content-type says form; '+' and %XX decoded through the existing query decoder). Probe 7/7 release + ASan; web-app's CreateProduct now accepts form OR JSON into one insert path;just web-app19/0.Multipart LANDED 2026-08-20 (same branch):
http/multipart.wo— RFC 7578 parts (fields + file parts with filename/mime), quoted or bare boundary, strict malformed-is-nil (missing closing marker, missing content-disposition),part_namedaccessor; whole-body within BODY_MAX, streaming parks behind 8/11. Probe 13/13 + reuse loop, release + ASan; CreateProduct accepts multipart/form/JSON;just web-app21/0. It surfaced the RETURN flavor of the interp-of-borrowed-place emitter bug (return "${p.content}"— corruption two requests after the handler); fixed in emit_return, pinned in the same fixture.The framework is written IN writeonce and imported like any dependency (iteration 15 is the prerequisite). TLS terminates at a reverse proxy — browsers get TLS+ALPN+h2 from nginx/caddy while the framework speaks HTTP/1.1 keep-alive behind it, so no TLS exists anywhere in the toolchain. h2c is the parked successor (after iterations 8/23/11, when multiplexing has a scheduler to pay off on).
Spec exists:
2026-08-18-web-framework-design.mdsections B (normative) and C (the parked h2c successor). Plan:2026-08-19-web-framework.md(6 tasks: types/builders; HTTP/1.1 parse+serve; router+interfaces+App; the web-app storefront; thejust web-appgate; docs closeout). Two enabling risks retired before planning: interface-field dispatch (probe) and the route-table owned-move double-free (fixed, pinned byrun/container-owned-move).
Goals
- The framework, incubated at
docs/examples/writeonce-framework/: an HTTP/1.1 keep-alive server core (extracted from the soak-proven log-watchermcppattern), a method+path router with:paramcaptures,Req/Resprecords with builder helpers, and the no-function-values handler model —Handler/Middlewarestructural interfaces dispatched by ICALL, with WO-E205 making a non-conforming handler a compile error and?Respmiddleware short-circuiting on the shipped?Tnarrowing. - The consuming app,
docs/examples/web-app/: a small storefront (Product/Orderas@tableclasses, list/show/create routes, one auth middleware, JSON responses) that imports the framework through[deps]— the sample exercises the whole chain: fetch → lock → build → serve → durable data across restart. - Honest limits stated where users read them: single-threaded blocking (concurrency arrives underneath via iterations 8/11), no chunked encoding, no WebSockets, JSON-first (no templates — the removed UI track stays removed).
- Relationship to iteration 25 recorded in both:
serviceblocks later lower onto this library — compiler sugar over the same router, never a rival stack.
Acceptance Criteria
- Given the web-app sample, when
just web-appruns, then deps fetch, the app builds, serves list/show/create with@tablepersistence across a process restart, answers 404/400 correctly, a deliberately trapping handler returns 500 while the server survives, and SIGTERM stops it cleanly — fd- and resident-flat under the opt-in soak. - Given a handler class missing
handle, when the app compiles, then WO-E205 names the class and interface. - Given nginx in front (documented config), when a browser hits it, then the browser negotiates h2 with the proxy while the backend link is HTTP/1.1 — proving the TLS/h2 story without TLS in writeonce.
- Given the framework extracted to its own repository, when the app's
[deps]URL is updated, then nothing else changes (success criterion 4 of the spec).
Out Of Scope
TLS in the toolchain (proxy-terminated by decision); HTTP/2 + the bytes/buffer type (parked to the h2c successor, after 8/23/11); chunked transfer encoding; WebSockets/SSE; templates/SSR; multipart uploads; performance work beyond the soak's flatness gate (benchmarks belong to 22's measurement backbone).
Proposed Solution
Framework modules http/, router/, app.wo as spec §B lays out; the
web-app acceptance script is the gate (curl matrix + restart + stop + soak);
just web-app wires fetch-build-serve-verify into one command. Plan follows
after this iteration is approved on the board.