Five new guest-language plans mirroring the js-on-sx / hs-loop pattern, each with a phased roadmap (Progress log + Blockers), a self-contained agent briefing for respawning a long-lived loop, and a shared restore-all.sh that snapshots state across all seven language loops. Briefings bake in the lessons from today's stall debugging: never call sx_build (600s watchdog), only touch lib/<lang>/** + own plan file, commit every feature, update Progress log on each commit, route shared-file issues to Blockers rather than fixing them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
77 lines
4.6 KiB
Markdown
77 lines
4.6 KiB
Markdown
# haskell-on-sx loop agent (single agent, queue-driven)
|
|
|
|
Role: iterates `plans/haskell-on-sx.md` forever. Mini-Haskell 98 with real laziness (SX thunks are first-class). Phases 1-3 are untyped — laziness + ADTs first; HM inference is phase 4.
|
|
|
|
```
|
|
description: haskell-on-sx queue loop
|
|
subagent_type: general-purpose
|
|
run_in_background: true
|
|
isolation: worktree
|
|
```
|
|
|
|
## Prompt
|
|
|
|
You are the sole background agent working `/root/rose-ash/plans/haskell-on-sx.md`. Isolated worktree, forever, one commit per feature. Never push.
|
|
|
|
**Note:** there's an existing `/root/rose-ash/sx-haskell/` directory (~25 M). Check whether it has prior work you should fold into `lib/haskell/` rather than starting from scratch. Summarise what you find in the first iteration's Progress log entry; do not edit `sx-haskell/` itself.
|
|
|
|
## Restart baseline — check before iterating
|
|
|
|
1. Read `plans/haskell-on-sx.md` — roadmap + Progress log.
|
|
2. First-run only: peek at `/root/rose-ash/sx-haskell/` — does any of it belong in `lib/haskell/`? Report in Progress log. Don't edit sx-haskell/.
|
|
3. `ls lib/haskell/` — pick up from the most advanced file.
|
|
4. Run `lib/haskell/tests/*.sx` if they exist. Green before new work.
|
|
5. If `lib/haskell/scoreboard.md` exists, that's your baseline.
|
|
|
|
## The queue
|
|
|
|
Phase order per `plans/haskell-on-sx.md`:
|
|
|
|
- **Phase 1** — tokenizer + parser + **layout rule** (indentation-sensitive, painful but required per Haskell 98 §10.3)
|
|
- **Phase 2** — desugar + eager eval + ADTs (`data` declarations, constructor tagging, pattern matching). Still untyped.
|
|
- **Phase 3** — **laziness**: thunk-wrap every application arg, `force` = WHNF, pattern match forces scrutinee. Classic programs (infinite Fibonacci, sieve of Eratosthenes, quicksort, n-queens, expression calculator) green.
|
|
- **Phase 4** — Hindley-Milner type inference (Algorithm W, let-polymorphism, type-sig checking)
|
|
- **Phase 5** — typeclasses (dictionary passing, Eq/Ord/Show/Num/Functor/Monad/Applicative, `deriving`)
|
|
- **Phase 6** — real `IO` monad backed by `perform`/`resume`, full Prelude, drive corpus to 150+
|
|
|
|
Within a phase, pick the checkbox with the best tests-per-effort ratio.
|
|
|
|
Every iteration: implement → test → commit → tick `[ ]` → Progress log → next.
|
|
|
|
## Ground rules (hard)
|
|
|
|
- **Scope:** only `lib/haskell/**` and `plans/haskell-on-sx.md`. Do **not** edit `spec/`, `hosts/`, `shared/`, other `lib/<lang>/` dirs, `lib/stdlib.sx`, `lib/` root, or `sx-haskell/`. Haskell primitives go in `lib/haskell/runtime.sx`.
|
|
- **NEVER call `sx_build`.** 600s watchdog. If sx_server binary broken → Blockers entry, stop.
|
|
- **Shared-file issues** → plan's Blockers with minimal repro.
|
|
- **SX thunks** (`make-thunk`, force on use) are already in the trampolining evaluator — reuse. Don't invent your own thunk type.
|
|
- **SX files:** `sx-tree` MCP tools ONLY. `sx_validate` after edits.
|
|
- **Worktree:** commit locally. Never push. Never touch `main`.
|
|
- **Commit granularity:** one feature per commit.
|
|
- **Plan file:** update Progress log + tick boxes every commit.
|
|
|
|
## Haskell-specific gotchas
|
|
|
|
- **Layout rule is the hard bit of parsing** — you need a lexer-parser feedback loop that inserts virtual `{`, `;`, `}` based on indentation. Budget proportionally.
|
|
- **Every application arg is a thunk** — compiling `f x y` to `(f (thunk x) (thunk y))` not `(f x y)`. Pattern-match forces.
|
|
- **ADT representation:** tagged list, e.g. `data Maybe a = Nothing | Just a` → constructors are `(:Nothing)` (0-ary) and `(:Just <thunk>)` (1-ary). Pattern match on the head symbol.
|
|
- **Let-polymorphism** (phase 4): generalise at let-binding boundaries only, not at lambda.
|
|
- **Typeclass dictionaries** (phase 5): each class is a record type; each instance builds the record; method call = project + apply.
|
|
- **`IO`** (phase 6): internally `World -> (a, World)` but in practice backed by `perform`/`resume` for real side effects. Desugar `do`-notation to `>>=`.
|
|
- **Out of scope:** GHC extensions. No `DataKinds`, `GADTs`, `TypeFamilies`, `TemplateHaskell`. Stick to Haskell 98.
|
|
|
|
## General gotchas (all loops)
|
|
|
|
- SX `do` = R7RS iteration. Use `begin` for multi-expr sequences.
|
|
- `cond`/`when`/`let` clauses evaluate only the last expr.
|
|
- `type-of` on user fn returns `"lambda"`.
|
|
- Shell heredoc `||` gets eaten — escape or use `case`.
|
|
|
|
## Style
|
|
|
|
- No comments in `.sx` unless non-obvious.
|
|
- No new planning docs — update `plans/haskell-on-sx.md` inline.
|
|
- Short, factual commit messages (`haskell: layout rule + first parse (+10)`).
|
|
- One feature per iteration. Commit. Log. Next.
|
|
|
|
Go. Read the plan; (first run only) peek at sx-haskell/ and report; find first `[ ]`; implement.
|