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

126 lines
6.3 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.
# 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 files** — `dream-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 `let`s 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.