writeonce/docs/active-slice-2026-08-23-chat-ws-lifecycle.md
shoney.arickathil 3bc85d85f3 docs(slice): marker reflects T4/T5 landed, the drain blocker, and the stale-artifact trap
- T4 monitor + T5 time.after landed in 4092074 (ids 89/90); marker still
  listed them pending because it came from master, which lacks that commit
- records the branch baseline (18 suites x 2 flavors, 0 fail) and the gate
  at 11 of 12 legs green
- names the stale-artifact trap: after a branch switch, compiler/_build and
  runtime/build hold the OTHER branch's binaries, and a v7-vs-v6 mismatch
  surfaces only as "no listener"
- the drain guarantee is now the single named blocker; nothing else in the
  slice should land before it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 23:28:25 +02:00

4.6 KiB
Raw Blame History

slice status
24 in-progress

Active slice — chat + actor lifecycle (iteration 24, absorbing 31 + 34)

Branch chat-ws-lifecycle. Spec: superpowers/specs/2026-08-23-chat-websocket-actor-lifecycle-design.md · plan: superpowers/plans/2026-08-23-chat-ws-lifecycle.md · board: stories/00-status.md.

Progress (2026-08-23)

  • ✅ T1 crypto (d14fa9f): sha1/sha256/hmac_sha256, ids 85–87, RFC vectors 18/0, corpus pin. Story 34's C-builtin resolution delivered.

  • ✅ T2 bounded mailboxes (92754a8): cap 1024 + WO_MAILBOX, sender-side atomic reserve, WO_T_ACTOR (trap 13) catchable. Plus a pre-existing compiler fix: try-arm Text places (bare e.msg) now copy before the arm's scope dies (was ASan use-after-free + SEGV).

  • ✅ T6 WS upgrade (79cfa01): ws_accept + accept-key + the 101 hijack sentinel; plain HTTP byte-identical (web-app 26/26).

  • ✅ T7 frame codec (7ad2ced): pure-.wo RFC 6455 parse/serialize, probe-verified against the RFC's own bytes.

  • ✅ T3 call/reply (ed69841): call parks + typed scalar reply (WO-E226 through actor-M erasure); actor DEATH landed with it — callers never hang (mid-call + to-dead both trap catchably). Fixed TRAPF's fiber-death leak/dangle en route.

  • ✅ T4 monitor + T5 time.after (56fe41a, ids 89/90): the lifecycle core. Corpus fixtures monitor-death, timer-delivery, timer-generation.

  • 🔄 T8 chat sample + T9 gate (6d729cc, then bbe0216): the sample and all five gate legs exist and run.

Every landed task: full battery 12/12, fresh-built.

Verified 2026-08-27 (branch merged up to master)

Merged master in (clean; the porch rename means chat now says use porch/... and its [deps] key is porch). Baseline on this branch: 18 runtime suites × both dispatch flavors, 0 fail, cli_smoke: OK.

just chat at CHAT_SOAK=20 — 11 of 12 legs green, including the two the plan required and the gate was missing (WO_SHARDS=1, WO_MAILBOX=8).

Three of the four failures found on 2026-08-27 were stale build artifacts, not code. Switching branches leaves compiler/_build/ and runtime/build/ holding the other branch's binaries: a woc emitting .wob v7 against a runtime expecting v6 reports only wovm: unsupported version 7, which the gate surfaces as "no listener". runtime/build/wovm_asan bit the same way. Rebuild both after any branch switch (just woc-build, make -C runtime wovm-asan) before believing a gate failure.

The remaining failure is a real bug and is NOT fixed — 2026-08-27-chat-drain-finding.md. On a fresh server the SIGTERM drain leaves a client at EOF with no close frame in 5 of 16 runs. Traced: main → Registry → Room → Writer; the Registry runs but the Room never processes its shutdown message, so the Writer's close branch never runs. Ruled out: the spin budget (a 1 s wall-clock deadline still failed 2 of 12), dummy_writer() spawning during shutdown, and write failure. The gate had been hiding it by draining a server the soak had already warmed.

Pending

  • 🔴 The drain guarantee — the one blocker. A send issued before the stop flag must be delivered before the engine stops. main cannot park after the flag (a park unwinds), so it spins, and spinning is not a barrier — the evidence says the Room's shard never adopts its inbox, not that it adopts it late. This is a semantic guarantee belonging to the actor lifecycle (31), not a tuning parameter: it wants a stated rule in the runtime lifecycle docs and a corpus fixture, not a bigger spin count. Nothing else in the slice should land before this, because the drain is half of what "actor lifecycle" means.
  • ⬜ T9 remainder — the 1k soak has only been run trimmed (CHAT_SOAK=20); run it at the default 1000 once the drain is fixed.
  • ⬜ T10 closeout — stories 24/31/34 → status: done with banners (note the scalar-reply v1 narrowing + three-argument monitor deviations), board standup entry, graph nodes, framework README ledger rows, runtime + chat CODE-LOGIC sections, delete this marker. Final battery.

This file is deleted when the slice lands (board convention). It lives flat in docs/ rather than a status folder — since 2026-08-26 no directory in this repo encodes state; status: above is the only place it is recorded.