Files
rose-ash/plans/dream-on-sx.md
giles 9dd9fb9c37 plans: layered-stack framing + chisel sequence + loop scaffolding
Design + ops scaffolding for the next phase of work, none of it touching
substrate or guest code.

lib-guest.md: rewrites Architectural framing as a 5-layer stack
  (substrate → lib/guest → languages → shared/ → applications),
  recursive dependency-direction rule, scaled two-consumer rule. Adds
  Phase B (long-running stratification) with sub-layer matrix
  (core/typed/relational/effects/layout/lazy/oo), language profiles, and
  the long-running-discipline section. Preserves existing Phase A
  progress log and rules.

ocaml-on-sx.md: scope reduced to substrate validation + HM + reference
  oracle. Phases 1-5 + minimal stdlib slice + vendored testsuite slice.
  Dream carved out into dream-on-sx.md; Phase 8 (ReasonML) deferred.
  Records lib-guest sequencing dependency.

datalog-on-sx.md: adds Phase 4 built-in predicates + body arithmetic,
  Phase 6 magic sets, safety analysis in Phase 3, Non-goals section.

New chisel plans (forward-looking, not yet launchable):
  kernel-on-sx.md       — first-class everything, env-as-value endgame
  idris-on-sx.md        — dependent types, evidence chisel
  probabilistic-on-sx.md — weighted nondeterminism + traces
  maude-on-sx.md        — rewriting as primitive
  linear-on-sx.md       — resource model, artdag-relevant

Loop briefings (4 active, 1 cold):
  minikanren-loop.md, ocaml-loop.md, datalog-loop.md, elm-loop.md, koka-loop.md

