From 04bf34544ba09619c2758cc4ae31f4a860025795 Mon Sep 17 00:00:00 2001 From: Stefano Fiorini Date: Thu, 5 Mar 2026 23:07:43 -0600 Subject: [PATCH] feat(create-plan): route review through shared runtime --- docs/CREATE-PLAN.md | 45 +++++++++++++-- skills/create-plan/claude-code/SKILL.md | 73 ++++++++++++++++++++--- skills/create-plan/codex/SKILL.md | 75 +++++++++++++++++++++--- skills/create-plan/cursor/SKILL.md | 77 ++++++++++++++++++++++--- skills/create-plan/opencode/SKILL.md | 73 ++++++++++++++++++++--- 5 files changed, 310 insertions(+), 33 deletions(-) diff --git a/docs/CREATE-PLAN.md b/docs/CREATE-PLAN.md index 817cfd7..820ca70 100644 --- a/docs/CREATE-PLAN.md +++ b/docs/CREATE-PLAN.md @@ -117,6 +117,8 @@ Verify Superpowers dependencies exist in your agent skills root: - Commits `.gitignore` update locally when added. - Asks which reviewer CLI and model to use (or accepts `skip` for no review). - Iteratively reviews the plan with the chosen reviewer (max 5 rounds) before generating files. +- Runs reviewer commands through `reviewer-runtime/run-review.sh` when available, with fallback to direct synchronous execution only if the helper is missing. +- Captures reviewer stderr and helper status logs for diagnostics and retains them on failed, empty-output, or operator-decision review rounds. - Produces: - `original-plan.md` - `final-transcript.md` @@ -129,11 +131,38 @@ Verify Superpowers dependencies exist in your agent skills root: After the plan is created (design + milestones + stories), the skill sends it to a second model for review: 1. **Configure** — user picks a reviewer CLI (`codex`, `claude`, `cursor`) and model, or skips -2. **Submit** — plan is written to a temp file and sent to the reviewer in read-only/ask mode -3. **Feedback** — reviewer evaluates correctness, risks, missing steps, alternatives, security -4. **Revise** — the planning agent addresses each issue and re-submits -5. **Repeat** — up to 5 rounds until the reviewer returns `VERDICT: APPROVED` -6. **Finalize** — approved plan is used to generate the plan file package +2. **Prepare** — plan payload and a bash reviewer command script are written to temp files +3. **Run** — the command script is executed through `reviewer-runtime/run-review.sh` when installed +4. **Feedback** — reviewer evaluates correctness, risks, missing steps, alternatives, security +5. **Revise** — the planning agent addresses each issue and re-submits +6. **Repeat** — up to 5 rounds until the reviewer returns `VERDICT: APPROVED` +7. **Finalize** — approved plan is used to generate the plan file package + +### Runtime Artifacts + +The review flow may create these temp artifacts: + +- `/tmp/plan-.md` — plan payload +- `/tmp/plan-review-.md` — normalized review text +- `/tmp/plan-review-.json` — raw Cursor JSON output +- `/tmp/plan-review-.stderr` — reviewer stderr +- `/tmp/plan-review-.status` — helper heartbeat/status log +- `/tmp/plan-review-.runner.out` — helper-managed stdout from the reviewer command process +- `/tmp/plan-review-.sh` — reviewer command script + +Status log lines use this format: + +```text +ts= level= state= elapsed_s= pid= stdout_bytes= stderr_bytes= note="" +``` + +`stall-warning` is a heartbeat/status-log state only. It is not a terminal review result. + +### Failure Handling + +- `completed-empty-output` means the reviewer exited without producing review text; surface `.stderr` and `.status`, then retry only after diagnosing the cause. +- `needs-operator-decision` means the helper reached hard-timeout escalation; surface `.status` and decide whether to keep waiting, abort, or retry with different parameters. +- Successful rounds clean up temp artifacts. Failed, empty-output, and operator-decision rounds should retain `.stderr`, `.status`, and `.runner.out` until diagnosed. ### Supported Reviewer CLIs @@ -143,6 +172,12 @@ After the plan is created (design + milestones + stories), the skill sends it to | `claude` | `claude -p --model --allowedTools Read` | No (fresh call each round) | `--allowedTools Read` | | `cursor` | `cursor-agent -p --mode=ask --model --trust --output-format json` | Yes (`--resume `) | `--mode=ask` | +For all three CLIs, the preferred execution path is: + +1. write the reviewer command to a bash script +2. run that script through `reviewer-runtime/run-review.sh` +3. fall back to direct synchronous execution only if the helper is missing or not executable + ## Template Guardrails All plan templates now include guardrail sections that enforce: diff --git a/skills/create-plan/claude-code/SKILL.md b/skills/create-plan/claude-code/SKILL.md index 70eaa72..5ff1499 100644 --- a/skills/create-plan/claude-code/SKILL.md +++ b/skills/create-plan/claude-code/SKILL.md @@ -71,7 +71,20 @@ Send the plan to the configured reviewer CLI for feedback. Revise and re-submit REVIEW_ID=$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8) ``` -Use for all temp file paths: `/tmp/plan-${REVIEW_ID}.md` and `/tmp/plan-review-${REVIEW_ID}.md`. +Use for temp artifacts: +- `/tmp/plan-${REVIEW_ID}.md` +- `/tmp/plan-review-${REVIEW_ID}.md` +- `/tmp/plan-review-${REVIEW_ID}.json` (Cursor only) +- `/tmp/plan-review-${REVIEW_ID}.stderr` +- `/tmp/plan-review-${REVIEW_ID}.status` +- `/tmp/plan-review-${REVIEW_ID}.runner.out` +- `/tmp/plan-review-${REVIEW_ID}.sh` + +Resolve the shared reviewer helper from the installed Claude Code skills directory: + +```bash +REVIEWER_RUNTIME=~/.claude/skills/reviewer-runtime/run-review.sh +``` #### Step 2: Write Plan to Temp File @@ -79,6 +92,13 @@ Write the complete plan (milestones, stories, design decisions, specs) to `/tmp/ #### Step 3: Submit to Reviewer (Round 1) +Write the reviewer invocation to `/tmp/plan-review-${REVIEW_ID}.sh` as a bash script: + +```bash +#!/usr/bin/env bash +set -euo pipefail +``` + **If `REVIEWER_CLI` is `codex`:** ```bash @@ -113,8 +133,7 @@ claude -p \ Be specific and actionable. If the plan is solid, end with exactly: VERDICT: APPROVED If changes are needed, end with exactly: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -146,10 +165,39 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If `jq` is not installed, inform the user: `brew install jq` (macOS) or equivalent. +Run the command script through the shared helper when available: + +```bash +if [ -x "$REVIEWER_RUNTIME" ]; then + "$REVIEWER_RUNTIME" \ + --command-file /tmp/plan-review-${REVIEW_ID}.sh \ + --stdout-file /tmp/plan-review-${REVIEW_ID}.runner.out \ + --stderr-file /tmp/plan-review-${REVIEW_ID}.stderr \ + --status-file /tmp/plan-review-${REVIEW_ID}.status +else + echo "Warning: reviewer runtime helper not found at $REVIEWER_RUNTIME; falling back to direct synchronous review." >&2 + bash /tmp/plan-review-${REVIEW_ID}.sh >/tmp/plan-review-${REVIEW_ID}.runner.out 2>/tmp/plan-review-${REVIEW_ID}.stderr +fi +``` + +After the command completes: +- If `REVIEWER_CLI=cursor`, extract the final review text: + +```bash +CURSOR_SESSION_ID=$(jq -r '.session_id' /tmp/plan-review-${REVIEW_ID}.json) +jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_ID}.md +``` + +- If `REVIEWER_CLI=codex` and the review text is only in `/tmp/plan-review-${REVIEW_ID}.runner.out`, move or copy the actual review body into `/tmp/plan-review-${REVIEW_ID}.md` before verdict parsing. + #### Step 4: Read Review & Check Verdict 1. Read `/tmp/plan-review-${REVIEW_ID}.md` -2. Present review to the user: +2. If the review failed, produced empty output, or reached helper timeout, also read: + - `/tmp/plan-review-${REVIEW_ID}.stderr` + - `/tmp/plan-review-${REVIEW_ID}.status` + - `/tmp/plan-review-${REVIEW_ID}.runner.out` +3. Present review to the user: ``` ## Plan Review — Round N (reviewer: ${REVIEWER_CLI} / ${REVIEWER_MODEL}) @@ -161,6 +209,8 @@ If `jq` is not installed, inform the user: `brew install jq` (macOS) or equivale - **VERDICT: APPROVED** → proceed to Phase 7 (Initialize workspace) - **VERDICT: REVISE** → go to Step 5 - No clear verdict but positive / no actionable items → treat as approved + - Helper state `completed-empty-output` → treat as failed review attempt, surface stderr/status, fix invocation or prompt handling, then retry + - Helper state `needs-operator-decision` → surface status log and decide whether to keep waiting, abort, or retry with different helper parameters - Max rounds (5) reached → proceed with warning #### Step 5: Revise the Plan @@ -214,8 +264,7 @@ Changes made: Re-review the full plan. If solid, end with: VERDICT: APPROVED If more changes needed, end with: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -242,6 +291,8 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If resume fails, fall back to fresh `cursor-agent -p` with context about prior rounds. +After updating `/tmp/plan-review-${REVIEW_ID}.sh`, run the same helper/fallback flow from Round 1. + Return to Step 4. #### Step 7: Present Final Result @@ -259,9 +310,17 @@ Return to Step 4. #### Step 8: Cleanup ```bash -rm -f /tmp/plan-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.json +rm -f /tmp/plan-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.json \ + /tmp/plan-review-${REVIEW_ID}.stderr \ + /tmp/plan-review-${REVIEW_ID}.status \ + /tmp/plan-review-${REVIEW_ID}.runner.out \ + /tmp/plan-review-${REVIEW_ID}.sh ``` +If the round failed, produced empty output, or reached operator-decision timeout, keep `.stderr`, `.status`, and `.runner.out` until the issue is diagnosed instead of deleting them immediately. + ### Phase 7: Initialize Local Plan Workspace (MANDATORY) At project root: diff --git a/skills/create-plan/codex/SKILL.md b/skills/create-plan/codex/SKILL.md index cbeac38..b4c359b 100644 --- a/skills/create-plan/codex/SKILL.md +++ b/skills/create-plan/codex/SKILL.md @@ -94,7 +94,20 @@ Send the plan to the configured reviewer CLI for feedback. Revise and re-submit REVIEW_ID=$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8) ``` -Use for all temp file paths: `/tmp/plan-${REVIEW_ID}.md` and `/tmp/plan-review-${REVIEW_ID}.md`. +Use for temp artifacts: +- `/tmp/plan-${REVIEW_ID}.md` - plan payload +- `/tmp/plan-review-${REVIEW_ID}.md` - normalized review text presented to the user +- `/tmp/plan-review-${REVIEW_ID}.json` - raw Cursor JSON (only for `cursor`) +- `/tmp/plan-review-${REVIEW_ID}.stderr` - reviewer stderr +- `/tmp/plan-review-${REVIEW_ID}.status` - helper heartbeat/status log +- `/tmp/plan-review-${REVIEW_ID}.runner.out` - helper-managed stdout from the reviewer command process +- `/tmp/plan-review-${REVIEW_ID}.sh` - reviewer command script + +Resolve the shared reviewer helper from the installed Codex skills directory: + +```bash +REVIEWER_RUNTIME=~/.codex/skills/reviewer-runtime/run-review.sh +``` #### Step 2: Write Plan to Temp File @@ -102,6 +115,13 @@ Write the complete plan (milestones, stories, design decisions, specs) to `/tmp/ #### Step 3: Submit to Reviewer (Round 1) +Write the reviewer invocation to `/tmp/plan-review-${REVIEW_ID}.sh` as a bash script: + +```bash +#!/usr/bin/env bash +set -euo pipefail +``` + **If `REVIEWER_CLI` is `codex`:** ```bash @@ -136,8 +156,7 @@ claude -p \ Be specific and actionable. If the plan is solid, end with exactly: VERDICT: APPROVED If changes are needed, end with exactly: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -169,10 +188,41 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If `jq` is not installed, inform the user: `brew install jq` (macOS) or equivalent. +Run the command script through the shared helper when available: + +```bash +if [ -x "$REVIEWER_RUNTIME" ]; then + "$REVIEWER_RUNTIME" \ + --command-file /tmp/plan-review-${REVIEW_ID}.sh \ + --stdout-file /tmp/plan-review-${REVIEW_ID}.runner.out \ + --stderr-file /tmp/plan-review-${REVIEW_ID}.stderr \ + --status-file /tmp/plan-review-${REVIEW_ID}.status +else + echo "Warning: reviewer runtime helper not found at $REVIEWER_RUNTIME; falling back to direct synchronous review." >&2 + bash /tmp/plan-review-${REVIEW_ID}.sh >/tmp/plan-review-${REVIEW_ID}.runner.out 2>/tmp/plan-review-${REVIEW_ID}.stderr +fi +``` + +After the command completes: +- If `REVIEWER_CLI=cursor`, extract the final review text: + +```bash +CURSOR_SESSION_ID=$(jq -r '.session_id' /tmp/plan-review-${REVIEW_ID}.json) +jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_ID}.md +``` + +- If `REVIEWER_CLI=codex` and the review text is only in `/tmp/plan-review-${REVIEW_ID}.runner.out`, move or copy the actual review body into `/tmp/plan-review-${REVIEW_ID}.md` before verdict parsing. + +Fallback is allowed only when the helper is missing or not executable. + #### Step 4: Read Review & Check Verdict 1. Read `/tmp/plan-review-${REVIEW_ID}.md` -2. Present review to the user: +2. If the review failed, produced empty output, or reached helper timeout, also read: + - `/tmp/plan-review-${REVIEW_ID}.stderr` + - `/tmp/plan-review-${REVIEW_ID}.status` + - `/tmp/plan-review-${REVIEW_ID}.runner.out` +3. Present review to the user: ``` ## Plan Review — Round N (reviewer: ${REVIEWER_CLI} / ${REVIEWER_MODEL}) @@ -184,6 +234,8 @@ If `jq` is not installed, inform the user: `brew install jq` (macOS) or equivale - **VERDICT: APPROVED** → proceed to Phase 7 (Initialize workspace) - **VERDICT: REVISE** → go to Step 5 - No clear verdict but positive / no actionable items → treat as approved + - Helper state `completed-empty-output` → treat as failed review attempt, surface stderr/status, fix invocation or prompt handling, then retry + - Helper state `needs-operator-decision` → surface status log and decide whether to keep waiting, abort, or retry with different helper parameters - Max rounds (5) reached → proceed with warning #### Step 5: Revise the Plan @@ -237,8 +289,7 @@ Changes made: Re-review the full plan. If solid, end with: VERDICT: APPROVED If more changes needed, end with: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -265,6 +316,8 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If resume fails, fall back to fresh `cursor-agent -p` with context about prior rounds. +After updating `/tmp/plan-review-${REVIEW_ID}.sh`, run the same helper/fallback flow from Round 1. + Return to Step 4. #### Step 7: Present Final Result @@ -282,9 +335,17 @@ Return to Step 4. #### Step 8: Cleanup ```bash -rm -f /tmp/plan-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.json +rm -f /tmp/plan-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.json \ + /tmp/plan-review-${REVIEW_ID}.stderr \ + /tmp/plan-review-${REVIEW_ID}.status \ + /tmp/plan-review-${REVIEW_ID}.runner.out \ + /tmp/plan-review-${REVIEW_ID}.sh ``` +If the round failed, produced empty output, or reached operator-decision timeout, keep `.stderr`, `.status`, and `.runner.out` until the issue is diagnosed instead of deleting them immediately. + ### Phase 7: Initialize Local Plan Workspace (MANDATORY) At project root: diff --git a/skills/create-plan/cursor/SKILL.md b/skills/create-plan/cursor/SKILL.md index a6f0826..26362ba 100644 --- a/skills/create-plan/cursor/SKILL.md +++ b/skills/create-plan/cursor/SKILL.md @@ -96,7 +96,24 @@ Send the plan to the configured reviewer CLI for feedback. Revise and re-submit REVIEW_ID=$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8) ``` -Use for all temp file paths: `/tmp/plan-${REVIEW_ID}.md` and `/tmp/plan-review-${REVIEW_ID}.md`. +Use for temp artifacts: +- `/tmp/plan-${REVIEW_ID}.md` +- `/tmp/plan-review-${REVIEW_ID}.md` +- `/tmp/plan-review-${REVIEW_ID}.json` (Cursor only) +- `/tmp/plan-review-${REVIEW_ID}.stderr` +- `/tmp/plan-review-${REVIEW_ID}.status` +- `/tmp/plan-review-${REVIEW_ID}.runner.out` +- `/tmp/plan-review-${REVIEW_ID}.sh` + +Resolve the shared reviewer helper from Cursor's installed skills directory: + +```bash +if [ -x .cursor/skills/reviewer-runtime/run-review.sh ]; then + REVIEWER_RUNTIME=.cursor/skills/reviewer-runtime/run-review.sh +else + REVIEWER_RUNTIME=~/.cursor/skills/reviewer-runtime/run-review.sh +fi +``` #### Step 2: Write Plan to Temp File @@ -104,6 +121,13 @@ Write the complete plan (milestones, stories, design decisions, specs) to `/tmp/ #### Step 3: Submit to Reviewer (Round 1) +Write the reviewer invocation to `/tmp/plan-review-${REVIEW_ID}.sh` as a bash script: + +```bash +#!/usr/bin/env bash +set -euo pipefail +``` + **If `REVIEWER_CLI` is `codex`:** ```bash @@ -138,8 +162,7 @@ claude -p \ Be specific and actionable. If the plan is solid, end with exactly: VERDICT: APPROVED If changes are needed, end with exactly: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -175,10 +198,39 @@ Notes on Cursor flags: - `-p` / `--print` — non-interactive mode, output to stdout - `--output-format json` — structured output with `session_id` and `result` fields +Run the command script through the shared helper when available: + +```bash +if [ -x "$REVIEWER_RUNTIME" ]; then + "$REVIEWER_RUNTIME" \ + --command-file /tmp/plan-review-${REVIEW_ID}.sh \ + --stdout-file /tmp/plan-review-${REVIEW_ID}.runner.out \ + --stderr-file /tmp/plan-review-${REVIEW_ID}.stderr \ + --status-file /tmp/plan-review-${REVIEW_ID}.status +else + echo "Warning: reviewer runtime helper not found at $REVIEWER_RUNTIME; falling back to direct synchronous review." >&2 + bash /tmp/plan-review-${REVIEW_ID}.sh >/tmp/plan-review-${REVIEW_ID}.runner.out 2>/tmp/plan-review-${REVIEW_ID}.stderr +fi +``` + +After the command completes: +- If `REVIEWER_CLI=cursor`, extract the final review text: + +```bash +CURSOR_SESSION_ID=$(jq -r '.session_id' /tmp/plan-review-${REVIEW_ID}.json) +jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_ID}.md +``` + +- If `REVIEWER_CLI=codex` and the review text is only in `/tmp/plan-review-${REVIEW_ID}.runner.out`, move or copy the actual review body into `/tmp/plan-review-${REVIEW_ID}.md` before verdict parsing. + #### Step 4: Read Review & Check Verdict 1. Read `/tmp/plan-review-${REVIEW_ID}.md` -2. Present review to the user: +2. If the review failed, produced empty output, or reached helper timeout, also read: + - `/tmp/plan-review-${REVIEW_ID}.stderr` + - `/tmp/plan-review-${REVIEW_ID}.status` + - `/tmp/plan-review-${REVIEW_ID}.runner.out` +3. Present review to the user: ``` ## Plan Review — Round N (reviewer: ${REVIEWER_CLI} / ${REVIEWER_MODEL}) @@ -190,6 +242,8 @@ Notes on Cursor flags: - **VERDICT: APPROVED** → proceed to Phase 7 (Initialize workspace) - **VERDICT: REVISE** → go to Step 5 - No clear verdict but positive / no actionable items → treat as approved + - Helper state `completed-empty-output` → treat as failed review attempt, surface stderr/status, fix invocation or prompt handling, then retry + - Helper state `needs-operator-decision` → surface status log and decide whether to keep waiting, abort, or retry with different helper parameters - Max rounds (5) reached → proceed with warning #### Step 5: Revise the Plan @@ -243,8 +297,7 @@ Changes made: Re-review the full plan. If solid, end with: VERDICT: APPROVED If more changes needed, end with: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -271,6 +324,8 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If resume fails, fall back to fresh `cursor-agent -p` with context about prior rounds. +After updating `/tmp/plan-review-${REVIEW_ID}.sh`, run the same helper/fallback flow from Round 1. + Return to Step 4. #### Step 7: Present Final Result @@ -288,9 +343,17 @@ Return to Step 4. #### Step 8: Cleanup ```bash -rm -f /tmp/plan-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.json +rm -f /tmp/plan-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.json \ + /tmp/plan-review-${REVIEW_ID}.stderr \ + /tmp/plan-review-${REVIEW_ID}.status \ + /tmp/plan-review-${REVIEW_ID}.runner.out \ + /tmp/plan-review-${REVIEW_ID}.sh ``` +If the round failed, produced empty output, or reached operator-decision timeout, keep `.stderr`, `.status`, and `.runner.out` until the issue is diagnosed instead of deleting them immediately. + ### Phase 7: Initialize Local Plan Workspace (MANDATORY) At project root: diff --git a/skills/create-plan/opencode/SKILL.md b/skills/create-plan/opencode/SKILL.md index a3d4cf5..cf03e55 100644 --- a/skills/create-plan/opencode/SKILL.md +++ b/skills/create-plan/opencode/SKILL.md @@ -88,7 +88,20 @@ Send the plan to the configured reviewer CLI for feedback. Revise and re-submit REVIEW_ID=$(uuidgen | tr '[:upper:]' '[:lower:]' | head -c 8) ``` -Use for all temp file paths: `/tmp/plan-${REVIEW_ID}.md` and `/tmp/plan-review-${REVIEW_ID}.md`. +Use for temp artifacts: +- `/tmp/plan-${REVIEW_ID}.md` +- `/tmp/plan-review-${REVIEW_ID}.md` +- `/tmp/plan-review-${REVIEW_ID}.json` (Cursor only) +- `/tmp/plan-review-${REVIEW_ID}.stderr` +- `/tmp/plan-review-${REVIEW_ID}.status` +- `/tmp/plan-review-${REVIEW_ID}.runner.out` +- `/tmp/plan-review-${REVIEW_ID}.sh` + +Resolve the shared reviewer helper from the installed OpenCode skills directory: + +```bash +REVIEWER_RUNTIME=~/.config/opencode/skills/reviewer-runtime/run-review.sh +``` #### Step 2: Write Plan to Temp File @@ -96,6 +109,13 @@ Write the complete plan (milestones, stories, design decisions, specs) to `/tmp/ #### Step 3: Submit to Reviewer (Round 1) +Write the reviewer invocation to `/tmp/plan-review-${REVIEW_ID}.sh` as a bash script: + +```bash +#!/usr/bin/env bash +set -euo pipefail +``` + **If `REVIEWER_CLI` is `codex`:** ```bash @@ -130,8 +150,7 @@ claude -p \ Be specific and actionable. If the plan is solid, end with exactly: VERDICT: APPROVED If changes are needed, end with exactly: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -163,10 +182,39 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If `jq` is not installed, inform the user: `brew install jq` (macOS) or equivalent. +Run the command script through the shared helper when available: + +```bash +if [ -x "$REVIEWER_RUNTIME" ]; then + "$REVIEWER_RUNTIME" \ + --command-file /tmp/plan-review-${REVIEW_ID}.sh \ + --stdout-file /tmp/plan-review-${REVIEW_ID}.runner.out \ + --stderr-file /tmp/plan-review-${REVIEW_ID}.stderr \ + --status-file /tmp/plan-review-${REVIEW_ID}.status +else + echo "Warning: reviewer runtime helper not found at $REVIEWER_RUNTIME; falling back to direct synchronous review." >&2 + bash /tmp/plan-review-${REVIEW_ID}.sh >/tmp/plan-review-${REVIEW_ID}.runner.out 2>/tmp/plan-review-${REVIEW_ID}.stderr +fi +``` + +After the command completes: +- If `REVIEWER_CLI=cursor`, extract the final review text: + +```bash +CURSOR_SESSION_ID=$(jq -r '.session_id' /tmp/plan-review-${REVIEW_ID}.json) +jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_ID}.md +``` + +- If `REVIEWER_CLI=codex` and the review text is only in `/tmp/plan-review-${REVIEW_ID}.runner.out`, move or copy the actual review body into `/tmp/plan-review-${REVIEW_ID}.md` before verdict parsing. + #### Step 4: Read Review & Check Verdict 1. Read `/tmp/plan-review-${REVIEW_ID}.md` -2. Present review to the user: +2. If the review failed, produced empty output, or reached helper timeout, also read: + - `/tmp/plan-review-${REVIEW_ID}.stderr` + - `/tmp/plan-review-${REVIEW_ID}.status` + - `/tmp/plan-review-${REVIEW_ID}.runner.out` +3. Present review to the user: ``` ## Plan Review — Round N (reviewer: ${REVIEWER_CLI} / ${REVIEWER_MODEL}) @@ -178,6 +226,8 @@ If `jq` is not installed, inform the user: `brew install jq` (macOS) or equivale - **VERDICT: APPROVED** → proceed to Phase 8 (Initialize workspace) - **VERDICT: REVISE** → go to Step 5 - No clear verdict but positive / no actionable items → treat as approved + - Helper state `completed-empty-output` → treat as failed review attempt, surface stderr/status, fix invocation or prompt handling, then retry + - Helper state `needs-operator-decision` → surface status log and decide whether to keep waiting, abort, or retry with different helper parameters - Max rounds (5) reached → proceed with warning #### Step 5: Revise the Plan @@ -231,8 +281,7 @@ Changes made: Re-review the full plan. If solid, end with: VERDICT: APPROVED If more changes needed, end with: VERDICT: REVISE" \ --model ${REVIEWER_MODEL} \ - --allowedTools Read \ - > /tmp/plan-review-${REVIEW_ID}.md + --allowedTools Read ``` **If `REVIEWER_CLI` is `cursor`:** @@ -259,6 +308,8 @@ jq -r '.result' /tmp/plan-review-${REVIEW_ID}.json > /tmp/plan-review-${REVIEW_I If resume fails, fall back to fresh `cursor-agent -p` with context about prior rounds. +After updating `/tmp/plan-review-${REVIEW_ID}.sh`, run the same helper/fallback flow from Round 1. + Return to Step 4. #### Step 7: Present Final Result @@ -276,9 +327,17 @@ Return to Step 4. #### Step 8: Cleanup ```bash -rm -f /tmp/plan-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.md /tmp/plan-review-${REVIEW_ID}.json +rm -f /tmp/plan-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.md \ + /tmp/plan-review-${REVIEW_ID}.json \ + /tmp/plan-review-${REVIEW_ID}.stderr \ + /tmp/plan-review-${REVIEW_ID}.status \ + /tmp/plan-review-${REVIEW_ID}.runner.out \ + /tmp/plan-review-${REVIEW_ID}.sh ``` +If the round failed, produced empty output, or reached operator-decision timeout, keep `.stderr`, `.status`, and `.runner.out` until the issue is diagnosed instead of deleting them immediately. + ### Phase 8: Initialize Local Plan Workspace (MANDATORY) At project root: