From b80cc32363bae40290fbac87b386cfe4539adbd7 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 6 Jun 2026 18:24:52 +0000 Subject: [PATCH] briefings: add persist-on-sx loop briefing Co-Authored-By: Claude Opus 4.8 (1M context) --- plans/agent-briefings/persist-loop.md | 115 ++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 plans/agent-briefings/persist-loop.md diff --git a/plans/agent-briefings/persist-loop.md b/plans/agent-briefings/persist-loop.md new file mode 100644 index 00000000..c33e9556 --- /dev/null +++ b/plans/agent-briefings/persist-loop.md @@ -0,0 +1,115 @@ +# persist-on-sx loop agent (single agent, queue-driven) + +Role: iterates `plans/persist-on-sx.md` forever. **Durable state on the SX kernel** +— the foundation substrate every other subsystem currently fakes with an in-memory +mutable list. Event log (append-only streams) + kv (current-state) over one +injectable backend; pure projections; snapshots; durable IO at the kernel's +`perform` boundary. This is **substrate-level**, not a guest language. + +``` +description: persist-on-sx queue loop +subagent_type: general-purpose +run_in_background: true +isolation: worktree +``` + +## Prompt + +You are the sole background agent working `plans/persist-on-sx.md`. Isolated +worktree `/root/rose-ash-loops/persist` on branch `loops/persist`, forever, one +commit per feature. Push to `origin/loops/persist` after every commit. Never touch +`main` or `architecture`. + +## Restart baseline — check before iterating + +1. Read `plans/persist-on-sx.md` — roadmap + Progress log. Note the scope table: + persist owns the **log** + **kv** facets; blobs are delegated (store the CID, + not the bytes); cache is out of scope. Do not event-source everything. +2. `ls lib/persist/` — pick up from the most advanced file. +3. If `lib/persist/tests/*.sx` exist, run them via `bash lib/persist/conformance.sh`. + Green before new work. +4. If `lib/persist/scoreboard.md` exists, that's your baseline. +5. **Learn the substrate before writing durable code.** persist sits on the kernel's + IO-suspension surface — the third CEK phase: `perform`, `cek-step-loop`, + `cek-resume`, `make-cek-suspended`. Study how IO is requested and resumed, and + how `spec/harness.sx` mocks an IO platform for tests (assert-io-*). Phases 1–3 + need NO real IO — the in-memory backend is pure SX. Real durable IO (Phase 4) + goes through `perform` and is tested against the mock-IO harness, not a real disk. + Verify the actual exported names with sx_find_all / grep before relying on them. + +## The queue + +Phase order per `plans/persist-on-sx.md`: + +- **Phase 1** — log + kv + in-memory backend (event record, injectable backend + protocol, append/read, kv get/put/delete, api). +- **Phase 2** — projections (`fold step seed`) + subscriptions; concurrency + conflict as a real result. +- **Phase 3** — snapshots + replay (checkpoint, replay = snapshot + tail, + determinism). +- **Phase 4** — durable backend via kernel IO (`perform`), blob-ref interface, + crash/restart replay against the mock-IO harness. + +Within a phase, pick the checkbox that unlocks the most tests per effort. + +Every iteration: implement → test → commit → tick `[ ]` → Progress log → next. + +## Ground rules (hard) + +- **Scope:** only `lib/persist/**` and `plans/persist-on-sx.md`. Do **not** edit + `spec/`, `hosts/`, `shared/`, or any `lib//`. You may **import** the + kernel's IO-suspension + platform-IO surface only. **Do NOT add host primitives.** + If a durable IO op you need doesn't exist, it belongs in `hosts/` (out of scope) → + Blockers entry with a minimal repro, and stop on that item. +- **NEVER call `sx_build`.** 600s watchdog. If the sx_server binary is broken → + Blockers entry, stop. Run tests by invoking the sx_server binary directly from a + conformance.sh (model it on an existing one, e.g. `lib/apl/conformance.sh`), + pointing `SX_SERVER` at `/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe` + — fresh worktrees have no `_build/`. +- **Determinism:** replay must be pure — same log → same state. No clocks/randomness + inside projections; timestamps live on the event, passed in. +- **Shared-file issues** → plan's Blockers with minimal repro; don't fix here. +- **SX files:** `sx-tree` MCP tools ONLY. **They take `file:` not `path:`** — a + wrong key yields `Yojson Type_error("Expected string, got null")`, which looks + like a broken binary but is just a param mismatch. `sx_validate` after edits. + Path-based edits (`sx_replace_node`) count comment headers in their indices and + can clobber the wrong node — re-read after, or prefer `sx_write_file` for small + files. +- **Unicode in `.sx`:** raw UTF-8 only, never `\uXXXX` escapes. +- **Commit granularity:** one feature per commit. Short factual messages + (`persist: kv facet get/put/delete + 6 tests`). Push to `origin/loops/persist`. +- **Plan file:** update Progress log (newest first) + tick boxes every commit. + +## persist-specific gotchas + +- **Two facets, not one.** Don't force current-state values (a stock count, a + config value, a session blob) through the event log — that's the kv facet. Event + log is for things whose *history* matters. +- **Backend is injected.** The in-memory backend is the test default; never hardwire + it. Every op goes through the backend protocol so file/pg/ipfs swap in unchanged. +- **Optimistic concurrency is a real result.** A conflicting append returns a + conflict value the caller can retry on — not a crash, not a silent overwrite. +- **Blobs by reference only.** persist stores a content-address/CID + metadata. The + bytes live in a content-addressed store (artdag/IPFS). Never put large payloads in + the log. +- **Replay determinism is the headline property.** Snapshot + tail must equal full + replay. Test it explicitly, both directions. + +## General gotchas (all loops) + +- SX `do` = R7RS iteration. Use `begin` for multi-expr sequences. +- `cond`/`when`/`let` clauses evaluate only the last expr — wrap multiples in `begin`. +- `let` is parallel, not sequential — nest `let`s when a binding references an earlier one. +- `env-bind!` creates a binding; `env-set!` mutates an existing one (walks scope chain). +- `sx_validate` after every structural edit. +- Namespace-prefix all helpers (`persist/...`) — short/host-colliding names get + silently shadowed or hang the runtime. + +## Style + +- No comments in `.sx` unless non-obvious. +- No new planning docs — update `plans/persist-on-sx.md` inline. +- Short, factual commit messages. +- One feature per iteration. Commit. Log. Push. Next. + +Go. Start by reading the plan; find the first unchecked `[ ]`; implement it.