From 2941faa8222dbbcf496bb0ae15e4915281181ea8 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Wed, 6 May 2026 15:28:08 +0200 Subject: [PATCH 1/4] refactor(opencode): make workflow forge-agnostic and read TODO.md from bare repo Drops all GitHub-specific tooling (gh CLI, draft PR creation) so the workflow stops at git commit and leaves push/PR/MR to the user. TODO.md is now expected to be a tracked file on the default branch. Phase 1 verifies the repo is bare via `git rev-parse --is-bare-repository`, resolves the default branch from HEAD / init.defaultBranch, and snapshots TODO.md via `git show "$DEFAULT_BRANCH:TODO.md"` to a tempfile that @pm reads in Phase 2. Phase 10 updates the live TODO.md inside the worktree and commits the change separately. The /review command drops its PR mode for the same reason; @pm documents the read-only-snapshot vs. live-worktree path distinction. --- config/opencode/agents/pm.md | 17 ++++-- config/opencode/commands/review.md | 6 +- config/opencode/commands/workflow.md | 84 +++++++++++++++------------- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/config/opencode/agents/pm.md b/config/opencode/agents/pm.md index 196844d..fa95269 100644 --- a/config/opencode/agents/pm.md +++ b/config/opencode/agents/pm.md @@ -11,13 +11,22 @@ tools: bash: false --- -You are a project management assistant. Your sole responsibility is reading and updating a local `TODO.md` file at the project root. You do **not** modify any other file under any circumstances. +You are a project management assistant. Your sole responsibility is reading and updating a `TODO.md` file. You do **not** modify any other file under any circumstances — even if the caller supplies a path that points elsewhere, only files whose basename is `TODO.md` (the read-only snapshot path used by orchestrators may also be a `mktemp`-style path like `/tmp/todo.XXXXXX.md`) are acceptable. ## File Location -The issue tracker lives at `./TODO.md` (relative to the working directory). If the file does not exist when an operation requires it: -- For read/list operations: report "TODO.md not found at " and stop. -- For create operations: create it with the header `# TODO\n\n` and proceed. +The caller supplies the TODO.md path in the prompt as an absolute path. There are two patterns: + +1. **Read-only snapshot** — the caller has extracted TODO.md from a git ref (e.g. `git show main:TODO.md`) into a temp file like `/tmp/todo.abc123.md`. Read it but do **not** write to it. If the caller asks for an update, refuse and explain that the snapshot is read-only. +2. **Live worktree path** — the caller passes a path like `/path/to/worktree/TODO.md`. Both reads and writes are allowed. + +The caller indicates the mode in the prompt (e.g. "read-only snapshot at ..." vs. "live file at ..."). When the mode is unclear, default to read-only and ask. + +If no path is provided, fall back to `./TODO.md` relative to the current working directory. This fallback is for ad-hoc invocations only. + +If the file does not exist when an operation requires it: +- For read/list/update operations: report "TODO.md not found at " and stop. +- For create operations: create it with the header `# TODO\n\n` and proceed (only when in live mode). ## TODO.md Schema diff --git a/config/opencode/commands/review.md b/config/opencode/commands/review.md index 245a75e..77522e0 100644 --- a/config/opencode/commands/review.md +++ b/config/opencode/commands/review.md @@ -1,5 +1,5 @@ --- -description: review changes [commit|branch|pr|@plan], defaults to uncommitted +description: review changes [commit|branch|@plan], defaults to uncommitted subtask: true --- @@ -16,12 +16,11 @@ Classify the input into one of these modes: | Pattern | Mode | |---------|------| | Empty / no arguments | **code:uncommitted** | -| Contains `github.com` or `pull` or is a bare number (e.g. `42`) | **code:pr** | | Hex string 7-40 chars (e.g. `a1b2c3d`) | **code:commit** | | File content provided via `@` reference (look for file contents in context) | **plan** | | Otherwise, treat as branch name | **code:branch** | -Use best judgement when the input is ambiguous. +Use best judgement when the input is ambiguous. The command is forge-agnostic — review remote pull/merge requests by checking out the branch locally and passing the branch name (or by passing the merge-base commit). --- @@ -33,7 +32,6 @@ Run the appropriate git commands to get the diff: - **code:uncommitted**: `git diff` + `git diff --cached` + `git status --short` (read untracked files too) - **code:commit**: `git show $ARGUMENTS` - **code:branch**: `git diff $ARGUMENTS...HEAD` -- **code:pr**: `gh pr view $ARGUMENTS` + `gh pr diff $ARGUMENTS` Then: 1. Identify all changed files from the diff diff --git a/config/opencode/commands/workflow.md b/config/opencode/commands/workflow.md index 736758c..3a5997b 100644 --- a/config/opencode/commands/workflow.md +++ b/config/opencode/commands/workflow.md @@ -1,5 +1,5 @@ --- -description: "Fire-and-forget multi-agent workflow: plan, test, implement, PR" +description: "Fire-and-forget multi-agent workflow: plan, test, implement, commit" agent: build --- @@ -13,21 +13,33 @@ If `$ARGUMENTS` is empty, stop immediately: "Usage: `/workflow ` (e.g. ## Phase 1: Repo Setup -Verify you are at the bare repo root and the environment is ready. +Verify you are in a bare git repo and that the issue tracker exists. -1. Confirm `.bare/` directory exists in the current working directory. If not, stop: "Not at bare repo root. Run from the directory containing `.bare/`." -2. Verify the repo is hosted on GitHub: `git remote get-url origin 2>/dev/null | grep -qE '(github\.com|^git@github\.com:)'`. If the command fails (no `origin` remote, or origin is not on GitHub), stop: "Workflow requires a GitHub remote at `origin` (used by `gh pr create` in Phase 10)." -3. Run `gh auth status`. If auth is expired or missing, stop: "GitHub CLI auth expired. Run `gh auth login` before retrying." -4. Proceed to Phase 2 to get issue context before creating the worktree. +1. Verify the current repository is bare: `git rev-parse --is-bare-repository 2>/dev/null` must output `true`. If not, stop: "Workflow requires a bare git repository (set up with `git clone --bare` or the `.bare/` + `.git` file pattern)." +2. Capture the bare repo root for later worktree creation: `BARE_REPO_ROOT="$(pwd)"`. +3. Determine the default branch (source of TODO.md and base for new worktrees). Resolve in order: + a. `git symbolic-ref --short HEAD` — the bare repo's HEAD + b. `git config init.defaultBranch` — the configured default + c. fall back to `main` + + Store as `DEFAULT_BRANCH`. +4. Verify TODO.md exists on the default branch: `git show "$DEFAULT_BRANCH:TODO.md" > /dev/null 2>&1`. If not, stop: "TODO.md not found on `$DEFAULT_BRANCH`. Commit a TODO.md there first — the workflow expects it to be a tracked file." +5. Snapshot TODO.md to a temp file so `@pm` can read it before any worktree exists: + ```bash + TODO_READ_PATH="$(mktemp -t todo.XXXXXX.md)" + git show "$DEFAULT_BRANCH:TODO.md" > "$TODO_READ_PATH" + ``` + Pass `$TODO_READ_PATH` to `@pm` in Phase 2 (read-only context). +6. Proceed to Phase 2. --- ## Phase 2: Issue Context -Use `@pm` to fetch the issue matching `$ARGUMENTS` from `./TODO.md`: +Use `@pm` to fetch the issue matching `$ARGUMENTS` from the snapshot at `$TODO_READ_PATH`: - Issue title, description, acceptance criteria - Labels and priority -- Any existing branch name / PR link +- Any existing branch name If the issue does not exist or `@pm` fails, stop with error. @@ -37,13 +49,13 @@ Derive a branch name: `-` (e.g. `abc-1-add- ## Phase 3: Repo Setup (continued) -From the bare repo root (the directory containing `.bare/`): +From `$BARE_REPO_ROOT`: -1. `git fetch origin` +1. If an `origin` remote is configured, run `git fetch origin` (best-effort; ignore failure if there is no remote). 2. Compute worktree directory: replace all `/` with `-` in the branch name (e.g. `feat/abc-1-foo` becomes `feat-abc-1-foo`) 3. Check if worktree directory already exists. If yes, enter it and verify `git status --porcelain` is empty. If dirty, stop: "Worktree exists but has uncommitted changes. Clean it up first." -4. If worktree does not exist: `git worktree add -b master` -5. Change working directory to the new worktree. +4. If worktree does not exist: `git worktree add -b "$DEFAULT_BRANCH"` +5. Change working directory to the new worktree. From here on, `./TODO.md` in the worktree is the **live, writable** copy that Phase 10 will update. --- @@ -88,7 +100,7 @@ Reviewers should evaluate testability: 3. If verdict is ACCEPTABLE from both (or JUSTIFIED COMPLEXITY from `@simplify`): proceed to Phase 6 4. If BLOCK or NEEDS WORK: revise the plan addressing findings, then re-review 5. **Convergence detection:** if reviewers return the same findings as the previous cycle, stop the loop early -6. If still unresolved after 3 cycles: note unresolved blockers and proceed anyway (they will be documented in the PR) +6. If still unresolved after 3 cycles: note unresolved blockers and proceed anyway (they will be documented in the workflow summary and commit message) --- @@ -184,7 +196,7 @@ Dispatch `@check` and `@simplify` in parallel to review the full implementation Provide reviewers with: - The original plan -- The full diff (`git diff master...HEAD`) +- The full diff (`git diff "$DEFAULT_BRANCH"...HEAD`) - Any decisions or deviations from the plan **Review loop (max 3 cycles):** @@ -193,57 +205,53 @@ Provide reviewers with: 3. If ACCEPTABLE: proceed to Phase 10 4. If issues found: fix them directly (no need to re-dispatch `@make` for small fixes), then re-review 5. **Convergence detection:** same findings twice = stop loop early -6. If unresolved after 3 cycles: document blockers, proceed to PR anyway +6. If unresolved after 3 cycles: document blockers, proceed to commit anyway --- -## Phase 10: Commit, PR, and Wrap Up +## Phase 10: Commit and Wrap Up -### Commit -- Stage all changes -- Write a conventional commit message summarizing the implementation +The workflow is forge-agnostic. It commits locally and stops. **Do not push, and do not open a pull/merge request** — the user chooses their forge and review workflow manually. + +### Commit Code Changes +- Stage code changes (everything except `TODO.md` and `.opencode/workflow-summary.md`, which are committed separately below) +- Write a conventional commit message summarizing the implementation. Reference the TODO.md issue ID in the body (e.g. `Refs: ABC-1`). - If changes are large/varied, use multiple atomic commits (one per logical unit) -### Draft PR -- `gh pr create --draft --title "" --body ""` -- PR body should include: - - Summary of what was implemented - - Reference to TODO.md issue ID - - Acceptance criteria checklist (from issue) - - Files changed with brief descriptions - - TDD summary: X tasks with tests (RED→GREEN), Y tasks NOT_TESTABLE with justifications - - Any test quality escalations and their resolution - - Unresolved blockers (if any from review loops) - - Review cycle outcomes - ### TODO Update -- Use `@pm` to update the issue in `./TODO.md`: - - Set the **PR** field to the draft PR URL +- Use `@pm` to update the issue in `./TODO.md` (worktree-local; this is the live, writable copy): - Set **Branch** to the worktree branch name - Set **Status** to `In Review` - - Add a comment with the PR link and a one-line summary + - Add a comment with the branch name, latest commit SHA, and a one-line summary - If acceptance-criteria checkboxes were addressed by the implementation, ask `@pm` to check them off +- Commit the TODO.md change as a separate atomic commit: `chore(todo): update status and progress` ### Local Summary - Write `.opencode/workflow-summary.md` in the worktree with: - Run timestamp - Issue reference and title - - Branch and PR link + - Branch name and final commit SHA(s) - Summary of implementation - TDD evidence (RED→GREEN per task, NOT_TESTABLE justifications) - Review outcomes (plan review + final review verdicts) - Unresolved items (if any) - Files changed +- Commit the summary: `chore(workflow): summary for ` + +### Cleanup +- Remove the temp snapshot from Phase 1: `rm -f "$TODO_READ_PATH"` --- ## Failure Handling At any phase, if an unrecoverable error occurs: -1. Write `.opencode/workflow-summary.md` with what was completed and what failed +1. Write `.opencode/workflow-summary.md` (in the worktree, if one exists) with what was completed and what failed 2. If any code was written, commit it with message `wip: incomplete workflow run for ` -3. If a branch exists with commits, create the draft PR noting it is incomplete -4. Stop execution +3. Leave the branch and worktree intact for the user to inspect — do not push, do not delete +4. If a worktree exists, use `@pm` to add a comment on the issue in `./TODO.md` summarising what failed +5. Remove the temp snapshot if it was created: `rm -f "$TODO_READ_PATH"` +6. Stop execution **Never hang on interactive prompts.** If any command appears to require input, treat it as a failure and follow the above procedure. From 37be2d9505c101fff970803eda4672efe19c6331 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Wed, 6 May 2026 15:33:11 +0200 Subject: [PATCH 2/4] fix(opencode): remove agent models and temperature --- config/opencode/agents/check.md | 1 - config/opencode/agents/make.md | 2 -- config/opencode/agents/pm.md | 1 - config/opencode/agents/simplify.md | 2 -- config/opencode/agents/test.md | 2 -- 5 files changed, 8 deletions(-) diff --git a/config/opencode/agents/check.md b/config/opencode/agents/check.md index 3017641..eb8bd67 100644 --- a/config/opencode/agents/check.md +++ b/config/opencode/agents/check.md @@ -1,7 +1,6 @@ --- description: Design reviewer that systematically identifies risks, gaps, and flaws in plans, architectures, and PRs mode: subagent -model: openai/gpt-5.3-codex temperature: 0.4 tools: # Read-only: no write/edit/shell diff --git a/config/opencode/agents/make.md b/config/opencode/agents/make.md index 41e10f7..6780ffa 100644 --- a/config/opencode/agents/make.md +++ b/config/opencode/agents/make.md @@ -1,8 +1,6 @@ --- description: Implements discrete coding tasks from specs with acceptance criteria, verifying each implementation before completion mode: subagent -model: anthropic/claude-sonnet-4-6-1m -temperature: 0.2 tools: write: true edit: true diff --git a/config/opencode/agents/pm.md b/config/opencode/agents/pm.md index fa95269..a0124be 100644 --- a/config/opencode/agents/pm.md +++ b/config/opencode/agents/pm.md @@ -1,7 +1,6 @@ --- description: Project management agent that manages issues in a local TODO.md file (status, comments, acceptance criteria) mode: subagent -model: anthropic/claude-haiku-4-5 tools: read: true glob: true diff --git a/config/opencode/agents/simplify.md b/config/opencode/agents/simplify.md index 1b4b195..04d0977 100644 --- a/config/opencode/agents/simplify.md +++ b/config/opencode/agents/simplify.md @@ -1,8 +1,6 @@ --- description: Spots overengineering and unnecessary complexity. Proposes concrete simplifications. mode: subagent -model: openai/gpt-5.3-codex -temperature: 0.4 tools: # Read-only: no write/edit/shell write: false diff --git a/config/opencode/agents/test.md b/config/opencode/agents/test.md index b3d6b25..af8fad1 100644 --- a/config/opencode/agents/test.md +++ b/config/opencode/agents/test.md @@ -1,8 +1,6 @@ --- description: Writes meaningful failing tests from task specs using TDD, verifying RED before handing off to @make mode: subagent -model: anthropic/claude-sonnet-4-6-1m -temperature: 0.2 tools: write: true edit: true From d22acf690634883490b2117b6668e328e1804374 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Wed, 6 May 2026 15:42:17 +0200 Subject: [PATCH 3/4] refactor(opencode): let @pm read TODO.md via git show, drop tempfile Gives @pm narrowly-scoped bash access (git show *, git rev-parse *) so it can read TODO.md directly from any git ref. The workflow no longer needs to mktemp + redirect the file before invoking the agent; Phase 2 just tells @pm the bare repo path and default branch and lets it run git show "$DEFAULT_BRANCH:TODO.md" itself. Cleanup steps for the temp snapshot are removed from Phase 10 and the failure handler. --- config/opencode/agents/pm.md | 31 ++++++++++++++++++---------- config/opencode/commands/workflow.md | 15 +++----------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/config/opencode/agents/pm.md b/config/opencode/agents/pm.md index a0124be..e32342c 100644 --- a/config/opencode/agents/pm.md +++ b/config/opencode/agents/pm.md @@ -7,25 +7,34 @@ tools: grep: true write: true edit: true - bash: false + bash: true +permission: + bash: + "*": deny + "git show *": allow + "git rev-parse *": allow --- -You are a project management assistant. Your sole responsibility is reading and updating a `TODO.md` file. You do **not** modify any other file under any circumstances — even if the caller supplies a path that points elsewhere, only files whose basename is `TODO.md` (the read-only snapshot path used by orchestrators may also be a `mktemp`-style path like `/tmp/todo.XXXXXX.md`) are acceptable. +You are a project management assistant. Your sole responsibility is reading and updating a `TODO.md` file. You do **not** modify any other file under any circumstances. -## File Location +## How to Read TODO.md -The caller supplies the TODO.md path in the prompt as an absolute path. There are two patterns: +There are two ways to read TODO.md, depending on what the caller tells you: -1. **Read-only snapshot** — the caller has extracted TODO.md from a git ref (e.g. `git show main:TODO.md`) into a temp file like `/tmp/todo.abc123.md`. Read it but do **not** write to it. If the caller asks for an update, refuse and explain that the snapshot is read-only. -2. **Live worktree path** — the caller passes a path like `/path/to/worktree/TODO.md`. Both reads and writes are allowed. +1. **From a git ref** (used when there is no working tree, e.g. inside a bare repo) — run `git show :TODO.md` and parse stdout. Example: caller says "read TODO.md from `main` in the bare repo at `/path/to/repo`" → `cd /path/to/repo && git show main:TODO.md`. This is **read-only**: never attempt to update TODO.md when invoked in this mode. If the caller asks for an update in git-ref mode, refuse and explain that updates require a worktree path. +2. **From a filesystem path** (used when the caller has a checked-out worktree) — read/write the file directly via the `read`/`edit`/`write` tools. The caller supplies an absolute path like `/path/to/worktree/TODO.md`. -The caller indicates the mode in the prompt (e.g. "read-only snapshot at ..." vs. "live file at ..."). When the mode is unclear, default to read-only and ask. +The caller indicates the mode in the prompt. When the mode is ambiguous, default to read-only git-ref mode and ask. -If no path is provided, fall back to `./TODO.md` relative to the current working directory. This fallback is for ad-hoc invocations only. +If no path or ref is provided, fall back to `./TODO.md` relative to the current working directory (ad-hoc invocations only). -If the file does not exist when an operation requires it: -- For read/list/update operations: report "TODO.md not found at " and stop. -- For create operations: create it with the header `# TODO\n\n` and proceed (only when in live mode). +## Bash Discipline + +The only bash commands you may run are `git show :TODO.md` and `git rev-parse ` (for verifying refs/repo state). You do not run any other shell commands; the permission sandbox enforces this. + +If TODO.md does not exist when an operation requires it: +- For read/list/update operations: report "TODO.md not found at " and stop. +- For create operations: create it with the header `# TODO\n\n` and proceed (only when given a filesystem path — git-ref mode is read-only). ## TODO.md Schema diff --git a/config/opencode/commands/workflow.md b/config/opencode/commands/workflow.md index 3a5997b..9bcd0af 100644 --- a/config/opencode/commands/workflow.md +++ b/config/opencode/commands/workflow.md @@ -24,19 +24,13 @@ Verify you are in a bare git repo and that the issue tracker exists. Store as `DEFAULT_BRANCH`. 4. Verify TODO.md exists on the default branch: `git show "$DEFAULT_BRANCH:TODO.md" > /dev/null 2>&1`. If not, stop: "TODO.md not found on `$DEFAULT_BRANCH`. Commit a TODO.md there first — the workflow expects it to be a tracked file." -5. Snapshot TODO.md to a temp file so `@pm` can read it before any worktree exists: - ```bash - TODO_READ_PATH="$(mktemp -t todo.XXXXXX.md)" - git show "$DEFAULT_BRANCH:TODO.md" > "$TODO_READ_PATH" - ``` - Pass `$TODO_READ_PATH` to `@pm` in Phase 2 (read-only context). -6. Proceed to Phase 2. +5. Proceed to Phase 2. --- ## Phase 2: Issue Context -Use `@pm` to fetch the issue matching `$ARGUMENTS` from the snapshot at `$TODO_READ_PATH`: +Dispatch `@pm` in **read-only git-ref mode**: tell it the bare repo path is `$BARE_REPO_ROOT` and to read TODO.md via `git show "$DEFAULT_BRANCH:TODO.md"`. Ask for the issue matching `$ARGUMENTS`: - Issue title, description, acceptance criteria - Labels and priority - Any existing branch name @@ -238,8 +232,6 @@ The workflow is forge-agnostic. It commits locally and stops. **Do not push, and - Files changed - Commit the summary: `chore(workflow): summary for ` -### Cleanup -- Remove the temp snapshot from Phase 1: `rm -f "$TODO_READ_PATH"` --- @@ -250,8 +242,7 @@ At any phase, if an unrecoverable error occurs: 2. If any code was written, commit it with message `wip: incomplete workflow run for ` 3. Leave the branch and worktree intact for the user to inspect — do not push, do not delete 4. If a worktree exists, use `@pm` to add a comment on the issue in `./TODO.md` summarising what failed -5. Remove the temp snapshot if it was created: `rm -f "$TODO_READ_PATH"` -6. Stop execution +5. Stop execution **Never hang on interactive prompts.** If any command appears to require input, treat it as a failure and follow the above procedure. From 28c7785816e228da5fbd2d5c765a0e69f53f4f48 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Wed, 6 May 2026 15:56:45 +0200 Subject: [PATCH 4/4] fix(opencode): pass absolute worktree path to every subagent dispatch Subagents do not inherit the orchestrator's `cd`, so dispatched prompts that referred to files relative to the worktree were resolved against the bare repo root and failed with "file not found" (observed when @check tried to read src/main.rs after Phase 3). Phase 3 now captures `WORKTREE_PATH="$(pwd)"` after entering the worktree. A new "Subagent Dispatch Convention" section requires every dispatch in phases 5, 7, 8, 9, and 10 to open with `Worktree: ` and pass file references as absolute paths under `$WORKTREE_PATH/`. Phase 9's diff command uses `git -C "$WORKTREE_PATH"` rather than relying on shell CWD, and @pm updates receive the explicit absolute path to `$WORKTREE_PATH/TODO.md`. --- config/opencode/commands/workflow.md | 34 ++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/config/opencode/commands/workflow.md b/config/opencode/commands/workflow.md index 9bcd0af..0009a63 100644 --- a/config/opencode/commands/workflow.md +++ b/config/opencode/commands/workflow.md @@ -49,7 +49,21 @@ From `$BARE_REPO_ROOT`: 2. Compute worktree directory: replace all `/` with `-` in the branch name (e.g. `feat/abc-1-foo` becomes `feat-abc-1-foo`) 3. Check if worktree directory already exists. If yes, enter it and verify `git status --porcelain` is empty. If dirty, stop: "Worktree exists but has uncommitted changes. Clean it up first." 4. If worktree does not exist: `git worktree add -b "$DEFAULT_BRANCH"` -5. Change working directory to the new worktree. From here on, `./TODO.md` in the worktree is the **live, writable** copy that Phase 10 will update. +5. Change working directory to the new worktree and capture its absolute path: `WORKTREE_PATH="$(pwd)"`. From here on, `$WORKTREE_PATH/TODO.md` is the **live, writable** copy that Phase 10 will update. + +--- + +## Subagent Dispatch Convention + +**Subagents do not inherit the orchestrator's `cd`.** When opencode dispatches `@check`, `@simplify`, `@test`, `@make`, or `@pm`, each starts with a fresh shell in an unspecified working directory and may resolve relative paths against the bare repo root rather than the worktree. This produces silent "file not found" failures for paths like `src/main.rs`. + +**Every dispatch prompt in Phases 5, 7, 8, 9, and 10 must:** + +1. Open with the header `Worktree: ` using the captured `$WORKTREE_PATH`. +2. State explicitly: "All file paths in this prompt are relative to that worktree. Read files via their absolute path (`/`); do not rely on the current working directory." +3. Pass any file reference (in code context, diff snippets, file lists) as an absolute path under `$WORKTREE_PATH/`. + +`@pm` invocations that update TODO.md must receive `$WORKTREE_PATH/TODO.md` as the live path. `@pm` invocations that only read from a git ref (Phase 2) instead receive `$BARE_REPO_ROOT` and the ref name. --- @@ -77,7 +91,7 @@ The plan should include: ## Phase 5: Review Plan -Dispatch `@check` and `@simplify` in parallel to review the plan. +Dispatch `@check` and `@simplify` in parallel to review the plan. Each dispatch prompt must follow the **Subagent Dispatch Convention** (header `Worktree: $WORKTREE_PATH`, absolute paths only). Reviewers should evaluate testability: - `@check`: Is the design testable? Are the right behaviors identified? (Review Framework §8) @@ -120,10 +134,10 @@ Include **Test Design** from Phase 4 when available, attached to the relevant ta ## Phase 7: Write Tests -For each task from Phase 6, dispatch `@test` with: +For each task from Phase 6, dispatch `@test` with (per the **Subagent Dispatch Convention** — `Worktree: $WORKTREE_PATH`, absolute paths): - The task spec (acceptance criteria, code context, files to modify) - The Test Design section from the plan (if provided) -- The test file path to create (following colocated pattern) +- The test file path to create as an absolute path under `$WORKTREE_PATH/` (following colocated pattern) `@test` writes failing tests and verifies RED with structured failure codes. @@ -156,9 +170,9 @@ If any non-matching file appears: discard `@test` output, report violation. ## Phase 8: Implement -Execute each task by dispatching `@make` with: +Execute each task by dispatching `@make` with (per the **Subagent Dispatch Convention** — `Worktree: $WORKTREE_PATH`, absolute paths): - The task spec (from Phase 6) -- Relevant code context (actual snippets) +- Relevant code context (actual snippets, with absolute file paths under `$WORKTREE_PATH/`) - **Pre-written failing tests and handoff from `@test` (if TESTS_READY)** `@make` runs in TDD mode when tests are provided: @@ -186,11 +200,11 @@ After all tasks complete, verify overall integration: ## Phase 9: Final Review -Dispatch `@check` and `@simplify` in parallel to review the full implementation (all changes across all files). +Dispatch `@check` and `@simplify` in parallel to review the full implementation (all changes across all files). Each dispatch prompt must follow the **Subagent Dispatch Convention** (header `Worktree: $WORKTREE_PATH`, absolute paths only). Provide reviewers with: - The original plan -- The full diff (`git diff "$DEFAULT_BRANCH"...HEAD`) +- The full diff (`git -C "$WORKTREE_PATH" diff "$DEFAULT_BRANCH"...HEAD`) - Any decisions or deviations from the plan **Review loop (max 3 cycles):** @@ -213,7 +227,7 @@ The workflow is forge-agnostic. It commits locally and stops. **Do not push, and - If changes are large/varied, use multiple atomic commits (one per logical unit) ### TODO Update -- Use `@pm` to update the issue in `./TODO.md` (worktree-local; this is the live, writable copy): +- Dispatch `@pm` (per the **Subagent Dispatch Convention**) and pass the live path `$WORKTREE_PATH/TODO.md` so it edits the worktree's writable copy. Ask it to: - Set **Branch** to the worktree branch name - Set **Status** to `In Review` - Add a comment with the branch name, latest commit SHA, and a one-line summary @@ -241,7 +255,7 @@ At any phase, if an unrecoverable error occurs: 1. Write `.opencode/workflow-summary.md` (in the worktree, if one exists) with what was completed and what failed 2. If any code was written, commit it with message `wip: incomplete workflow run for ` 3. Leave the branch and worktree intact for the user to inspect — do not push, do not delete -4. If a worktree exists, use `@pm` to add a comment on the issue in `./TODO.md` summarising what failed +4. If a worktree exists, dispatch `@pm` (with header `Worktree: $WORKTREE_PATH` and the absolute path `$WORKTREE_PATH/TODO.md`) to add a comment on the issue summarising what failed 5. Stop execution **Never hang on interactive prompts.** If any command appears to require input, treat it as a failure and follow the above procedure.