- 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)
659 lines
33 KiB
Markdown
659 lines
33 KiB
Markdown
# 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.
|