Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m2s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
116 lines
5.9 KiB
Markdown
116 lines
5.9 KiB
Markdown
# 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/<lang>/`. 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.
|