diff --git a/config/opencode/commands/workflow.md b/config/opencode/commands/workflow.md index b71f0bd..464b02d 100644 --- a/config/opencode/commands/workflow.md +++ b/config/opencode/commands/workflow.md @@ -14,25 +14,56 @@ You are executing the multi-agent workflow inside the worktree this opencode ses If `$ARGUMENTS` is empty, stop immediately: "Usage: `/workflow [base-branch]` (e.g. `/workflow ABC-1`). The ID must exist as `./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. +Parse `$ARGUMENTS`: the first whitespace-separated token is the issue ID, an optional second token overrides the base branch. Store as `ISSUE_ID`. + +--- + +## Run Artifacts + +The orchestrator writes plan and task-spec artifacts to a per-run directory in the worktree. Subagents read these by absolute path rather than from inline prompt text. This keeps dispatch prompts small, eliminates paraphrase drift between dispatches (`@check` and `@simplify` see the same plan byte-for-byte), and gives Dispatch Hygiene's Finalized-Text Rule a physical anchor — the file *is* the final version. + +**Directory layout** (relative to `$WORKTREE_PATH`): + +``` +.workflow/ +└── run-/ + ├── plan.md # Phase 3 output — finalized + ├── task-1.md # Phase 5 output — one file per task + ├── task-2.md + └── summary.md # Phase 9 output (the run summary) +``` + +Define `RUN_DIR="$WORKTREE_PATH/.workflow/run-$ISSUE_ID"` once in Phase 1 and reference it everywhere downstream. Create the directory in Phase 3 (`mkdir -p "$RUN_DIR"`). + +**Authoring rules:** +- Files are written by the orchestrator, never by subagents. +- Files are passed to subagents as absolute paths: e.g. *"the plan is at `/plan.md`; read it before responding."* The dispatch prompt body should be short — agent role, artifact path, per-dispatch context (worktree path, branch, base branch). **Do not quote artifact contents inline.** +- Mid-loop revisions (Phase 4 review cycle, Phase 5 task respec, etc.) edit the file in place; every subsequent dispatch reads the new version automatically. + +**Lifecycle:** +- Files persist across phases until the run finishes. +- Files are **not committed** (same as `summary.md`). Recommend `.workflow/` in `.gitignore`. +- Multiple runs on the same issue overwrite the prior run's artifacts. Save anything you want to keep before re-running. --- ## 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 the TODO tracker exists: +2. Capture the worktree path: `WORKTREE_PATH="$(pwd)"`. +3. Verify the TODO tracker exists: - `./TODO/` directory must exist. If not, stop: "TODO/ directory not found in the current worktree. Commit a TODO/ folder with one file per issue plus a README.md index." - `./TODO/README.md` must exist. If not, stop: "TODO/README.md not found. Add the category index file before running the workflow." - - `./TODO/.md` must exist. If not, stop: "Issue file `./TODO/.md` not found for ID parsed from `$ARGUMENTS`." -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`): + - `./TODO/$ISSUE_ID.md` must exist. If not, stop: "Issue file `./TODO/.md` not found for ID parsed from `$ARGUMENTS`." +4. 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." +5. Capture the current branch: `BRANCH_NAME="$(git symbolic-ref --short HEAD)"`. +6. 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 `." -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." +7. 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." +8. Set the run-artifacts directory: `RUN_DIR="$WORKTREE_PATH/.workflow/run-$ISSUE_ID"`. Phase 3 will `mkdir -p "$RUN_DIR"` before writing the first artifact. --- @@ -52,7 +83,7 @@ If the issue's status is `Todo`, ask `@pm` to set it to `In Progress` and propag ## Phase 3: Plan -Analyze the codebase. Create a detailed implementation plan addressing the issue's requirements and acceptance criteria. +Analyze the codebase. Create a detailed implementation plan addressing the issue's requirements and acceptance criteria, then write it to `$RUN_DIR/plan.md` (run `mkdir -p "$RUN_DIR"` first if the directory doesn't exist). All Phase 4 reviewer dispatches read this file. The plan should include: - Problem summary (from issue context) @@ -70,7 +101,7 @@ The plan should include: **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. +Before saving `plan.md`, apply **Dispatch Hygiene** (below). The file on disk is what reviewers will read in Phase 4 — there is no second chance to revise during dispatch. --- @@ -135,7 +166,7 @@ If any check trips, **do not dispatch.** Fix and re-validate. Repeated trips on ## 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. +Dispatch `@check` and `@simplify` in parallel to review `$RUN_DIR/plan.md`. The dispatch prompt is short — agent role, the absolute path to the plan, the worktree path, and any per-dispatch reviewer focus. Tell each reviewer to read the plan from disk; do **not** paste the plan inline. Apply **Dispatch Hygiene** to each dispatch prompt. Reviewers should evaluate testability: - `@check`: Is the design testable? Are the right behaviors identified? (Review Framework §8) @@ -147,10 +178,10 @@ Reviewers should evaluate testability: - Note conflicts explicitly **Review loop (max 3 cycles):** -1. Send plan to both reviewers +1. Dispatch both reviewers against `$RUN_DIR/plan.md`. 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 +4. If BLOCK or NEEDS WORK: edit `$RUN_DIR/plan.md` in place addressing findings (re-apply Dispatch Hygiene to the updated file), 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) @@ -158,7 +189,9 @@ Reviewers should evaluate testability: ## Phase 5: Split into Tasks -Break the approved plan into discrete tasks for `@make`. Each task needs: +Break the approved plan into discrete tasks. **Write each task to `$RUN_DIR/task-.md`** (1-indexed: `task-1.md`, `task-2.md`, …). Phase 6 (`@test`) and Phase 7 (`@make`) read these files by absolute path. + +Each task file must contain: | Required | Description | |----------|-------------| @@ -226,10 +259,13 @@ Apply **Dispatch Hygiene** to each task spec before dispatch in Phase 7. 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) +For each task from Phase 5, dispatch `@test` with a short prompt that names: +- The absolute path to the task spec: `$RUN_DIR/task-.md` — `@test` reads acceptance criteria, code context, and files-to-modify from there. +- The absolute path to the plan, if test design context is needed: `$RUN_DIR/plan.md`. +- The worktree path (so `@test` resolves source files correctly). +- The test file path to create. + +Do **not** quote task or plan content inline — `@test` reads from disk. `@test` writes failing tests and verifies RED with structured failure codes. @@ -255,11 +291,11 @@ To get a clean runtime RED, dispatch a **stub-first `@make` pass** *before* `@te **Stub pass (split from Phase 7's body pass):** -1. Dispatch `@make` in **standard mode** (no tests exist yet) with this exact scope: +1. Dispatch `@make` in **standard mode** (no tests exist yet). The dispatch prompt names `$RUN_DIR/task-.md` as the source spec and adds this stub-pass-specific scope inline: - **Goal:** add the planned API as `todo!()`-bodied stubs so the test will compile. - **Files to modify:** the relevant `src/.rs` for module tests, or `src/lib.rs` plus any new `src/.rs` for integration tests (the latter need `pub mod …;` declarations so the test crate can import). - **Stubs only:** every function body is exactly `todo!()`. Every method body is exactly `todo!()`. 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, visibility). Lift signatures from the Phase 3 plan / Phase 5 task spec. + - **Signatures must match the planned final API exactly** (return types, lifetimes, generics, visibility). Lift signatures from the 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. @@ -293,10 +329,12 @@ Apply **Dispatch Hygiene** to each `@make` spec before sending. Repeated trips o This applies to **all** `@make` invocations: standard mode, TDD mode, stub-pass, body-pass, and integration-fix dispatches. -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)** +Execute each task by dispatching `@make` with a short prompt: +- The absolute path to the task spec: `$RUN_DIR/task-.md` — `@make` reads acceptance criteria, code context, and files-to-modify from there. +- The worktree path. +- **Pre-written failing tests and handoff from `@test` (if TESTS_READY)** — these are short and per-dispatch, so include them inline in the prompt. + +Do **not** quote the task spec inline. `@make` runs in TDD mode when tests are provided: 1. Entry validation: run tests, verify RED, check failure codes match handoff @@ -326,9 +364,9 @@ After all tasks complete, verify overall integration: 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 absolute path to `$RUN_DIR/plan.md` (the same file Phase 4 reviewed; mid-loop revisions will have updated it in place) - The full diff (`git diff "$BASE_BRANCH"...HEAD`) -- Any decisions or deviations from the plan +- Any decisions or deviations from the plan, captured inline in the dispatch prompt **Review loop (max 3 cycles):** 1. Send implementation to both reviewers @@ -348,7 +386,7 @@ Provide reviewers with: 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 anything under `TODO/`** (committed separately below) and **do not stage `.opencode/workflow-summary.md`** (intentionally never committed — see Local Summary). +- Stage code changes only. **Do not stage anything under `TODO/`** (committed separately below) and **do not stage anything under `.workflow/`** (intentionally never committed — these are per-run artifacts). - Write a conventional commit message summarizing the implementation. Reference the TODO issue ID in the body (e.g. `Refs: GAL-39`). - If changes are large/varied, use multiple atomic commits (one per logical unit) @@ -360,8 +398,8 @@ The workflow is forge-agnostic. It commits locally and stops. **Do not push, and - If acceptance-criteria checkboxes were addressed by the implementation, ask `@pm` to check them off (flip `- [ ]` to `- [x]` under `## Acceptance criteria`). - Commit the TODO/ changes as a separate atomic commit: `chore(todo): update status and progress`. Stage the issue file plus any propagated index file (README.md or parent file). -### Local Summary -- Write `.opencode/workflow-summary.md` in the worktree with: +### Run Summary +- Write `$RUN_DIR/summary.md` 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) @@ -370,15 +408,15 @@ The workflow is forge-agnostic. It commits locally and stops. **Do not push, and - 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. +- **Do not commit anything under `.workflow/`.** The whole directory is per-run, per-branch state. Recommend the user add `.workflow/` 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 `. Stage code only — exclude `.opencode/workflow-summary.md`. +1. Write `$RUN_DIR/summary.md` (creating `$RUN_DIR` first if it doesn't exist) with what was completed and what failed. Do **not** stage or commit anything under `.workflow/`. +2. If any code was written, commit it with message `wip: incomplete workflow run for `. Stage code only — exclude `.workflow/` and `TODO/`. 3. Leave the branch and worktree intact for the user to inspect — do not push, do not delete. 4. Dispatch `@pm` against `./TODO/` (live filesystem mode) to add a comment on the issue file (`./TODO/.md`) summarising what failed. 5. Stop execution.