8000 planner targets.json rules; task-worktree merge records the lineage on Claude Code by adeelahmad · Pull Request #18 · adeelahmad/aloop · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ tag in lockstep. Tag releases as `vMAJOR.MINOR.PATCH`.
overrides it (`breach:` line) and acts per class (SKILL.md "Breach classes").

### Added
- **`task-worktree merge <TASK_ID> <BRANCH>`** records the §4.7 lineage on Claude Code, where the
host makes the worktree and the supervisor merges it (so `task-worktree remove` never runs): a
`--no-ff` merge, then `worktree.merged` + one `commit.created` per merged commit. SKILL.md tells the
supervisor to merge with it (a raw `git merge` left live runs 11–14 with no traceable commits), and
`make e2e-live` now checks every merged commit answers `events trace`.
- Stuck release: a worker that hits the same gate block 3 times in a row (one gate, task,
attempt and worktree; `AGENTIC_STUCK_BLOCKS`) is released **unverified** instead of
looping until its time box (live run 10 lost 29 minutes to a RED worker that stopped 29
Expand Down Expand Up @@ -245,6 +250,9 @@ tag in lockstep. Tag releases as `vMAJOR.MINOR.PATCH`.
reading it stays allowed. 2 checks failed before.

### Fixed
- The planner persona states `targets check`'s rules (`{"targets": [...]}`, `symbol` only for code
that exists, `planned_symbol` with `create`/`extend` for new code), so its first `targets.json`
passes (live runs 12–14: 2–3 blocks each).
- The planner persona lists the exact frontmatter and `##` sections `planning-artifacts.kdl`
requires, so its first write passes (every live run so far wrote each artifact twice: 8–12
write blocks per run).
Expand Down
2 changes: 1 addition & 1 deletion docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ spec; this table is the plan. Versions are targets, not promises.
| Milestone | Target | Contents | Status |
|---|---|---|---|
| **M0 — Hygiene** | v0.10.x | Mark `DESIGN` / `ARCHITECTURE` / `KICKSTART` historical; fix stale counts (8 → 9 roles) and the README CI section; add the `CONTRIBUTING.md` the README badge links to; one live-session smoke test of the hook wiring (open since `DEVLOG` v0.1) | done: live smoke test `make smoke-live YES=1` (6 checks, ~$0.004 on haiku); its first run found the Linux fail-open in `gate-supervisor-scope` (fixed, regression test added) |
| **M0.8 — North-star run** | v0.11.x | `make e2e-live YES=1`: a one-line intent (semver parser) goes through retrospective, intake, standards, planner, RED/SCAFFOLD/GREEN per task, structural review and the final gate to merged, tested code in a real Claude Code session, with the approval given up front. Reason: nothing had ever run the whole loop live; the first run found that no role gate fired on plugin installs | run 1: done end to end, 19 min, $1.15 (sonnet supervisor, haiku workers), 22 tests on main, 9/11 checks; found and fixed the `aloop:<role>` matcher bug, a selfcheck crash and copy-merging. Run 2: **11/11**, 12m46s, $0.92, host gates on every role, worktree branches merged with `--no-ff`; found gates looping on the supervisor's contract slips (fixed). Run 3: 11/11, 12m00s, **$0.79**; found GREEN looping on RED's unformatted tests (fixed: RED/SCAFFOLD run the format check) and selfcheck missing the contract in Claude Code worktrees (fixed: the contract is copied in). Run 4 (all fixes): 11/11, 17m56s, $1.10, 12 gate blocks and no loops (28 → 17 → 12). Cost varies $0.79–1.15 per run; next: cut it (scaffold symbol parsing slips such as `(enum,`, supervisor turns), then a second intent beyond the semver fixture. Run 5: 11/11 but 29 min, $1.83, 44 blocks (the planner made 5 tasks; 27 false isolation blocks after workers `cd`'d to the main tree, fixed; subagents also read the plugin's own source, which costs tokens). Run 6: 11/11, **11m10s, $0.65**, plugin-source reads 30 → 2 after the agent prompts said not to; found a dispatch-before-contract loop (25 blocks, fixed by `gate-dispatch`) and annotated scaffold-symbol lines (fixed). Run 7 (after #9): 11/11, 13m46s, $0.98, 20 blocks, no dispatch loop; found RED blocked for listing an earlier task's passing tests, scaffold-symbols tables with a header row and trait-impl lines, and a guessed memory.md frontmatter (all fixed; `aloop init` now seeds memory.md). The re-plan coverage loss is now caught by `gate-final` (every planned test must be on main). Run 8, **second intent** (`INTENT=wordfreq`, two dependent stories): 12/12, 18m05s, $1.53, 54 blocks; found scope globs expanded against the worktree (29 GREEN blocks) and `mod common;` across test crates reported as a HIGH duplicate (57 review halts), both fixed. Run 9 (wordfreq again): 12/12, 19m42s, $1.56, 29 blocks; the ctx-symbols fix had not reached the run (`ensure-tools` rebuilt only on a version bump, fixed) and the planner named story dirs `S1-01/` (block message now names `s1-01-<slug>/`). Run 10 (rebuilt tools): 12/12, $1.20, but 44m48s and 45 blocks: the duplicate false positive is gone (0 HIGH); a RED worker's Write/Edit to the story's output.md was refused by Claude Code's worktree isolation and it stopped 29 times without trying a shell append (fixed: the block and the personas say how), plus 3 stale-`ATTEMPT` tamper blocks (fixed). Fixed after run 10: a worker that repeats an identical block 3 times is released unverified with a `STUCK` marker the supervisor acts on (reason: 29 minutes lost in run 10). Run 11 (all run-10 fixes): 12/12, **12m56s, $0.86, 6 blocks** (from 44m48s, $1.20, 45): no repeated block, one RED report-append block fixed on the first retry, one scaffold fmt block, two structural-reviewer comms blocks (STORY_DIR unset for a sprint-wide review, then a stale block) and 12 `gate-validate-artifact` write blocks on the planner's artifacts. Fixed after run 11: the artifact-write block carries md-db's diagnostics (the planner guessed twice per artifact: 12 of 25 verdicts), `gate-dispatch` requires an existing `STORY_DIR` and names the sprint dir for a whole-wave structural review (2 blocks), and OpenCode reports a stuck release as unverified. Run 12 (those fixes): 12/12, 15m22s, $1.10, 21 blocks: the planner fixed each artifact on the first retry (8 write blocks, from 12) and the reviewer's contract had `STORY_DIR`, but a stale worktree checkout under `.claude/worktrees/` made `ctx-symbols conflicts` report every symbol of main as a duplicate and the reviewer was blocked 10 times on a HIGH finding it could not fix (fixed: the walk skips host checkouts, `.agentic/`, `.transcripts/`). The stuck release now covers the structural reviewer and the final gate too (reason: 10 identical blocks, run 12). Gap: `targets check` blocked the planner twice because a context target named a planned symbol not yet in `src/lib.rs` (reason: planned symbols do not exist before SCAFFOLD; §4.6 owner to decide). Run 13 (those fixes): 12/12, 16m31s, $1.33, 16 blocks; the first build of the walk exclusion also excluded a worktree that IS a host checkout, so the scaffold gate counted every symbol 0 times (9 blocks; the worker was then released by the stuck release and the run still finished); fixed before the run ended (the exclusion applies below the walk root) and covered by a conformance case. Open: `targets check` blocks on the planner's first `targets.json` (2 per run, fixed on retry; §4.6 owner), and sub-agents reading the plugin's own source rose to 17 (from 2–10). Run 14 (all fixes): 12/12, **13m47s, $0.88, 11 blocks**, one host-run block in all (RED touched `src/lib.rs`, fixed on retry), no stuck worker; the rest are planning write blocks fixed on the first retry and workers' own self-checks. Next: supervisor-written GREEN instructions overreaching the next task; cut the planner's first-write blocks (its templates should pass the schema as written) |
| **M0.8 — North-star run** | v0.11.x | `make e2e-live YES=1`: a one-line intent (semver parser) goes through retrospective, intake, standards, planner, RED/SCAFFOLD/GREEN per task, structural review and the final gate to merged, tested code in a real Claude Code session, with the approval given up front. Reason: nothing had ever run the whole loop live; the first run found that no role gate fired on plugin installs | run 1: done end to end, 19 min, $1.15 (sonnet supervisor, haiku workers), 22 tests on main, 9/11 checks; found and fixed the `aloop:<role>` matcher bug, a selfcheck crash and copy-merging. Run 2: **11/11**, 12m46s, $0.92, host gates on every role, worktree branches merged with `--no-ff`; found gates looping on the supervisor's contract slips (fixed). Run 3: 11/11, 12m00s, **$0.79**; found GREEN looping on RED's unformatted tests (fixed: RED/SCAFFOLD run the format check) and selfcheck missing the contract in Claude Code worktrees (fixed: the contract is copied in). Run 4 (all fixes): 11/11, 17m56s, $1.10, 12 gate blocks and no loops (28 → 17 → 12). Cost varies $0.79–1.15 per run; next: cut it (scaffold symbol parsing slips such as `(enum,`, supervisor turns), then a second intent beyond the semver fixture. Run 5: 11/11 but 29 min, $1.83, 44 blocks (the planner made 5 tasks; 27 false isolation blocks after workers `cd`'d to the main tree, fixed; subagents also read the plugin's own source, which costs tokens). Run 6: 11/11, **11m10s, $0.65**, plugin-source reads 30 → 2 after the agent prompts said not to; found a dispatch-before-contract loop (25 blocks, fixed by `gate-dispatch`) and annotated scaffold-symbol lines (fixed). Run 7 (after #9): 11/11, 13m46s, $0.98, 20 blocks, no dispatch loop; found RED blocked for listing an earlier task's passing tests, scaffold-symbols tables with a header row and trait-impl lines, and a guessed memory.md frontmatter (all fixed; `aloop init` now seeds memory.md). The re-plan coverage loss is now caught by `gate-final` (every planned test must be on main). Run 8, **second intent** (`INTENT=wordfreq`, two dependent stories): 12/12, 18m05s, $1.53, 54 blocks; found scope globs expanded against the worktree (29 GREEN blocks) and `mod common;` across test crates reported as a HIGH duplicate (57 review halts), both fixed. Run 9 (wordfreq again): 12/12, 19m42s, $1.56, 29 blocks; the ctx-symbols fix had not reached the run (`ensure-tools` rebuilt only on a version bump, fixed) and the planner named story dirs `S1-01/` (block message now names `s1-01-<slug>/`). Run 10 (rebuilt tools): 12/12, $1.20, but 44m48s and 45 blocks: the duplicate false positive is gone (0 HIGH); a RED worker's Write/Edit to the story's output.md was refused by Claude Code's worktree isolation and it stopped 29 times without trying a shell append (fixed: the block and the personas say how), plus 3 stale-`ATTEMPT` tamper blocks (fixed). Fixed after run 10: a worker that repeats an identical block 3 times is released unverified with a `STUCK` marker the supervisor acts on (reason: 29 minutes lost in run 10). Run 11 (all run-10 fixes): 12/12, **12m56s, $0.86, 6 blocks** (from 44m48s, $1.20, 45): no repeated block, one RED report-append block fixed on the first retry, one scaffold fmt block, two structural-reviewer comms blocks (STORY_DIR unset for a sprint-wide review, then a stale block) and 12 `gate-validate-artifact` write blocks on the planner's artifacts. Fixed after run 11: the artifact-write block carries md-db's diagnostics (the planner guessed twice per artifact: 12 of 25 verdicts), `gate-dispatch` requires an existing `STORY_DIR` and names the sprint dir for a whole-wave structural review (2 blocks), and OpenCode reports a stuck release as unverified. Run 12 (those fixes): 12/12, 15m22s, $1.10, 21 blocks: the planner fixed each artifact on the first retry (8 write blocks, from 12) and the reviewer's contract had `STORY_DIR`, but a stale worktree checkout under `.claude/worktrees/` made `ctx-symbols conflicts` report every symbol of main as a duplicate and the reviewer was blocked 10 times on a HIGH finding it could not fix (fixed: the walk skips host checkouts, `.agentic/`, `.transcripts/`). The stuck release now covers the structural reviewer and the final gate too (reason: 10 identical blocks, run 12). Gap: `targets check` blocked the planner twice because a context target named a planned symbol not yet in `src/lib.rs` (reason: planned symbols do not exist before SCAFFOLD; §4.6 owner to decide). Run 13 (those fixes): 12/12, 16m31s, $1.33, 16 blocks; the first build of the walk exclusion also excluded a worktree that IS a host checkout, so the scaffold gate counted every symbol 0 times (9 blocks; the worker was then released by the stuck release and the run still finished); fixed before the run ended (the exclusion applies below the walk root) and covered by a conformance case. Open: `targets check` blocks on the planner's first `targets.json` (2 per run, fixed on retry; §4.6 owner), and sub-agents reading the plugin's own source rose to 17 (from 2–10). Run 14 (all fixes): 12/12, **13m47s, $0.88, 11 blocks**, one host-run block in all (RED touched `src/lib.rs`, fixed on retry), no stuck worker; the rest are planning write blocks fixed on the first retry and workers' own self-checks. The supervisor's GREEN mandates in runs 11–14 named one symbol and `src/lib.rs only`, and the diff scope (from `tasks.md` or `targets scope`) bounds them anyway, so the "GREEN instructions overreaching" item is closed as not reproduced. The planner persona now carries the schema's artifact shapes and the `targets check` rules (to measure). Next: sub-agents reading the plugin's own source (4–17 reads per run: tokens), and a live check that every commit on main traces to its task and intent (`events trace`, §4.7, never measured live) |
| **M0.6 — Gates fail closed** | v0.11.x | A gate that crashes (exit 1, e.g. an unbound variable) is a non-blocking hook error on Claude Code, so the action goes through. Make every gate trap unexpected errors into exit 2 with the reason, and add a conformance case per gate. Reason: the smoke run showed one real instance | done: `_failclosed.sh` on all 10 sub-agent gates + supervisor-scope inside a sprint; `scripts/test/fail-closed.test.py` (5 checks). Left fail-open on purpose: `gate-commit-author` and `gate-validate-artifact` outside a sprint, which see every session on the machine |
| **M0.7 — Supervisor-owned task contract** | v0.11.x | The contract lives in the main tree, `.agentic/state/tasks/<TASK_ID>.env`, and the dispatch prompt's first line names the task; gates and the time box find it from the host's transcript, a worktree `task.env` that disagrees blocks, and sub-agents may not Write/Edit `.agentic/state/` or `task.env`. Settled by a live probe: Claude Code's `isolation: "worktree"` makes `.claude/worktrees/agent-<id>` at dispatch, so a pre-written in-worktree contract was impossible there. Bash writes are guarded too (a command naming the contract with a write verb is blocked; a heuristic, so an obfuscated write still gets through). On hosts with no sub-agent transcript the worktree's `TASK_ID` (or its `.agentic/worktrees/<id>` path) picks the contract | done: `make conformance` (58 today) + `scripts/test/{budget-worktree,supervisor-scope}.test.py` |
| **M0.5 — Rename to aloop** | v0.11.0 | Plugin, marketplace, skill, CLI (`aloop`, `aloop init`), OpenCode plugin file and docs renamed; `agentic`, `agentic init`, `agentic-init` and `agentic bind` kept as aliases; OpenCode/Codex installs clean up pre-rename files. Data layout and settings keys unchanged (moved to M1). GitHub repo rename is the owner's call | done: `scripts/test/rename-compat.test.py` |
Expand Down
8 changes: 7 additions & 1 deletion plugin/agents/planner.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,13 @@ Write `targets.json` beside tasks.md when you know what each task changes: one e
change (`change_ref` C1…, `task`, `operation` create|modify|extend|refactor|replace|delete,
`path`, `symbol` or `planned_symbol`, a one-line `reason`, `evidence_refs`, `constraints`).
Planned files stay planned: never create stubs. `targets check <STORY_DIR>` (also run by
gate-stage2-complete) proves each target against tasks.md and the real tree.
gate-stage2-complete) proves each target against tasks.md and the real tree. Its rules, so
the first write passes (live runs 12–14 hit each of these):
- the file is `{"targets": [...]}`, never a bare list;
- `symbol` names something that EXISTS in the tree now; a function this sprint will add is a
`planned_symbol` — `create` for a new file (the path must not exist yet), `extend` for a new
symbol in an existing file (`"operation": "extend", "path": "src/lib.rs", "planned_symbol": "count_words"`);
- `modify|refactor|replace|delete` need a `symbol` that exists (or `planned_symbol` for `extend`).

## Hard limits
- Writes no production code; does not start RED.
Expand Down
2 changes: 1 addition & 1 deletion plugin/bin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ ctx-symbols) → WARN + grep fallback; never a silent pass.
| `install` | `aloop install codex\|opencode [--project DIR\|--global] [--uninstall]` — renders agents/skills/commands (+ the OpenCode plugin from `hosts/opencode/`) from this plugin's sources; `status`; `claude` |
| `host` | the `HostAdapter` interface (ROADMAP §4.9, `_host.py`): Claude Code is the reference, Codex and OpenCode are adapters. `describe [--host H] [--json]` prints the contract (capabilities, spawn/wait/send/cancel/subscribe vocabulary, compact/rotate, isolation, gate install/enforcement, tool policy, resolved models) · `check` (every adapter complete; gates `native` or `outer`, never warn; in `make test-hosts`) · `worktree create\|remove\|diff TASK`. A capability a host lacks raises `Unsupported`, never a guess. |
| `host-adapter` | SubagentStart/Stop: register sub-agents (`.agentic/state/agents/`) for the ledger; PreToolUse on Codex: a worker must `aloop bind <worktree>` first, then its commands/patches must stay in it (denied otherwise) |
| `task-worktree` | `add\|path\|remove <TASK_ID>` — per-task worktree at `.agentic/worktrees/<TASK_ID>` (branch `agentic/<TASK_ID>`) for hosts without built-in isolation |
| `task-worktree` | `add\|path\|remove <TASK_ID>` — per-task worktree at `.agentic/worktrees/<TASK_ID>` (branch `agentic/<TASK_ID>`) for hosts without built-in isolation; `merge <TASK_ID> <BRANCH>` — `--no-ff` merge of a host-made branch that emits `worktree.merged` + `commit.created` (the lineage on Claude Code) |
| `bind` | a worker's first command on Codex/OpenCode: validates its worktree (`aloop bind <path>`) |
| `_usage.py` | token usage from any host's log: Claude transcripts, Codex rollouts (`.jsonl`/`.zst`, cumulative totals → per-call rows), the OpenCode plugin's usage log |
| `aloop-init` | project setup: `--show` the defaults for the human, `--apply KEY=VALUE…` writes `docs/agents/defaults.md`, the managed `.gitignore` lines and the repo-local git author; `--ensure-gitignore` (SessionStart, worktree-hygiene) re-adds them |
Expand Down
Loading
Loading
0