writeonce/docs/stories/language-runtime-database/31-actor-lifecycle.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

112 lines
4.9 KiB
Markdown

---
iteration: "31"
status: refine
chain: 3
---
# Iteration 31 — actor lifecycle: request/response, backpressure, death, timers
> Format: `product/story-iteration-template`. Part of
> [Story — one language, one runtime, one database, one binary](00-story.md).
>
> **Inserted 2026-08-21** (concurrency-chain re-sequence; the iteration
> was named as "new 31" in the 2026-08-20 code-review re-sequence — this
> is its story file). Third in the chain,
> **stage 3 → 22 → 31 → 24 → 23 → 32**: chat
> ([iteration 24](24-chat-websocket-workload.md)) cannot be written
> honestly without these four mechanisms.
## Why this iteration exists
The arc's stages 1+2 shipped `spawn`/`send` mechanism without lifecycle:
`send` is one-way and callers `sleep`-poll to await an answer; the
mailbox FIFO grows without bound (a hot sender can exhaust a shard's
memory); an actor that traps dies silently (nobody learns, nothing
restarts, its mailbox rots); and there is no timer surface beyond a
fiber blocking in `time.sleep`. Every real serving program — chat first —
is made of request/response turns, bounded queues, death notices, and
deadlines. Without this iteration the arc is a demo, not a runtime.
## Goals
- **Request/response over one-way sends.** A caller can send and park
until the reply arrives — one surface, no `sleep`-polling, no second
concurrency vocabulary. Ownership rules unchanged: the request moves,
the reply moves back.
- **Bounded mailboxes with a stated backpressure policy.** A mailbox has
a cap; what happens at the cap (park the sender vs error) is decided by
the spec, one policy, doctrine-pure — no silent unbounded growth
anywhere in the runtime.
- **Actor death is observable.** A trap or normal exit produces a signal
another actor can receive; a fiber-trap already isolates (stage 1) —
this makes the fact of death deliverable, so a supervisor CAN be
written in `.wo`.
- **Timers as messages.** A deadline or interval delivers to a mailbox
like any other send, riding the shard's existing io_uring/epoll
timeout plumbing (arc T4) — no new event loop.
## Acceptance Criteria (draft — the spec refines)
- What to achieve?
- **Given** an actor that answers requests,
- **when** a caller awaits the reply,
- **then** the caller's fiber parks (the shard serves other fibers,
TID-verified), resumes with the moved reply, and never busy-waits.
- What to achieve?
- **Given** a mailbox at its cap,
- **when** another send arrives,
- **then** the stated backpressure policy fires deterministically,
memory stays bounded (RSS flat under a hot-sender soak), and no
message is silently dropped.
- What to achieve?
- **Given** an actor that traps mid-message,
- **when** it dies,
- **then** its drop maps run (ASan zero leaks), a death signal
reaches the observer that asked for one, and a supervisor written
in `.wo` can respawn it.
- What to achieve?
- **Given** a timer armed by an actor,
- **when** it fires,
- **then** the actor receives it as an ordinary message on its own
shard, and cancelling before expiry means it never delivers.
## Out Of Scope
- Supervision TREES / OTP-scale restart policy — a `.wo` library once
death signals exist, not runtime policy.
- Priorities and custom scheduling — the reduction budget stays the only
fairness mechanism.
- Distributed (cross-process) supervision — no network layer exists.
- Changing the ownership-move rule or the unified address surface —
iteration 8's decisions stand.
## Info
Forks the spec must settle:
1. **The request/response surface.** A reply-address baked into the
message shape vs a runtime-level call that parks — and what the
compiler checks (does a request type name its reply type?).
2. **The backpressure policy at the cap.** Park the sender (natural with
fibers, risks deadlock cycles) vs fail the send (explicit, pushes
handling to the program). One policy, stated; not configurable per
mailbox in v1.
3. **The death-signal shape.** Erlang's link (bidirectional, dies
together) vs monitor (one-way notice) — likely monitor-only v1.
4. **The timer surface.** Builtin (`time.after` delivering a message) vs
actor-spawned sleeper fiber — and cancellation semantics.
Sources: the 2026-08-20 code-review findings (the gaps this iteration
answers), the arc plan's stage-2 deviations
([`2026-08-20-shard-fiber-arc.md`](../../superpowers/plans/2026-08-20-shard-fiber-arc.md)
— the unbounded FIFO is deviation 4's mutex inbox), and BEAM precedent
already surveyed in
[`docs/plan/exploration/fibers/00-fibers.md`](../../plan/exploration/fibers/00-fibers.md).
## Proposed Solution
Brainstorm → spec → plan after the arc's stage 3 lands and iteration 22
has its baseline (the mailbox-cap and inbox-ring decisions want 22's
mutex number). The spec is written against iteration 24's needs — chat
names the lifecycle mechanisms it consumes, this iteration names chat as
its first honest consumer.