writeonce/docs/stories/porch/10-memory-features-over-table.md
shoney.arickathil f3215c2f43 docs(status): master-only follow-ups to the 2026-09-15 cherry-pick
- the agent rename database-developer → codd (and its guide) happened inside
  lang-18's `aab4878` on dev, which stays there; the `docs(agents)` pick
  brought codd.md in beside the old file — remove the old name and its guide
- docs/stories/porch/09-idempotent-replay.md: added on dev by `79e6da4`, whose
  earlier pick onto master (`refactor(porch-store)`) landed without it — the
  board, porch 1 and porch 4 link to it
- docs/stories/porch/10-memory-features-over-table.md: the refine stub
  language 18's docs commit created on dev; the board and porch 00-story link
  to it, the code it waits on is not on master
- docs/examples/skill-catalog/README.md: the story link fix from `b3d8c40` that its
  earlier pick (`8311330`) dropped in conflict resolution — dev's version taken
- `just linkcheck` on master: every remaining broken link is a wmux story or
  spec (track not picked) or a developer-local `.dev/reference` symlink

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 01:24:36 +02:00

2.8 KiB
Raw Blame History

track iteration status readiness
porch 10 pending refine

porch 10 — memory features over @table: TTL cache, feature flags, durable jobs

Part of Story — porch, the writeonce web framework. Stub, created 2026-09-11 by the language-18 re-brainstorm (fork 1): the three .wo pieces of language 18 moved here; 18 keeps the language + engine half, transaction { }. Their spec text is Part B of 2026-08-20-memory-db-features-design.md; its jobs section is superseded (below).

Carried over from 18, already settled — do not re-brainstorm

  1. Cache: pure .wo, TTL + capacity, lazy expiry on read, FIFO eviction over LRU (stated tradeoff), Text values (no generics), a time-injected seam (get_at/put_at) so the fixture injects stamps instead of sleeping.
  2. Flags: @table(name: "wf_flags") with name @unique and an Int 0/1 on; a read-through map filled on first read, updated in the same call as the write. Framework tables carry the wf_ prefix.
  3. Job row: wf_jobs — kind, payload (Text, json), attempts, not_before (wall ms, 0 = due). enqueue is an ordinary insert and is what goes inside the business write's transaction { }.

Re-settled by 18 on 2026-09-11 (fork 2) — the execution model

Drain-on-request and the Dispatcher.idle() seam are retired: they assumed "no timers", which has been false since iteration 24. A job runner is an actor the app spawns; the app sends it a poke after the block's closing brace (a send inside the block is WO-E111 by design — the row must be durable before anyone acts on it); the runner queries due jobs (not_before <= time.now, take budget), deletes on success, bumps attempts on failure, and re-arms itself with time.after for the earliest not_before (one-shot, generation-counter idiom). The table is the durable outbox; the poke is a hint — at boot the app pokes once and every survivor runs without a request. The engine provides nothing new.

To refine here (what makes this ready)

  • Budget per drain and the backoff shape (app-side in v1 per the spec — keep or move into the runner?).
  • Where the runner lives (porch-owned actor class vs app-owned satisfying an interface — the Jr/Mw wrapper pattern).
  • The web-app demo and gate legs (order + confirm job in one block, kill -9 after the POST, restart, the job runs; flags across restart) — these need 18's T1–T6 landed first.
  • Whether porch 1's pool actor is the runner's home (serialize through the same actor that owns store writes) or a second actor.

Needs

Language 18 (transaction { }) for the demo's headline; nothing else beyond what spawn/send/time.after and @table already provide.