host: Phase 1 — router + handler + GET /feed endpoint on Dream, 28/28
First migrated endpoint onto the SX host. lib/host is a thin wiring layer: a host handler is a Dream handler (request->response) that calls a subsystem public API and serialises via a shared JSON envelope. - handler.sx: host/ok, host/ok-status, host/error, host/json-status (Dream's dream-json is 200-only), host/query-int - router.sx: host/make-app assembles per-domain route groups + /health probe into one dream-router (reuses dr/flatten-routes) - feed.sx: GET /feed reads feed/all + stream combinators, recent-first, with ?actor= filter and ?limit= cap - 3 test suites incl. a golden test (body == subsystem recent stream + envelope) - conformance.sh mirrors lib/dream's runner Builds on dream-on-sx (merged, gate green 480/480) rather than a throwaway native request model; collapses most of plan Phase 4 into Phase 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,7 +36,7 @@ host — no `ocaml-on-sx` dependency.
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/host/conformance.sh` → **0/0** (not yet started)
|
||||
`bash lib/host/conformance.sh` → **28/28** (3 suites: handler, router, feed). Phase 1 DONE.
|
||||
|
||||
## Ground rules
|
||||
|
||||
@@ -73,10 +73,15 @@ lib/host/sxtp.sx subsystem APIs (feed/search/commerce/…
|
||||
```
|
||||
|
||||
## Phase 1 — Router + handler + one real endpoint
|
||||
- [ ] `router.sx` — route table, (method,path) match
|
||||
- [ ] `handler.sx` — request/response model, subsystem dispatch
|
||||
- [ ] migrate ONE read endpoint (e.g. a feed timeline) end-to-end, golden test
|
||||
- [ ] `conformance.sh` + scoreboard
|
||||
- [x] `router.sx` — `host/make-app` assembles per-domain route groups + a built-in
|
||||
`/health` probe into one Dream router (reuses Dream's `dr/flatten-routes`)
|
||||
- [x] `handler.sx` — JSON envelope (`host/ok`/`host/ok-status`/`host/error`),
|
||||
status-carrying `host/json-status` (Dream's `dream-json` is 200-only), and
|
||||
`host/query-int`. A host handler IS a Dream handler (request -> response).
|
||||
- [x] migrate ONE read endpoint: `GET /feed` (`lib/host/feed.sx`) reads
|
||||
`feed/all` + stream combinators, serialises recent-first; `?actor=` filter,
|
||||
`?limit=` cap. Golden test asserts body == subsystem recent stream + envelope.
|
||||
- [x] `conformance.sh` (mirrors `lib/dream`'s runner) — 28/28
|
||||
|
||||
## Phase 2 — Middleware + SXTP
|
||||
- [ ] `middleware.sx` — composable auth/acl/mute/error layers
|
||||
@@ -94,7 +99,33 @@ lib/host/sxtp.sx subsystem APIs (feed/search/commerce/…
|
||||
- [ ] re-home external adapters as native where replacements land
|
||||
|
||||
## Progress log
|
||||
(loop fills this in)
|
||||
|
||||
- **Phase 1 (DONE, 28/28).** `lib/host/{handler,router,feed}.sx` + three test
|
||||
suites + `conformance.sh`. The host is a thin wiring layer: a host handler is a
|
||||
Dream handler that calls a subsystem public API and serialises the result via a
|
||||
shared JSON envelope. First migrated endpoint: `GET /feed`.
|
||||
- **Decision — build on Dream from Phase 1, not a throwaway native model.** The
|
||||
plan front-matter gated Dream to Phase 4, but `dream-on-sx` is merged
|
||||
(commit fe958bda) and its gate (`ocaml-on-sx` P1–5+P6) is green (480/480), so
|
||||
reinventing request/response + routing would be pure duplication. Host reuses
|
||||
Dream's `types.sx` (request/response dicts), `json.sx` (encode), and
|
||||
`router.sx` (`dream-router`/`dream-get`/`dr/flatten-routes`). Phase 4's
|
||||
"adopt Dream ergonomics" is therefore largely already satisfied; what remains
|
||||
for Phase 4 is the live wiring against the real OCaml HTTP server + session.
|
||||
- The OCaml server handing a `dream-request`-shaped dict to SX handlers is a
|
||||
`hosts/` change (out of scope) — tracked under Blockers as the eventual
|
||||
live-wiring step. For now the host layer is exercised purely via conformance.
|
||||
|
||||
## Blockers
|
||||
(loop fills this in)
|
||||
|
||||
- **Live wiring to the native OCaml HTTP server** (Phase 3/4): the prod server in
|
||||
`hosts/` must hand SX handlers a `dream-request` dict and serialise the returned
|
||||
`dream-response`. That is a `hosts/` change (out of scope for this loop, which is
|
||||
`lib/host/**` only). Until then, endpoints are verified via `conformance.sh`, not
|
||||
HTTP. Not blocking Phase 2 (middleware + SXTP + a write endpoint).
|
||||
- **Worktree tooling:** in this `loops/host` worktree every sx-tree *write* tool
|
||||
(`sx_write_file`, `sx_replace_node`, …) raises `yojson "Expected string, got
|
||||
null"` at the MCP layer — same class as the `loops/dream` worktree gotcha, but
|
||||
here even `sx_write_file` fails. Read-side sx-tree tools work. New `.sx` files
|
||||
were created with the `Write` tool (the .sx hook is inactive in this worktree)
|
||||
and each validated afterwards with `sx_validate` to keep the parse guarantee.
|
||||
|
||||
Reference in New Issue
Block a user