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
|
||||
---
|
||||
|
||||
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 <absolute path>" 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 <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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <ISSUE-ID>` (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: `<issue-id-lowercase>-<slugified-title>` (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 <dir-name> -b <branch-name> master`
|
||||
5. Change working directory to the new worktree.
|
||||
4. If worktree does not exist: `git worktree add <dir-name> -b <branch-name> "$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 "<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
|
||||
- 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 <issue-id> 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 <issue-id>`
|
||||
|
||||
### 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 <issue-id>`
|
||||
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.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue