Files
rose-ash/plans/agent-briefings/dream-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

6.3 KiB
Raw Blame History

dream-on-sx loop agent (single agent, queue-driven)

Role: iterates plans/dream-on-sx.md forever. OCaml's Dream web framework on the SX CEK — the chosen ergonomic HTTP layer for the rose-ash host (Dream, not Quart). Maps onto SX with almost no impedance: handler = request -> response, middleware = handler -> handler, @@ = function composition, request → response promise = (perform (:http-respond …)). One feature per commit.

description: dream-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree

DO NOT START WITHOUT THE PREREQUISITE (the one gate)

Dream is activated (target user confirmed — rose-ash is moving off Quart onto Dream) but gated on the OCaml foundation:

  1. ocaml-on-sx Phases 15 + Phase 6 minimal stdlib green. Dream is written in OCaml-on-SX; it needs the OCaml evaluator + ADTs + the minimal stdlib slice (Bytes, Buffer, more String, etc. — see the plan's "Stdlib additions").

Pre-flight:

cat /root/rose-ash/lib/ocaml/scoreboard.md 2>/dev/null | head -15

Confirm the scoreboard shows Phases 15 + the stdlib slice green. If it does not, stop and record a Blockers entry ("dream gated on ocaml-on-sx Phase N"). Do not start. The native server (host-on-sx Phases 13) carries the host until then.

Prompt

You are the sole background agent working /root/rose-ash/plans/dream-on-sx.md, in an isolated git worktree on branch loops/dream, forever, one commit per feature. Push to origin/loops/dream after every commit. Never touch main or architecture.

Restart baseline — check before iterating

  1. Read plans/dream-on-sx.md — Roadmap + Progress log + Blockers + the semantic mapping table.
  2. Run the pre-flight. If the ocaml gate is not green, stop and update Blockers.
  3. ls lib/dream/ — pick up from the most advanced file. No dir → start at Core types.
  4. If lib/dream/tests/*.sx exist, run them via the epoch protocol against sx_server.exe. Green before new work.

The queue

Roadmap per plans/dream-on-sx.md (five types: request, response, handler, middleware, route — everything else is a function over them):

  • Core types (lib/dream/types.sx) — request/response/route records
  • Router (lib/dream/router.sx) — dream-get/post/…, dream-scope, dream-router dispatch, path params, dream-param
  • Middleware (lib/dream/middleware.sx) — dream-pipeline (left-fold compose), logger, content-type
  • Sessions (lib/dream/session.sx) — cookie-backed, dream-session-field / dream-set-session-field / dream-invalidate-session
  • Flash (lib/dream/flash.sx) — single-request cookie store
  • Forms + CSRF (lib/dream/form.sx) — dream-form (Ok/Err), multipart, signed CSRF tokens, dream-csrf-tag
  • WebSockets (lib/dream/websocket.sx) — upgrade, send/receive/close
  • Static filesdream-static, ETags, ranges
  • dream-run — wire root handler into perform (:http-listen …)
  • Demos (lib/dream/demos/) — hello, counter (sessions), chat (ws), todo (forms+CSRF)
  • Tests (lib/dream/tests/) — routing, middleware compose, session round-trip, CSRF accept/reject, flash read-after-write (60+)

Within a section, pick the box with the best tests-per-effort ratio. Every iteration: implement → test → commit → tick [ ] → Progress log → push → next.

Dream-specific gotchas

  • Don't reinvent the SX HTTP server. Dream wraps the existing perform (:http-listen …) / (:http-respond …); it does not implement its own listener loop. dream-run installs the root handler, no socket code.
  • Middleware is plain composition. m1 @@ m2 @@ handler = (m1 (m2 handler)), left-fold. dream-pipeline folds a list; identity = dream-no-middleware. No framework magic.
  • Handler is request -> response (the promise is the SX effect). Keep handlers pure-ish: they read the request and perform IO; don't thread global state.
  • Path params are extracted at routing time:name segments, ** wildcard; dream-param req "name" reads what the router matched. Don't re-parse the path in the handler.
  • CSRF tokens are stateless + signed, session-scoped — verify on dream-form; return (Err :csrf-token-invalid), never throw.
  • Stdlib gaps are ocaml-on-sx's job, mostly. If Dream needs a stdlib function not present, prefer a Dream-internal helper; only escalate to ocaml-on-sx (Blockers / its loop) for genuinely core additions per the plan's stdlib list. Per the plan, those land in lib/ocaml/runtime.sx — coordinate, don't edit it from here unless the plan's scope explicitly allows it.

Ground rules (hard)

  • Scope: only lib/dream/** and plans/dream-on-sx.md (plus the named stdlib additions in lib/ocaml/runtime.sx if and only if the plan's scope section authorizes them — otherwise Blockers). Do not edit spec/, hosts/, shared/, or other lib/<lang>/.
  • 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/dream. Never main/architecture. (main push = PRODUCTION deploy — never from this loop.)
  • Commits: one feature per commit (dream: router dispatch + path params + 6 tests).
  • Plan file: Progress log + tick boxes every commit.
  • Blocked 2 iterations on one issue → Blockers entry, move on.

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 lets when one binding references an earlier one.
  • env-bind! creates a binding; env-set! mutates an existing one.
  • Namespace-prefix guest helpers (dream-… is the public surface; internal helpers dr/…).
  • 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. Run the pre-flight. If the ocaml-on-sx gate is not green, stop and report. Otherwise read the plan, find the first unchecked [ ], implement it — start with Core types.