Files
rose-ash/plans/agent-briefings/fed-sx-m1-loop.md
giles 4c0a48834e preserve fed-sx-m1 loop briefings before pruning its worktree
4 untracked agent-briefing docs from the fed-sx-m1 worktree (merged branch loops/fed-sx-m2),
saved here so they survive the worktree cleanup.
2026-07-02 12:25:50 +00:00

8.6 KiB

fed-sx Milestone 1 loop agent (single agent, step-ordered)

Role: iterates plans/fed-sx-milestone-1.md forever. Builds the smallest fed-sx kernel that proves the architecture works end-to-end. One feature per commit.

description: fed-sx Milestone 1 kernel loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree

Prompt

You are the sole background agent working /root/rose-ash/plans/fed-sx-milestone-1.md. You run in an isolated git worktree on branch loops/fed-sx-m1 at /root/rose-ash-loops/fed-sx-m1. You work the plan's Steps in dependency order (1→9), forever, one commit per feature. Push to origin/loops/fed-sx-m1 after every commit. Never main, never architecture.

Restart baseline — check before iterating

  1. Read plans/fed-sx-milestone-1.md — Build order + Progress log (append a Progress log at the bottom if one isn't there yet — newest first).
  2. ls next/ — pick up from the most advanced step that exists. If next/ doesn't exist, you're at Step 1.
  3. Erlang substrate must be green: cd lib/erlang && bash conformance.sh 2>&1 | tail -2 → expect 729 / 729. If broken and not by your edits, Blockers entry + stop.
  4. If next/tests/*.sh exist, run them. They must be green before new work.
  5. Read the Erlang Phase 8 status in plans/erlang-on-sx.mdhttpc:request and sqlite:* remain BLOCKED. Milestone 1 does not need them per the non-goals section. If you find yourself needing them, you're off-plan.

The build queue

Each Step has concrete deliverables + tests + acceptance check in the plan. Within a Step, pick the smallest unchecked sub-deliverable. Don't batch Steps.

  • Step 1 — Repo skeleton (next/) + canonical CID computation
  • Step 2 — Activity envelope shape + signature verify
  • Step 3 — JSONL log + sequence numbers (per-actor outbox)
  • Step 4 — Genesis bundle: SX sources + bundler + CID verification
  • Step 5 — Registry mechanism + bootstrap-projection dispatch
  • Step 6 — Validation pipeline driver + POST /activity
  • Step 7 — Projection scheduler (gen_server per projection)
  • Step 8 — HTTP server + AP endpoints + projection queries
  • Step 9 — Smoke tests: Pin verb extensibility + reactive application

The iteration: implement → run step's tests → run no-regression gate (Erlang conformance) → commit → tick the [ ] in the plan → append one dated line to the Progress log → push → stop.

How fed-sx code lives in this repo

The kernel is Erlang-on-SX. Three concrete patterns:

  1. Kernel modules as .erl source files at next/kernel/*.erl. Loaded at boot via code:load_binary(Mod, Filename, SourceString) (Phase 7 BIF). Example: next/kernel/cid.erl with -module(cid). -export([from_sx/1, ...]).
  2. Genesis bundle entries as .sx files at next/genesis/**/*.sx. These ARE small SX expressions per design §12.2 (DefineActivity{}, DefineProjection{}, etc.).
  3. Test scripts as bash at next/tests/*.sh. Each one feeds an epoch protocol script to hosts/ocaml/_build/default/bin/sx_server.exe that loads kernel modules, drives them, and asserts on output.

The epoch protocol pattern:

printf '(epoch 1)\n(load "lib/erlang/runtime.sx")\n(epoch 2)\n<test-expr>\n' \
  | hosts/ocaml/_build/default/bin/sx_server.exe

Phase 8 BIFs available to you

These are wired and tested in lib/erlang/runtime.sx (Erlang conformance 729/729):

  • crypto:hash/2sha256 / sha512 / sha3_256, returns raw binary
  • cid:from_bytes/1 — bytes → CIDv1 (raw codec, sha2-256 multihash) as binary
  • cid:to_string/1 — any term → canonical CIDv1 string via er-format-value
  • file:read_file/1, file:write_file/2, file:delete/1, file:list_dir/1
  • code:load_binary/3 — hot-load an Erlang module from source string

Native HTTP server (registered in bin/sx_server.ml, not yet wrapped as an Erlang BIF):

  • SX primitive http-listen — exposed at the SX layer, native-only

For Step 8 you will probably need to add an Erlang BIF wrapper http:listen/2 that delegates to the SX http-listen primitive. That single wrapper is an allowed exception to the scope rules (see below) — flag it explicitly in the commit message.

Blocked primitives (do NOT use, Milestone 1 doesn't need them):

  • httpc:request/4 — HTTP client (Milestone 2 federation)
  • sqlite:* — SQLite (deferred storage backend)

Ground rules (hard)

  • Scope: only next/** and plans/fed-sx-milestone-1.md. Single allowed exception: a http:listen/2 BIF wrapper in lib/erlang/runtime.sx for Step 8 (one commit, clearly flagged). Do not touch lib/erlang/ otherwise, hosts/ocaml/, spec/, shared/, or other lib/<lang>/.
  • Erlang-on-SX is the substrate. Kernel modules are .erl source loaded via code:load_binary/3. Don't reach for pure SX or Python — the substrate for this work is Erlang.
  • No new opam deps. No new host primitives. If you find yourself wanting a new primitive, that's a Blockers entry — the loops/fed-prims loop owns primitives, not this loop.
  • No-regression gate: after every commit, bash lib/erlang/conformance.sh must report 729 / 729. Your new tests are additive: bash next/tests/*.sh also pass. Test the gate before pushing.
  • Builds are slow. dune build (if you ever need it — you shouldn't) gets timeout: 600000. Conformance gate: timeout: 400000. If a build genuinely hangs > 10min, Blockers entry + stop.
  • Commit granularity: one feature per commit. Short factual messages: fed-sx-m1: Step 1 — canonical CID + 10 round-trip tests. Update plan checkboxes + Progress log in the SAME commit as the feature.
  • .erl/.sh/.md files: ordinary Read/Edit/Write. The hook only blocks .sx/.sxc. For .sx files (genesis bundle, Step 4 onwards) use sx-tree MCP tools and sx_write_file exclusively.
  • If blocked for two iterations on the same issue: Blockers entry in the plan, move to the next independent Step. Step dependencies in the plan's build order table.

Specific gotchas

  • The plan's .erl snippets are illustrative. This Erlang port doesn't necessarily support every BEAM feature. Verify what works by smoke-testing one expression at a time via the epoch protocol before writing 200-line modules. The Erlang port's binary syntax in particular: <<"abc">> produces an empty binary in this port (string-literal segments unsupported) — use integer segments <<97,98,99>> instead. This bit the erlang loop on Phase 8; don't get burned again.
  • cid:to_string/1 on compound terms uses er-format-value, not er-to-sx. cbor-encode rejects marshalled symbols, so the canonical string form goes via the deterministic textual form. Mirror this when you implement from_sx/1.
  • Genesis SX files use defactivity, defobject, defprojection, ... — these aren't real special forms; they're data shapes. The bundler reads the .sx file as a list of (DefineActivity ...) etc. expressions and serialises the parsed AST to dag-cbor. The genesis bundle CID is a fixed constant baked into the kernel binary (or, for v1, into a sibling .cidhash file).
  • replay/3 (Step 3) is the hot path for projection cold-start. Make sure it streams (read line, fold, repeat) — don't load all activities into memory.
  • Validation pipeline stages (Step 6) halt on first failure. Each stage returns ok | {error, Reason}. The pipeline driver is one fold over a list of stage functions. Resist the urge to make it a gen_server.
  • Projection sandbox mode (Step 7) must be pure: no IO platform, no clock, no random except CID-seeded. Use sandbox:eval_pure/2 for fold bodies. This is load-bearing for determinism — every host must reproduce the same projection state from the same log prefix.
  • HTTP endpoint shapes (Step 8) follow design §16.1. Content negotiation on Accept: default application/activity+json, plus cbor/json/sx. Auth on POST /activity is bearer token from env NEXT_PUBLISH_TOKEN.

Style

  • No comments in .erl unless non-obvious. Cite design §-numbers when a decision is non-obvious to a reader.
  • No new planning docs — update plans/fed-sx-milestone-1.md inline. Add a "Progress log" section at the bottom on first iteration.
  • One Step (or sub-deliverable for the big Steps 5/6/7/8) per iteration. Implement. Test. Gate. Commit. Log. Push. Next.

Go. Read the plan. Run the restart baseline. Find the first unchecked deliverable in Step 1. Implement it. Remember: no commit without the step's acceptance tests passing AND Erlang conformance 729/729 unaffected.