- engine: wo_idx_probe answers single-column equality from the index
hash buckets (idx_hash_key1 reproduces idx_hash bit for bit; verify
compares exactly as the slab walk did, so results identical);
composite indexes keep the walk; both executors wired (local + DB
actor RPC)
- compiler: probe_key_of_where lowers "var.col == key" on an indexed
column to DB_PROBE; all where guards still run (guard stays the
final arbiter); keys = ident/int-literal only; Float/Bytes excluded
(engine raw-eq narrower than VM float-eq)
- measured: reads 1.3k -> 1.3M ops/s, p50 600us -> 1us (~x850);
query x830; mixread 1.3k -> 89k s1, 21 -> ~1.9k sN
- gate policy moved into the driver (tolerance_for: refresh-proof);
latency floors max(4x,100us); quick mode skips poll-bound mix
floors; both tolerance classes proven to bite
- proof: test_table wo_idx_probe suite (RED first), corpus
query-index-probe 105/0, full battery green, TSan clean, two
campaigns pass the refreshed baseline
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- constraints-and-grammar: gram.y PK/FK productions, pg_constraint,
RI trigger semantics; writeonce direction — @key as unique alias
(id stays THE key), ref actions (@on_delete), backlink-implies-index
(improves on postgres' not-auto-created FK index)
- indexing-and-point-lookup: AM roster + algorithms (Lehman-Yao,
linear hashing), TID = row address; writeonce gap — probe walks
slabs while idx_bucket exists; O(1) slice direction, non-goals
- card index updated; Rust-era plan-10/11/12 links unlinked (rot)
- docs/guides/database-developer-subagent.md: format, paste-ready
agent definition (doctrine/file map/gates), verification, division
of labor
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- bench/baseline.json: 74 metrics from the first full campaign;
tolerances tuned by a two-run repeatability check (mix* 50%,
read/query 35%, rest 15% — rationale in _config)
- gate bites: --check mode; doctored copy fails, both real runs 74/0
- headline: durable seed 4.5k/s vs ram 297k/s (23's case); reads
O(table) at ~1.5k/s; mixread 1280 vs 21 ops/s single-vs-multi
(the arc's price); msgrate 13.4M vs 2.45M (mutex-inbox number)
- arc delta recorded in story 8; findings in sample README
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Mixer actors: 90/10 read/write, per-actor histograms merged through
the store itself (Hist rows) — exact aggregate percentiles
- msgrate: one-way flood at a worker-placed sink; measured 15.3M
msgs/s same-heap vs 2.06M cross-shard — the mutex-inbox number
- finding: point lookups are O(table) (probe walks all slabs), so
read-heavy mix is quadratic in store size — all-mode calibrated to
N/10 mix ops; the number 22 exists to publish
- TSan clean both shard counts (setarch -R, fibers-gate pattern)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- seed/read/query/write/wal/verify/verify-acked + all (one-process
campaign: RAM store dies with the process)
- per-op time.ticks, 1us-bucket histogram percentiles (reservoir
deviation: no element-write/sort in language; better tail anyway)
- Meta expectation rows ride the same WAL verify checks
- finding: hand-built multi<TableClass> SEGVs on drop (elems classed
OWNED, refs are scalar ids) — worked around, recorded
- finding: reads ~1.6k/s p50 595us vs 287k/s inserts — probe walks
all slabs; the number 22 exists to surface
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- worker DB builtins marshal to shard 0: requester-side slot encode
(VM heaps never read cross-shard), owner executes serialized in
adopt, reply unparks via new WO_PARK_INBOX park + envelope 3/4
- engine gains thread-agnostic slot entry points (insert_slots,
update_field_slot, val_encode/clone, wo_db_exec_req); traps and
messages byte-identical to the local path
- main.c: engine + replay boot BEFORE shards spawn; workers assert
rt.db/rt.wal NULL; busy shard adopts inbox once per slice
- latent stage-1 bug fixed: shared io_uring params static raced by
lazy worker init lost park wakes (~1/20 hangs); params per-vm,
short submit now fails loud
- new sample docs/examples/db-actor + just db-actor gate 8/0 (multi
x3, uring/epoll forced, single byte-exact, WAL replay pair);
ASan+TSan 6/6; full battery green
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- five-property map in marker doc: atomicity/durability/recovery
proven or held (18); concurrency control = stage 3's property;
space reclamation RAM done (slot reuse), disk = new story 32
- story 08: three stage-3 criteria (one commit per write RPC +
ack-after-owner-fsync, workers WAL-free + replay-before-serve,
no torn reads under TSan corpus); arc plan stage 3 carries them
- refine/32-wal-checkpoint.md: snapshot + truncate, bounded replay,
crash-during-checkpoint safe; four forks; after 23
- chain now stage 3 -> 22 -> 31 -> 24 -> 23 -> 32 in all 10 docs;
boards + seq bumps synced
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 08 landed in discarded/ by mis-drop, swept into prior commit with
two dead links; corrected to stories/.../in-progress/ per intent
- 11 joins it (one arc, active slice)
- board doctrine: active stories bucket named; all links re-verified
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- one marker doc, deleted on landing; board doctrine names the
second folder exception
- board In-progress row was stale (nothing active + dead anchor);
now points at marker + arc plan tasks 7-8
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- io_uring is a must; epoll approach discarded (developer decision)
- plan superseded by shard-fiber-arc plan of record; banner + row in
plan/discarded.md; file kept as idea reference
- three live pointers repointed: status language-track row 8,
principles enforced-by, story 08 note
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- code-verified ready: arc stages 1+2 merged to master; stage 3
concrete in plan (tasks 7-8); rt.db set on primary only
(main.c), worker_late_init memsets rt — WO_T_DB hole real
- 22/23/24/31 stay in refine/: open forks, no bench harness,
no crypto builtins, chain-blocked
- links fixed both directions; board doctrine names hold/ bucket
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- iterations 18/25/26 marked hold in their spec + plan headers
- 25's story file removal committed; plan doc stays for resumption
- web-framework spec's relates-to flags 25 held
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Float full stack: literals (fraction/exponent; `0..10` still a range), f64
opcodes 34-41, @table column, WAL bit-exact replay, json fractions in and
shortest-round-trip out. IEEE-quiet — FDIV never traps where DIV does.
- Bytes: a wo_str with its own class id, so alloc/free/copy are shared but no
Text builtin accepts one; len/at/slice/eq/concat, base64 both ways, json
boundary as base64; TEXT_COPY preserves the kind.
- No implicit Int/Float mixing (WO-E201 in the typechecker, not the emitter,
which picks the opcode from one side and would misread the other).
- One IEEE deviation: float_cmp total order (NaN last, -0.0 == +0.0) for
indexes and order-by, keys canonicalized to match. `?Float` nil is a
reserved quiet NaN — the zero word is +0.0, WO_NIL_SCALAR's bits are -2.0.
- Renderer prefers fixed over exponential in 1e-6..1e21: pure shortest makes
a price of 900.0 read `9e+02`. One renderer for interp/json/float_to_text.
- Fixed en route: lexer double-counted the leading digit; is_scalar_shaped
took Float/Bytes as Int-shaped; Bytes ownership needed a shared heap-scalar
predicate or temps never dropped; order-by bit-compared negatives backwards.
- Iteration 17: `kind = "library"` (absent = program; bad value = WO-E109),
entry-less check mode retiring the `--emit` workaround, Go's `internal/` as
WO-E108 at the consumer's `use`. Driver-only; VM/.wob/GC untouched.
- Framework reorg: internal/{parse,serve}.wo; http/form.wo split out to keep
media_type/form_values public (parse.wo had grown public surface).
- Docs: link audit (97 -> 88 broken, conflict markers resolved, 2 duplicate
stories removed), 00-code-review verified 26/27, iterations re-sequenced.
- Also carries the pre-staged pub(read)/using/#if work from the index.
- Gates: corpus 103/0, test_wal 156/0, web-app 26/0, oop-accept ALL MET.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- developer directive: pending iteration IDs now ARE the priority order;
LANDED iterations keep historical numbers (code comments and commit
history cite them — records, not a queue); 8/11 (the half-landed
arc), 17 (parked, artifacts on a branch), 18 (next, artifacts named)
also frozen
- mapping (recorded in 00-story): 19<-20 Float+Bytes, 20<-9c attach,
21<-9d keypair, 22<-9e benchmarks, 23<-9f io_uring WAL, 24<-19 chat,
25<-10 services, 26<-12 blue-green, 27<-9g query corpus,
28<-14 skillhost, 29<-13 metaprogramming
- 11 story files renamed; every doc reference re-numbered (word-boundary
sweep for the lettered 9x ids, phrase-level for numeric ones); the
iterations table rewritten with Seq == priority and "(was N)" notes;
story-scoped link check: zero broken
- merge-recovery folded in: the partial master merge had dropped the
chat story, the fibers exploration note, the arc spec+plan, the
framework-v2 plan, and the iteration-17 spec+plan — all restored from
their branches and renumbered consistently
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- brainstorm settled four forks: Float FULL STACK in one iteration
(literal, IEEE f64 VM ops via u64 bitcast, @table column + WAL slot,
json fidelity — json.c's own comment names the hole: fractions are
malformed because "the language has no [float]"); IEEE-754 QUIET
semantics (division never traps, NaN flows; Int keeps DIV0; no
implicit mixing — float(i)/trunc(f) bridges); BYTES ships alongside
(binary carrier: multipart files, WS frames for 19, crypto digests;
Text goes back to meaning text); iteration 20 + spec before code
(.wob/WAL version bump earns a written spec)
- the rest of the missing-type survey recorded with reasons: Result/
Option expressible today (?T + payload unions), tuples covered by
records + doctrine, Decimal stays cents-until-a-workload, Char/
Unicode its own future story, Set/ADTs parked post-12, scalar
newtypes need the rejected `abstract`
- one indexed-storage deviation from raw IEEE spec'd loudly: a Float
index needs a total order — NaN sorts last
- board row, story-table row (seq 26), graph node (9+16 -> 20 -> 19;
crypto gate wants Bytes)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- spawn placement: round-robin across shards (same-shard when the
engine is absent/single); the actor's mailbox and delivery belong to
its HOME thread — a spawn to another shard travels as an ADOPT
envelope, a send as a SEND envelope (mutex-guarded inbox + eventfd
wake; the spec's lock-free rings stay a disclosed deviation until
9e measures the mutex)
- workers: first envelope triggers lazy full-vm init UNDER the inbox
mutex (TSan caught the memset racing a concurrent push, twice — the
second was inbox_push reading wake_efd outside the lock; both fixed,
gate x8 + battery clean); serve loop = adopt -> run to drained ->
wait on the plane (the wake eventfd is watched by io_uring POLL_ADD
oneshot / epoll level-triggered on BOTH backends)
- ownership across heaps: every allocation stamps rt->shard_id into
the header (the field reserved since iteration 2); a drop on the
wrong shard routes home as a FREE envelope — the owner's arena stays
single-threaded by construction; at teardown routed frees become
no-ops (arenas die wholesale) which is what un-danced the freed-mutex
ASan SEGV the first ordering had
- WO-E222: an actor's state or message type that is (or transitively
contains) an inferred-traced class refuses at the spawn/send — with
round-robin every actor is potentially remote; corpus-pinned
(compile-fail/traced-send, inference-aware: Box contains ?Node)
- determinism narrowed per spec: oop-e2e pins WO_SHARDS=1 (exact
outputs); the fibers gate grows multi-shard SET assertions + a TSan
run (wovm-tsan target; setarch -R fallback for kernel 6.5+ ASLR)
- NEXT_RUNNABLE honors engine shutdown for parked workers (deadlock
hole closed); io_wait's adopt-wake (rc 1) no longer reads as fatal
- battery: oop-e2e 93/0, fibers 10/0 x8 (+WO_IO=epoll), log-watcher
7/0, employee 8/0, web-app 21/0, deps 8/0, runtime tests 16/16
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- wo_engine + wo_engine_start/stop: one pinned pthread per extra core
(pthread_setaffinity_np); shard 0 is the primary (entry + database);
workers idle on a wake eventfd until fibers arrive (T6) or shutdown
- default = all cores (the arc's brave landing), WO_SHARDS=1..64
overrides; N=1 spawns no threads — byte-identical to stage 1
- worker vms are LAZY: identity + wake fd only until their first fiber
arrives — 20 idle shards must not cost 1.25 GiB of eager arenas
(they did: the web-app gate flaked on exactly that before the fix;
3 consecutive green runs after)
- engine stops (join + destroy) before the primary's teardown
- battery at the 20-core default: oop-e2e 92/0, fibers 8/0,
log-watcher 7/0 (+WO_SHARDS=1 identical), web-app 21/0 x3,
employee 8/0, deps 8/0, runtime tests 16/16 files green
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- docs/examples/fibers: part 1 is TIMING-FREE and byte-exact — main
sends three messages then burns reductions; each budget expiry hands
the Counter actor exactly one delivery (cooperative mechanics,
preemptive fairness, BEAM's shape); part 2 parks a Sleeper actor
mid-receive on the I/O plane while main keeps ticking — the wake
lands between ticks, proving a sleeping fiber blocks nobody
- the missing "sleeper: up" on the first run was main-return-reap
working as specced (main ended before the deadline); the demo's
window widened so the wake is observable
- scripts/fibers-accept.sh + `just fibers` (8 checks): build, part-1
exact + part-2 ordering invariants on auto/uring/epoll backends,
and an ASan-runtime rebuild+run
- README points at the doctrine writeup (exploration/fibers)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- park.c/park.h: one event loop per shard. io_uring PRIMARY (raw
io_uring_setup/io_uring_enter, uapi structs mirrored, 5.4-floor ops:
POLL_ADD for fd readiness, TIMEOUT for sleeps, user_data = the fiber);
epoll+deadline-scan FALLBACK behind the startup probe; WO_IO=
uring|epoll forces either so CI proves both on one kernel
- park protocol: a blocking builtin fills cur->park_* and returns
WO_SYS_PARKED; resume either RE-EXECUTES it (fd readiness: accept/
read/write retry) or continues PAST it (sleep: result preset,
park_done=1 — re-executing would restart the full duration)
- sysio: listener + accepted fds nonblocking (accept4 SOCK_NONBLOCK);
accept/read park on EAGAIN; write parks on EAGAIN with its partial
progress carried across the retry in park_wr_at; sleep parks on a
deadline — with ONE fiber the plane's wait IS the blocking call,
program mode is the degenerate case, not a special one
- scheduler: NEXT_RUNNABLE waits on the plane when the queue empties;
a stop interrupting the wait reaps EVERY fiber (queued and parked)
and returns the clean-stop status; parked fibers are GC roots and
fib_reap_all drains them
- proof: full battery green on the uring path (oop-e2e 92/0,
log-watcher 7/0 incl. the mcp accept/read/write loop, employee 8/0,
web-app 21/0, deps 8/0), WO_IO=epoll battery green (log-watcher 7/0,
web-app 21/0), WO_IO=uring forced green, LW_SOAK=8 10/0 (fd + RSS
flatness holds over parked I/O)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- language: `spawn Cls { fields }` expression (ctor semantics — fields
MOVE; result is the address); `actor M` parametric field type
(contextual like multi/map — actor stays a legal identifier); `send`
is a builtin free-fn name, not a keyword (shadowing rule applies)
- typing: M inferred from Cls's receive(msg: M); WO-E221 when receive
is missing, mis-armed, or M is not a class/record/union; send checks
addr is `actor M` and the message IS an M (silent when underivable);
ctor half of spawn delegates to the Ctor arm (completeness, ?T, E207)
- ownership: send's message TRANSFERS (sender's later use = WO-E301,
corpus-pinned); spawn's fields move via the ctor machinery; an
address is Copy
- emit: spawn lowers to ctor + LOADK receive's method index + BUILTIN
68; send is BUILTIN 69 with the message excluded from fresh-arg drops
(the runtime owns it now)
- runtime: wo_actor (moved-in instance, receive idx, growable FIFO
mailbox, one delivery fiber at a time); delivery reuses the fiber
context across messages and re-queues per message (fairness — an
actor never monopolizes); the runtime drops each message after its
receive returns; actor state/queued/in-flight messages are GC roots;
teardown drops everything (main-return reap included); loader knows
the two arities
- corpus: run/actor-echo (typed spawn/send, one-at-a-time delivery
interleaved with main by budget — output exact, ASan-clean),
compile-fail/spawn-no-receive (WO-E221), send-after-move (WO-E301)
- battery green: oop-e2e 92/0, woc-test, wovm-test, log-watcher 7/0,
employee 8/0, web-app 21/0, deps-accept 8/0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- fiber states (RUNNABLE/PARKED/DONE), intrusive FIFO run queue,
wo_vm_spawn_fiber (calloc'd context, frame 0 set up like wo_vm_call)
- reduction budget: WO_REDUCTIONS (default 4000), checked at loop
BACK-EDGES AFTER the jump lands so the saved pc is the loop head —
a pre-instruction save at budget 1 re-executes the jump into the
same decrement and livelocks (found by reasoning, pinned by the
budget-1 test; deviation from the spec's three-site wording,
recorded in the yield macro's comment)
- FIBER_DONE: main returning ends the program and reaps every
remaining fiber through vm_unwind (drop maps run); a spawned fiber
ending frees silently; its return value is discarded by contract
- TRAPF: an uncaught trap in a spawned fiber kills that fiber ALONE
(stderr report, program lives); in main it stays the program's death
- WO_SYS_STOPPED reaps all fibers wherever it lands (main unlinked
from the queue and unwound if a spawned fiber caught the stop)
- vm_gc_roots walks the live fiber plus every queued one
- test_fiber (45 checks, ASan): EXACT round-robin interleave at budget
1 across three fibers pushing tags into one shared multi;
main-return reaps a spinning fiber holding an owned Big (ASan proves
the free); a DIV0 fiber dies alone, main answers 0
- full battery green: wovm-test, oop-e2e 89/0, woc-test, log-watcher
7/0, employee 8/0, web-app 21/0, deps-accept 8/0 (scheduler dormant
= one branch per back-edge)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- wo_fiber = the interpreter state wo_vm held inline: register window,
frame stack, catch stack, caught-error slot; wo_vm keeps module,
runtime, the embedded fiber 0 (main) and the cur pointer every
interpreter access now reads through
- vm_gc_roots split into a per-fiber walker + the all-fibers caller
(one fiber today; the loop is where stage 1 T2 adds the rest)
- PURE refactor, no functional change to hide behind: full battery
byte-identical — wovm-test (test, test-iso, cli_smoke) green,
oop-e2e 89/0, woc-test green, log-watcher 7/0, employee 8/0,
web-app 21/0, deps-accept 8/0
- plan: docs/superpowers/plans/2026-08-20-shard-fiber-arc.md task 1
(plan/spec docs live on branch language-surface-strictness)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- done/ (11): 1, 2, 3, 4, 6, 7, 7b, 9, 9b, 15, 16 — landed iterations
(9/9b remainders live in the post-12 drain list, not in the files)
- refine/ (8): 9c, 9d, 9e, 9f, 9g, 11, 13, 14 — everything marked
"no spec yet / brainstorm before planning"
- root keeps: 00-story (index), 05 (partial, plan 8 open), 8/10/12
(specs or plans exist), 17 (parked, spec+plan approved), 18 (next)
- every cross-reference re-pathed and VERIFIED resolving: board, specs,
plans, employee-list README, story table, intra-story links (moved
files' relative links deepened one level; done/7b's 9e pointer now
crosses to refine/)
- pre-existing dead link noted, not touched: refine/11-fibers.md points
at docs/plan/exploration/fibers/00-fibers.md which does not exist
(predates the move)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 00-story.md iterations table rows reordered into implementation order
with a Seq column; # stays an immutable ID (files never renumber —
every board/spec/plan references by number)
- order: 1-7b, 9, 9b, 15, 16 (landed, landing order) -> 18 NEXT (spec
approved) -> 9c -> 9d -> 9e -> 8 -> 9f -> 11 -> 10 -> 12 -> 9g -> 14
-> 13; 17 parked row at the end, slots anywhere after 16 on directive
- story note + board implementation-order list synced (18 inserted as
item 2 after the parked-17 note; 9g now explicitly before 14; list
renumbered)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- re-analyzed every story/spec/plan markdown for dependency statements
- added: iteration 17's OUTGOING edge (framework internal/ reorg + check
mode, WO-E108/E109 reserved); 1-6 foundation anchor; 9b -> 10 ("service
blocks want query results"); 14's gap fan-out node; post-12 parked
drain cluster with dashed scope-directive edges (13 + drain are
directive-held, not technically blocked)
- new graph 2: the concurrency chain — 8/9f/11 and EVERYTHING they gate:
keep-alive parking retirement, h2c, body/response streaming + commit
point, cancellation, pub/sub+WS, 9c's rejected async-statement
alternative, schedulable idle timeouts, fiber jobs (+18),
cancellation->rollback (+18+cancel)
- graph 3 notes 9d's keypair crypto is its own C impl, neither waits for
nor feeds the crypto-fork gate; storage-integration rows point at
their real owners (future migrations story, 9-series query surface)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- docs/00-dependency-graph.md: three mermaid graphs — story iterations
(hard edges only; 18 is the only spec-approved node with all
prerequisites green), framework v1 ledger items (three recurring
gates: net seams, crypto fork, iterations 8/11; nine slices startable
today in any order), framework v2 internals (cache/flags independent,
transaction{} is the critical path, jobs compose on it)
- maintenance rule: node classes update in the same change as board rows
- board links the graph up top; spec 18 banner -> APPROVED, plan next
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- framework README core checklist expanded into the v1 STATUS LEDGER:
seven categories (transport, routing, request/response, context &
middleware, storage integration, security, crypto), every item
marked done / partial-with-named-gap / candidate / parked-behind-8-11
/ needs-runtime-seam
- verified before labeling: BODY_MAX caps headers AND body (size limits
done); net has no timeout or unix-socket or peer-address surface
(runtime seams); language has NO bitwise operators, so SHA/HMAC/CRC32
must be C runtime builtins or bit ops land first (fork to brainstorm);
radix routing waits for 9e to measure the linear scan first
- crypto hard stop recorded: HS256 unlocks and nothing past it
- memory-rich features relabeled FRAMEWORK V2 = iteration 18 (story +
spec banners + board rows); v1 gaps land as slices per the ledger
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Part A transaction: one wal_commit at block end over the existing
staged batch; reads see own writes (RAM stays authoritative); trap
unwinding out = abort (undo list: insert->remove, update/delete->
pre-image, captured before RAM apply, txn-only cost); try inside
keeps the block alive; WO-E110 lexical nesting, WO_T_DB dynamic;
no new opcodes, no .wob bump (internal builtins + catch-frame-shaped
abort marker); E108/E109 stay reserved for parked 17
- Part B: cache.wo (ttl_ms/cap, lazy time.now-ms expiry, FIFO over LRU
with the tradeoff stated, Text values via json); flags.wo (@table
wf_flags, on as Int 0/1 - Bool columns unproven, read-through map,
set updates table+map); jobs.wo (@table wf_jobs, enqueue composes
with transaction, JobRunner interface, App.jobs(take r, budget),
Dispatcher.idle() called post-accept PRE-PARSE - deterministic for
the SIGKILL durability proof, unlike after-response)
- web-app demo: transactional order+confirm enqueue, GET /jobs count,
POST /flags/:name with a flag-gated header on the product list
- gate: SIGKILL-after-201/restart/drain proof + flags persistence;
corpus carries transaction-commit/abort + WO-E110 + cache-ttl
(stamps injected, no sleeps)
- board row 18 -> spec written, awaiting review
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- http/multipart.wo: RFC 7578 whole-body parsing within BODY_MAX —
boundary from the raw content-type (quoted or bare, key
case-insensitive), parts split on --boundary, each part = headers,
blank line, content; filename + per-part content-type kept (lowercased)
- strict malformed-is-nil: no closing --boundary-- marker, a part
without content-disposition, missing blank line, no boundary param,
wrong media type — all nil, the caller's 400
- part_named(parts, name): first matching field's content, caller-owned
- web-app CreateProduct now accepts multipart/form/JSON (curl -F shape)
into the shared insert path
- probe 13/13 + 3x reuse loop (fields, crlf-in-content, quoted boundary,
file part, zero-part close, five malformed shapes) release + ASan
- gate grows 19 -> 21: multipart create 201, missing closing marker 400
- README: multipart row ✅ (all three body hooks done), limits updated;
story 16 + board record the landing
- gates: web-app 21/0, oop-e2e 89/0, deps-accept 8/0, log-watcher 7/0,
employee 8/0, woc-test green
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- emit_return's place test matched only bare Ident/Field/Index, so
`return "${p.content}"` (p a loop borrow) returned the part's own
string; the caller's eventual drop freed it under the container —
arena corruption surfacing two requests later (multipart slice)
- the return test now sees through Interp exactly as copy_place_text
does (is_borrowed_value_t, container reads excluded); bare
Ident/Field/Index behavior at return unchanged
- interp-borrowed-field fixture grows the return flavor (fn first),
50 iterations exact
- gates: oop-e2e 89/0 (ASan stage), woc-test green
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>