Restore scripts mirror the loop pattern:
  restore-{minikanren,ocaml,datalog,jit-perf,lib-guest}.sh
  Each captures worktree state, plan progress, MCP health, tmux status.
  Includes the .mcp.json absolute-path patch instruction (fresh worktrees
  have no _build/, so the relative mcp_tree path fails on first launch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:27:50 +00:00

6.3 KiB
Raw Blame History

Dream-on-SX: OCaml's Dream web framework on the SX CEK

[deferred — depends on ocaml-on-sx + a target user]

Carved out of plans/ocaml-on-sx.md. The OCaml-on-SX plan was scoped down to substrate validation + HM + reference oracle (Phases 15 + minimal stdlib slice). Dream is the practical alternative-stack story — the opposite framing — and only makes sense if a real user wants to write rose-ash apps in OCaml/Dream.

Do not start without:

  1. OCaml-on-SX Phases 15 + Phase 6 minimal stdlib green.
  2. A concrete target user. "OCaml programmers in general" is not a target. "Person X wants to write feature Y on rose-ash in Dream" is.

If those conditions are not met, this plan stays cold.

Why this might be worth doing (when the time comes)

Dream is the cleanest middleware-shaped HTTP framework in any language:

  • handler = request -> response promise
  • middleware = handler -> handler
  • m1 @@ m2 @@ handler — left-fold composition

It maps onto SX with almost no impedance — @@ is function composition, request → response promise is (perform (:http-respond ...)), middleware chain is plain SX function composition. So the integration cost is low if the OCaml-on-SX foundation is in place.

The user-facing story: rose-ash users who'd never touch s-expressions might write Dream/OCaml apps that integrate with the same federation, auth, and storage primitives. Demo: a Dream app serving sx.rose-ash.com — the framework that describes the runtime it runs on.

Dream semantic mappings

Dream construct SX mapping
handler = request -> response promise (fn (req) (perform (:http-respond ...)))
middleware = handler -> handler (fn (next) (fn (req) ...))
Dream.router [routes] (ocaml-dream-router routes) — dispatch on method+path
Dream.get "/path" h route record {:method "GET" :path "/path" :handler h}
Dream.scope "/p" [ms] [rs] prefix mount with middleware chain
Dream.param req "name" path param extracted during routing
m1 @@ m2 @@ handler (m1 (m2 handler)) — left-fold composition
Dream.session_field req "k" (perform (:session-get req "k"))
Dream.set_session_field req "k" v (perform (:session-set req "k" v))
Dream.flash req (perform (:flash-get req))
Dream.form req (perform (:form-parse req)) — returns Ok/Error ADT
Dream.websocket handler (perform (:websocket handler))
Dream.run handler starts SX HTTP server with handler as root

Roadmap

The five types: request, response, handler = request -> response, middleware = handler -> handler, route. Everything else is a function over these.

  • Core types in lib/dream/types.sx: request/response records, route record.
  • Router in lib/dream/router.sx: - dream-get path handler, dream-post path handler, etc. for all HTTP methods. - dream-scope prefix middlewares routes — prefix mount with middleware chain. - dream-router routes — dispatch tree, returns handler; no match → 404. - Path param extraction: :name segments, ** wildcard. - dream-param req name — retrieve matched path param.
  • Middleware in lib/dream/middleware.sx: - dream-pipeline middlewares handler — compose middleware left-to-right. - dream-no-middleware — identity. - Logger: (dream-logger next req) — logs method, path, status, timing. - Content-type sniffer.
  • Sessions in lib/dream/session.sx: - Cookie-backed session middleware. - dream-session-field req key, dream-set-session-field req key val. - dream-invalidate-session req.
  • Flash messages in lib/dream/flash.sx: - dream-flash-middleware — single-request cookie store. - dream-add-flash-message req category msg. - dream-flash-messages req — returns list of (category, msg).
  • Forms + CSRF in lib/dream/form.sx: - dream-form req — returns (Ok fields) or (Err :csrf-token-invalid). - dream-multipart req — streaming multipart form data. - CSRF middleware: stateless signed tokens, session-scoped. - dream-csrf-tag req — returns hidden input fragment for SX templates.
  • WebSockets in lib/dream/websocket.sx: - dream-websocket handler — upgrades request; handler (fn (ws) ...). - dream-send ws msg, dream-receive ws, dream-close ws.
  • Static files: dream-static root-path — serves files, ETags, range requests.
  • dream-run: wires root handler into SX's perform (:http-listen ...).
  • Demos in lib/dream/demos/: - hello.mllib/dream/demos/hello.sx: "Hello, World!" route. - counter.mllib/dream/demos/counter.sx: in-memory counter with sessions. - chat.mllib/dream/demos/chat.sx: multi-room WebSocket chat. - todo.mllib/dream/demos/todo.sx: CRUD list with forms + CSRF.
  • Tests in lib/dream/tests/: routing dispatch, middleware composition, session round-trip, CSRF accept/reject, flash read-after-write — 60+ tests.

Stdlib additions Dream will need

Dream pushes beyond OCaml-on-SX's Phase 6 minimal stdlib slice. When this plan activates, OCaml-on-SX gets a follow-on phase that adds at minimum:

  • Bytes (binary buffers — request bodies, websocket frames)
  • Buffer (mutable string building)
  • Format (full pretty-printer, not just Printf.sprintf)
  • More String (index_opt, contains, starts_with, ends_with, replace_all)
  • Sys (argv, getenv_opt, getcwd)
  • Hashtbl extensions (iter, fold, length, remove)
  • Map.Make / Set.Make functors

Confirm scope before starting; some of these may be addable as Dream-internal helpers rather than full stdlib modules.

Ground rules

  • Scope: only lib/dream/** and plans/dream-on-sx.md. Plus the stdlib additions listed above which land in lib/ocaml/runtime.sx.
  • Hard prerequisite: OCaml-on-SX Phases 15 + Phase 6 minimal stdlib. Verify scoreboard before starting.
  • SX files: sx-tree MCP tools only.
  • Don't reinvent the SX HTTP server. Dream wraps the existing perform (:http-listen ...) — it does not implement its own listener loop.

Progress log

(awaiting activation conditions)

Blockers

(none yet — plan is cold)