specrails-core 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +103 -310
  2. package/bin/specrails-core.mjs +3 -1
  3. package/dist/installer/cli.js +4 -0
  4. package/dist/installer/cli.js.map +1 -1
  5. package/dist/installer/commands/framework.js +64 -49
  6. package/dist/installer/commands/framework.js.map +1 -1
  7. package/dist/installer/commands/init.js +102 -66
  8. package/dist/installer/commands/init.js.map +1 -1
  9. package/dist/installer/commands/update.js +80 -74
  10. package/dist/installer/commands/update.js.map +1 -1
  11. package/dist/installer/commands/v5-migration.js +14 -0
  12. package/dist/installer/commands/v5-migration.js.map +1 -1
  13. package/dist/installer/phases/framework-lifecycle.js +2 -0
  14. package/dist/installer/phases/framework-lifecycle.js.map +1 -1
  15. package/dist/installer/phases/scaffold.js +191 -258
  16. package/dist/installer/phases/scaffold.js.map +1 -1
  17. package/dist/installer/runtime/pipeline-state.js +801 -0
  18. package/dist/installer/runtime/pipeline-state.js.map +1 -0
  19. package/dist/installer/util/exec.js +6 -1
  20. package/dist/installer/util/exec.js.map +1 -1
  21. package/dist/installer/util/fs.js +11 -2
  22. package/dist/installer/util/fs.js.map +1 -1
  23. package/dist/installer/util/install-transaction.js +246 -0
  24. package/dist/installer/util/install-transaction.js.map +1 -0
  25. package/dist/installer/util/registry.js +20 -0
  26. package/dist/installer/util/registry.js.map +1 -1
  27. package/docs/ci-cd.md +57 -0
  28. package/docs/user-docs/codex-vs-claude-code.md +23 -151
  29. package/docs/user-docs/core-updates.md +70 -0
  30. package/docs/user-docs/provider-pipelines.md +53 -0
  31. package/integration-contract.json +179 -66
  32. package/package.json +5 -2
  33. package/templates/agents/sr-developer.md +9 -11
  34. package/templates/agents/sr-reviewer.md +26 -33
  35. package/templates/codex-skills/batch-implement/SKILL.md +58 -244
  36. package/templates/codex-skills/implement/SKILL.md +136 -338
  37. package/templates/codex-skills/rails/sr-architect/SKILL.md +7 -0
  38. package/templates/codex-skills/rails/sr-developer/SKILL.md +13 -0
  39. package/templates/codex-skills/rails/sr-reviewer/SKILL.md +39 -5
  40. package/templates/codex-skills/retry/SKILL.md +37 -117
  41. package/templates/commands/specrails/batch-implement.md +16 -288
  42. package/templates/commands/specrails/implement.md +62 -1057
  43. package/templates/commands/specrails/retry.md +22 -314
  44. package/templates/gemini-commands/batch-implement.toml +28 -40
  45. package/templates/gemini-commands/implement.toml +55 -114
  46. package/templates/gemini-commands/retry.toml +21 -0
  47. package/templates/kimi/specrails/run-skill.mjs +51 -2
  48. package/templates/runtime/provider-pipeline.md +55 -0
@@ -1,122 +1,42 @@
1
1
  ---
2
2
  name: retry
3
- description: "Resume a previously-attempted $implement pipeline for a ticket. Detects what's already on disk (OpenSpec change package, partial code, ticked tasks.md) and re-invokes $implement so the architect/developer/reviewer agents skip work that's already correct and pick up where the prior run left off. Use when the user invokes `$retry #N` after a $implement run that ended in `todo` or `blocked`."
3
+ description: "Resume the first invalid implement phase using the durable pipeline journal and explicit role handoffs."
4
4
  license: MIT
5
- compatibility: "Codex-native. Thin wrapper around $implement — relies on the implement pipeline's existing idempotence rather than tracking its own state."
5
+ compatibility: "Codex-native root-level role delegation; no nested implement or assumed provider conversation memory."
6
6
  ---
7
7
 
