From a2b4369035033a05bc37f256112e84b05fa6d4d4 Mon Sep 17 00:00:00 2001 From: Sheldon Finlay Date: Fri, 27 Mar 2026 11:48:15 -0400 Subject: [PATCH] feat: launch execution in tmux, orchestrator monitors progress --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- skills/run/SKILL.md | 185 ++++++++++---------------------- 3 files changed, 56 insertions(+), 133 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 11a95ab..bb97044 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "agent-loop", "source": "./", "description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Plan interactively, then execute with full visibility.", - "version": "0.7.0", + "version": "0.8.0", "author": { "name": "Sheldon" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 5100d5d..b205b33 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agent-loop", - "version": "0.7.0", + "version": "0.8.0", "description": "Autonomous generator-evaluator agent loop for long-running coding tasks. Plan with /agent-loop:init, then execute with /agent-loop:run.", "author": { "name": "Sheldon" diff --git a/skills/run/SKILL.md b/skills/run/SKILL.md index 5ac84e4..e68da7a 100644 --- a/skills/run/SKILL.md +++ b/skills/run/SKILL.md @@ -1,19 +1,17 @@ --- name: run -description: "Agent Loop — single entry point. Scaffolds .loop/ if missing, generates stories if no prd.json, then runs the generator-evaluator loop with full visibility." +description: "Agent Loop — single entry point. Scaffolds .loop/ if missing, generates stories if no prd.json, then launches autonomous execution in tmux." --- # /run — Agent Loop -Single entry point for the agent loop. Handles setup, planning, and execution automatically based on what's already done. +Single entry point for the agent loop. Handles setup and planning interactively, then launches autonomous execution in a tmux session. ## Usage ``` -/agent-loop:run # Full flow: setup → stories → loop -/agent-loop:run 3 # Limit to 3 loop iterations +/agent-loop:run # Full flow: setup → stories → launch /agent-loop:run --skip-eval # Skip evaluator pass -/agent-loop:run --story US-003 # Run only a specific story ``` ## Instructions @@ -88,151 +86,76 @@ Agent( --- -## Phase 3: Validate +## Phase 3: Validate and Launch 1. Read `.loop/prd.json` and verify: - Has a `userStories` array (NOT `sprints`, `stories`, or `tasks`) - Each story has: `id`, `title`, `passes`, `priority` - If invalid, show the error and stop. -2. Read `.loop/config.json` for `mode`, `maxIterations`, `evalRetries`, `scopeBudgets`. +2. Read `.loop/config.json` for `mode`, `maxIterations`. -3. Find prompts. Check these paths (first match wins): - - `.loop/prompts/` (local) - - `~/.claude/plugins/cache/agent-loop/agent-loop/*/prompts/` (plugin cache) +3. Verify `.loop/loop.sh` exists and is executable. - If no prompts found, stop with error. +4. Parse arguments for any flags to pass through (e.g., `--skip-eval`). -4. Parse arguments: number → max iterations, `--skip-eval`, `--story ` +5. Build the loop.sh command with any flags: ---- +```bash +LOOP_CMD=".loop/loop.sh" +# Add --skip-eval if requested +# Add --max N if specified +``` -## Phase 4: Execute Loop +6. Launch in tmux: -Report: +```bash +tmux new-session -d -s agent-loop -c "$LOOP_CMD" +``` -> **Loop Ready** +7. Report to the user: + +> **Loop launched in tmux session `agent-loop`** +> - Stories: {total} to complete > - Mode: {mode} -> - Stories: {passed}/{total} complete -> - Max iterations: {N} -> - Eval: {on/off} > -> Starting. Interrupt me at any time. - -For each iteration (1 to max iterations): - -### 4a. Find Next Story - -Find the story with the lowest `priority` where `passes` is `false` and `blocked` is not `true`. If `--story` was specified, use that story. - -**If no actionable story remains:** -- All `passes: true` → report success and stop -- Some `blocked: true` → report which ones -- Stop - -### 4b. Report Iteration Start - -> **Iteration {N}/{max} — {story.id}: {story.title}** - -If the story has `[REJECTED]` in `notes`, summarize the feedback. - -### 4c. Assemble Generator Prompt - -Read and concatenate with `---` separator: -1. `{prompt_path}/generator/_base.md` -2. `{prompt_path}/generator/{mode}.md` - -Substitute variables: -- `{{MAX_FILES_TO_READ}}` → from config scopeBudgets -- `{{MAX_LINES_TO_WRITE}}` → from config scopeBudgets -- `{{MAX_FILES_TO_MODIFY}}` → from config scopeBudgets -- `{{MODE}}` → mode -- `{{ITERATION}}` → current iteration -- `{{MAX_ITERATIONS}}` → max iterations -- `{{LOOP_DIR}}` → absolute path to `.loop/` -- `{{PROJECT_ROOT}}` → project root -- `{{CURRENT_STORY_ID}}` → story ID - -### 4d. Capture Pre-Generator Git State - -Run `git rev-parse HEAD` and save the SHA. - -### 4e. Dispatch Generator Agent - -``` -Agent( - prompt: , - description: "Generator: {story.id}", - subagent_type: "general-purpose", - mode: "bypassPermissions" -) -``` - -### 4f. Check Completion Signal - -If output contains `COMPLETE`, report done and stop. - -### 4g. Evaluator (unless skipped) - -If `--skip-eval` or `config.skipEval` is true, skip to 4h and treat as PASS. - -Otherwise, read and concatenate: -1. `{prompt_path}/evaluator/_base.md` -2. `{prompt_path}/evaluator/{mode}.md` - -Substitute same variables plus `{{PRE_GENERATOR_SHA}}` and `{{CURRENT_STORY_ID}}`. - -``` -Agent( - prompt: , - description: "Evaluator: {story.id}", - subagent_type: "general-purpose", - mode: "bypassPermissions" -) -``` - -Parse verdict: -- `PASS` → PASS -- `REJECT` → REJECT, extract reason -- No verdict → REJECT (fail-safe) - -### 4h. Update State - -**PASS:** Set `passes: true` in prd.json. Report: **{story.id} PASSED** - -**REJECT:** Increment `rejections`, append `[REJECTED] {reason}` to `notes`. Report: **{story.id} REJECTED** — {reason} - -If `rejections >= evalRetries`: set `blocked: true`. Report: **{story.id} BLOCKED** - -### 4i. Append Progress - -Append to `.loop/progress.md`: - -```markdown -### {story.id} — {story.title} -Date: {date} -Iteration: {N} -Verdict: {verdict} - ---- -``` - -### 4j. Continue - -Show: `{passed}/{total} stories complete` - -Continue to next iteration. +> **Monitor:** +> - Watch live: `tmux attach -t agent-loop` +> - Check progress: read `.loop/progress.md` +> - Check status: read `.loop/prd.json` +> - Stop the loop: `tmux kill-session -t agent-loop` +> +> I can also check on progress for you — just ask "how's it going?" --- -## Loop Exit +## Monitoring -> **Loop Complete** -> - Iterations: {N} +If the user asks about progress (e.g., "status", "how's it going", "check progress"): + +1. Read `.loop/prd.json` — count passed/failed/blocked stories +2. Read `.loop/progress.md` — show the latest session log entries +3. Capture recent tmux output: + +```bash +tmux capture-pane -t agent-loop -p | tail -30 +``` + +4. Report: + +> **Loop Status** > - Stories: {passed}/{total} complete, {blocked} blocked +> - Current: {last story from progress.md} +> - tmux session: {running/stopped} -## Error Handling +--- -- Agent fails or empty output → warn and continue -- prd.json unparseable → stop -- User says "stop" → end loop, report status +## When Loop Completes + +The tmux session exits when `loop.sh` finishes. If the user asks for a summary: + +1. Read `.loop/prd.json` for final story statuses +2. Read `.loop/progress.md` for the full session log +3. Check git log for commits made during the run + +Report the final status and suggest `/agent-loop:triage` if any stories are blocked.