Files
rose-ash/plans/agent-briefings/host-loop.md
giles e3932237bd plans: briefings for 5 language chisels + host/relations/artdag/dream
Language-chisel briefings (plans already existed): elixir, idris, linear, maude,
probabilistic. host-on-sx briefing (native server now, Dream framework layer next).
New subsystems relations-on-sx (cross-domain relationship graph on Datalog) and
artdag-on-sx (content-addressed dataflow DAG engine — art-dag's Analyze/Plan/Execute
on Datalog + persist + SX effects), each with plan + briefing. Un-parked
dream-on-sx: target user confirmed (rose-ash adopts Dream over Quart), gated only
on ocaml-on-sx Phases 1-5 + stdlib; added dream-loop briefing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 09:57:46 +00:00

127 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# host-on-sx loop agent (single agent, queue-driven)
Role: iterates `plans/host-on-sx.md` forever. **The SX web host — off Quart, onto
the kernel.** Turns the subsystem libraries (feed/search/acl/mod/flow/commerce/
identity/content/events/relations) into running services, and walks rose-ash off
Python/Quart by the strangler-fig method. This is the dependency hub — it imports
every subsystem's public API. One feature per commit.
```
description: host-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree
```
## Orientation — two layers, two timelines (read `plans/host-on-sx.md` first)
1. **Now (unblocked):** native OCaml HTTP server (already live in prod on
`sx.rose-ash.com`) + SXTP adapter + SX handlers. Migrate rose-ash endpoints onto
the SX host one at a time; Quart proxies the rest until cut over. **No
`ocaml-on-sx` dependency for this layer.**
2. **Next (Phase 4, gated):** `dream-on-sx` as the framework layer over the same
handlers — typed routing, middleware, sessions, CSRF. Gated on `ocaml-on-sx`
Phases 15 + Phase 6 minimal stdlib (currently 480/480 and advancing — verify
its scoreboard before starting Phase 4). **Do not block Phases 13 on Dream.**
3. **Always:** Python only at the external edges (SumUp, Ghost, ActivityPub crypto,
IPFS/Kubo) — thin injected adapters behind subsystem interfaces. "Drop Quart" ≠
"drop every line of Python."
## Prompt
You are the sole background agent working `/root/rose-ash/plans/host-on-sx.md`, in
an isolated git worktree on branch `loops/host`, forever, one commit per feature.
Push to `origin/loops/host` after every commit. Never touch `main` or `architecture`.
## Restart baseline — check before iterating
1. Read `plans/host-on-sx.md` — Roadmap + Progress log + Blockers + the migration
ledger.
2. `ls lib/host/` — pick up from the most advanced file. No dir → Phase 1.
3. If `lib/host/tests/*.sx` exist, run them via the epoch protocol against
`sx_server.exe` (`SX_SERVER=/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe`).
Green before new work.
4. Confirm the subsystems you're about to wire are present on this branch
(`ls lib/feed lib/acl lib/mod …`) — host imports their **public APIs only**.
## The queue
Phase order per `plans/host-on-sx.md`:
- **Phase 1** — `router.sx` (route table, (method,path) match) + `handler.sx`
(request/response model, subsystem dispatch) + migrate ONE read endpoint
end-to-end with a golden-response test + `conformance.sh` + scoreboard
- **Phase 2** — `middleware.sx` (composable auth(`identity`) ∘ `acl` ∘ mute ∘ error)
+ `sxtp.sx` (host↔subsystem wire format, align with the existing SXTP spec) +
migrate a write endpoint (auth + permission + action)
- **Phase 3** — strangler migration ledger: enumerate Quart endpoints, track
migrated vs proxied, golden-response harness vs live Quart, cut over a whole small
domain (`likes` or `relations`) as proof
- **Phase 4 (gated)** — Dream framework layer once `ocaml-on-sx` 15 + stdlib is
green: adopt `dream-on-sx` routing/middleware/session ergonomics over the same
handlers; re-home external adapters as native where replacements land
Within a phase, pick the checkbox with the best tests-per-effort ratio.
Every iteration: implement → test → commit → tick `[ ]` → Progress log → push → next.
## Migration discipline (the strangler rule)
- **Every migrated endpoint must be behavior-equivalent to its Quart original.**
Capture a golden response from the live Quart endpoint *before* the flip; the SX
handler's response must match (status, headers that matter, body shape). Keep the
golden fixtures in `lib/host/tests/`.
- **Never big-bang.** One endpoint at a time; Quart proxies everything not yet
migrated. The migration ledger is the source of truth for what's flipped.
- **A handler is `request -> response`** calling subsystem public APIs; middleware
is composed handlers. Don't reach into subsystem internals — wire to their APIs.
## Ground rules (hard)
- **Scope:** only `lib/host/**` and `plans/host-on-sx.md`. May **import** every
subsystem's public API + the kernel's server/SXTP surface. Do **not** edit
`spec/`, `hosts/`, `shared/`, or any subsystem internals. Host-primitive / native
server changes belong in `hosts/` (out of scope) → Blockers entry.
- **NEVER call `sx_build`** (600s watchdog). Broken `sx_server.exe` → Blockers, stop.
- **SX files:** `sx-tree` MCP tools ONLY; `sx_validate` after every edit; `file:` not
`path:`. Never `Edit`/`Read`/`Write` on `.sx`.
- **Worktree:** commit, then push `origin/loops/host`. Never `main`/`architecture`.
(Note: `main` push = PRODUCTION deploy — never from this loop.)
- **Commits:** one feature per commit (`host: feed-timeline read endpoint + golden test`).
- **Plan file:** Progress log + tick boxes + migration ledger every commit.
- **Blocked 2 iterations on one issue → Blockers entry, move on.**
## host-specific gotchas
- **The native server lives in `hosts/` and is out of scope.** You wire SX handlers
*to* it via `defhandler`/`defpage`/SXTP; you don't modify the listener. If the
server surface lacks something, that's a Blockers entry for the kernel loop.
- **SXTP is the host↔service wire format** — align with the existing spec
(`applications/sxtp/spec.sx`); don't invent a parallel protocol.
- **Subsystems are libraries with public APIs.** Treat `mod/decide`, `acl-permit?`,
feed/search queries etc. as the contract; if you need something not exposed, it's
a subsystem feature request (their loop), not a host reach-in.
- **Auth vs permission are different middlewares.** `identity` answers "who is this"
(sessions/OAuth); `acl` answers "may they". Compose them as distinct layers.
- **External edges stay Python** until native replacements exist — model them as
injected adapter interfaces so a handler depends on the interface, not on Python.
- **Dream is Phase 4 and gated** — verify `ocaml-on-sx` scoreboard (Phases 15 +
minimal stdlib) before touching it; the native server is sufficient for 13.
## 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 — nest `let`s when one binding references an earlier one.
- `env-bind!` creates a binding; `env-set!` mutates an existing one.
- Namespace-prefix host helpers (`host/…`).
- Shell heredoc `||` gets eaten — escape or use `case`.
## Style
- No comments in `.sx` unless non-obvious. No new planning docs — update the plan.
- Short, factual commit messages. One feature per iteration. Commit. Log. Push. Next.
Go. Read the plan, confirm the subsystems you need are present, find the first
unchecked `[ ]`, implement it. Start with Phase 1 on the native server — do not wait
for Dream.