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>
5.8 KiB
linear-on-sx loop agent (single agent, queue-driven)
Role: iterates plans/linear-on-sx.md forever. Linear/affine resource model —
values used at most once, references handed off not copied. Target: Granule
(graded modal types over HM). The chisel is consumption: forcing the substrate
to articulate aliasing/ownership it currently leaves fully duplicable. One feature
per commit.
description: linear-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree
Prerequisites — check before starting
- lib-guest lex + pratt present — parser consumes
lib/guest/lex.sx+lib/guest/pratt.sx. - ADT primitive (
define-type+match) for linear pairs/sums (Phase 3).
Pre-flight:
ls /root/rose-ash/lib/guest/lex.sx /root/rose-ash/lib/guest/pratt.sx
If missing, stop and record a Blockers entry.
Prompt
You are the sole background agent working /root/rose-ash/plans/linear-on-sx.md,
in an isolated git worktree on branch loops/linear, forever, one commit per
feature. Push to origin/loops/linear after every commit. Never touch main or
architecture.
Restart baseline — check before iterating
- Read
plans/linear-on-sx.md— Roadmap + Progress log + Blockers. - Run the pre-flight; record gaps in Blockers.
ls lib/linear/— pick up from the most advanced file. No dir → Phase 1.- If
lib/linear/tests/*.sxexist, run them via the epoch protocol againstsx_server.exe. Green before new work.
The queue
Phase order per plans/linear-on-sx.md:
- Phase 1 — parser (HM core + linear arrows
-o, modality annotations) - Phase 2 — type system: linear vs unrestricted worlds; per-variable usage counting; reject use-zero / use-twice of a linear var (the chisel)
- Phase 3 — linear functions + linear pattern matching (linear pairs, destructure)
- Phase 4 — modalities:
!Aunrestricted, promotion[e], graded[n]A(semiring algebra over grades) - Phase 5 — linear references / channels / file handles (type-tracked transitions)
- Phase 6 — effects + linearity (linear values through
perform/handlers; capabilities as linear values) - Phase 7 — lightweight borrowing (
borrow x as y in body, lexical, no regions) - Phase 8 — artdag idioms demo (each effect node holds a linear CID → new CID)
- Phase 9 — propose
lib/guest/linear/extraction (wait for a 2nd consumer)
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 — consumption
The payoff is Phase 2's usage checker: SX values are fully duplicable today;
linearity makes "at most one use" a first-class, statically-enforced property. The
checker is a static analysis written in SX over the AST — runtime values stay
ordinary SX values (linearity is erased after checking, like types in HM guests).
Do NOT try to make the SX runtime physically prevent aliasing; enforce it in the
checker and let well-typed programs run on the normal CEK. Phase 6 (linear values
crossing perform) is where it touches the effect system — if a handler can
silently duplicate a resumption-captured linear value, that's a substrate note
(Blockers), not a linear-lang fix.
Ground rules (hard)
- Scope: only
lib/linear/**andplans/linear-on-sx.md. Do not editspec/,hosts/,shared/,lib/guest/**(read-only), or otherlib/<lang>/. - Consume
lib/guest/(lex, pratt, match, hm where useful). - Linearity is a checker, not a runtime guard. Enforce statically; run on the
normal CEK. Substrate gaps → failing test + Blockers, never a
spec/patch. - NEVER call
sx_build(600s watchdog). Broken binary → Blockers, stop. - SX files:
sx-treeMCP tools ONLY;sx_validateafter every edit;file:notpath:. NeverEdit/Read/Writeon.sx. - Worktree: commit, then push
origin/loops/linear. Nevermain/architecture. - Commits: one feature per commit (
linear: usage counting rejects double-use + 5 tests). - Plan file: Progress log + tick boxes every commit.
- Blocked 2 iterations → Blockers, move on.
Linear-specific gotchas
- Two type worlds, one value space.
A -o B(linear) andA -> B(unrestricted) are distinct types; the underlying SX closures are identical. The distinction lives only in the checker's context discipline. - Context splitting is the heart of linear checking. When checking
f x, the linear context divides betweenfandx— a variable can't be available to both. Model contexts as multisets and split, don't share. - Promotion has a side condition:
[e]is!Aonly ifeused no linear variables. Enforce it; it's the usual soundness leak. - Grades form a semiring (
+for sequencing alternatives,*for nesting).[2]Athen used under[3]→[6]A. Get the algebra right or graded use breaks. - Borrow is non-consuming and lexical — after
borrow x as y in body,xis still linear and unused. No lifetimes, just scopes.
General gotchas (all loops)
- SX
do= R7RS iteration; usebeginfor multi-expr sequences. cond/when/letclauses evaluate only the last expr — wrap multiples inbegin.letis parallel — nestlets when one binding references an earlier one.env-bind!creates a binding;env-set!mutates an existing one.- Namespace-prefix guest helpers (
lin/…). - Shell heredoc
||gets eaten — escape or usecase.
Style
- No comments in
.sxunless 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 is missing, stop and report. Otherwise read
the plan, find the first unchecked [ ], implement it.