Files
rose-ash/plans/agent-briefings/elixir-loop.md
giles e3932237bd plans: briefings for 5 language chisels + host/relations/artdag/dream
Language-chisel briefings (plans already existed): elixir, idris, linear, maude,
probabilistic. host-on-sx briefing (native server now, Dream framework layer next).
New subsystems relations-on-sx (cross-domain relationship graph on Datalog) and
artdag-on-sx (content-addressed dataflow DAG engine — art-dag's Analyze/Plan/Execute
on Datalog + persist + SX effects), each with plan + briefing. Un-parked
dream-on-sx: target user confirmed (rose-ash adopts Dream over Quart), gated only
on ocaml-on-sx Phases 1-5 + stdlib; added dream-loop briefing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 09:57:46 +00:00

5.9 KiB

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

Role: iterates plans/elixir-on-sx.md forever. Elixir on the CEK/VM — the companion to lib/erlang/. Most runtime semantics are Erlang's (BEAM); the chisel is the Elixir-specific surface: the macro system (quote/unquote), |>, with, defmodule/def/defp, protocol dispatch, structs. One feature per commit.

description: elixir-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree

Prerequisites — check before starting

  1. lib-guest lex + pratt present — Elixir's tokenizer/parser consume lib/guest/lex.sx + lib/guest/pratt.sx.
  2. lib/erlang/ present — Phase 2 reuses Erlang's pattern-match engine for =, function heads, and case. Do not re-implement unification; import it.
  3. ADT primitive (define-type + match) in the SX core — needed for structs (Phase 5). Track via plans/sx-improvements.md.

Pre-flight:

ls /root/rose-ash/lib/guest/lex.sx /root/rose-ash/lib/guest/pratt.sx /root/rose-ash/lib/erlang/runtime.sx

If lib-guest or lib/erlang is missing, stop and record a Blockers entry. (The ADT primitive is only needed at Phase 5 — start earlier phases without it.)

Prompt

You are the sole background agent working /root/rose-ash/plans/elixir-on-sx.md, in an isolated git worktree on branch loops/elixir, forever, one commit per feature. Push to origin/loops/elixir after every commit. Never touch main or architecture.

Restart baseline — check before iterating

  1. Read plans/elixir-on-sx.md — Roadmap + Progress log + Blockers tell you where you are.
  2. Run the pre-flight. Record any missing prerequisite in Blockers.
  3. ls lib/elixir/ — pick up from the most advanced file. No dir → Phase 1.
  4. If lib/elixir/tests/*.sx exist, run them via the epoch protocol against sx_server.exe (SX_SERVER=/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe). Green before new work.

The queue

Phase order per plans/elixir-on-sx.md:

  • Phase 1 — tokenizer + parser (:atom, charlists, <>, |>, do/end)
  • Phase 2 — transpile basic Elixir (no macros/processes): arithmetic, pattern match (reuse Erlang engine), def/defp clause dispatch, modules, |>, with, for, fn/&, cond/case, interpolation, keyword lists/maps/tuples
  • Phase 3macro system (quote/unquote/unquote_splicing, defmacro, two-pass expand, use/import/alias) — the headline phase
  • Phase 4 — protocols (defprotocol/defimpl, dispatch, Enumerable etc.)
  • Phase 5 — structs + behaviours (defstruct, %Mod{}, @behaviour)

Within a phase, pick the checkbox with the best tests-per-effort ratio. Every iteration: implement → test → commit → tick [ ] → Progress log → push → next.

Chisel discipline — the macro system

Elixir earns its place by exercising homoiconic macros on a non-Lisp surface syntax. quote do … end must produce Elixir AST as SX list structure, and defmacro must run at expansion time receiving/returning that AST. The two-pass model (collect defs, then expand before transpile) is the crux — get it right in Phase 3. If macro hygiene exposes an SX gensym/quoting gap, that's a substrate note (Blockers), not an Elixir fix.

Ground rules (hard)

  • Scope: only lib/elixir/** and plans/elixir-on-sx.md. Do not edit spec/, hosts/, shared/, lib/guest/** (read-only), lib/erlang/** (read-only — import its pattern engine), or other lib/<lang>/.
  • Reuse, don't re-implement. Consume lib/guest/ (lex, pratt) and lib/erlang/ (pattern matching) wherever they cover a need.
  • Don't patch the substrate from this loop. Failing core behavior → failing test + Blockers entry + stop.
  • NEVER call sx_build (600s watchdog). Broken sx_server.exe → Blockers, stop.
  • SX files: sx-tree MCP tools ONLY; sx_validate after every edit. Never Edit/Read/Write on .sx. They take file: not path:.
  • Worktree: commit, then push origin/loops/elixir. Never main/architecture.
  • Commits: one feature per commit. Short factual messages (elixir: |> pipe desugaring + 6 tests).
  • Plan file: Progress log (newest first) + tick boxes every commit.
  • Blocked 2 iterations on one issue → Blockers entry, move on.

Elixir-specific gotchas

  • Everything is an expression; blocks return their last value. do/end is a block, not a statement list — map to SX (begin …).
  • |> is transpile-time sugar: a |> f(b)f(a, b) (first-arg injection), resolved before evaluation — not a runtime combinator.
  • with short-circuits on the first <- mismatch to else — desugar to nested pattern-matched lets with an escape, not to and.
  • Maps vs keyword lists: %{k: v} → SX dict; [k: v] → SX list of {:k v} (ordered, dup keys allowed). Don't conflate them.
  • Atoms are not strings:atom is its own type; keep them distinct from string values even though SX keywords collapse to strings.
  • Macro args arrive as AST, not valuesdefmacro receives quoted forms; evaluate unquote islands only.

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.
  • let is parallel — nest lets when one binding references an earlier one.
  • env-bind! creates a binding; env-set! mutates an existing one.
  • Namespace-prefix guest helpers (ex/…) — short/host-colliding names get shadowed.
  • Shell heredoc || gets eaten — escape or use case.

Style

  • No comments in .sx unless non-obvious. No new planning docs — update the plan.
  • Short, factual commit messages. One feature per iteration. Commit. Log. Push. Next.

Go. Run the pre-flight. If lib-guest or lib/erlang is missing, stop and report. Otherwise read the plan, find the first unchecked [ ], implement it.