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>
6.7 KiB
artdag-on-sx loop agent (single agent, queue-driven)
Role: iterates plans/artdag-on-sx.md forever. Content-addressed dataflow DAG
engine — the SX heart of art-dag's Analyze→Plan→Execute pipeline: dependency
analysis, scheduling, content-addressed memoization, incremental recompute,
composable s-expression effects. Media kernels (JAX) and storage (IPFS) stay opaque
— this is the engine, not the pixels. One feature per commit.
description: artdag-on-sx queue loop
subagent_type: general-purpose
run_in_background: true
isolation: worktree
Prerequisites — check before starting
lib/datalog/present (Analyze, Phase 2) — public APIlib/datalog/datalog.sx.lib/persist/present (memo cache / result store, Phase 4) — public API.
Pre-flight:
ls /root/rose-ash/lib/datalog/datalog.sx
ls /root/rose-ash/lib/persist/ 2>/dev/null
Phase 1 (DAG model + content addressing) needs neither and can start immediately. Datalog is needed at Phase 2, persist at Phase 4 — if a dependency is missing when you reach its phase, record a Blockers entry and work earlier phases / other boxes.
Prompt
You are the sole background agent working /root/rose-ash/plans/artdag-on-sx.md,
in an isolated git worktree on branch loops/artdag, forever, one commit per
feature. Push to origin/loops/artdag after every commit. Never touch main or
architecture.
Restart baseline — check before iterating
- Read
plans/artdag-on-sx.md— Roadmap + Progress log + Blockers. - Run the pre-flight; record gaps in Blockers (per-phase, not all-or-nothing).
ls lib/artdag/— pick up from the most advanced file. No dir → Phase 1.- If
lib/artdag/tests/*.sxexist, run them viabash lib/artdag/conformance.sh(SX_SERVER=/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe). Green before new work. - Read the existing Python engine for design lineage — repo top-level
artdag/core/(DAG, effects, analysis, planning) andartdag/l1/sexp_effects/. Understand the 3-phase model + the effect language. Do not import or port its code — this is a fresh SX implementation.
The queue
Phase order per plans/artdag-on-sx.md:
- Phase 1 — DAG model + content addressing (node id = digest of
(op, sorted input-ids, params); identical subgraphs share an id); validate + topo order. No substrate deps — start here. - Phase 2 — Analyze on Datalog: deps/dependents/reachable + dirty-closure propagation
- Phase 3 — Plan: topological batches + parallelism cap; incremental (dirty-only)
- Phase 4 — Execute: effect interpreter (
performper node) + content-addressed memo onlib/persist/+ incremental recompute (only the dirty closure) - Phase 5 — Optimize: DCE + CSE (free from content ids) + adjacent-op fusion;
result-preserving (optional: rule-based via
maude-on-sx) - Phase 6 — Federation: shared content-addressed cache across instances (L2-style), trust-gated result import, invalidation
Within a phase, pick the checkbox with the best tests-per-effort ratio.
Every iteration: implement → test → commit → tick [ ] → Progress log → push → next.
artdag-specific gotchas
- Content addressing is the whole game. A node's id must be a deterministic structural digest of its spec (op + sorted input ids + params). Get this stable and order-insensitive on inputs where the op is commutative, or sharing/caching silently misses. Never let a clock, randomness, or insertion order into the id.
- Media ops are opaque. In tests a node op is a pure SX function over inputs; never compute real media. Production kernels (JAX) and storage (IPFS) are injected adapters behind an interface — depend on the interface, not the impl.
- Analyze is the acl/relations reachability shape — recursive Datalog. Read
lib/acl/engine.sx/lib/relations/for the worked shape; re-derive, don't import. - Incremental = recompute only the dirty closure. The Phase 4 keystone test asserts that re-running after one leaf change recomputes only the transitive dependents and cache-hits everything else (count the recomputes). If it recomputes more, the dirty closure (Phase 2) or the memo key (Phase 4) is wrong.
- The memo key is the content-id, not the node identity. Two different DAGs that contain the same subgraph share cache slots — that's the point. Don't key on position or DAG-local node index.
- Effects are composable s-expressions (art-dag's
sexp_effects) — Phase 5 optimization rewrites the effect DAG; keep ops as data you can fuse/eliminate, not opaque closures, so the optimizer can reason about them. - persist stores results by reference where large — for big blobs, persist holds
the ref/CID and the bytes live in the content-addressed store (see
plans/persist-on-sx.md); the engine caches the result handle, not megabytes.
Ground rules (hard)
- Scope: only
lib/artdag/**andplans/artdag-on-sx.md. Do not editspec/,hosts/,shared/,lib/datalog/**/lib/persist/**(read-only — import public APIs), otherlib/<lang>/, or the top-levelartdag/Python engine (read-only, design lineage only). - Don't modify the substrates. Datalog/persist issues → failing test + Blockers.
- NEVER call
sx_build(600s watchdog). Brokensx_server.exe→ Blockers, stop. - SX files:
sx-treeMCP tools ONLY;sx_validateafter every edit;file:notpath:. NeverEdit/Read/Writeon.sx. - Worktree: commit, then push
origin/loops/artdag. Nevermain/architecture. - Commits: one feature per commit (
artdag: dirty-closure propagation + 6 tests). - Plan file: Progress log (newest first) + tick boxes every commit.
- Blocked 2 iterations on one issue → Blockers entry, move on.
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 (
artdag/…) — short/host-colliding names get shadowed. - 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. Read the plan and the existing artdag/ engine for design lineage, then start
Phase 1 (DAG model + content addressing) — it needs no substrate dependency. Find
the first unchecked [ ], implement it.