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.
This commit is contained in:
parent
4ec1561af4
commit
2941faa822
3 changed files with 61 additions and 46 deletions
|
|
@ -11,13 +11,22 @@ tools:
|
||||||
bash: false
|
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
|
## 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:
|
The caller supplies the TODO.md path in the prompt as an absolute path. There are two patterns:
|
||||||
- For read/list operations: report "TODO.md not found at <absolute path>" and stop.
|
|
||||||
- For create operations: create it with the header `# TODO\n\n` and proceed.
|
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 <absolute path>" and stop.
|
||||||
|
- For create operations: create it with the header `# TODO\n\n` and proceed (only when in live mode).
|
||||||
|
|
||||||
## TODO.md Schema
|
## TODO.md Schema
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
subtask: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -16,12 +16,11 @@ Classify the input into one of these modes:
|
||||||
| Pattern | Mode |
|
| Pattern | Mode |
|
||||||
|---------|------|
|
|---------|------|
|
||||||
| Empty / no arguments | **code:uncommitted** |
|
| 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** |
|
| Hex string 7-40 chars (e.g. `a1b2c3d`) | **code:commit** |
|
||||||
| File content provided via `@` reference (look for file contents in context) | **plan** |
|
| File content provided via `@` reference (look for file contents in context) | **plan** |
|
||||||
| Otherwise, treat as branch name | **code:branch** |
|
| 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:uncommitted**: `git diff` + `git diff --cached` + `git status --short` (read untracked files too)
|
||||||
- **code:commit**: `git show $ARGUMENTS`
|
- **code:commit**: `git show $ARGUMENTS`
|
||||||
- **code:branch**: `git diff $ARGUMENTS...HEAD`
|
- **code:branch**: `git diff $ARGUMENTS...HEAD`
|
||||||
- **code:pr**: `gh pr view $ARGUMENTS` + `gh pr diff $ARGUMENTS`
|
|
||||||
|
|
||||||
Then:
|
Then:
|
||||||
1. Identify all changed files from the diff
|
1. Identify all changed files from the diff
|
||||||
|
|
|
||||||
|
|
@ -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
|
agent: build
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -13,21 +13,33 @@ If `$ARGUMENTS` is empty, stop immediately: "Usage: `/workflow <ISSUE-ID>` (e.g.
|
||||||
|
|
||||||
## Phase 1: Repo Setup
|
## 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/`."
|
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. 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)."
|
2. Capture the bare repo root for later worktree creation: `BARE_REPO_ROOT="$(pwd)"`.
|
||||||
3. Run `gh auth status`. If auth is expired or missing, stop: "GitHub CLI auth expired. Run `gh auth login` before retrying."
|
3. Determine the default branch (source of TODO.md and base for new worktrees). Resolve in order:
|
||||||
4. Proceed to Phase 2 to get issue context before creating the worktree.
|
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
|
## 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
|
- Issue title, description, acceptance criteria
|
||||||
- Labels and priority
|
- 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.
|
If the issue does not exist or `@pm` fails, stop with error.
|
||||||
|
|
||||||
|
|
@ -37,13 +49,13 @@ Derive a branch name: `<issue-id-lowercase>-<slugified-title>` (e.g. `abc-1-add-
|
||||||
|
|
||||||
## Phase 3: Repo Setup (continued)
|
## 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`)
|
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."
|
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 <dir-name> -b <branch-name> master`
|
4. If worktree does not exist: `git worktree add <dir-name> -b <branch-name> "$DEFAULT_BRANCH"`
|
||||||
5. Change working directory to the new worktree.
|
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
|
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
|
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
|
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:
|
Provide reviewers with:
|
||||||
- The original plan
|
- 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
|
- Any decisions or deviations from the plan
|
||||||
|
|
||||||
**Review loop (max 3 cycles):**
|
**Review loop (max 3 cycles):**
|
||||||
|
|
@ -193,57 +205,53 @@ Provide reviewers with:
|
||||||
3. If ACCEPTABLE: proceed to Phase 10
|
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
|
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
|
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
|
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.
|
||||||
- Stage all changes
|
|
||||||
- Write a conventional commit message summarizing the implementation
|
### 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)
|
- If changes are large/varied, use multiple atomic commits (one per logical unit)
|
||||||
|
|
||||||
### Draft PR
|
|
||||||
- `gh pr create --draft --title "<conventional title>" --body "<execution report>"`
|
|
||||||
- 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
|
### TODO Update
|
||||||
- Use `@pm` to update the issue in `./TODO.md`:
|
- Use `@pm` to update the issue in `./TODO.md` (worktree-local; this is the live, writable copy):
|
||||||
- Set the **PR** field to the draft PR URL
|
|
||||||
- Set **Branch** to the worktree branch name
|
- Set **Branch** to the worktree branch name
|
||||||
- Set **Status** to `In Review`
|
- 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
|
- 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
|
### Local Summary
|
||||||
- Write `.opencode/workflow-summary.md` in the worktree with:
|
- Write `.opencode/workflow-summary.md` in the worktree with:
|
||||||
- Run timestamp
|
- Run timestamp
|
||||||
- Issue reference and title
|
- Issue reference and title
|
||||||
- Branch and PR link
|
- Branch name and final commit SHA(s)
|
||||||
- Summary of implementation
|
- Summary of implementation
|
||||||
- TDD evidence (RED→GREEN per task, NOT_TESTABLE justifications)
|
- TDD evidence (RED→GREEN per task, NOT_TESTABLE justifications)
|
||||||
- Review outcomes (plan review + final review verdicts)
|
- Review outcomes (plan review + final review verdicts)
|
||||||
- Unresolved items (if any)
|
- Unresolved items (if any)
|
||||||
- Files changed
|
- Files changed
|
||||||
|
- Commit the summary: `chore(workflow): summary for <issue-id>`
|
||||||
|
|
||||||
|
### Cleanup
|
||||||
|
- Remove the temp snapshot from Phase 1: `rm -f "$TODO_READ_PATH"`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Failure Handling
|
## Failure Handling
|
||||||
|
|
||||||
At any phase, if an unrecoverable error occurs:
|
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 <issue-id>`
|
2. If any code was written, commit it with message `wip: incomplete workflow run for <issue-id>`
|
||||||
3. If a branch exists with commits, create the draft PR noting it is incomplete
|
3. Leave the branch and worktree intact for the user to inspect — do not push, do not delete
|
||||||
4. Stop execution
|
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.
|
**Never hang on interactive prompts.** If any command appears to require input, treat it as a failure and follow the above procedure.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue