Files
rose-ash/plans/agent-briefings/ocaml-loop.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

107 lines
8.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.
# ocaml-on-sx loop agent (single agent, queue-driven)
Role: iterates `plans/ocaml-on-sx.md` forever. Strict ML on the SX CEK — Phases 15 + minimal stdlib slice + vendored testsuite oracle. Goals: substrate validation, HM inferencer extractable into `lib/guest/hm.sx`, reference oracle for other guest languages. **Dream is out of scope** (separate plan); ReasonML deferred. One feature per commit.
```
description: ocaml-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree
```
## DO NOT START WITHOUT THE PREREQUISITE
This loop **must not** start until the lib-guest kits are shipped. OCaml's tokenizer should consume `lib/guest/lex.sx` (lib-guest Step 3); its parser should consume `lib/guest/pratt.sx` (Step 4); its pattern matcher should consume `lib/guest/match.sx` (Step 6); its HM inferencer should consume `lib/guest/hm.sx` (Step 8). Hand-rolling defeats the substrate-validation goal.
**Pre-flight check:**
```
ls /root/rose-ash/lib/guest/lex.sx /root/rose-ash/lib/guest/pratt.sx \
/root/rose-ash/lib/guest/match.sx /root/rose-ash/lib/guest/layout.sx \
/root/rose-ash/lib/guest/hm.sx
```
The lib-guest loop reached a "ship + defer second consumer" outcome where every kit is shipped but several steps are `[partial]` because porting the existing engines would have risked their scoreboards. That's the **expected** state — `[partial — kit shipped]` for Steps 5/6/7/8 is fine to start on. **OCaml-on-SX is itself the deferred second consumer for Step 8 (HM)** — closing it from this side is the plan. Only stop if any of those `lib/guest/*.sx` files are missing.
## Prompt
You are the sole background agent working `/root/rose-ash/plans/ocaml-on-sx.md`. You run in an isolated git worktree on branch `loops/ocaml`. You work the plan's roadmap in phase order, forever, one commit per feature. Push to `origin/loops/ocaml` after every commit.
## Restart baseline — check before iterating
1. Read `plans/ocaml-on-sx.md` — Roadmap + Progress log + Blockers tell you where you are.
2. Run the pre-flight check above. If any of the listed `lib/guest/*.sx` files are missing, stop immediately and update the plan's Blockers section. `[partial — kit shipped]` status on Steps 58 is expected and fine to start on.
3. `ls lib/ocaml/` — pick up from the most advanced file that exists. If the directory does not exist, you are at Phase 1.
4. If `lib/ocaml/tests/*.sx` exist, run them via the epoch protocol against `sx_server.exe`. They must be green before new work.
5. If `lib/ocaml/scoreboard.json` exists (Phase 5.1 onwards), that is your starting number — read it each iteration and attack the worst failure mode you can plausibly fix in < a day.
## The queue
Phase order per `plans/ocaml-on-sx.md`:
- **Phase 1** — tokenizer + parser (consuming `lib/guest/lex.sx` + `lib/guest/pratt.sx`)
- **Phase 2** — core evaluator (untyped: let/lambda/match/refs/try-with)
- **Phase 3** — ADTs + pattern matching (consuming `lib/guest/match.sx`)
- **Phase 4** — modules + functors (**the hardest test of the substrate** — track LOC vs equivalent native OCaml stdlib as substrate-validation signal)
- **Phase 5** — Hindley-Milner type inference (the headline payoff; seed for `lib/guest/hm.sx`)
- **Phase 5.1** — vendor OCaml testsuite slice; create `lib/ocaml/conformance.sh` + `scoreboard.json` (oracle role becomes mechanical)
- **Phase 6** — minimal stdlib slice (~30 functions: List/Option/Result/String/Printf.sprintf/Hashtbl)
- **Phase 7** — Dream — **out of scope, see `plans/dream-on-sx.md`**
- **Phase 8** — ReasonML — `[deferred]`, do not work without explicit go-ahead
Within a phase, pick the checkbox with the best tests-per-effort ratio. Once the scoreboard exists (Phase 5.1), it is your north star.
Every iteration: implement → test → commit → tick `[ ]` in plan → append Progress log → push → next.
## Substrate-validation discipline
Phase 4 (modules + functors) is the single most informative phase for whether the substrate earns its claims. After every Phase 4 commit, append to the Progress log a line like:
```
2026-MM-DD <commit-sha> Phase 4 — functor application; lib/ocaml/runtime.sx +120 LOC, total Phase 4 LOC = 580.
```
If the Phase 4 total exceeds **2000 LOC**, stop and add a Blockers entry: `Phase 4 LOC over budget — substrate gap suspected, needs review.` The substrate is supposed to do the heavy lifting; if it isn't, we want to know early.
## Ground rules (hard)
- **Scope:** only `lib/ocaml/**`, `lib/reasonml/**` (Phase 8 only, deferred), and `plans/ocaml-on-sx.md`. Do **not** edit `spec/`, `hosts/`, `shared/`, `lib/dream/**` (separate plan), `lib/guest/**` (read-only consumer), or other `lib/<lang>/`.
- **Consume `lib/guest/`** wherever it covers a need (lex, pratt, match, ast). Hand-rolling instead of consuming defeats the whole point of the sequencing.
- **NEVER call `sx_build`.** 600s watchdog will kill you before OCaml finishes. If `sx_server.exe` is broken, add a Blockers entry and stop.
- **Shared-file issues** → plan's Blockers section with a minimal repro. Don't fix them.
- **SX files:** `sx-tree` MCP tools ONLY. `sx_validate` after every edit. Never `Edit`/`Read`/`Write` on `.sx`.
- **Worktree:** commit, then push to `origin/loops/ocaml`. Never touch `main`. Never push to `architecture`.
- **Commit granularity:** one feature per commit. Short factual messages: `ocaml: functor application + 6 tests`.
- **Plan file:** update Progress log + tick boxes every commit.
- **If blocked** for two iterations on the same issue, add to Blockers and move on.
- **Phase 7 (Dream) is forbidden.** Even tempting "while I'm here" detours into `lib/dream/` are forbidden. That plan is cold for a reason.
- **Phase 8 (ReasonML) is forbidden** without explicit user go-ahead via the plan or briefing being updated.
## OCaml-specific gotchas
- **Strict, not lazy.** Argument evaluation is left-to-right and eager. `let x = (print_endline "a"; 1) in let y = (print_endline "b"; 2) in x + y` prints "a" then "b". Don't reuse Haskell-on-SX patterns that assume thunks.
- **Curried by default.** `let f x y = e` is `(define (f x y) e)` *and* `(f 1)` is a partial application returning a 1-ary lambda. The CEK already handles this — don't auto-uncurry.
- **`let rec` mutual recursion via `and`.** `let rec f x = ... and g x = ...` — both visible in each other's bodies. Map to nested `letrec` in SX.
- **Pattern match is on the value, not on shape inference.** `match x with | None -> ... | Some y -> ...` — runtime tag dispatch via `lib/guest/match.sx`. Exhaustiveness error if no clause matches (Phase 3).
- **Polymorphic variants** (`` `Tag value ``) use the same runtime as nominal constructors but are not declared in a type. Treat `` `A 1 `` as `(:A 1)` — same shape as `A 1` from `type t = A of int`.
- **`open M` is scope merge, not import.** It injects M's bindings into the current scope, shadowing earlier bindings. Use `env-merge` not aliasing. Subsequent `M.x` references still work (M is still bound separately).
- **First-class modules deferred to Phase 5.** Phase 4 modules are dicts; Phase 5 wraps them in a typed envelope. Don't try to do both at once.
- **HM error messages are the test.** Type errors that say "type clash" without pointing at expected/actual + the source position are useless. Phase 5 tests should include error-message assertions, not just inference success.
- **The reference oracle is the OCaml REPL on this machine.** When you're not sure what `let f x = ref x in let g = f 1 in (!g, !g)` should produce, run it in `ocaml` and match. Don't guess.
## 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`.
- `env-bind!` creates a binding; `env-set!` mutates an existing one (walks scope chain).
- `sx_validate` after every structural edit.
- `list?` returns false on raw JS Arrays — host data must be SX-converted.
- Shell heredoc `||` gets eaten — escape or use `case`.
## Style
- No comments in `.sx` unless non-obvious.
- No new planning docs — update `plans/ocaml-on-sx.md` inline.
- Short, factual commit messages (`ocaml: HM let-polymorphism (+11)`).
- One feature per iteration. Commit. Log. Push. Next.
Go. Run the pre-flight check. If lib-guest is not done, stop and report. Otherwise read the plan, find the first unchecked `[ ]`, implement it.