`git diff --name-only` only shows tracked files with unstaged modifications. It does not show untracked files — which is precisely the state of any new test file @test creates, since @test's sandbox denies `git add`. The pre/post snapshots therefore both missed new files entirely and `comm -23 post pre` returned nothing, letting the gate cheerfully conclude nothing changed even when @test had just created tests/foo.rs (or, worse, src/lib.rs). Switch both snapshots to `git status --porcelain | sed 's/^...//' | sort -u`, which captures modified, staged, and untracked files in a single pass. Inline rationale notes the untracked blind spot so the orchestrator does not fall back to git diff.
392 lines
23 KiB
Markdown
392 lines
23 KiB
Markdown
---
|
||
description: "Multi-agent workflow for the current worktree: plan, test, implement, commit"
|
||
agent: build
|
||
---
|
||
|
||
You are executing the multi-agent workflow inside the worktree this opencode session was started from. Run all phases without waiting for user input. The user has walked away.
|
||
|
||
**Prerequisites (the user handles before launching opencode):**
|
||
- A git worktree is checked out for the issue's feature branch
|
||
- `opencode` was launched from the root of that worktree
|
||
- `TODO.md` is committed to the repo and present at `./TODO.md`
|
||
|
||
**Task reference:** $ARGUMENTS
|
||
|
||
If `$ARGUMENTS` is empty, stop immediately: "Usage: `/workflow <ISSUE-ID> [base-branch]` (e.g. `/workflow ABC-1`). The ID must exist in `./TODO.md`. Base branch defaults to `main` (then `master`)."
|
||
|
||
Parse `$ARGUMENTS`: the first whitespace-separated token is the issue ID, an optional second token overrides the base branch.
|
||
|
||
---
|
||
|
||
## Phase 1: Sanity Check
|
||
|
||
1. Verify CWD is a non-bare git worktree: `git rev-parse --is-bare-repository 2>/dev/null` must output `false`. If not, stop: "Workflow must be run from a non-bare worktree (the directory opencode was launched in)."
|
||
2. Verify `./TODO.md` exists. If not, stop: "TODO.md not found in the current worktree. Commit a TODO.md to the repo first."
|
||
3. Verify HEAD is not detached: `git symbolic-ref --short HEAD` must succeed. If it fails, stop: "Cannot run on a detached HEAD. Check out a feature branch first."
|
||
4. Capture the current branch: `BRANCH_NAME="$(git symbolic-ref --short HEAD)"`.
|
||
5. Resolve the base branch (`BASE_BRANCH`):
|
||
- If `$ARGUMENTS` provided a second token, use it.
|
||
- Else if `git rev-parse --verify --quiet main` succeeds, use `main`.
|
||
- Else if `git rev-parse --verify --quiet master` succeeds, use `master`.
|
||
- Else stop: "Could not determine base branch (no `main` or `master`). Pass it as the second argument: `/workflow <ISSUE-ID> <base-branch>`."
|
||
6. Verify the current branch is not the base branch: if `BRANCH_NAME == BASE_BRANCH`, stop: "Cannot run workflow on the base branch (`$BASE_BRANCH`). Switch to a feature branch first."
|
||
|
||
---
|
||
|
||
## Phase 2: Issue Context
|
||
|
||
Dispatch `@pm` to read `./TODO.md` (live filesystem mode) and fetch the issue matching the parsed ID:
|
||
- Issue title, description, acceptance criteria
|
||
- Labels and priority
|
||
- Existing status
|
||
|
||
If the issue does not exist or `@pm` fails, stop with error.
|
||
|
||
If the issue's status is `Backlog` or `Todo`, ask `@pm` to set it to `In Progress` (this edit will be staged in Phase 9 alongside other TODO.md updates).
|
||
|
||
---
|
||
|
||
## Phase 3: Plan
|
||
|
||
Analyze the codebase. Create a detailed implementation plan addressing the issue's requirements and acceptance criteria.
|
||
|
||
The plan should include:
|
||
- Problem summary (from issue context)
|
||
- Proposed approach with rationale
|
||
- Files to modify (with brief description of changes)
|
||
- New files to create
|
||
- Risks and open questions
|
||
- **Test Design (conditional — include for non-trivial tasks):**
|
||
- Key behaviors to verify (what tests should assert)
|
||
- Edge cases and error conditions worth testing
|
||
- What explicitly should NOT be tested (prevents bloat)
|
||
- Testability concerns (heavy external deps, GPU-only paths, etc.)
|
||
|
||
**Include Test Design for:** Public API changes, bug fixes with behavioral impact, new features with business logic, multi-module changes.
|
||
**Skip Test Design for:** Config-only changes, decorator swaps, import reorganization, documentation.
|
||
When skipped, `@test` derives test cases directly from acceptance criteria.
|
||
|
||
After drafting, apply **Dispatch Hygiene** (below) to the plan — it is a dispatch artifact and gets sent to `@check`/`@simplify` in Phase 4.
|
||
|
||
---
|
||
|
||
## Dispatch Hygiene
|
||
|
||
This applies to **every** subagent dispatch (Phases 4, 6, 7, 8) **and** to artifacts that will be dispatched (the plan from Phase 3, the task specs from Phase 5). Apply these checks before sending — fix the artifact, then re-check.
|
||
|
||
### Finalized-Text Rule
|
||
|
||
The artifact must be **finalized** — single-author text, no contradictions, no open questions. Forbidden:
|
||
|
||
- "Actually, that's wrong — let me correct…"
|
||
- "Wait, let me reconsider…"
|
||
- Two versions of the same code block, one labelled "corrected" or appearing after a revision pass
|
||
- Open questions or ambiguities the orchestrator hasn't resolved
|
||
- Mid-text revisions visible to the recipient
|
||
|
||
If you find yourself revising while writing, stop, redo the artifact from scratch with the corrected understanding, and only then dispatch. Subagents are fresh-context — they cannot reliably resolve which of two contradictory drafts is canonical, and reviewers cannot give a clean verdict on a self-contradicting plan.
|
||
|
||
### No-Implementation-in-Plan-or-Spec Rule
|
||
|
||
Plans (Phase 3) and task specs (Phase 5) are **not** the place to write the answer. They describe what to do; `@make` writes how.
|
||
|
||
Provide:
|
||
- Approach with rationale
|
||
- Files to modify with brief descriptions
|
||
- Function signatures, type declarations, data shapes (structure, not logic)
|
||
- Constraints, invariants, integration contracts
|
||
- Risks and edge cases
|
||
|
||
Do **not** provide:
|
||
- Drop-in code blocks longer than ~5 lines that constitute "the answer"
|
||
- Full function bodies for the changes being planned
|
||
- Complete `match` arms / branch logic / loop bodies for new behavior
|
||
- Pre-written test bodies (those come from `@test`, or from `@make` for Rust unit-only)
|
||
- Stage-by-stage code transformations spelled out as ready-to-commit diffs
|
||
|
||
If you've already written the implementation in the plan or spec, the artifact has overstepped. Convert finished code into structural description (signature + intent) and let `@make` produce the body.
|
||
|
||
**Allowed in plans/specs:**
|
||
- Existing code being replaced, marked as "current state"
|
||
- Function signatures and type/struct/enum declarations (data, not logic)
|
||
- Tiny inline constants (`pub const FOO: f32 = 30.0;`)
|
||
- Test specifications as one-line behavior descriptions ("input X → expect Y")
|
||
|
||
### Pre-Dispatch Validation (MANDATORY)
|
||
|
||
Scan the artifact and reject (revise, retry) if any of the following are present:
|
||
|
||
| Check | Why it matters |
|
||
|---|---|
|
||
| `bash -c`, `sh -c`, `zsh -c`, `fish -c` (anywhere, including inside `nix develop --command bash -c …`) | `@make`/`@test` sandboxes deny all `*-c` shell invocations and any nested `bash` would bypass the per-command allowlist. Replace with one direct command per line: `nix develop -c cargo check`, etc. |
|
||
| `nix develop --command bash` / `nix develop -c bash` / `nix develop -c sh` | Same — inner shell escapes the sandbox. Wrap each toolchain command directly. |
|
||
| Any `cd <path> && …` | Subagents cannot `cd`. Rewrite to use absolute paths. |
|
||
| Code blocks longer than ~5 lines that draft the answer | Violates No-Implementation-in-Plan-or-Spec. Trim to structure (signature + "current state" only). |
|
||
| Two versions of the same code, "actually let me correct…", or open questions | Violates the Finalized-Text Rule. Redo the artifact. |
|
||
| Test bodies inside `@make` specs when tests are coming from `@test` | Duplicates the TDD handoff. |
|
||
|
||
If any check trips, **do not dispatch.** Fix and re-validate. Repeated trips on a single task signal a Phase 5 split problem — go back and split.
|
||
|
||
---
|
||
|
||
## Phase 4: Review Plan
|
||
|
||
Apply **Dispatch Hygiene** to the plan and to each reviewer prompt before sending. Dispatch `@check` and `@simplify` in parallel to review the plan.
|
||
|
||
Reviewers should evaluate testability:
|
||
- `@check`: Is the design testable? Are the right behaviors identified? (Review Framework §8)
|
||
- `@simplify`: Is the test scope appropriate? Over-testing proposed?
|
||
|
||
**Merge rules:**
|
||
- `@check` safety/correctness findings are hard constraints
|
||
- If `@simplify` recommends removing something `@check` flags as needed, `@check` wins
|
||
- Note conflicts explicitly
|
||
|
||
**Review loop (max 3 cycles):**
|
||
1. Send plan to both reviewers
|
||
2. Merge findings
|
||
3. If verdict is ACCEPTABLE from both (or JUSTIFIED COMPLEXITY from `@simplify`): proceed to Phase 5
|
||
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 workflow summary and commit message)
|
||
|
||
---
|
||
|
||
## Phase 5: Split into Tasks
|
||
|
||
Break the approved plan into discrete tasks for `@make`. Each task needs:
|
||
|
||
| Required | Description |
|
||
|----------|-------------|
|
||
| **Task** | Clear description of what to implement |
|
||
| **Acceptance Criteria** | Specific, testable criteria (checkbox format) |
|
||
| **Code Context** | Actual code snippets from the codebase, not just file paths |
|
||
| **Files to Modify** | Explicit list, mark new files with "(create)" |
|
||
| **Test File** | Path for test file. **Pick the pattern that matches the project's language** — see "Test File Path by Language" below. |
|
||
|
||
### Test File Path by Language
|
||
|
||
The test file path must follow the language's actual test layout. **Do not invent paths that look colocated but aren't valid for the language** (e.g. `src/tests/test_<feature>.rs` is *not* a Rust test location — it's a regular `src/` submodule).
|
||
|
||
- **Python**
|
||
- Colocated: `<module>/tests/test_<feature>.py (create)`
|
||
- Top-level: `tests/test_<feature>.py (create)`
|
||
- **Rust**
|
||
- Crate-level integration tests: `tests/<feature>.rs (create)` (or, in a workspace, `<crate>/tests/<feature>.rs`).
|
||
- **If the test references not-yet-existing public API**, the task automatically requires a **stub-first `@make` pre-pass** before `@test` runs (see Phase 6 → "Rust integration TDD: stub-first"). Plan for two `@make` dispatches per such task: stub pass, then body pass.
|
||
- **Unit-test-only tasks (in-source `#[cfg(test)] mod tests`):** mark the task as `NOT_TESTABLE` with reason `Rust unit-only` — `@test` cannot write inside production source. `@make` writes those inline as part of its production change.
|
||
- **Polyglot Nix flake**
|
||
- Match the host language of the code under change (Python or Rust rules above), wrapping commands in `nix develop -c …` per the agents' devshell rule.
|
||
|
||
Include **Integration Contracts** when a task adds/changes function signatures, APIs, config keys, or has dependencies on other tasks.
|
||
|
||
Include **Test Design** from Phase 3 when available, attached to the relevant task(s).
|
||
|
||
**Task size:** ~10-30 minutes each, single coherent change, clear boundaries.
|
||
|
||
### Split Heuristic — when in doubt, split
|
||
|
||
A task must be **split** if any of the following apply:
|
||
|
||
- It touches more than two distinct concerns (e.g. *constants + new component + sprite spawn + new system + main wiring* is **five** concerns — at least three tasks).
|
||
- It changes more than ~50 lines across more than 2 files.
|
||
- It mixes data/structural changes (constants, types, components) with runtime/system changes (new ECS systems, scheduling, render loops).
|
||
- It mixes pure-logic changes (math helpers) with stateful changes (queries, world mutation).
|
||
- It mixes new APIs with their first call sites in the same task.
|
||
|
||
When a task fails the heuristic, split into:
|
||
1. **Foundations** — new constants, types, components (no behavior change yet).
|
||
2. **Implementation** — the actual production logic, calling the foundations.
|
||
3. **Wiring** — registration in `main.rs` / `lib.rs` / app-builder.
|
||
|
||
Each split is dispatched separately to `@make` and verified before the next.
|
||
|
||
### Code Context — what to include
|
||
|
||
The **Code Context** field exists so `@make` can find the seam to modify. Provide:
|
||
|
||
- The existing code being replaced (verbatim, marked as "current state"), with ~5–10 lines of surrounding context
|
||
- Function signatures of helpers `@make` will need to call
|
||
- The file's relevant import block
|
||
|
||
For everything you must **not** include — drop-in replacements, full function bodies, pre-written test bodies, "here is what to write" — see **Dispatch Hygiene → No-Implementation-in-Plan-or-Spec Rule** above.
|
||
|
||
If the task is so well-specified that you've already written the implementation, the task is too small for `@make` (apply it directly) or you've over-determined the design (revisit Phase 3).
|
||
|
||
Apply **Dispatch Hygiene** to each task spec before dispatch in Phase 7.
|
||
|
||
---
|
||
|
||
## Phase 6: Write Tests
|
||
|
||
Apply **Dispatch Hygiene** to each `@test` prompt before sending.
|
||
|
||
For each task from Phase 5, dispatch `@test` with:
|
||
- 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)
|
||
|
||
`@test` writes failing tests and verifies RED with structured failure codes.
|
||
|
||
**Post-step file gate (MANDATORY):**
|
||
Before dispatching `@test`, snapshot every modified, staged, *and untracked* file. `git diff --name-only` alone misses untracked files, which is precisely the state of any new test file `@test` creates (it cannot `git add`). Use `git status --porcelain` so the gate sees them:
|
||
```bash
|
||
git status --porcelain | sed 's/^...//' | sort -u > /tmp/pre_test_baseline.txt
|
||
```
|
||
After `@test` completes, list NEW changes (in the post-snapshot but not the pre-snapshot):
|
||
```bash
|
||
git status --porcelain | sed 's/^...//' | sort -u | comm -23 - /tmp/pre_test_baseline.txt > /tmp/test_new_files.txt
|
||
```
|
||
Each line in `/tmp/test_new_files.txt` is a file path that did not exist (or was unmodified) before `@test` ran. The gate validates each one against the patterns below.
|
||
All new files must match the project's test patterns:
|
||
- Python: `**/test_*.py`, `**/*_test.py`, `**/conftest.py` (new only), `**/test_data/**`, `**/test_fixtures/**`
|
||
- Rust: `tests/**/*.rs`, `**/tests/**/*.rs` (workspace-style `<crate>/tests/...`), `**/test_data/**`, `**/test_fixtures/**`
|
||
|
||
**Anti-patterns — discard the output even if the glob matches:**
|
||
- Anything under `src/` for Rust (e.g. `src/tests/foo.rs`, `src/**/tests/...`). `src/tests/` is a regular module path under `src/`, not a Rust test location, and `@test` cannot wire it up via `mod` declarations in production source. Such paths indicate the task spec gave a wrong test path — escalate, don't accept the file.
|
||
|
||
If any non-matching file appears, or any anti-pattern matches: discard `@test` output, report violation.
|
||
|
||
**Decision table — handling `@test` results:**
|
||
|
||
| Condition | Action |
|
||
|-----------|--------|
|
||
| `TESTS_READY` + `escalate_to_check: false` | Proceed to Phase 7 |
|
||
| `TESTS_READY` + `escalate_to_check: true` | Route tests to `@check` for light review. `@check` diagnoses, caller routes fixes to `@test`. Then proceed. |
|
||
| `NOT_TESTABLE` (general reasons) | Route to `@check` for sign-off on justification. If approved, task goes to `@make` without tests. |
|
||
| `NOT_TESTABLE` reason `Rust unit-only` | See "Rust unit-only routing" below. **Do not** include test code in the `@make` spec; pass test specs only. |
|
||
| `BLOCKED` | Investigate. May need to revise task spec or plan. |
|
||
| Test passes immediately | Investigate — behavior may already exist. Task spec may be wrong. |
|
||
|
||
### Rust unit-only routing
|
||
|
||
When `@test` returns `NOT_TESTABLE: Rust unit-only` (the implementation needs in-source `#[cfg(test)] mod tests` blocks that `@test` is forbidden from writing), the orchestrator must:
|
||
|
||
1. Get `@check`'s sign-off on the justification (no integration-test seam exists).
|
||
2. Build the `@make` spec with **test specifications**, not test code:
|
||
- "Add `#[cfg(test)] mod foo_tests` at the bottom of `<file>` exercising:"
|
||
- For each behavior, a one-line description: input → expected output, edge case to cover, error path to assert.
|
||
- Where applicable, name the function under test and the assertion type (`assert_eq!`, `assert!`, panic on invalid input).
|
||
3. **Forbidden in the `@make` spec:** complete `#[test] fn …` bodies, full module blocks, or any `@test`-style RED-verified test code. `@make` writes the inline tests itself based on the spec.
|
||
4. After `@make` completes, the orchestrator runs the test suite once to confirm RED→GREEN evidence and includes it in the workflow summary.
|
||
|
||
This keeps the agents in their lanes: `@test` never writes inside `src/`, `@make` writes both the tests and the production code in a single coherent change, and the orchestrator sees explicit test pass evidence.
|
||
|
||
### Rust integration TDD: stub-first (mandatory)
|
||
|
||
Rust integration tests live in a separate test crate (`tests/<feature>.rs`) that imports from `lib.rs`. Any test referencing not-yet-existing public API can only RED at *build* time, which masks assertion diagnostics. To avoid this, **for every Rust task whose `@test` step writes an integration test against public API that does not yet exist**, dispatch a stub-first `@make` pass *before* `@test` runs:
|
||
|
||
**Stub pass (split from Phase 7's body pass):**
|
||
|
||
1. Dispatch `@make` in **standard mode** (no tests exist yet) with this exact scope:
|
||
- **Goal:** add the planned public API as `todo!()`-bodied stubs so the integration test will compile.
|
||
- **Files to modify:** `src/lib.rs` (add `pub mod …;` declarations) plus any new `src/<module>.rs` files containing the stub functions/structs.
|
||
- **Stubs only:** every function body is exactly `todo!()`. Every method body is exactly `todo!()`. Public structs may use `pub struct Foo;` or `pub struct Foo { /* fields TBD */ }` — but no logic.
|
||
- **Signatures must match the planned final API exactly** (return types, lifetimes, generics) — otherwise the integration test will mismatch later. Lift signatures from the Phase 3 plan / Phase 5 task spec.
|
||
- **Acceptance criteria:** `cargo check` (wrapped in `nix develop -c …` if the project has a devshell) passes; no test command is run.
|
||
- **Dispatch Hygiene still applies:** the stub pass is small and finalized — no draft bodies, no contradictory signatures.
|
||
2. Verify `cargo check` passed in `@make`'s output. If not, fix and re-dispatch the stub pass before continuing.
|
||
3. Dispatch `@test` as normal. The integration test now compiles; running it panics on `todo!()` at runtime, which is a clean `MISSING_BEHAVIOR` RED with a stack trace — far better than the build-error-RED form.
|
||
4. Continue to Phase 7's body pass (`@make` in TDD mode), where the same files are revisited and the `todo!()` bodies are replaced.
|
||
|
||
**This routing is mandatory** for new public API in Rust. It is **not** required when the integration test exercises an existing public API (e.g. a behavior fix where the function already exists) — in that case `@test` runs directly and `@make` modifies the body in Phase 7.
|
||
|
||
The stub pass and the body pass each produce their own atomic commit (per Phase 9 rules): `feat(<scope>): scaffold <thing> with todo!() stubs` followed by `feat(<scope>): implement <thing>` (or whichever conventional type fits).
|
||
|
||
**Parallelism:** Independent tasks can have tests written in parallel.
|
||
**Constraint:** `@test` must not modify existing conftest.py files (prevents collision during parallel execution).
|
||
|
||
---
|
||
|
||
## Phase 7: Implement
|
||
|
||
Apply **Dispatch Hygiene** to each `@make` spec before sending. Repeated trips on a single task signal a Phase 5 split problem — go back and split.
|
||
|
||
Execute each task by dispatching `@make` with:
|
||
- The task spec (from Phase 5, finalized per Dispatch Hygiene)
|
||
- Relevant code context (seam-revealing snippets only — see Phase 5 "Code Context — what to include")
|
||
- **Pre-written failing tests and handoff from `@test` (if TESTS_READY)**
|
||
|
||
`@make` runs in TDD mode when tests are provided:
|
||
1. Entry validation: run tests, verify RED, check failure codes match handoff
|
||
2. Implement minimal code to make tests pass (GREEN)
|
||
3. Regression check on broader area
|
||
4. Refactor while keeping green
|
||
5. Report RED→GREEN evidence
|
||
|
||
**Escalation:** If `@make` flags test quality concerns during entry validation:
|
||
1. `@make` reports the issue to caller
|
||
2. Caller routes to `@check` for diagnosis
|
||
3. `@check` reports findings
|
||
4. Caller routes to `@test` for fixes
|
||
5. Fixed tests return to `@make`
|
||
|
||
For NOT_TESTABLE tasks, `@make` runs in standard mode.
|
||
|
||
After all tasks complete, verify overall integration:
|
||
- Run the project's test suite if available
|
||
- Run linting/type checking if configured
|
||
- Fix any integration issues between tasks
|
||
|
||
---
|
||
|
||
## Phase 8: Final Review
|
||
|
||
Apply **Dispatch Hygiene** to each reviewer prompt before sending. Dispatch `@check` and `@simplify` in parallel to review the full implementation (all changes across all files).
|
||
|
||
Provide reviewers with:
|
||
- The original plan
|
||
- The full diff (`git diff "$BASE_BRANCH"...HEAD`)
|
||
- Any decisions or deviations from the plan
|
||
|
||
**Review loop (max 3 cycles):**
|
||
1. Send implementation to both reviewers
|
||
2. Merge findings (same precedence rules as Phase 4)
|
||
3. If ACCEPTABLE: proceed to Phase 9
|
||
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 commit anyway
|
||
|
||
---
|
||
|
||
## Phase 9: Commit and Wrap Up
|
||
|
||
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 only. **Do not stage `TODO.md`** (committed separately below) and **do not stage `.opencode/workflow-summary.md`** (intentionally never committed — see Local Summary).
|
||
- 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)
|
||
|
||
### TODO Update
|
||
- Dispatch `@pm` against `./TODO.md` (live filesystem mode). Ask it to:
|
||
- Set **Branch** to `$BRANCH_NAME`
|
||
- Set **Status** to `In Review`
|
||
- 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 <issue-id> status and progress`
|
||
|
||
### Local Summary
|
||
- Write `.opencode/workflow-summary.md` in the worktree with:
|
||
- **Run timestamp** — capture it from the shell at write time: `date -Iseconds` (e.g. `2026-05-07T11:24:13+02:00`). **Do not** use a placeholder like `???:???:??` or "session date" — if you cannot get a real timestamp, omit the field entirely rather than fabricating one.
|
||
- Issue reference and title
|
||
- 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
|
||
- **Do not commit this file.** It is a per-run, per-branch artifact; committing it would create merge conflicts whenever multiple workflow branches are merged. Leave it untracked. Recommend the user add `.opencode/` to `.gitignore` if not already.
|
||
|
||
---
|
||
|
||
## Failure Handling
|
||
|
||
At any phase, if an unrecoverable error occurs:
|
||
1. Write `.opencode/workflow-summary.md` with what was completed and what failed. Do **not** stage or commit this file.
|
||
2. If any code was written, commit it with message `wip: incomplete workflow run for <issue-id>`. Stage code only — exclude `.opencode/workflow-summary.md`.
|
||
3. Leave the branch and worktree intact for the user to inspect — do not push, do not delete.
|
||
4. Dispatch `@pm` against `./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.
|