Files
rose-ash/plans/agent-briefings/haskell-loop.md
giles 859361d86a
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
plans: haskell-completeness phases 7-16 + updated loop briefing
String=[Char] via pure-SX views, show, error, numeric tower,
Data.Map, Data.Set, records, IORef, exceptions. Briefing updated
to point at new plan; old phases 1-6 plan untouched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 17:40:53 +00:00

7.7 KiB
Raw Blame History

haskell-on-sx loop agent (single agent, queue-driven)

Role: iterates plans/haskell-completeness.md forever. Mini-Haskell 98 with real laziness (SX thunks are first-class). Phases 16 are complete; this loop works Phases 716.

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-loops/haskell/plans/haskell-completeness.md. Isolated worktree, forever, one commit per feature. Push to origin/loops/haskell after every commit.

Restart baseline — check before iterating

  1. Read plans/haskell-completeness.md — roadmap + Progress log.
  2. ls lib/haskell/ — orient on current state.
  3. Run bash lib/haskell/test.sh. All 775 tests must be green before new work.
  4. Check lib/haskell/scoreboard.md — baseline is 156/156 (18 programs).

The queue

Phase order per plans/haskell-completeness.md:

  • Phase 7 — String = [Char] via O(1) string-view dicts. No OCaml changes. Read the "String-view design" section below before touching anything.
  • Phase 8show for arbitrary types; deriving Show generates proper instances; print x = putStrLn (show x).
  • Phase 9error / undefined; partial functions raise; top-level runner catches and a new hk-test-error helper checks error messages.
  • Phase 10 — Numeric tower: fromIntegral, Float/Double literals, sqrt/floor/ceiling/round/truncate, Fractional/Floating stubs.
  • Phase 11Data.Map — weight-balanced BST in pure SX in map.sx.
  • Phase 12Data.Set — BST in pure SX in set.sx.
  • Phase 13where in typeclass instances + default methods.
  • Phase 14 — Record syntax: data Foo = Foo { bar :: Int }, accessors, update r { field = v }, record patterns.
  • Phase 15IORef — mutable cells via existing perform/resume IO.
  • Phase 16 — Exception handling: catch, try, throwIO, evaluate.

Within a phase, pick the checkbox with the best tests-per-effort ratio.

Every iteration: implement → test → commit → tick [ ] → Progress log → push.

String-view design (Phase 7 — read before touching strings)

A string view is a pure-SX dict {:hk-str buf :hk-off n}. Native SX strings also satisfy hk-str? (offset = 0 implicitly). No OCaml changes needed.

  • hk-str? covers both native strings and view dicts.
  • hk-str-head v returns the character at offset n as an integer (ord value). Char = integer throughout.
  • hk-str-tail v returns a new view dict with offset n+1; O(1).
  • hk-str-null? v is true when offset ≥ string length.
  • In match.sx, the ":" cons-pattern branch checks hk-str? on the scrutinee before the normal tagged-list path. On a string: head = char-int, tail = shifted view (or (list "[]") if exhausted).
  • chr n converts an integer back to a single-character SX string for display and for ++.
  • ++ between two strings concatenates natively via str; no cons-spine built.
  • The natural hazard: any code that checks (list? v) or (= (first v) ":") on a value must be audited — string views are dicts, not lists. Check hk-str? first in every dispatch chain.

Conformance test programs

For each phase's conformance programs:

  1. WebFetch the source from one of:
  2. Adapt minimally — no GHC extensions, no external packages beyond Data.Map/Data.Set/Data.IORef (once those phases are done).
  3. Cite the source as a comment at the top of the .sx test file.
  4. Add the program name (without .sx) to PROGRAMS in lib/haskell/conformance.sh.
  5. Run bash lib/haskell/conformance.sh and verify green before committing.

Target: scoreboard grows from 156 → 300+ as phases complete.

Ground rules (hard)

  • Scope: only lib/haskell/** and plans/haskell-completeness.md. Do not edit spec/, hosts/, shared/, other lib/<lang>/ dirs, lib/stdlib.sx, lib/ root.
  • NEVER call sx_build. 600s watchdog. If sx_server binary broken → Blockers entry in the plan, stop.
  • Shared-file issues → plan's Blockers section with minimal repro.
  • SX thunks (make-thunk, force on use) already in the trampolining evaluator — reuse. String views are SX dicts, not thunks.
  • SX files: sx-tree MCP tools ONLY (sx_read_subtree, sx_find_all, sx_replace_node, sx_insert_child, sx_insert_near, sx_replace_by_pattern, sx_rename_symbol, sx_validate, sx_write_file). sx_validate after every edit. Never Edit/Read/Write on .sx files.
  • Shell, Markdown, JSON: edit with normal tools.
  • Worktree: commit then push to origin/loops/haskell. Never touch main.
  • Commit granularity: one feature per commit.
  • Plan file: update Progress log + tick boxes every commit.
  • Tests: bash lib/haskell/test.sh must stay green. Never regress existing 775 tests. After new programs, run bash lib/haskell/conformance.sh.

Haskell-specific gotchas

  • String views are dicts(list? v) returns false for a string view. Audit every value-dispatch chain in match.sx and eval.sx for this.
  • Char = integer'a' parses to int 97. chr 97 = "a" (1-char string). Do not represent Char as a 1-char SX string internally.
  • deriving Show (Phase 8): nested constructor args need parens if their show string contains a space. Rule: if string-contains (show arg) " " then "(" ++ show arg ++ ")" else show arg.
  • error tag (Phase 9): use (raise (list "hk-error" msg)). The top-level hk-run-io guard must catch this tag; do not let hk-error leak as an uncaught SX exception into the test runner's output.
  • Data.Map module resolution (Phase 11): qualified imports import qualified Data.Map as Map need the eval import handler to resolve the dotted module name to the map.sx namespace dict. Check hk-bind-decls! import arm.
  • Record update field index (Phase 14): r { field = v } needs the field → positional-index mapping at runtime. Store it in hk-constructors when registering :con-rec.
  • IORef mutation (Phase 15): dict-set! is the SX in-place mutator. The IORef dict is heap-allocated and passed by reference — mutation is safe.
  • Every application arg is a thunkf x y(f (thunk x) (thunk y)). Pattern-match forces before matching. Builtins force their args.
  • ADT representation: ("Just" thunk), ("Nothing"), (":" h t), ("[]").
  • Let-polymorphism: generalise at let-binding boundaries only, not lambda.
  • Typeclass dictionaries: class = record; instance = record value; method call = project + apply. Defaults stored under "__default__ClassName_method", used as fallback when the instance dict lacks the key.
  • Out of scope: GHC extensions. No DataKinds, GADTs, TypeFamilies, TemplateHaskell. Haskell 98 only.

General gotchas (all loops)

  • SX do = R7RS iteration. Use begin for multi-expression sequences.
  • cond/when/let clauses evaluate only the last expression.
  • type-of on user fn returns "lambda".
  • Shell heredoc || gets eaten by bash — escape or use case.
  • keys on an SX dict returns keys in implementation-defined order.

Style

  • No comments in .sx unless non-obvious.
  • No new planning docs — update plans/haskell-completeness.md inline.
  • Short, factual commit messages (haskell: string-view O(1) head/tail (+15)).
  • One feature per iteration. Commit. Log. Next.

Go. Read plans/haskell-completeness.md; find the first [ ]; implement.