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>
6.8 KiB
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)
- 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. Noocaml-on-sxdependency for this layer. - Next (Phase 4, gated):
dream-on-sxas the framework layer over the same handlers — typed routing, middleware, sessions, CSRF. Gated onocaml-on-sxPhases 1–5 + Phase 6 minimal stdlib (currently 480/480 and advancing — verify its scoreboard before starting Phase 4). Do not block Phases 1–3 on Dream. - 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
- Read
plans/host-on-sx.md— Roadmap + Progress log + Blockers + the migration ledger. ls lib/host/— pick up from the most advanced file. No dir → Phase 1.- If
lib/host/tests/*.sxexist, run them via the epoch protocol againstsx_server.exe(SX_SERVER=/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe). Green before new work. - 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 (
likesorrelations) as proof - Phase 4 (gated) — Dream framework layer once
ocaml-on-sx1–5 + stdlib is green: adoptdream-on-sxrouting/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 -> responsecalling subsystem public APIs; middleware is composed handlers. Don't reach into subsystem internals — wire to their APIs.
Ground rules (hard)
- Scope: only
lib/host/**andplans/host-on-sx.md. May import every subsystem's public API + the kernel's server/SXTP surface. Do not editspec/,hosts/,shared/, or any subsystem internals. Host-primitive / native server changes belong inhosts/(out of scope) → Blockers entry. - NEVER call
sx_build(600s watchdog). Brokensx_server.exe→ Blockers, stop. - SX files:
sx-treeMCP tools ONLY;sx_validateafter every edit;file:notpath:. NeverEdit/Read/Writeon.sx. - Worktree: commit, then push
origin/loops/host. Nevermain/architecture. (Note:mainpush = 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 viadefhandler/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.
identityanswers "who is this" (sessions/OAuth);aclanswers "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-sxscoreboard (Phases 1–5 + minimal stdlib) before touching it; the native server is sufficient for 1–3.
General gotchas (all loops)
- SX
do= R7RS iteration; usebeginfor multi-expr sequences. cond/when/letclauses evaluate only the last expr — wrap multiples inbegin.letis parallel — nestlets 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 usecase.
Style
- No comments in
.sxunless 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.