feat(work): dispatch loops + auto-ticks state on approve
Previously the orchestrator ran exactly one implementer + reviewer pair,
printed "(Automatic state mutation by the orchestrator is v2.)", and
exited — the human had to tick the bullet, flip story status, rebuild
state, and re-invoke for every slice. V2 closes the loop:
- Parses the JSON the implementer + reviewer prompts ask the agents to
emit (`parseAgentJson` — tolerates both ```json fenced and bare
trailing { ... } shapes). The reviewer's `decision` and the
implementer's `status` are the orchestrator's discriminators.
- On approve: ticks the bullet in `_story.md` and writes it back. If
the story now has zero unchecked bullets, flips its frontmatter
`status: in-progress → done`; if all sibling stories are also done,
flips the epic's frontmatter the same way. Commits the mutation on
the host as a separate `chore(work): tick/finish ...` commit so the
implementer's slice commit stays clean. `_state.json` regenerates
via the existing pre-commit `rebuild-state` hook.
- On reject: re-dispatches the implementer with the reviewer's notes
appended to TASK_FILE_CONTENT, bounded by SANDCASTLE_MAX_ATTEMPTS
(default 3). On the (max+1)th reject the loop exits 1 with the last
notes printed.
- After every approved slice, calls findNextTask again and dispatches
the next ready bullet — including across story boundaries (the
state-builder treats any non-done story with satisfied deps as
ready, so flipping story 01 to done unblocks story 02 automatically).
- Flags: `--once` (legacy single-slice behavior) and `--max-tasks N`
bound the loop. Default is unlimited — matches the
continuous-execution preference.
Auth/sandbox setup is now pulled out of the per-iteration path so the
loop reuses one sandbox across slices.
This commit is contained in:
@@ -13,7 +13,13 @@
|
||||
* ready Prints every ready story
|
||||
* blocked Prints every blocked story + what each is waiting on
|
||||
* dispatch Print the next dispatch plan; with --execute invokes
|
||||
* sandcastle to run the implementer + reviewer pair
|
||||
* sandcastle to run the implementer + reviewer pair.
|
||||
* --execute LOOPS through every ready task by default;
|
||||
* bound with --once or --max-tasks N. After each
|
||||
* approved slice the orchestrator ticks the bullet,
|
||||
* flips story/epic status if complete, and commits
|
||||
* the state mutation as `chore(work): ...` on top of
|
||||
* the implementer's slice commit.
|
||||
* decompose <id> Validate an approved PRD + print the decompose plan;
|
||||
* with --execute invokes sandcastle's decomposer agent
|
||||
* to write the epic folder + per-story files
|
||||
@@ -135,7 +141,7 @@ function usage() {
|
||||
"Usage: pnpm work <rebuild-state|status|next|ready|blocked|dispatch|decompose|prd-ship>",
|
||||
);
|
||||
console.log(
|
||||
" dispatch Print the next dispatch plan (use --execute to invoke sandcastle)",
|
||||
" dispatch Print the next dispatch plan (use --execute to invoke sandcastle; loops by default — bound with --once / --max-tasks N)",
|
||||
);
|
||||
console.log(
|
||||
" decompose <prd-id> Decompose an approved PRD into epic + stories (use --execute to invoke sandcastle)",
|
||||
|
||||
Reference in New Issue
Block a user