writeonce/docs/00-dependency-graph.md
shoney.arickathil 3a73938d2e docs(status): reconcile board, graph and story tables with the 2026-09-09..11 landings
- board: language 18 row (hold lifted 2026-09-11, split — 18 keeps
  transaction { }, cache/flags/jobs to porch 10); In-progress rows for
  databasev2 4 part B / 5 / language 18 and the Active slice; databasev2
  rows 2 (CLOSED, 6a), 4 (part B re-brainstormed), 5 (ready), 7 (CLOSED),
  13 (new); the held list drops 18
- dependency graph: new §8 databasev2 (nodes 1–13, edges, states table);
  graph 1's 23/32 nodes turn done and their edge becomes undirected (they
  compose; neither needs the other); language 18 / porch 10 nodes and
  edges across the porch and language graphs; wmux gains the databasev2 2
  edge (DB2W) the prose already named
- databasev2 00-story: sequence rows 1/2/4/5/7/8/11/12/13/14, the ASCII
  graph (2 no longer needs 1; 2 → 11, 12) and the order rationale
- 01: the budget finding redirected to 5; 06: the Needs line marked
  superseded, task 7's 2026-08-30 measurement quoted; 09: the report's
  group-by is still refused, schema-sharing is language-track work; 10: an
  in-tree signing answer exists (rv2 9), Ed25519-vs-reuse still open
- porch 00-story: row 10 (memory features over @table, refine stub) and
  the "not porch's" table updated for the split

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 423b3c187b626f69da1ddb942c3c7849a3ee5a73)
2026-09-15 01:16:24 +02:00