8
- You are the **retry orchestrator**. The user wants to continue a
9
- prior `$implement` run for a single ticket without redoing work
10
- that's already correct on disk.
11
-
12
- You are NOT a separate pipeline. You inspect what `$implement`
13
- left behind, summarise the current state, and re-invoke
14
- `$implement` with a hint about what's already in place. The
15
- implement skill is idempotent — architect reuses an existing
16
- `${SPECRAILS_REPO_DIR:-.}/openspec/changes/<slug>/`, developer detects ticked tasks and
17
- already-correct files, reviewer re-validates from scratch.
18
-
19
- **Repository location.** `openspec/**` and `.git` live under
20
- `${SPECRAILS_REPO_DIR:-.}` (unset ⇒ `.` ⇒ classic in-repo run); inspect change
21
- artefacts there. The ticket store and `.specrails/agent-memory/` are run-state,
22
- relative to the working directory.
23
-
24
- ## How the user invokes you
25
-
26
- - `$retry #N` — retry the implement run for ticket `N`.
27
- - `$retry #N --yes` — same, non-interactive.
28
-
29
- ## Steps
30
-
31
- ### 0. Locate the prior run's artefacts
32
-
33
- 1. Confirm the repo root with `git -C "${SPECRAILS_REPO_DIR:-.}" rev-parse --show-toplevel`.
34
- 2. Load the ticket (run-state, relative to the working directory):
35
- `jq '.tickets["<ID>"]' .specrails/local-tickets.json`. If
36
- the ticket doesn't exist, stop and report.
37
- 3. Inspect what's already on disk for this ticket:
38
- - **Architect artefacts**: any matching plan file under
39
- `.specrails/agent-memory/explanations/` named
40
- `*-architect-ticket-<ID>.md`. List the latest.
41
- - **OpenSpec change package**: any
42
- `${SPECRAILS_REPO_DIR:-.}/openspec/changes/<slug>/` whose proposal.md mentions
43
- the ticket title or whose tasks.md has tasks scoped to
44
- the ticket. Find the slug.
45
- - **tasks.md progress**: count `[x]` vs `[ ]` boxes in
46
- `${SPECRAILS_REPO_DIR:-.}/openspec/changes/<slug>/tasks.md`.
47
- - **Reviewer verdict**: latest matching
48
- `*-reviewer-ticket-<ID>.confidence-score.json`. Read
49
- the issues list and overall score.
50
-
51
- ### 1. Summarise (≤6 lines)
52
-
53
- Print a concise state summary so the user sees what you
54
- detected:
55
-
56
- ```
57
- Prior run for #<ID>:
58
- Plan: <path or "missing">
59
- Change pkg: openspec/changes/<slug>/ (<found / missing>)
60
- Tasks: <X>/<N> ticked
61
- Last review: <score>/100 — <verdict>
62
- Open issues: <count> (top: "<first issue note, truncated>")
63
- ```
64
-
65
- If no prior artefacts exist, say so explicitly — `$retry` on a
66
- ticket that was never attempted is just `$implement`, and you
67
- fall through to step 2 anyway.
68
-
69
- ### 2. Re-invoke $implement
70
-
71
- `spawn_agent` (full-history fork, no agent_type / model /
72
- reasoning_effort). `send_message`:
73
-
74
- > `$implement`
75
- >
76
- > Ticket id: `<TICKET_ID>`
77
- > Mode: **retry**
78
- >
79
- > A prior run left:
80
- > - plan at `<plan-path-or-none>`
81
- > - change package at `openspec/changes/<slug>/` (<found|missing>)
82
- > - tasks.md progress: <X>/<N> ticked
83
- > - last reviewer score: <N>/100 with <K> open issues
84
- >
85
- > Open issues from the last review (verbatim):
86
- > - <issue 1 from confidence-score.json>
87
- > - <issue 2>
88
- > - ...
89
- >
90
- > Honour these on this retry:
91
- > 1. If the change package exists and proposal.md is sane,
92
- > REUSE it. The architect should refine design.md / tasks.md
93
- > if the issues call for it, not start from scratch.
94
- > 2. The developer should pick up at the first un-ticked task
95
- > box. Already-ticked boxes whose files match the intended
96
- > state should NOT be redone.
97
- > 3. The reviewer re-runs from scratch — no caching of prior
98
- > verdict.
99
- >
100
- > Follow the $implement skill instructions exactly. Reply
101
- > with the standard implement summary.
102
-
103
- `wait_agent`. `close_agent`. Print the sub-agent's reply
104
- verbatim as your own final report.
105
-
106
- ## What you must NOT do
107
-
108
- - **Do NOT re-implement the pipeline**. You only inspect +
109
- delegate. The implement skill owns the actual work.
110
- - **Do NOT modify any file directly** — neither the OpenSpec
111
- package nor the ticket. The spawned `$implement` does that.
112
- - **Do NOT skip the "open issues" passthrough**. If the last
113
- review listed fixes, the next pipeline needs to see them
114
- verbatim — that's what makes retry produce a different
115
- result than a fresh `$implement`.
116
- - **Do NOT loop on retry**. If the user wants a second retry,
117
- they invoke `$retry #N` again themselves. One retry per
118
- invocation.
119
- - **Do NOT pass `agent_type`, `model`, or `reasoning_effort`**
120
- to `spawn_agent` on full-history forks.
121
- - **Do NOT touch `.claude/agent-memory/`** — codex projects
122
- use `.specrails/agent-memory/`.
8
+ You are the retry orchestrator. Accept `$retry #N`, `$retry <change>`, and `--yes`.
9
+ Resolve `${SPECRAILS_REPO_DIR:-.}` only as the legacy source default; the installed
10
+ pipeline helper and SPECRAILS_EXECUTION_CONTEXT provide the authoritative roots.
11
+ Call `status` for the existing run/change. Report its completed phases and
12
+ `resumePhase`. Do not search other projects or guess a change from a matching title.
13
+ When there is no journal, report the missing run/context and require explicit new
14
+ admission; do not silently initialize a replacement retry scope. Never erase existing
15
+ code or use a checked task alone as proof of implementation.
16
+
17
+ Read `.codex/skills/implement/SKILL.md` as the phase definition; execute its remaining
18
+ roles DIRECTLY from this root agent. Do not spawn `$implement` as a sub-agent.
19
+ Use `spawn_agent`, `send_message` and `wait_agent` only for `$sr-architect`,
20
+ `$sr-developer`, `$sr-reviewer` or explicitly configured installed custom roles.
21
+ Preserve the configured provider model; do not pass model/reasoning_effort on
22
+ full-history forks. Give every role the bounded explicit handoff from the shared
23
+ contract, including unchanged frozen acceptance criteria and exact prior findings.
24
+
25
+ - Architect resumes only if status says design is invalid/missing/blocked.
26
+ - Developer resumes the first incomplete or stale task; do not repeat valid design.
27
+ - Reviewer resumes semantic review with the actual candidate and verification
28
+ receipts. If findings require code changes, record developer running and invoke
29
+ developer with those exact findings, then reviewer again (at most one fix round).
30
+ - Never assume a `MAX_TURNS` or successful process exit completed a phase. Save the
31
+ checkpoint and invoke the same role with the pending work; two continuations
32
+ without file/task/evidence progress stop as blocked with the outstanding action.
33
+ - Archive uses `archive-check`, followed by reviewer archive-only authorization;
34
+ missing/low confidence or stale checks never become success through retry.
35
+ - Ship resumes only missing authorized Core-owned delivery; CI checks existing
36
+ delivery without shipping again. Host-owned ship/ci record skipped; backlog and
37
+ worktrees remain with their owner. Backlog closure also compares live requirements
38
+ with frozen scope at context.backlogPath, as implement requires.
39
+
40
+ Record each outcome with the helper. A blocked phase is resumable, never an
41
+ intentionally skipped phase. Report the run, change, resumed roles, verification,
42
+ archive outcome and any remaining blocker. No recursive retry loops.
@@ -1,299 +1,27 @@
1
- # Batch Implementation Orchestrator
1
+ # Batch Implement
2
2
 
