writeonce/docs/plan/exploration/c-runtime/02-single-binary.md
shoney.arickathil c0b0dbb846 docs: audit all markdown against the code, fix findings, flatten status folders
- 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>
2026-08-26 19:20:22 +02:00

90 lines
7.1 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.

# 02 — The end goal: the writeonce single binary on this runtime environment
**Context sources:** [`00-plan.md`](00-plan.md) (the runtime-environment phases, A–B ✅), [`01-architecture.md`](01-architecture.md) (the one-address trace), `../../../runtime/wo-language.md` ("one binary per project; no runtime to install on the target host"; `.wo` has "its own lexer, parser, analyzer, and bytecode"), `../../09-concurrency-scaleout.md`–`12` (the Rust product track this proves out), `../../../runtime/database/02-wo-language.md` (catalog + transaction semantics the payload carries).
## The end goal, stated once
> A developer writes `.wo` files. `wo build` emits **one static binary**. That binary **is** the runtime environment described in this track — thread-per-core shards, the mlock'd RAM arena, io_uring event loops, WAL dual-write, boot-time recovery — with the application **inside it** as data and bytecode. Deploy = copy one file to a Linux host. Nothing to install; the only "VM" underneath is the Linux kernel.
This resolves the phrase "runs **in** this runtime environment": writeonce is the **Go model, not the JVM model**. The environment is not a process you start and feed programs to — it is a **runtime kernel** statically linked into every application binary. What `wo-rt-c` builds phase by phase is that kernel, proven in C, ported to Rust per plans 09–12.
```mermaid
flowchart TB
subgraph BIN["ONE BINARY (output of `wo build`)"]
subgraph APP["application payload — compiled from .wo"]
CAT["catalog<br/>types/classes → slot geometry"]
RT2["route table<br/>service decls → method+path+op"]
BC["logic bytecode<br/>fn methods, triggers, queries"]
UIA["UI assets<br/>SSR templates + manifest + CSS"]
end
subgraph KERN["runtime kernel — this track"]
BOOT["boot loader<br/>size arena from catalog, WAL replay"]
SCHED["shard scheduler<br/>thread-per-core, SO_REUSEPORT"]
LOOP["event loops<br/>epoll → io_uring"]
ENG["engine primitives<br/>arena slots, bitmaps, indexes"]
WAL["commit pipeline<br/>RAM apply → WAL → group fsync → ack"]
HTTP["HTTP + WS"]
end
end
LINUX["Linux kernel — epoll/io_uring, mmap/mlock, signalfd/eventfd, page cache"]
APP -->|"consumed at boot<br/>and at dispatch"| KERN
KERN --> LINUX
```
## The embedding contract
The seam between the two halves is narrow and data-shaped — the compiler emits **tables**, the kernel consumes them. Five entries:
| Payload artifact | Emitted from | Consumed by | Exists today as |
| --- | --- | --- | --- |
| **Catalog** — per type/class: field layout, slot size, unique keys, shard key | `type`/`class` decls (`crates/rt/src/compile.rs`) | boot loader: arena geometry (`arena_hdr` is its miniature); engine: row codecs | `rt::compile::Catalog`, built per `wo run` |
| **Route table** — `(method, path pattern, operation, type id)` | `service` blocks | HTTP dispatch | `rt::server::router` |
| **Logic bytecode** — method/trigger/query programs | `fn` bodies, `on` blocks, schema-layer DML | a bytecode interpreter running **inside the owning shard's thread** — serial execution = ACID isolation for free | parse-and-discard (13b lands the executor) |
| **UI assets** — SSR templates, manifest, flattened CSS, `wo-runtime.js` | `##ui` triplets (plan 14) | HTTP static + SSR renderer | design (plans 13d/14) |
| **App manifest** — name, version, default port/threads | `wo.toml` | boot banner, env-var defaults | `wo.toml` parsing TBD |
Two consequences worth locking:
1. **The shard key comes from the catalog, not the kernel.** `wo-rt-c` hashes connections (4-tuple) because it has no catalog; the product routes *operations* by the catalog's shard key (plan 09 decision 5: customer id, author id) — a request landing on any thread sends an in-process message to the owning shard. Phase A's `SO_REUSEPORT` spread is the transport layer of that story, not the final routing.
2. **Bytecode runs where the data lives.** A `set_price` method executes on the shard that owns the product row — the interpreter is invoked from the event loop, runs to completion, commits through the WAL pipeline. No cross-thread data access; cross-shard transactions escalate to 2PC (plan 09e).
## Boot sequence of the single binary
What `./myapp` does before serving — each step already prototyped or phased:
| # | Step | Proven by |
| --- | --- | --- |
| 1 | Read embedded catalog → compute arena geometry (shards × slot families) | `arena_hdr` (phase B ✅) |
| 2 | `mmap` + `MAP_POPULATE` + `mlock` the arena (hugepages, 4 K fallback) | phase B ✅ |
| 3 | Replay per-shard WAL/snapshot from disk into the arena, in parallel | phase E |
| 4 | Spawn `WO_THREADS` pinned shard threads, each with ring + `SO_REUSEPORT` listener | phase A ✅ / phase C |
| 5 | Install route table + bytecode programs per shard | 13b / this contract |
| 6 | Listeners open; signalfd→eventfd shutdown armed | phase A ✅ |
Steps 1–2 and 4–6 exist in `wo-rt-c` today with the notes store standing in for the catalog. The end state swaps the hard-coded `slot_note` for catalog-driven slot families — the kernel code does not otherwise change shape.
## What runs where — `.wo` construct → runtime home
| `.wo` construct | At runtime, inside the binary |
| --- | --- |
| `type` / `class` fields | a slot family in each shard's arena slice |
| `class` `fn` methods | bytecode executed serially in the owning shard's thread (`POST /api/<t>/:id/<m>`) |
| `service rest … expose` | route-table entries dispatched by the HTTP layer |
| `on <event>` triggers | bytecode hooked into the commit pipeline, same transaction |
| `LIVE select` / `subscribe` | per-shard subscription registry; deltas fan out one message per shard (09d) |
| `##ui` screens | SSR render + manifest at GET routes; live patches ride the same deltas |
| `policy` rules | predicate rewrites applied before the engine touches slots |
| `main { … }` | bytecode run once at boot step 5½, before listeners open |
## Division of labor (locked by the C-vs-Rust decision)
- **`wo-rt-c` (C)** — proves each kernel syscall sequence first: threads/arena (✅), io_uring, WAL, recovery, bench. It will never parse `.wo`; its notes store is the stand-in payload.
- **`crates/rt` (Rust)** — the product: owns the compiler front-end today (lexer→catalog, Stage 2 shipped) and absorbs each proven kernel sequence per plans 09–12, where ownership makes the shard discipline a compile-time guarantee.
- **Optional phase G** (named in [`00-plan.md`](00-plan.md)): splice the `wo-db` C++ query engine onto `wo-rt-c` as an end-to-end C-family demonstrator of this document — valuable as proof, never the product.
## Cross-references
- [`00-plan.md`](00-plan.md) — the kernel phases; [`01-architecture.md`](01-architecture.md) — the one-address trace through the same stack.
- [`README.md`](../../../../README.md) — the user-facing single-binary promise this document implements.
- `../../13-class-model-live-pricing.md` (13b methods) — the payload-side track.
- `../../09-concurrency-scaleout.md` — shard-key routing and 2PC the contract defers to.