659 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Dependency graphs — iterations and framework features
> Companion to [00-status.md](stories/00-status.md) (states live THERE; this page
> carries the edges). An arrow `A --> B` means **A must exist before B**;
> a dashed arrow is a scope DIRECTIVE, not a technical dependency. Use it
> to pick the next implementation: anything whose incoming arrows are all
> green is startable today. Rebuilt 2026-08-20 from a sweep of every
> story/spec/plan markdown (the "misses" pass: iteration 17's outgoing
> edges, the concurrency chain, the parked drain, 9b→25, 28's gap
> fan-out, 20's fiber caveat), and **refreshed 2026-08-26** against the
> code and the story frontmatter: graph 1 had drifted a generation
> behind — it still showed 17 parked and 18 as next, and it used the
> pre-renumber ids 10/12/13/14 for what are now stories 25/26/29/28. All
> iterations through 38 are now nodes.
## 1. Story iterations
```mermaid
flowchart TD
classDef done fill:#1a7f37,color:#fff,stroke:none
classDef parked fill:#6e7781,color:#fff,stroke:none
classDef specd fill:#0969da,color:#fff,stroke:none
classDef open fill:#eac54f,color:#000,stroke:none
classDef inprog fill:#8250df,color:#fff,stroke:none
FOUND["1–6 foundation: doctrine, VM, compiler, binary, surface, stdlib"]:::done
I7["7 log-watcher proof"]:::done
I7b["7b inferred GC + per-shard mark-sweep"]:::done
I9["9 database engine"]:::done
I9b["9b @table + query"]:::done
I15["15 deps package manager"]:::done
I16["16 web framework v1 core"]:::done
I17["17 library kind + internal/ ✅ 2026-08-20"]:::done
FWREORG["framework internal/ reorg + check mode ✅ landed with 17 (WO-E108/E109 shipped)"]:::done
I19["19 Float + Bytes ✅ 2026-08-20"]:::done
I37["37 wo-html components + raw text literal ✅ 2026-08-25"]:::done
I35["35 net runtime seams ✅ 2026-08-23"]:::done
I36["36 operator parity: not/bitwise/hex literals — code landed 2026-08-22, awaiting the manual pass"]:::specd
RELEASE["packaging + release pipeline ✅ 2026-08-25 (no story: VERSION, just dist, install-accept, release.yml)"]:::done
I18["18 transaction{} 🔄 hold lifted + split 2026-09-11 (cache/flags/jobs → porch 10, graph 4); T1–T6, T8, T9 landed same day, corpus green; open: kill -9 battery (T7)"]:::inprog
I9c["20 cross-program tables (⏸ hold 2026-08-21; channel half-built)"]:::parked
I9d["21 keypair attach auth (⏸ hold 2026-08-21; crypto floor now exists via 34)"]:::parked
I9e["22 durability + throughput baseline ✅ 2026-08-21"]:::done
I8["8 shard-actor runtime ✅ 2026-08-21"]:::done
I24["24 chat + actor lifecycle 🔄 THE LIVE SLICE (absorbing 31 + 34)"]:::specd
I34["34 crypto builtins ✅ code landed as 24's T1 (ids 85-87)"]:::done
I31["31 actor lifecycle — call/mailbox-cap/death landed in 24; monitor + time.after (ids 89/90) open"]:::specd
I9f["23 io_uring group-commit ✅ part A 2026-08-28 as databasev2 4 (part B refine)"]:::done
I32["32 WAL checkpoint ✅ 2026-08-29 as databasev2 3 (compaction by rewrite + rename)"]:::done
I33["33 single-file store WO_DATA=<path>.db (driver-only, off-chain)"]:::open
I25["25 HTTP service layer — `service` blocks (⏸ hold 2026-08-21; story file removed, plan remains)"]:::parked
I11["11 fibers ✅ 2026-08-21"]:::done
I26["26 blue-green deploy (⏸ hold)"]:::parked
I29["29 metaprogramming @derive (⏸ hold)"]:::parked
I28["28 skillhost workload (⏸ hold; demoted)"]:::parked
I38["38 content platform capabilities: fs mutation verbs + net.connect"]:::open
I9g["27 query grammar corpus (⏸ hold; likely collapses)"]:::parked
I30["30 observability, CI, fuzz — release-only CI exists; per-change gates + fuzz open (no story file)"]:::open
GAPS["28's gap fan-out, what is LEFT of it: fs metadata, FFI-vs-out-of-process (bounded subprocess + stdio transport moved to 42)"]:::open
I42["42 bounded subprocess ✅ 2026-09-01: proc.run bounded + parked (pidfd), proc.run_dl; streaming form deferred by name"]:::done
DRAIN["parked drain, what is LEFT of it: WO-E225 roster, ADT roster, group-by aggregates"]:::parked
FOUND --> I7
FOUND --> I9
I7 --> I7b
I9 --> I9b
I9b --> I15
I15 --> I16
I15 --> I17
I16 --> I17
I17 --> FWREORG
I16 --> I37
I19 --> I37
I17 --> RELEASE
I9 --> I18
I16 --> I18
I9 --> I9c
I9c --> I9d
I9c --> I25
I9b --> I25
I16 --> I25
I9b --> I9e
I7b --> I8
I9e --> I9f
I8 --> I9f
I8 --> I11
I19 --> I34
I34 --> I24
I8 --> I24
I11 --> I24
I35 --> I24
I31 --- I24
%% 23 and 32 compose on the WAL commit path; neither needs the other (databasev2 story, corrected 2026-08-29)
I9f --- I32
I32 --- I33
I9 --> I26
I25 --> I26
I9g --> I28
I7 --> I28
I28 --> GAPS
I11 --> I42
I24 --> I42
I16 --> I38
I32 --> I38
I36 -.reopens the pure-wo HMAC question.-> I34
I26 -.scope directive.-> I29
I26 -.scope directive.-> DRAIN
```
Reading it: **the live slice is 24** (chat + actor lifecycle, absorbing 31
and 34), and the chain behind it, 23 → 32, is done (databasev2 4 part A
2026-08-28, databasev2 3 2026-08-29). Everything else with all-green
incoming arrows is startable: **33** (driver-only, off-chain), **38** (the
fs-mutation and outbound-socket gaps), and **30**'s remaining half
(per-change CI and fuzzing — the release pipeline covered only publishing).
**36** needs no work, only the developer's manual pass over
`docs/examples/operators/`. The held tail — 20/21, 25, 26, 27, 28, 29 — (18's
hold lifted 2026-09-11, above) resumes on its own precedence notes; 29 and
what is left of the drain still
sit behind 26 by the 2026-08-08 scope directive (dashed), not by any
technical edge. Note what left the drain: `pub(read)`, `using` and `#if` all
shipped, so only the WO-E225/ADT rosters and group-by aggregates remain in
it.
## 2. The concurrency chain (iterations 8 / 23 / 11 and everything they gate)
The runtime's concurrency work is the single biggest unlocker — every
⏸ row in the framework ledger and two v2 follow-ons hang off it.
```mermaid
flowchart TD
classDef rt fill:#8250df,color:#fff,stroke:none
classDef gated fill:#eac54f,color:#000,stroke:none
classDef v2 fill:#0969da,color:#fff,stroke:none
classDef done fill:#1a7f37,color:#fff,stroke:none
I7b2["7b per-shard collector (done — the precondition 8 waited on)"]:::rt
I8x["8 shard-actor runtime: thread-per-core, ownership-move messages"]:::rt
I9fx["23 io_uring group-commit (batch = queue drain) ✅ part A 2026-08-28"]:::done
I11x["11 fibers: reduction-budget preemption, blocking builtins park"]:::rt
I9ex["22 baseline (numbers 8/23 sign against)"]:::rt
KEEPAL["keep-alive parking retired ✅ iteration 35 (app-owned fiber-per-connection + idle deadline)"]:::rt
H2C2["h2c HTTP/2 cleartext (spec §C: also needs 23)"]:::gated
STREAM2["request body streaming + backpressure"]:::gated
SRESP2["streaming responses + explicit commit point"]:::gated
CANCEL2["per-request cancellation propagation"]:::gated
PUBSUB2["DONE 2026-08-27 — pub/sub + WebSockets (iteration 24: ws_accept + wsframe + room actors)"]:::done
ASYNC9C["20 async attach statements (rejected-for-now alternative)"]:::gated
TIMEOUTS2["idle timeouts become schedulable (net seam still needed)"]:::gated
FIBJOBS2["fiber-scheduled jobs (replaces drain-on-request; queue table stays)"]:::v2
CANCELRB["cancellation → transaction rollback"]:::v2
I18x["18 transaction{} (jobs moved to porch 10, 2026-09-11 — graph 4)"]:::v2
I7b2 --> I8x
I9ex --> I9fx
I8x --> I9fx
I8x --> I11x
I8x --> KEEPAL
I11x --> KEEPAL
I8x --> H2C2
I9fx --> H2C2
I11x --> H2C2
I11x --> STREAM2
I11x --> SRESP2
I11x --> CANCEL2
I8x --> PUBSUB2
I11x --> PUBSUB2
I11x --> ASYNC9C
I11x --> TIMEOUTS2
I11x --> FIBJOBS2
I18x --> FIBJOBS2
I11x --> CANCELRB
I18x --> CANCELRB
CANCEL2 --> CANCELRB
```
## 3. Framework v1 — remaining ledger items
Three gates recur: **net seams** (runtime `net` builtins), the **crypto
fork** (bitwise operators + hex literals landed with iteration 36, so
digests are now expressible in pure `.wo` — pure-`.wo` vs C-builtin is
story 34's brainstorm before the slice), and the
**concurrency chain above** (its gated nodes are not repeated here).
```mermaid
flowchart TD
classDef gate fill:#8250df,color:#fff,stroke:none
classDef ready fill:#1a7f37,color:#fff,stroke:none
classDef blocked fill:#eac54f,color:#000,stroke:none
classDef done fill:#6e7781,color:#fff,stroke:none
CORS["CORS middleware ✅ slice 2"]:::done
SECH["security-headers middleware ✅ slice 2"]:::done
HOSTV["host validation (421) ✅ slice 2"]:::done
STRICT["strict-parsing audit (dup Content-Length = 400) ✅ slice 2"]:::done
WILD["wildcard segments *rest ✅ slice 2"]:::done
PREC["precedence: registration order stands, wildcards last by construction ✅"]:::done
GROUPS["route groups + group middleware ✅ slice 2"]:::done
CTX["req.ctx bag ✅ slice 2"]:::done
XFF["client_ip: X-Forwarded-For parsing ✅ slice 2 (peer VERIFY stays gated)"]:::done
ACCEPT["accepts(): response-side negotiation ✅ slice 2"]:::done
NETSEAM["GATE CLEARED: iteration 35 landed the net seams — _dl deadlines, listen_unix, peer (ids 91-95)"]:::done
TMOUT["read/write/idle timeouts ✅ iteration 35 (serve_conn read_ms/idle_ms)"]:::done
UNIX["unix socket binding ✅ iteration 35"]:::done
PEERV["trusted-proxy PEER verification — net.peer landed; the verify middleware is a ready framework slice"]:::ready
CRYPTO["GATE CLEARED: iteration 34 landed C builtins — sha1/sha256/hmac_sha256 (ids 85-87)"]:::done
SHA["sha1/sha256/hmac_sha256 ✅ iteration 34; SHA-512/CRC32 wait for a consumer"]:::done
ETAG["ETag + If-None-Match 304 ✅ slice 2"]:::done
COOKIE["signed cookies"]:::ready
CSRF["CSRF"]:::ready
SESS["session integrity"]:::ready
HOOKV["webhook verification"]:::ready
JWT["JWT HS256 (HARD STOP after)"]:::ready
RADIX["radix-tree routing"]:::blocked
I9E3["GATE: router scan unmeasured — 22's harness landed but benched the DB, not the router; perf-targets entry first"]:::gate
STORAGE["storage-integration rows: migrations (future story), eager loading + tenant roots (query-surface work, 9-series)"]:::blocked
NETSEAM --> TMOUT
NETSEAM --> UNIX
NETSEAM --> PEERV
CRYPTO --> SHA
SHA --> ETAG
SHA --> COOKIE
SHA --> CSRF
SHA --> SESS
SHA --> HOOKV
SHA --> JWT
I9E3 --> RADIX
```
**Slice 2 landed (2026-08-23, branch `framework-v1b`):** every
formerly-green node plus the crypto chain's first consumers — CORS,
security headers, host validation (421), strict dup-Content-Length,
`*rest` wildcards, route groups + group middleware, `req.ctx`,
`client_ip`, `accepts()`, ETag/304 — all gated by `just web-app`
(38 checks). The after-middleware seam (`After`/`use_after`) carries
the response-header half. Now READY with the digest builtins landed:
signed cookies, CSRF, session integrity, webhook verification, JWT
HS256 (the hard stop). Still gated: timeouts/unix-socket/peer-verify
(story 35's net seams) and the radix tree (router scan unmeasured).
Note: 21's keypair crypto is its own C implementation (already on
branch `keypair-auth`) — it neither waits for nor feeds this chain.
## 4. Language 18 — `transaction { }` (was "Framework v2"; split 2026-09-11)
**Redrawn 2026-09-11.** The hold lifted (developer: "implement language 18")
and codd-shoney re-settled the scope: 18 is now the engine + language block
alone. `cache.wo`, `flags.wo`, `jobs.wo` and the transactional demo moved to
[porch 10](stories/porch/10-memory-features-over-table.md) (`refine`, stub),
which needs 18's `transaction { }` for its jobs demo and porch 1–3 otherwise.
```mermaid
flowchart TD
classDef piece fill:#0969da,color:#fff,stroke:none
classDef inprog fill:#8250df,color:#fff,stroke:none
classDef refine fill:#eac54f,color:#000,stroke:none
TXN["language 18: transaction{} — compiler block, kind-6 log record, engine undo list, VM re-raise: landed 2026-09-11 (T1–T6); open: kill -9 battery"]:::inprog
TPRMW["txn-per-request middleware (v1 ledger's storage row; single-thread OK)"]:::piece
P10["porch 10: cache.wo, flags.wo, jobs.wo + the transactional demo (stub, refine)"]:::refine
TXN --> TPRMW
TXN -. moved 2026-09-11 .-> P10
```
`transaction { }` is the only engine + language work left in this iteration;
everything that only needed the WAL's staged batch as a `.wo` consumer moved
downstream to the track that owns `.wo` product code. Fiber-scheduled jobs and
cancellation→rollback appear in graph 2 — they need iteration 11 as well as 18.
## 5. porch — the web framework track
States live on [the board's porch section](stories/00-status.md). **The whole
track (2–8) is `readiness: ready`** as of the 2026-09-06 brainstorm; **1** is
done, **9** is held (blocked on the lang-41 arena hang, not an enhancement).
Three independent roots: **2** (the auth chain), **6** (the streaming chain),
**5** (anytime, no incoming edges at all — not even iteration 2). **10** is a
`refine` stub added 2026-09-11 (language 18's split — TTL cache, `@table`
feature flags, durable job queue) and is not part of the "whole track ready"
count.
This graph makes the **cross-track language edges** visible: the three builtins
the track needs, each drawn as a `lang` node feeding the story that owns it.
```mermaid
flowchart TD
classDef done fill:#1a7f37,color:#fff,stroke:none
classDef ready fill:#0969da,color:#fff,stroke:none
classDef held fill:#6e7781,color:#fff,stroke:none
classDef lang fill:#8250df,color:#fff,stroke:none
classDef refine fill:#eac54f,color:#000,stroke:none
TXN["language 18: transaction{} (T1 in flight)"]:::lang
RB["random_bytes builtin ✅ 2026-09-09 (bare-name, id 119 — one shared enum with wob.h/loader arity) — porch 2 Phase A"]:::done
DFL["language work: deflate + crc32 builtins (C) — porch 7 Phase C"]:::lang
TU["language work: time.utc builtin (gmtime sibling of time.local) — porch 8 Phase A"]:::lang
P1["porch 1 store-backed middleware ✅ 2026-08-30"]:::done
P2["porch 2 randomness + cookies"]:::ready
P3["porch 3 sessions"]:::ready
P4["porch 4 CSRF"]:::ready
P5["porch 5 routing + response ergonomics (zero upstream deps)"]:::ready
P6["porch 6 streaming core"]:::ready
P7["porch 7 SSE + compression"]:::ready
P8["porch 8 static files + lifecycle"]:::ready
P9["porch 9 idempotent replay (ready — unblocked 2026-09-09)"]:::ready
P10["porch 10 memory features over @table: cache/flags/jobs (stub, refine — split from language 18, 2026-09-11)"]:::refine
L41["language 41 actor-arena double free ✅ fixed 63065ff (cross-shard marshal)"]:::done
L44["language 44 poison-on-free ✅ (41's decision 3: a freed header can never pass for live; double free aborts)"]:::done
L41 -.follow-up.-> L44
RB --> P2
P2 --> P3
P2 --> P4
P3 --> P4
P6 --> P7
P6 --> P8
P5 --> P7
P5 --> P8
DFL --> P7
TU --> P8
L41 -.fixed 2026-09-09 — no longer blocks.-> P9
P1 -.re-scope 79e6da4: replay-on-retry split out of 1.-> P9
TXN --> P10
P1 --> P10
P2 --> P10
P3 --> P10
```
Edges corrected by the 2026-09-06 brainstorm: `P5 --> P7` (gzip's
`Accept-Encoding` reuses iteration 5's q-value ranking) stays, but the old
`P2 --> P7` edge is **gone** — story 7 decided `Vary` accumulates by comma-join
(iteration 5's shape), not iteration 2's repeated-header work. `P5 --> P8` is the
`Download`/`Attachment` helper. The three `lang` nodes are the track's entire
language bill; each is a builtin with a named consumer, none shipped as
decoration. **10** (added 2026-09-11) needs language 18's `transaction { }`
for its jobs demo and 1–3 for the store pattern, session-keyed cache and
flags read-through — see graph 4 for 18's own state.
## 5a. porch's language-driven gaps (out-of-scope features and the language stories that own them)
These are the features fiber ships that porch deliberately does **not** — each
excluded because a language primitive does not exist yet. Every edge points from
the owning language story to the porch feature it would unblock (see the
[porch↔fiber scope-gap analysis](plan/exploration/fiber/01-porch-vs-fiber-scope-gap.md)).
```mermaid
flowchart LR
classDef done fill:#1a7f37,color:#fff,stroke:none
classDef refine fill:#eac54f,color:#000,stroke:none
classDef held fill:#6e7781,color:#fff,stroke:none
classDef gap fill:#cf222e,color:#fff,stroke:none
classDef inprog fill:#8250df,color:#fff,stroke:none
L29["language 29 @derive (⏸ hold)"]:::held
L38["language 38 net.connect ✅ landed (id 110); proxy middleware now buildable"]:::done
L43["runtime-v2 8 symmetric cipher (refine, NEW 2026-09-06)"]:::refine
L30["runtime-v2 7 observability (refine, moved from language 30, 2026-09-06)"]:::refine
L18["language 18 transaction{} (hold lifted 2026-09-11; T1 in flight) — TTL cache moved to porch 10"]:::inprog
L31["language 31 cancellation ✅ (landed in 24)"]:::done
BIND["typed request binding (fiber Bind)"]:::gap
PROXY["reverse proxy + outbound HTTP client"]:::gap
ENC["encrypted cookies (fiber encryptcookie)"]:::gap
METRICS["metrics / pprof / expvar endpoints"]:::gap
CACHE["cache middleware + recovery rollback"]:::gap
TIMEOUT["per-handler timeout + streaming backpressure"]:::gap
L29 --> BIND
L38 --> PROXY
L43 --> ENC
L30 --> METRICS
L18 --> CACHE
L31 --> TIMEOUT
```
31 (cancellation) is already green — per-handler timeout and streaming
backpressure are unblocked at the language level and wait only on a porch slice
to consume them. The other five gaps are gated on an upstream story: two
brand-new runtime-v2 iterations (8 cipher, 7 observability — moved out of the
language track 2026-09-06), one language iteration on hold (29) and one
unheld and in flight (18, since 2026-09-11 — its TTL-cache half of `CACHE` now
lives in porch 10), one pending a spec (38). Landed enablers the
track already consumed — 34 (crypto digests), 36 (bit operators), 35 (net
seams) — are green in graphs 1–3 and not repeated here.
## 6. wmux — the multiplexer track (wmux 1) and its gap chain
The tmux study's gaps, remapped as buildable edges now that iteration 42
landed. Every yellow node is an iteration of the
[runtime-v2 track](stories/runtime-v2/00-story.md) ("the runtime beyond
sockets"), ALL `readiness: ready` since the track-wide brainstorm
([spec](superpowers/specs/2026-09-01-runtime-v2-design.md), 2026-09-01) —
[1 streaming subprocess](stories/runtime-v2/01-streaming-subprocess.md) ·
[2 PTY](stories/runtime-v2/02-pty.md) ·
[3 signals as events](stories/runtime-v2/03-signals-as-events.md) ·
[4 termios](stories/runtime-v2/04-termios.md) ·
[5 fd passing](stories/runtime-v2/05-fd-passing.md). wmux — its own
track, first of the softwares built with writeonce — is the driving
workload that consumes them all — [wmux 1](stories/wmux/01-wmux.md).
```mermaid
flowchart TD
classDef done fill:#1a7f37,color:#fff,stroke:none
classDef gap fill:#eac54f,color:#000,stroke:none
classDef product fill:#0969da,color:#fff,stroke:none
classDef later fill:#6e7781,color:#fff,stroke:none
I42w["42 bounded subprocess ✅ 2026-09-01"]:::done
GSTREAM["runtime-v2 1 ✅ 2026-09-02 streaming subprocess: Child fds driven by the net verbs, wait_dl, signal"]:::done
GPTY["runtime-v2 2 ✅ 2026-09-02 PTY: spawn_pty + resize"]:::done
GSIG["runtime-v2 3 ✅ 2026-09-02 signals as events: signal.on delivers Signal records"]:::done
GTERMIOS["runtime-v2 4 ✅ 2026-09-02 termios: raw/restore, restore a runtime obligation"]:::done
GFDPASS["runtime-v2 5 ✅ 2026-09-02 fd passing: send_fd/recv_fd/connect_unix"]:::done
GVTE["VTE grid in pure .wo + unicode width tables ✅ (rung 2; UTF-8 decode + term.width landed)"]:::done
DB2W["databasev2 2 per-table durable/resident ✅ 2026-09-10 — durable default + WAL wmux 1 persists sessions/scrollback into"]:::done
WMUX["wmux 1 foundation ✅ 2026-09-02 (was language 43): server owns sessions/PTYs in durable tables, thin client hands over its tty — reattach after server RESTART replays from the WAL"]:::done
W2["wmux 2 the screen ✅ VTE grid"]:::done
W3["wmux 3 windows + status ✅"]:::done
W4["wmux 4 split panes ✅ (2-pane vertical)"]:::done
W5["wmux 5 copy mode ✅"]:::done
W6["wmux 6 multi-client ✅ (mirroring)"]:::done
W7["wmux 7 command system ✅"]:::done
W8["wmux 8 hooks + control ✅"]:::done
W9["wmux 9 parity audit ✅"]:::done
W10["wmux 10 layout tree — 🟡 first slice DONE 2026-09-03: horizontal split-window -h, select-pane -L/R/U/D, zoom; 2-pane max, N-way/swap/break/persistence pending"]:::gap
W11["wmux 11 formats + options + key rebinding ✅ 2026-09-02 — durable options/binds, #{...} status format, one run_command dispatcher; folded rung 14's prompt-race fix; fixed a PTY-EIO reader spin + a kill-session chunk race. gate 36/0"]:::done
W12["wmux 12 resize + mouse — 🟡 first slice DONE 2026-09-03/04: attach-time term.size sizing + SGR mouse (wheel/click/status-row); live SIGWINCH + min-size pending (rt2 3/6 ready)"]:::gap
W13["wmux 13 copy selection + search — 🟡 first slice DONE 2026-09-03: char-range vi v/y yank → buffer+OSC52; only search + rectangle pending"]:::gap
W14["wmux 14 control surface (prompt-race fix DONE in rung 11; narrows to control-mode commands + %notifications)"]:::gap
W15["wmux 15 terminfo — 🟡 terminfo-lite DONE 2026-09-03: a TERM allowlist retired the foreign-TERM refusal; full compiled-terminfo parsing pending"]:::gap
W16["wmux 16 durability polish (pane persistence, killw compaction) — 🟡 first slice DONE 2026-09-02: Window owns+reaps its panes (spawns in-actor so wait_dl works on its shard), zombie leak fixed, gate 37/0"]:::gap
W18["wmux 18 key tables (new, from the config audit) — 🟡 first slice DONE 2026-09-03: no-prefix RootBind table, Meta/named key_code, tty key decoder in Input; bind-key -n works; gate 42/0. copy-mode-vi + -r repeat pending. Also landed: dynamic sizing (term.size), alt-screen, erase 0/1, SGR reset, UTF-8 decode, O(n log n) replay"]:::gap
W19["wmux 19 mouse-driven UX (new) — 🟡 active-pane border + status-row click→window DONE 2026-09-04; drag-resize/drag-select pending. Forks open (scope split, motion mode, drag owner)"]:::gap
W17["wmux 17 formats v2 ✅ 2026-09-03 — #(shell) cached+timer, recursive #{...} conditionals/modifiers, #{time}/#{host_short}/#{window_name}"]:::done
W20["wmux 20 display-popup ✅ 2026-09-03/04 — session-owned modal float, -B borderless, rounded border, popup wheel forward; drove the OSC-swallow + frame-coalesce VTE fixes"]:::done
W21["wmux 21 sesh + switch-client ✅ 2026-09-04 — in-session switch-client -t/-l, reg threaded into sessions, sync call hand-off (fds move without close, B spawns a fresh Input, old Input exits on success), B-occupied refuses. Fixed a ?actor nullable schema-reorder. Gate 54/0"]:::done
W22["wmux 22 theming ✅ 2026-09-04 — style_sgr engine (fg/bg/attrs from durable options), active-pane border marker, automatic-rename via OSC title"]:::done
W23["wmux 23 plugin ports — thumbs/fzf/fzf-url via capture-pane + a popup picker (port vs tmux-compat shim). Forks open"]:::gap
W11 --> W18
W12 --> W19
W13 --> W19
W10 -.drag-resize only.-> W19
W11 --> W17
W2 --> W20
W6 --> W21
W20 --> W21
W11 --> W22
W10 --> W22
W20 --> W23
W12 --> W23
WMUX --> W2
W2 --> W3
W3 --> W4
W4 --> W5
W5 --> W6
W6 --> W7
W7 --> W8
W8 --> W9
W9 --> W10
W4 --> W10
W7 --> W11
W6 --> W12
W5 --> W13
W8 --> W14
W1TERM["(rung 1 fixed-profile refusal)"]:::done
W1TERM -.retired by.-> W15
W10 --> W16
TINFO["terminfo fork: parse the db in .wo vs fixed xterm-256color + refusal by name (decide at 43's brainstorm)"]:::later
TMONO["time.mono returns (status clock, repaint pacing) — v2"]:::later
I42w --> GSTREAM
GSTREAM --> GPTY
GPTY --> WMUX
GSIG --> WMUX
GTERMIOS --> WMUX
GFDPASS --> WMUX
GVTE --> WMUX
DB2W --> WMUX
TINFO -.settled at wmux's brainstorm.-> WMUX
TMONO -.v2.-> WMUX
```
**The track landed whole on 2026-09-02** — every runtime edge into wmux
is green. The VTE grid + unicode-width node landed (rung 2), and the ladder
is now through rung 22 (see the wmux table on the board); rungs 10/12/13/15
have first slices, rung 23 (plugin ports + a tmux-compat CLI) remains the
big open item. Sibling reuse:
the alacritty Wayland stage reuses GFDPASS + GVTE; the zen CDP driver
now lacks only a WebSocket client; skillhost (28) has its stdin
transport. One edge added 2026-09-10: [databasev2 2](stories/databasev2/02-table-storage-modes.md) → wmux 1, drawn above as `DB2W`, because wmux 1 persists sessions/scrollback in durable `@table` classes and replays from the WAL on reattach — the dependency the prose already named without a node.
## 7. jarvis — the AI-assistant track and everything it waits on
The sixth track ([jarvis](stories/jarvis/00-story.md)): an AI assistant built in
writeonce. **The runtime side is done** — the whole outbound HTTPS path landed
2026-09-09 (runtime-v2 9, both directions, live-gated) and language 41 is fixed.
What jarvis 1 waits on now is purely the **framework**: the developer set the
order *porch first, then jarvis*. So this graph is the porch→jarvis chain.
```mermaid
flowchart TD
classDef done fill:#1a7f37,color:#fff,stroke:none
classDef ready fill:#0969da,color:#fff,stroke:none
classDef refine fill:#eac54f,color:#000,stroke:none
NC["net.connect (id 110) ✅"]:::done
TLS["rv2 9 in-process TLS 1.3 ✅ — net.connect_tls / read_tls / write_tls (115–117), net.accept_tls (118)"]:::done
L41["language 41 cross-shard marshal ✅"]:::done
WOHTML["wo-html / writeonce-view ✅"]:::done
RB["random_bytes builtin (porch 2 phase A / lang 39) — surfaces the runtime's getrandom"]:::ready
P2["porch 2 randomness + cookies (ready)"]:::ready
P3["porch 3 sessions (ready)"]:::ready
P4["porch 4 CSRF (ready)"]:::ready
P5["porch 5 routing + response ergonomics (ready, zero deps)"]:::ready
P6["porch 6 streaming core (ready)"]:::ready
P7["porch 7 SSE + compression (ready)"]:::ready
P8["porch 8 static + lifecycle (ready)"]:::ready
P9["porch 9 idempotent replay (ready — unblocked by L41)"]:::ready
J1["jarvis 1 — the chat loop (ready; forks auto-approved, review_pending)"]:::ready
J2["jarvis 2 — tool use / agent loop (refine)"]:::refine
J3["jarvis 3 — retrieval (RAG) (refine)"]:::refine
NC --> TLS
RB --> P2
P2 --> P3
P2 --> P4
P3 --> P4
P5 --> P7
P5 --> P8
P6 --> P7
P6 --> P8
L41 --> P9
TLS --> J1
P2 --> J1
P3 --> J1
P4 -. CSRF-protects the POST once built .-> J1
P6 --> J1
P7 --> J1
WOHTML --> J1
J1 --> J2
J1 --> J3
```
**jarvis 1's dependency list, from the code and the stories (2026-09-09):**
| jarvis 1 needs | for | state |
| --- | --- | --- |
| `net.connect_tls` / `net.read_tls` / `net.write_tls` (runtime-v2 9) | dialing the LLM API over HTTPS, streaming its SSE reply | ✅ landed, live-gated |
| `net.connect` (id 110) | the TCP under it | ✅ landed |
| language 41 fix | actors carrying messages across shards without the double free | ✅ landed |
| `@table` | durable `Conversation` / `Message` history | ✅ exists |
| wo-html / writeonce-view | the chat page | ✅ exists |
| **porch 2** randomness + cookies (needs the `random_bytes` builtin first) | session id + signed cookie | ready, **unbuilt** |
| **porch 3** sessions | the session principal history is keyed to | ready, unbuilt (after 2) |
| **porch 6** streaming core | incremental response writes | ready, unbuilt |
| **porch 7** SSE + compression | token streaming to the browser | ready, unbuilt (after 5 + 6) |
| porch 4 CSRF | protecting `POST /message` (bearer-gated until then) | ready, unbuilt (after 2 + 3) |
| porch 5 routing + response ergonomics | the route surface | ready, unbuilt, zero deps |
**Build order that satisfies it** (the porch critical path to jarvis): the
`random_bytes` builtin → porch 2 → porch 3 → porch 5 → porch 6 → porch 7 (→ porch
4, 8, 9 to complete porch) → **jarvis 1**. Nothing on the runtime side is
outstanding; every remaining edge into jarvis 1 is a porch iteration.
## 8. databasev2 — the database beyond RAM
The third track ([databasev2](stories/databasev2/00-story.md)): what happens
when the data does not fit in memory. Its 3 and 4 are the language track's 32
and 23 renumbered — graph 1 still carries them as `I32`/`I9f`, green since
2026-08-29/28. Arrows point AT the iteration that needs the other, as in the
track's own ASCII graph; two edges are undirected: 3–4, which compose on the
WAL commit path and need each other in neither direction, and 2–3 (added
2026-09-10 — this graph had dropped it; the story's own graph always carried
it, [00-story.md:169-171](stories/databasev2/00-story.md)) — 2 needs 3's
offset map to survive compaction, and 3 has called 2's row API since task 5d,
so the coupling runs both ways. 9 and 10 (cross-program tables, keypair
attach) are held and not drawn.
```mermaid
flowchart TD
classDef done fill:#1a7f37,color:#fff,stroke:none
classDef inprog fill:#8250df,color:#fff,stroke:none
classDef ready fill:#0969da,color:#fff,stroke:none
classDef refine fill:#eac54f,color:#000,stroke:none
classDef hold fill:#6e7781,color:#fff,stroke:none
D1["databasev2 1 RAM ceiling measured ✅ 2026-08-27"]:::done
D2["databasev2 2 per-table durable/resident ✅ 2026-09-10 — 6a: refuse durable:true without WO_DATA, WO_EPHEMERAL=1 escape, .wob v8 table bit"]:::done
D3["databasev2 3 WAL checkpoint ✅ 2026-08-29 (was 32)"]:::done
D4["databasev2 4 group commit 🔄 — part A ✅ 2026-08-28; part B re-brainstormed 2026-09-10, GO measured (forks 6/7), fold pending — refine (was 23)"]:::inprog
D5["databasev2 5 bounded tables + eviction — ready 2026-09-10 (12 forks, review_pending), status pending; Phase A is the resident byte budget moved from 2 (2026-09-09)"]:::ready
D6["databasev2 6 cold tiering — hold (superseded by 2's resident: keys)"]:::hold
D7["databasev2 7 single-file store ✅ 2026-09-10 — WO_DATA=<path>.db (was 33)"]:::done
D8["databasev2 8 query grammar from corpora — hold, refine (count landed 2026-08-16; exists open) (was 27)"]:::hold
D11["databasev2 11 bounded delta chains ✅ 2026-08-30"]:::done
D12["databasev2 12 schema migrations ✅ 2026-08-31"]:::done
D13["databasev2 13 fresh-log keys-resident seed SEGV ✅ fixed 2026-09-10"]:::done
P1["porch 1 store-backed middleware ✅ 2026-08-30"]:::done
P2["porch 2 randomness + cookies (ready)"]:::ready
P3["porch 3 sessions (ready)"]:::ready
D1 -- budget default follows the measurement --> D5
D2 -- the byte budget, moved 2026-09-09 --> D5
D2 --> D11
D2 --> D12
D3 --- D4
D3 --- D2
D2 -- volatile tables; store.wo is default-durable today, so fork 6 makes WO_DATA or WO_EPHEMERAL=1 whole-program --> P1
D2 --> P2
D2 --> P3
D2 -- the offset map D13's fix touches --> D13
D12 -- the schema head record D13's fix touches --> D13
```
Node D13, added 2026-09-10, fixed the same day: a defect found while smoking
databasev2 7, not that iteration's fault (it reproduced identically in the
pre-existing directory form). It needed 2 (the keys-resident offset map) and
12 (the schema head record) — both are the mechanism the crash lived in.
Fixed by `6310078` (`wo_wal_next_offset` stages the pending schema head
before returning an offset) + `1b6750d` (NULL-`msg` guard in
`wo_wal_fold_row_at`); `just residency` 32/0. The separate
`residency.keys.fit` rc 74 bug (compaction/replay of keys-resident offsets)
is **not** the same defect and stays open under codd.md's "Next bugs".
**States as of 2026-09-10** (the board carries the words; this is the glance):
| databasev2 | status / readiness | what is left |
| --- | --- | --- |
| 1 RAM ceiling | ✅ done | — |
| 2 per-table storage | ✅ done (2026-09-10) | — (6a landed with the `.wob` v8 table bit; 6b lives in 5) |
| 3 WAL checkpoint | ✅ done | — |
| 4 group commit | 🔄 in-progress / refine | part B re-brainstormed 2026-09-10 (GO measured, forks 6/7); fold into the story, `.dev/zack/databasev2-4b.md` |
| 5 bounded tables | ⬜ pending / **ready** (2026-09-10) | developer review of the twelve `review_pending` forks, or a prebuild brief for Phase B; Phase A is startable now |
| 6 cold tiering | ⏸ hold / refine | superseded by 2; revisit only on a measurement |
| 7 single-file store | ✅ done (2026-09-10) | — (`WO_DATA` is a path, never a sentinel; `review_pending` developer second review) |
| 8 query grammar | ⏸ hold / refine | `count` landed; `exists` waits for a corpus |
| 11 bounded delta chains | ✅ done | — |
| 12 schema migrations | ✅ done | — |
| 13 fresh-log keys-resident seed SEGV | ✅ done (2026-09-10) | — (`residency.keys.fit` rc 74 is a separate, still-open bug) |
## Maintenance rule
When an iteration or slice lands, update its node's class here in the
same change that moves the board row — the two documents answer
different questions (status vs. edges) and drift kills both.