3
- Macro-orchestrator above `/specrails:implement`. Accepts a set of feature references, computes a dependency-aware wave execution plan, invokes `/specrails:implement` per wave, and produces a batch-level progress dashboard and final report. All per-feature pipeline work (sr-architect, sr-developer, sr-reviewer, git, CI) is fully delegated to `/specrails:implement`.
3
+ **Input:** $ARGUMENTS — selected ticket references, dependency hints, --dry-run/--preview or existing aggregate change for retry.
4
4
 
5
- **MANDATORY: Always follow this pipeline exactly as written. NEVER skip, shortcut, or "optimize away" any phase — even if the batch seems small enough to handle directly. The orchestrator MUST compute waves, confirm with the user, and invoke `/specrails:implement` per wave as specified. Do NOT implement any feature yourself in the main conversation. No exceptions.**
5
+ ## One scope and one candidate
6
6
 
7
- **Input:** $ARGUMENTS — one or more feature references with optional flags:
7
+ Use implement's installed runtime and immutable execution context. Host context.specs[] is the batch; never replace it from another repository's backlog. Standalone init --change <aggregate-change> --tickets "17,18" freezes local entries once; freeform/multi-repo uses explicit scope request/context.
8
8
 
9
- - **Feature refs**: `#85 #71 #63` (GitHub issue numbers) — required, at least two
10
- - **`--deps "<spec>"`**: inline dependency spec, e.g. `"#71 -> #85, #63 -> #85"` (meaning #71 and #63 must complete before #85)
11
- - **`--concurrency N`**: max features running in parallel across waves (default: 3)
12
- - **`--wave-size N`**: max features per wave regardless of concurrency (default: unlimited)
13
- - **`--dry-run` / `--preview`**: passed through to each `/specrails:implement` invocation; no git or backlog operations will run
9
+ There is **one aggregate OpenSpec change and one journal**, not a full pipeline per ticket. Delegate to implement once with all frozen specs and selected roots. Architect, developer, reviewer, confidence, archive and delivery gates are mandatory and resumable.
14
10
 
15
- **IMPORTANT:** Before running, ensure Read/Write/Bash/Glob/Grep permissions are set to "allow" — subagents cannot request permissions interactively.
11
+ ## Dependency plan
16
12
 
17
- ---
13
+ 1. Validate dependency IDs against selected specs/completed external prerequisites; reject cycles or missing prerequisites.
14
+ 2. One architect designs shared contracts and task groups labeled with ticket/repository ID. Cross-repository behavior belongs to the same acceptance matrix.
15
+ 3. Execute dependency-ordered groups in supplied roots; serialize shared-file/contract changes. Profile routing selects appropriate roles; each handoff includes exact context/runtime paths.
16
+ 4. Collect foreground terminal results. Task start or unsupported PASS is not completion.
17
+ 5. Scoped tests support development; one full receipt covers the aggregate candidate and cross-repository integration. Reviewer reuses it unchanged; edits need a fresh final full pass.
18
18
 
19
- ## Desktop rail execution context (isolated worktree)
19
+ Never recursively launch implement for each wave, change the run identity, allocate nested worktrees, guess a main branch, merge copied file lists or delete supplied roots. Respect host/Core ownership from entry.
20
20
 
21
- specrails-desktop launches this command INSIDE an isolated rail worktree allocated for the batch. Detect it: the working directory path contains `/worktrees/` (e.g. `~/.specrails/projects/<slug>/worktrees/ticket-N`), typically on a `feat/...` branch. When that is the case, ALL of the following hold — they override any instinct to the contrary:
21
+ ## Acceptance and completion
22
22
 
23
- - **You ARE the assigned executor of this rail.** The desktop's own bookkeeping (rail slots, ticket-ownership rows in its `jobs.sqlite`, state under `~/.specrails/`) describes THIS very launch — it is never evidence of a competing process. NEVER read specrails-desktop's internal databases or state files, and NEVER stop to ask "which process should run this batch".
24
- - **The current worktree + current branch ARE the workspace for the WHOLE batch.** Implement every ticket here, in dependency order — including tickets whose refs differ from the branch name. The desktop assembles this branch into a batch PR after you finish; nothing needs to land on the integration branch (main) first. Do NOT create sibling worktrees, do NOT switch branches, do NOT run any ticket "against main in the base repo".
25
- - **Run tickets SEQUENTIALLY (effective concurrency 1)** regardless of `--concurrency`: parallel pipelines editing one shared checkout corrupt each other. Wave order still sequences the work; only the parallelism collapses.
26
- - Everything else (per-ticket `/specrails:implement` delegation, wave gates, failure isolation, final report) applies unchanged.
23
+ Review every ticket's criteria before canonical confidence. Runtime reviewer and archive approval gates precede official archive. Missing implementation/regressions, low confidence or one required failed repo keeps the batch incomplete; preserve per-ticket/repository retry progress.
27
24
 
28
- ---
25
+ Preview remains unverified until runtime apply checks an unchanged base and executes checks on applied candidate. Retry resumes earliest invalid phase, preserving valid design and successful delivery.
29
26
 
30
- ## Phase 0: Parse Input
31
-
32
- ### Step 1: Extract feature refs
33
-
34
- Scan `$ARGUMENTS` for issue/ticket references (e.g. `#85`, `#71`). Collect into `FEATURE_REFS` list. If fewer than 2 refs are found, stop and print:
35
-
36
- ```
37
- [batch-implement] Error: at least 2 feature refs are required. For a single feature, use /specrails:implement directly.
38
- ```
39
-
40
- ### Step 2: Extract flags
41
-
42
- Scan `$ARGUMENTS` for control flags:
43
-
44
- - If `--dry-run` or `--preview` is present: set `DRY_RUN=true`. This flag is forwarded to every `/specrails:implement` call.
45
- - If `--deps "<spec>"` is present: capture the quoted string as `DEPS_SPEC`. Strip from arguments.
46
- - If `--concurrency N` is present: set `CONCURRENCY=N` (integer ≥ 1). Default: 3.
47
- - If `--wave-size N` is present: set `WAVE_SIZE=N` (integer ≥ 1). Default: unlimited (no per-wave cap).
48
- - If `--profiles "<spec>"` is present: parse a per-rail profile map of the form `ref=profile-name,ref=profile-name,...`. Capture as `PROFILE_MAP` and strip from arguments. Each mapped ref's `/specrails:implement` invocation will run under the named profile (the profile must exist at `.specrails/profiles/<profile-name>.json`). Unmapped refs inherit the batch-level profile resolution (see below).
49
-
50
- **If `DRY_RUN=true`**, print:
51
- ```
52
- [dry-run] Preview mode active — /specrails:implement will be called with --dry-run for each wave.
53
- ```
54
-
55
- ### Step 3: Fetch issue titles
56
-
57
- For each ref in `FEATURE_REFS`, fetch the issue title to use in progress output:
58
-
59
- ```bash
60
- {{BACKLOG_VIEW_CMD}} --json number,title
61
- ```
62
-
63
- Store as `FEATURE_TITLES` map: `{ref: title}`.
64
-
65
- ---
66
-
67
- ## Phase 1: Wave Planning
68
-
69
- ### Step 1: Parse dependency graph
70
-
71
- Build a directed graph `DEP_GRAPH` where an edge `A -> B` means "A must complete before B starts".
72
-
73
- Parse `DEPS_SPEC` (if provided) by splitting on `,` and parsing each token as `<ref> -> <ref>`.
74
-
75
- ```
76
- for each token in DEPS_SPEC.split(","):
77
- left, right = token.split("->")
78
- DEP_GRAPH.add_edge(left.strip(), right.strip())
79
- ```
80
-
81
- All refs in `FEATURE_REFS` that appear in no edge are treated as independent (no dependencies).
82
-
83
- ### Step 2: Detect circular dependencies
84
-
85
- Run cycle detection on `DEP_GRAPH`:
86
-
87
- ```
88
- visited = {}
89
- rec_stack = {}
90
-
91
- function has_cycle(node):
92
- visited[node] = true
93
- rec_stack[node] = true
94
- for neighbor in DEP_GRAPH.neighbors(node):
95
- if not visited[neighbor] and has_cycle(neighbor):
96
- return true
97
- elif rec_stack[neighbor]:
98
- return true
99
- rec_stack[node] = false
100
- return false
101
-
102
- CYCLES = [node for node in FEATURE_REFS if not visited[node] and has_cycle(node)]
103
- ```
104
-
105
- If `CYCLES` is non-empty: stop and print:
106
-
107
- ```
108
- [batch-implement] Error: circular dependency detected.
109
- Cycle involves: <ref-list>
110
- Fix the --deps spec and re-run.
111
- ```
112
-
113
- ### Step 3: Compute waves via Kahn's algorithm
114
-
115
- ```
116
- in_degree = {ref: 0 for ref in FEATURE_REFS}
117
- for each edge (A -> B) in DEP_GRAPH:
118
- in_degree[B] += 1
119
-
120
- WAVES = []
121
- ready = [ref for ref in FEATURE_REFS if in_degree[ref] == 0]
122
- sort ready alphabetically (stable ordering)
123
-
124
- while ready is non-empty:
125
- wave = ready[:WAVE_SIZE] # cap at WAVE_SIZE if set; else take all
126
- remaining = ready[WAVE_SIZE:] if WAVE_SIZE else []
127
- WAVES.append(wave)
128
- for ref in wave:
129
- for neighbor in DEP_GRAPH.neighbors(ref):
130
- in_degree[neighbor] -= 1
131
- if in_degree[neighbor] == 0:
132
- remaining.append(neighbor)
133
- sort remaining alphabetically
134
- ready = remaining
135
- ```
136
-
137
- Set `TOTAL_WAVES = len(WAVES)`.
138
-
139
- ### Step 4: Print execution plan and ask for confirmation
140
-
141
- Print the wave execution plan:
142
-
143
- ```
144
- ## Batch Execution Plan
145
-
146
- Total features : <N>
147
- Total waves : <TOTAL_WAVES>
148
- Max concurrency: <CONCURRENCY>
149
- Dry-run : <yes / no>
150
-
151
- | Wave | Features | Depends On |
152
- |------|----------|------------|
153
- | 1 | #85, #71 | — |
154
- | 2 | #63 | #85, #71 |
155
-
156
- Dependency graph:
157
- #71 -> #63
158
- #85 -> #63
159
-
160
- Proceed? (yes / no / edit-deps)
161
- ```
162
-
163
- Wait for user confirmation.
164
-
165
- - **`yes`**: proceed to Phase 2.
166
- - **`no`**: stop. Print `[batch-implement] Aborted by user.`
167
- - **`edit-deps`**: ask the user to provide a corrected `--deps` spec, re-run Phase 1 from Step 1.
168
-
169
- ---
170
-
171
- ## Phase 2: Wave Execution Loop
172
-
173
- Execute waves sequentially. Within each wave, invoke `/specrails:implement` for all features in parallel (up to `CONCURRENCY` at a time).
174
-
175
- ### Progress Dashboard
176
-
177
- Before starting each wave, print the current dashboard state:
178
-
179
- ```
180
- ## Batch Progress
181
-
182
- | # | Feature | Title | Wave | Status | Notes |
183
- |---|---------|-------|------|--------|-------|
184
- | 1 | #85 | <title> | 1 | done | |
185
- | 2 | #71 | <title> | 1 | done | |
186
- | 3 | #63 | <title> | 2 | running| |
187
- | 4 | #42 | <title> | 2 | blocked| depends on #63 |
188
- | 5 | #17 | <title> | 3 | pending| |
189
- ```
190
-
191
- Status values:
192
- - `pending` — not yet started
193
- - `running` — `/specrails:implement` invocation is active
194
- - `done` — `/specrails:implement` completed successfully
195
- - `failed` — `/specrails:implement` exited with an error
196
- - `blocked` — a dependency failed; this feature will not run
197
-
198
- ### Wave invocation
199
-
200
- For each wave `W`:
201
-
202
- 1. Print: `[wave W/TOTAL_WAVES] Starting — features: <ref-list>`
203
- 2. For each feature batch of size ≤ `CONCURRENCY` within the wave:
204
- - For every ref in the batch, determine the profile spawn env:
205
- - If `PROFILE_MAP` contains an entry for this ref, set `SPECRAILS_PROFILE_PATH=<abs path to .specrails/profiles/<mapped-name>.json>` for this invocation only.
206
- - Otherwise, inherit whatever `$SPECRAILS_PROFILE_PATH` was set by the caller (e.g. specrails-desktop), or leave unset so the rail falls back to `.specrails/profiles/project-default.json` or legacy mode.
207
- - Invoke `/specrails:implement` with the feature refs and forwarded flags:
208
- ```
209
- SPECRAILS_PROFILE_PATH=<resolved-per-rail-path> /specrails:implement <ref> [--dry-run]
210
- ```
211
- - Each ref in the batch spawns with its own resolved profile path — **distinct rails in the same batch MAY use distinct profiles concurrently**.
212
- - Run invocations in the batch **concurrently in the FOREGROUND**: emit every agent invocation for the batch in a single message with `run_in_background: false`. They still run in parallel, and your turn blocks until all of them return.
213
- - **NEVER use `run_in_background: true`, and NEVER end your reply while a wave is still running.** In headless/pipeline execution (`claude -p`, specrails-desktop loops) the host tears the process down as soon as your turn ends — background agents are killed before they write a single file. Replies like "wave 1 is running in the background, I'll pick it up when it finishes" lose the entire wave.
214
- - Wait for all in the batch to complete before starting the next batch.
215
- 3. For each completed invocation, record outcome in `WAVE_RESULTS`:
216
- - `{ref, wave, status: "done" | "failed", profile: "<name or empty>", error_summary: "..." | null}`
217
-
218
- ### Failure isolation
219
-
220
- After each wave completes:
221
-
222
- ```
223
- FAILED_THIS_WAVE = [ref for ref in wave if WAVE_RESULTS[ref].status == "failed"]
224
-
225
- for each ref in FAILED_THIS_WAVE:
226
- BLOCKED = all refs in DEP_GRAPH.descendants(ref)
227
- for each blocked_ref in BLOCKED:
228
- WAVE_RESULTS[blocked_ref] = {status: "blocked", reason: "depends on failed " + ref}
229
- remove blocked_ref from all future waves
230
- ```
231
-
232
- A failed feature blocks ONLY its transitive dependents. Features in other branches of the dependency graph continue unaffected.
233
-
234
- Print updated dashboard after each wave.
235
-
236
- ### Wave completion gate
237
-
238
- Before starting wave W+1, confirm all features in wave W have status `done` or `blocked`. Never start a downstream wave while upstream features are still running.
239
-
240
- ---
241
-
242
- ## Phase 3: Batch Report
243
-
244
- After all waves complete (or all remaining features are blocked), print the final batch report.
245
-
246
- ```
247
- ## Batch Implementation Report
248
-
249
- Run completed: <ISO 8601 timestamp>
250
- Dry-run: <yes / no>
251
-
252
- ### Summary
253
-
254
- | Metric | Count |
255
- |--------|-------|
256
- | Total features | N |
257
- | Succeeded | N |
258
- | Failed | N |
259
- | Blocked (dep failure) | N |
260
-
261
- ### Per-Feature Results
262
-
263
- | # | Feature | Title | Wave | Status | Notes |
264
- |---|---------|-------|------|--------|-------|
265
- | 1 | #85 | <title> | 1 | done | |
266
- | 2 | #71 | <title> | 1 | failed | see /specrails:implement output |
267
- | 3 | #63 | <title> | 2 | blocked| depends on #71 |
268
-
269
- ### Merge Conflicts
270
-
271
- [List any merge conflicts reported by /specrails:implement across all waves. If none: "No merge conflicts detected."]
272
-
273
- | Feature | File | Conflicting Region |
274
- |---------|------|--------------------|
275
- | #85 | src/utils/parser.ts | function parseQuery |
276
-
277
- ### Next Steps
278
-
279
- [If all features succeeded:]
280
- All features implemented. Review open PRs and monitor CI.
281
-
282
- [If any features failed:]
283
- Re-run failed features individually:
284
- /specrails:implement <failed-ref>
285
- /specrails:implement <failed-ref>
286
-
287
- [If any features were blocked:]
288
- Once failed features are fixed, re-run blocked features:
289
- /specrails:implement <blocked-ref> [--deps "..."]
290
- ```
291
-
292
- ---
293
-
294
- ## Error Handling
295
-
296
- - If a `/specrails:implement` invocation fails: record failure, apply failure isolation, continue remaining waves
297
- - If GitHub CLI is unavailable (detected during issue title fetch): proceed without titles, show refs only
298
- - If `--deps` spec contains unknown refs: warn and continue — unknown refs are ignored in graph construction
299
- - Never block the entire batch on a single feature failure. Always produce a final report.
27
+ Core-owned backlog may close only after complete delivery and matching current/frozen requirements. Host-owned backlog remains for host acceptance. Report partial outcomes and preserve reviewable work.