ace-assign 0.37.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 (104) hide show
  1. checksums.yaml +7 -0
  2. data/.ace-defaults/assign/catalog/composition-rules.yml +211 -0
  3. data/.ace-defaults/assign/catalog/recipes/batch-tasks.recipe.yml +44 -0
  4. data/.ace-defaults/assign/catalog/recipes/documentation.recipe.yml +35 -0
  5. data/.ace-defaults/assign/catalog/recipes/fix-and-review.recipe.yml +32 -0
  6. data/.ace-defaults/assign/catalog/recipes/implement-simple.recipe.yml +29 -0
  7. data/.ace-defaults/assign/catalog/recipes/implement-with-pr.recipe.yml +48 -0
  8. data/.ace-defaults/assign/catalog/recipes/release-only.recipe.yml +34 -0
  9. data/.ace-defaults/assign/catalog/steps/apply-feedback.step.yml +22 -0
  10. data/.ace-defaults/assign/catalog/steps/commit.step.yml +22 -0
  11. data/.ace-defaults/assign/catalog/steps/create-pr.step.yml +28 -0
  12. data/.ace-defaults/assign/catalog/steps/create-retro.step.yml +22 -0
  13. data/.ace-defaults/assign/catalog/steps/fix-tests.step.yml +22 -0
  14. data/.ace-defaults/assign/catalog/steps/lint.step.yml +22 -0
  15. data/.ace-defaults/assign/catalog/steps/mark-task-done.step.yml +57 -0
  16. data/.ace-defaults/assign/catalog/steps/onboard-base.step.yml +19 -0
  17. data/.ace-defaults/assign/catalog/steps/onboard.step.yml +19 -0
  18. data/.ace-defaults/assign/catalog/steps/plan-task.step.yml +17 -0
  19. data/.ace-defaults/assign/catalog/steps/pre-commit-review.step.yml +34 -0
  20. data/.ace-defaults/assign/catalog/steps/push-to-remote.step.yml +28 -0
  21. data/.ace-defaults/assign/catalog/steps/rebase-with-main.step.yml +28 -0
  22. data/.ace-defaults/assign/catalog/steps/reflect-and-refactor.step.yml +57 -0
  23. data/.ace-defaults/assign/catalog/steps/release-minor.step.yml +23 -0
  24. data/.ace-defaults/assign/catalog/steps/release.step.yml +23 -0
  25. data/.ace-defaults/assign/catalog/steps/reorganize-commits.step.yml +28 -0
  26. data/.ace-defaults/assign/catalog/steps/research.step.yml +19 -0
  27. data/.ace-defaults/assign/catalog/steps/review-pr.step.yml +22 -0
  28. data/.ace-defaults/assign/catalog/steps/security-audit.step.yml +22 -0
  29. data/.ace-defaults/assign/catalog/steps/split-subtree-root.step.yml +25 -0
  30. data/.ace-defaults/assign/catalog/steps/squash-changelog.step.yml +28 -0
  31. data/.ace-defaults/assign/catalog/steps/task-load.step.yml +29 -0
  32. data/.ace-defaults/assign/catalog/steps/update-docs.step.yml +38 -0
  33. data/.ace-defaults/assign/catalog/steps/update-pr-desc.step.yml +28 -0
  34. data/.ace-defaults/assign/catalog/steps/verify-e2e.step.yml +42 -0
  35. data/.ace-defaults/assign/catalog/steps/verify-test-suite.step.yml +48 -0
  36. data/.ace-defaults/assign/catalog/steps/verify-test.step.yml +36 -0
  37. data/.ace-defaults/assign/catalog/steps/work-on-task.step.yml +23 -0
  38. data/.ace-defaults/assign/config.yml +48 -0
  39. data/.ace-defaults/assign/presets/fix-bug.yml +65 -0
  40. data/.ace-defaults/assign/presets/quick-implement.yml +41 -0
  41. data/.ace-defaults/assign/presets/release-only.yml +35 -0
  42. data/.ace-defaults/assign/presets/work-on-docs.yml +41 -0
  43. data/.ace-defaults/assign/presets/work-on-task.yml +179 -0
  44. data/.ace-defaults/nav/protocols/skill-sources/ace-assign.yml +19 -0
  45. data/.ace-defaults/nav/protocols/wfi-sources/ace-assign.yml +19 -0
  46. data/CHANGELOG.md +1415 -0
  47. data/README.md +87 -0
  48. data/Rakefile +16 -0
  49. data/docs/exit-codes.md +61 -0
  50. data/docs/getting-started.md +121 -0
  51. data/docs/handbook.md +40 -0
  52. data/docs/usage.md +224 -0
  53. data/exe/ace-assign +16 -0
  54. data/handbook/guides/fork-context.g.md +231 -0
  55. data/handbook/skills/as-assign-compose/SKILL.md +24 -0
  56. data/handbook/skills/as-assign-create/SKILL.md +23 -0
  57. data/handbook/skills/as-assign-drive/SKILL.md +24 -0
  58. data/handbook/skills/as-assign-prepare/SKILL.md +23 -0
  59. data/handbook/skills/as-assign-recover-fork/SKILL.md +22 -0
  60. data/handbook/skills/as-assign-run-in-batches/SKILL.md +23 -0
  61. data/handbook/skills/as-assign-start/SKILL.md +25 -0
  62. data/handbook/workflow-instructions/assign/compose.wf.md +256 -0
  63. data/handbook/workflow-instructions/assign/create.wf.md +215 -0
  64. data/handbook/workflow-instructions/assign/drive.wf.md +666 -0
  65. data/handbook/workflow-instructions/assign/prepare.wf.md +469 -0
  66. data/handbook/workflow-instructions/assign/recover-fork.wf.md +233 -0
  67. data/handbook/workflow-instructions/assign/run-in-batches.wf.md +212 -0
  68. data/handbook/workflow-instructions/assign/start.wf.md +46 -0
  69. data/lib/ace/assign/atoms/assign_frontmatter_parser.rb +173 -0
  70. data/lib/ace/assign/atoms/catalog_loader.rb +101 -0
  71. data/lib/ace/assign/atoms/composition_rules.rb +219 -0
  72. data/lib/ace/assign/atoms/number_generator.rb +110 -0
  73. data/lib/ace/assign/atoms/preset_expander.rb +277 -0
  74. data/lib/ace/assign/atoms/step_file_parser.rb +207 -0
  75. data/lib/ace/assign/atoms/step_numbering.rb +227 -0
  76. data/lib/ace/assign/atoms/step_sorter.rb +66 -0
  77. data/lib/ace/assign/atoms/tree_formatter.rb +106 -0
  78. data/lib/ace/assign/cli/commands/add.rb +102 -0
  79. data/lib/ace/assign/cli/commands/assignment_target.rb +55 -0
  80. data/lib/ace/assign/cli/commands/create.rb +63 -0
  81. data/lib/ace/assign/cli/commands/fail.rb +43 -0
  82. data/lib/ace/assign/cli/commands/finish.rb +88 -0
  83. data/lib/ace/assign/cli/commands/fork_run.rb +229 -0
  84. data/lib/ace/assign/cli/commands/list.rb +166 -0
  85. data/lib/ace/assign/cli/commands/retry_cmd.rb +42 -0
  86. data/lib/ace/assign/cli/commands/select.rb +45 -0
  87. data/lib/ace/assign/cli/commands/start.rb +40 -0
  88. data/lib/ace/assign/cli/commands/status.rb +407 -0
  89. data/lib/ace/assign/cli.rb +144 -0
  90. data/lib/ace/assign/models/assignment.rb +107 -0
  91. data/lib/ace/assign/models/assignment_info.rb +66 -0
  92. data/lib/ace/assign/models/queue_state.rb +326 -0
  93. data/lib/ace/assign/models/step.rb +197 -0
  94. data/lib/ace/assign/molecules/assignment_discoverer.rb +57 -0
  95. data/lib/ace/assign/molecules/assignment_manager.rb +276 -0
  96. data/lib/ace/assign/molecules/fork_session_launcher.rb +102 -0
  97. data/lib/ace/assign/molecules/queue_scanner.rb +130 -0
  98. data/lib/ace/assign/molecules/skill_assign_source_resolver.rb +376 -0
  99. data/lib/ace/assign/molecules/step_renumberer.rb +227 -0
  100. data/lib/ace/assign/molecules/step_writer.rb +246 -0
  101. data/lib/ace/assign/organisms/assignment_executor.rb +1299 -0
  102. data/lib/ace/assign/version.rb +7 -0
  103. data/lib/ace/assign.rb +141 -0
  104. metadata +289 -0
@@ -0,0 +1,666 @@
1
+ ---
2
+ doc-type: workflow
3
+ title: Drive Assignment Workflow
4
+ purpose: workflow instruction for driving ace-assign assignment execution
5
+ ace-docs:
6
+ last-updated: 2026-03-18
7
+ last-checked: 2026-03-21
8
+ ---
9
+
10
+ # Drive Assignment Workflow
11
+
12
+ ## Purpose
13
+
14
+ Drive agent execution through an active assignment by continuously checking status, executing the current step, and reporting completion. This is the main execution loop for working through an assignment workflow.
15
+
16
+ ## Prerequisites
17
+
18
+ - An active assignment exists (created via `ace-assign create` or `/as-assign-create`)
19
+ - Assignment has at least one pending or in_progress step
20
+
21
+ ## Assignment Context Propagation
22
+
23
+ When working with multiple concurrent assignments, the active assignment is resolved in this order:
24
+
25
+ 1. `--assignment <id>` flag on any command (highest priority)
26
+ 2. `.current` symlink (set via `ace-assign select <id>`)
27
+ 3. `.latest` symlink (auto-updated on any activity)
28
+ 4. Scan all assignments (fallback)
29
+
30
+ If this workflow is invoked with an argument (for example `/as-assign-drive abc123@010.01`), treat that value as the initial assignment target. If no argument is provided, resolve one active assignment and pin it for the entire loop.
31
+
32
+ ```bash
33
+ # Set once from workflow argument (empty when not provided)
34
+ ASSIGNMENT_TARGET="${1:-}"
35
+
36
+ # Resolve and pin assignment identity for the full drive loop
37
+ if [ -n "$ASSIGNMENT_TARGET" ]; then
38
+ STATUS_JSON=$(ace-assign status --assignment "$ASSIGNMENT_TARGET" --format json)
39
+ else
40
+ # Only here: resolve active assignment once before pinning target
41
+ STATUS_JSON=$(ace-assign status --format json)
42
+ fi
43
+ ASSIGNMENT_ID=$(echo "$STATUS_JSON" | ruby -rjson -e 'puts JSON.parse(STDIN.read).dig("assignment", "id")')
44
+ if [ -z "$ASSIGNMENT_ID" ]; then
45
+ echo "No active assignment found"
46
+ exit 1
47
+ fi
48
+ if [ -z "$ASSIGNMENT_TARGET" ]; then
49
+ ASSIGNMENT_TARGET="$ASSIGNMENT_ID"
50
+ fi
51
+ ```
52
+
53
+ ### Explicit Assignment Targeting (Recommended)
54
+
55
+ Use explicit flags to propagate assignment context across subprocesses and tools:
56
+
57
+ ```bash
58
+ # Explicitly target assignment on every command
59
+ ace-assign status --assignment abc123
60
+ ace-assign finish --message done.md --assignment abc123
61
+ ace-assign fail --message "err" --assignment abc123
62
+ ```
63
+
64
+ Once `ASSIGNMENT_TARGET` is pinned, do not run unscoped execution commands (`status`, `start`, `finish`, `fail`, `retry`, `add`) inside the drive loop.
65
+
66
+ ### Subtree Fork Scope (Explicit `@<step-number>`)
67
+
68
+ For split-task delegation, run the entire subtree in one forked process:
69
+
70
+ ```bash
71
+ ace-assign status --assignment abc123@010.01
72
+ ace-assign finish --message done.md --assignment abc123@010.01
73
+ ```
74
+
75
+ When an assignment target includes scope (`<id>@<root>`), `ace-assign finish --message` advances only within that subtree and stops when the subtree is complete.
76
+
77
+ Helper command:
78
+
79
+ ```bash
80
+ ace-assign fork-run --root 010.01 --assignment abc123
81
+ ```
82
+
83
+ ### Multi-Assignment Management
84
+
85
+ ```bash
86
+ # List all active assignments
87
+ ace-assign list
88
+
89
+ # List including completed
90
+ ace-assign list --all
91
+
92
+ # Switch active assignment
93
+ ace-assign select <id>
94
+
95
+ # Clear explicit selection (revert to most recent)
96
+ ace-assign select --clear
97
+
98
+ # Target specific assignment without switching
99
+ ace-assign status --assignment <id>
100
+ ace-assign finish --message done.md --assignment <id>
101
+ ```
102
+
103
+ ## Execution Loop
104
+
105
+ Repeat the following cycle until all steps are done or failed:
106
+
107
+ ### Step Execution Policy
108
+
109
+ - Planned steps are mandatory work items. Do not skip them by judgment.
110
+ - For each active step, do exactly one of:
111
+ 1. Execute the step and report completion with `ace-assign finish --message`
112
+ 2. Attempt execution, capture blocker evidence, and mark failed with `ace-assign fail`
113
+ - Never use report text to "skip" or synthesize completion for planned steps.
114
+ - **Fork-delegation constraint**: If the active step has `FORK: yes`, the driver MUST delegate via `ace-assign fork-run`. The driver MUST NOT execute fork-marked steps inline, absorb remaining fork children after partial failure, or inject retry steps as top-level siblings. All fork recovery goes through re-fork (see [Fork-Run Crash Recovery](#fork-run-crash-recovery-partial-completion)).
115
+ - **Conditional release in review subtrees**: A `release` step inside a review cycle (e.g., `[review-pr, apply-feedback, release]`) MUST skip the version bump when prior sibling steps produced no code changes. If `apply-feedback` reported no findings or `git diff HEAD~1 --stat` shows only report files, mark release done with "no-op: no changes to release" instead of bumping.
116
+
117
+ ### Adaptation Assessment (After Each Step)
118
+
119
+ After completing or failing each step, evaluate whether the assignment needs adaptation:
120
+
121
+ - **Test failures detected** → Consider adding a fix-tests step:
122
+ ```bash
123
+ ace-assign add "fix-tests" --instructions "Fix failing tests identified in step NNN" --assignment "$ASSIGNMENT_TARGET"
124
+ ```
125
+
126
+ - **Review found critical issues** → Consider adding an apply-critical-fixes step:
127
+ ```bash
128
+ ace-assign add "apply-critical-fixes" --instructions "Address critical review findings before proceeding" --assignment "$ASSIGNMENT_TARGET"
129
+ ```
130
+
131
+ - **Missing prerequisite discovered** → Consider adding the prerequisite step:
132
+ ```bash
133
+ ace-assign add "missing-prereq" --instructions "Complete prerequisite work discovered during step NNN" --assignment "$ASSIGNMENT_TARGET"
134
+ ```
135
+
136
+ - **Metadata hint**: Step file contains `trigger_on_failure` — if the step failed, inject the referenced step type
137
+
138
+ Use `decision_notes` from step metadata (if present) as additional guidance for these assessments.
139
+
140
+ - **Review-cycle circuit breaker**: When a review fork subtree fails due to provider unavailability (not code bugs), evaluate whether to attempt the next review cycle:
141
+ - If the **first** review cycle (valid) failed on providers: skip remaining cycles (fit, shine). Mark them done with "skipped: provider unavailable for prior cycle" reports.
142
+ - If the **second** cycle (fit) failed after valid succeeded: skip shine. Valid already captured correctness issues.
143
+ - **Never retry a provider-failed review cycle more than once.** If the re-fork also fails on providers, mark the cycle done-with-skip and move on.
144
+
145
+ - **Transient network failure retry**: When a fork subtree fails due to a transient network error (connection reset, DNS timeout, socket hangup) — as opposed to provider unavailability or auth failure — wait 30 seconds and re-fork once. If the re-fork also fails on a network error, treat it as a hard failure and apply the circuit breaker rules above. Auth errors (401/403) and not-found errors (404) are never transient — fail immediately on those.
146
+
147
+ ### 1. Check Status
148
+
149
+ ```bash
150
+ STATUS_OUTPUT=$(ace-assign status --assignment "$ASSIGNMENT_TARGET" 2>&1)
151
+ echo "$STATUS_OUTPUT"
152
+ ```
153
+
154
+ Read the output to identify:
155
+ - Assignment ID (must remain equal to pinned `ASSIGNMENT_ID`)
156
+ - Current step number, name, and status
157
+ - Current step's instructions
158
+ - Current step's skill reference (if any)
159
+ - Remaining steps in the queue
160
+
161
+ **Note:** `ace-assign status` is the source of truth for assignment state. The step files in the `steps/` directory are the backing store, but always query status via the command for accurate information.
162
+
163
+ ### 2. Auto-Delegate Fork Subtrees (When Applicable)
164
+
165
+ Before executing the current step inline, check whether the active step is inside a fork-enabled subtree.
166
+
167
+ #### Pre-Fork Clean Tree Guard
168
+
169
+ Before launching any `fork-run`, verify the working tree is clean:
170
+
171
+ ```bash
172
+ DIRTY=$(git status --short)
173
+ if [ -n "$DIRTY" ]; then
174
+ # Filter out expected assignment metadata (always dirty during drive)
175
+ UNRELATED=$(echo "$DIRTY" | grep -v '\.ace-local/assign/' | grep -v '\.ace-tasks/' | grep -v '\.ace-retros/')
176
+ if [ -n "$UNRELATED" ]; then
177
+ echo "WARNING: Unrelated dirty files detected before fork-run:"
178
+ echo "$UNRELATED"
179
+ # Commit to prevent fork agent stall
180
+ ace-git-commit -i "pre-fork: commit dirty tree before ${FORK_ROOT}"
181
+ fi
182
+ fi
183
+ ```
184
+
185
+ This prevents fork agents from stalling on pre-existing unrelated changes. Assignment metadata files (`.ace-local/`, `.ace-tasks/`, `.ace-retros/`) are expected to be dirty during drive execution and are excluded.
186
+
187
+ #### Delegation Rule
188
+
189
+ **FORK SIGNAL**: If a step row shows `yes` in the `FORK` column, the step itself has `context: fork` and MUST be delegated via `fork-run`.
190
+
191
+ | Column | Meaning | Action |
192
+ |--------|---------|--------|
193
+ | `FORK: yes` | Step has `context: fork` | Delegate via `fork-run` |
194
+ | `FORK: ` (empty) | Step is not fork-enabled | Execute inline (or inspect fork-enabled children if batch parent) |
195
+
196
+ **Example status output:**
197
+ ```
198
+ NUMBER STATUS NAME FORK CHILDREN
199
+ ------------------------------------------------------------------------------
200
+ 010 ✓ Done onboard
201
+ 020 ○ Pending implement-step yes
202
+ ```
203
+
204
+ Step 020 shows `FORK: yes` → run:
205
+ ```bash
206
+ ace-assign fork-run --assignment <id>@020
207
+ ```
208
+
209
+ **Delegation boundary rule**
210
+
211
+ - Outside a delegated fork scope, do NOT execute fork steps inline.
212
+ - If status output is already scoped to `Current Step: <root>.*` via `--assignment <id>@<root>`, the fork boundary is already entered: continue inline and never call `fork-run` again for the same `<root>`.
213
+ - If the current step is a top-level step with `FORK: yes` and no matching scope is active, delegate immediately.
214
+
215
+ #### Nested Batch Containers (Container → Fork Children)
216
+
217
+ A batch container (e.g., `010`) may have children but no fork context itself (`FORK` column empty). In that case, delegate child steps according to scheduler metadata on the parent:
218
+
219
+ - `batch_parent: true`
220
+ - `parallel: true|false`
221
+ - `max_parallel: <N>`
222
+ - `fork_retry_limit: <N>` (default `1`)
223
+
224
+ **How to distinguish:**
225
+ - **Direct fork target**: `FORK: yes` on the current step → fork-run the current step.
226
+ - **Batch container**: `FORK: ` on parent, but children include `FORK: yes` steps.
227
+
228
+ **Pattern for batch containers:**
229
+ ```bash
230
+ # Read scheduler metadata from parent step 010
231
+ # parallel=false => sequential, still fork every child
232
+ # parallel=true => windowed fork concurrency with max_parallel
233
+ ```
234
+
235
+ **Sequential mode (`parallel: false`)**
236
+
237
+ - Iterate pending child steps in number order.
238
+ - For each child with `FORK: yes`, run:
239
+ - `ace-assign fork-run --assignment <id>@<child>`
240
+ - Re-check status after each child.
241
+ - Do not pause for user input between children — treat the batch loop as a single unit (see Batch Continuation Rule below).
242
+
243
+ **Parallel mode (`parallel: true`)**
244
+
245
+ - `max_parallel` is an in-flight concurrency cap, not a wave size.
246
+ - Maintain up to `max_parallel` in-flight child `fork-run` processes.
247
+ - Launch only child steps with `FORK: yes`.
248
+ - Refill a free slot immediately when any child completes, until pending queue is empty.
249
+ - Do not launch a fixed group and wait for the whole group to finish before launching more work.
250
+
251
+ **Rolling scheduler loop (required)**
252
+
253
+ 1. Build pending fork-child queue in step-number order.
254
+ 2. Launch children until `in_flight == max_parallel` or pending is empty.
255
+ 3. Wait for any in-flight child to finish, then record done/failed state.
256
+ 4. If child succeeded, immediately launch the next pending child; if no pending remains, continue draining in-flight children.
257
+ 5. Stop only when both pending and in-flight are empty.
258
+
259
+ **Batch Continuation Rule**
260
+
261
+ The driver MUST NOT pause for user input between child fork-runs within a batch container. After each child completes:
262
+
263
+ 1. Verify the child's reports (see Subtree Guard below).
264
+ 2. If reports indicate successful completion, immediately launch the next pending child.
265
+ 3. Treat the entire batch loop as a single unit of execution — only pause on quality concerns flagged during report review.
266
+ 4. For timeout-constrained environments: launch `fork-run` in background, poll for completion, then loop to the next child without pausing.
267
+
268
+ **Failure policy (retry-then-stop)**
269
+
270
+ - On any child failure:
271
+ - Pause launching new children immediately.
272
+ - Wait for in-flight children to finish.
273
+ - Retry failed child once (`fork_retry_limit=1` default).
274
+ - If retry succeeds, resume launches.
275
+ - If retry fails, stop driving and fail the batch subtree.
276
+
277
+ #### Example
278
+
279
+ ```bash
280
+ STATUS_JSON=$(ace-assign status --assignment "$ASSIGNMENT_TARGET" --format json)
281
+ ASSIGNMENT_ID=$(echo "$STATUS_JSON" | ruby -rjson -e 'puts JSON.parse(STDIN.read).dig("assignment", "id")')
282
+ FORK_ROOT=$(echo "$STATUS_JSON" | ruby -rjson -e '
283
+ p = JSON.parse(STDIN.read)["current_step"]
284
+ puts p["number"] if p && p["context"] == "fork"
285
+ ')
286
+ if [ -n "$FORK_ROOT" ]; then
287
+ ace-assign fork-run --assignment "${ASSIGNMENT_ID}@${FORK_ROOT}"
288
+ # Re-check status after subtree delegation completes
289
+ continue
290
+ fi
291
+ ```
292
+
293
+ `fork-run` executes the entire subtree in one dedicated process and returns when the subtree is complete or failed.
294
+
295
+ > **Long-running execution:** `fork-run` typically takes 10-30 minutes depending on subtree complexity. If your environment has bash timeout limits (e.g., Claude Code's 10-minute Bash tool limit), run `fork-run` in background and poll for completion:
296
+ >
297
+ > ```bash
298
+ > # Run fork-run in background (use run_in_background: true in Claude Code)
299
+ > ace-assign fork-run --assignment "${ASSIGNMENT_ID}@${FORK_ROOT}" &
300
+ >
301
+ > # Poll scoped status every 5 minutes until subtree completes
302
+ > while true; do
303
+ > STATUS_JSON=$(ace-assign status --assignment "${ASSIGNMENT_ID}@${FORK_ROOT}" --format json)
304
+ > COMPLETE=$(echo "$STATUS_JSON" | ruby -rjson -e '
305
+ > json = JSON.parse(STDIN.read)
306
+ > steps = json["steps"] || []
307
+ > puts steps.all? { |step| step["status"] == "done" || step["status"] == "failed" }
308
+ > ')
309
+ > [ "$COMPLETE" = "true" ] && break
310
+ > sleep 300
311
+ > done
312
+ > ```
313
+
314
+ #### Subtree Completion: Task Status Verification
315
+
316
+ After a fork subtree completes (work-on-task finishes successfully):
317
+
318
+ 1. **Verify ace-taskflow status matches assignment status.** If the assignment shows `work-on-task` as done but ace-taskflow still shows `in-progress`, status drift has occurred.
319
+
320
+ 2. **If mark-task-done step was NOT included in the assignment** (common for ad-hoc assignments):
321
+ ```bash
322
+ # Manually sync status before reporting subtree complete
323
+ ace-task done {taskref}
324
+ ace-task {taskref} # Verify it shows status: done
325
+ ```
326
+
327
+ 3. **Report the subtree complete only after verification.** This prevents the orchestrator from showing work as done while ace-taskflow shows it as in-progress.
328
+
329
+ #### Subtree Guard: Review Fork Reports Before Continuing
330
+
331
+ After fork-run returns and completion is verified, the driver acts as the **guard** for the subtree. Before continuing to the next step:
332
+
333
+ 1. **Read all subtree report files** from `.ace-local/assign/<assignment-id>/reports/`:
334
+ ```bash
335
+ # List and read all reports for the completed subtree
336
+ ls .ace-local/assign/${ASSIGNMENT_ID}/reports/${FORK_ROOT}.*
337
+ # Read each report file to review the forked agent's work
338
+ ```
339
+ 2. **Check for uncommitted changes** left by the fork agent:
340
+ ```bash
341
+ DIRTY=$(git status --short)
342
+ if [ -n "$DIRTY" ]; then
343
+ echo "WARNING: Fork subtree ${FORK_ROOT} left uncommitted changes:"
344
+ echo "$DIRTY"
345
+ # Commit orphaned changes as safety net
346
+ ace-git-commit -i "commit changes left by fork subtree ${FORK_ROOT}"
347
+ fi
348
+ ```
349
+ Fork agents are expected to commit all their work. Uncommitted files indicate incomplete commit discipline — note this when reviewing reports.
350
+ 3. **Verify quality**: Check that reports indicate successful completion, not just step advancement.
351
+ 4. **Flag concerns**: If any report indicates partial work, errors, or skipped steps, stop and ask the user before continuing.
352
+ 5. **Only then continue** the main drive loop to the next step.
353
+
354
+ > The driver is the only entity with cross-subtree visibility. Skipping report review means errors in one subtree propagate silently to the next.
355
+
356
+ #### Queue Advancement After Batch Container Completion
357
+
358
+ After all fork subtrees within a batch container complete, the container auto-marks as Done. However, the queue pointer may not automatically advance to the next top-level step.
359
+
360
+ **After verifying all fork subtree reports**, if `ace-assign status` shows no Active step (all completed steps but no new in-progress step), run:
361
+ ```bash
362
+ ace-assign start --assignment "$ASSIGNMENT_TARGET"
363
+ ```
364
+ This advances the queue to the next pending top-level step.
365
+
366
+ #### Fork-Run Recovery
367
+
368
+ When `fork-run` exits non-zero, invoke the fork recovery workflow:
369
+
370
+ ```bash
371
+ ace-bundle wfi://assign/recover-fork
372
+ ```
373
+
374
+ Or invoke via skill: `/as-assign-recover-fork ${ASSIGNMENT_ID}@${FORK_ROOT}`
375
+
376
+ The recovery workflow handles three scenarios:
377
+
378
+ | Scenario | Signal | Recovery |
379
+ |----------|--------|----------|
380
+ | **Crash with partial progress** | `exit != 0` + uncommitted files or mixed step status | Commit partial work, inject recovery-onboard + continue-work children, re-fork |
381
+ | **Provider unavailability** | `exit != 0` + timeout/hang error (no code bug) | LLM-tool steps: inline or retry child. Code steps: wait or escalate |
382
+ | **Mixed state after provider failure** | Done + failed + pending children | Inject retry children, re-fork |
383
+
384
+ **Key principles** (enforced by the recovery workflow):
385
+
386
+ - Never execute fork work inline (except LLM-tool steps during provider unavailability)
387
+ - Recovery steps are always children inside the subtree, never top-level siblings
388
+ - Recovery-onboard must list explicit report file paths (not semantic references)
389
+ - Continue-work must copy the original failed step's instructions verbatim
390
+
391
+ See `wfi://assign/recover-fork` for the full protocol, detection rules, and recovery step construction templates.
392
+
393
+ ### 3. Execute Current Step
394
+
395
+ Based on the step configuration:
396
+
397
+ #### If Step Has a `skill:` Field
398
+
399
+ Invoke the referenced skill as the primary action, extracting parameters from the instructions:
400
+
401
+ ```yaml
402
+ - name: work-on-task
403
+ skill: as-task-work
404
+ instructions: |
405
+ Work on task 148.
406
+ Follow project conventions.
407
+ ```
408
+
409
+ **Agent Action:** Run `/as-task-work 148` then follow the skill workflow.
410
+
411
+ #### If Step Has No Skill
412
+
413
+ Follow the instructions directly, performing the described work:
414
+
415
+ ```yaml
416
+ - name: setup
417
+ instructions: |
418
+ Install dependencies.
419
+ Configure the database.
420
+ Verify installation.
421
+ ```
422
+
423
+ **Agent Action:** Execute each instruction line as a task.
424
+
425
+ ### 4. External Action Rule (Attempt-First)
426
+
427
+ For external-facing steps (for example PR/review/release/push/update lifecycle steps):
428
+
429
+ - Attempt the step command(s) first.
430
+ - If blocked, capture concrete evidence:
431
+ - command attempted
432
+ - exact error output
433
+ - why the step cannot proceed
434
+ - Mark step failed with evidence (do not report synthetic completion).
435
+
436
+ ```bash
437
+ ace-assign fail --message "Command failed: <cmd>. Error: <exact stderr>" --assignment "$ASSIGNMENT_TARGET"
438
+ ```
439
+
440
+ ### 5. Write Report (Only After Real Execution)
441
+
442
+ After completing the step work, write a brief report summarizing what was accomplished:
443
+
444
+ ```bash
445
+ # Write report content to a temp file
446
+ cat > /tmp/step-report.md << 'EOF'
447
+ ## Summary
448
+
449
+ Completed the setup step successfully:
450
+
451
+ - Installed all dependencies via npm install
452
+ - Configured PostgreSQL database connection
453
+ - Verified installation with health check
454
+
455
+ All setup prerequisites are now satisfied.
456
+ EOF
457
+
458
+ # Submit report to advance the queue
459
+ ace-assign finish --message /tmp/step-report.md --assignment "$ASSIGNMENT_TARGET"
460
+ ```
461
+
462
+ ### 6. Verify State Transition (Required)
463
+
464
+ After each `ace-assign finish --message` or `ace-assign fail`, verify queue state:
465
+
466
+ ```bash
467
+ POST_STATUS=$(ace-assign status --assignment "$ASSIGNMENT_TARGET" 2>&1)
468
+ echo "$POST_STATUS"
469
+ ```
470
+
471
+ Required checks:
472
+ - If report succeeded: active step advanced consistently with work performed
473
+ - If fail succeeded: assignment is stalled or moved according to retry/add logic
474
+ - If output mismatches expected transition: stop and ask user before continuing
475
+
476
+ ### 7. Handle Failures
477
+
478
+ If a step cannot be completed:
479
+
480
+ ```bash
481
+ # Mark step as failed with reason
482
+ ace-assign fail --message "Tests failed: test_greet, test_shout" --assignment "$ASSIGNMENT_TARGET"
483
+ ```
484
+
485
+ Then decide on next action:
486
+
487
+ #### Option A: Retry the Failed Step
488
+
489
+ ```bash
490
+ ace-assign retry <step-number> --assignment "$ASSIGNMENT_TARGET"
491
+ ```
492
+
493
+ Creates a new step linked to the original. Original remains visible as failed.
494
+
495
+ #### Option B: Add a Fix Step
496
+
497
+ ```bash
498
+ ace-assign add "fix-issue" --instructions "Fix the failing tests and verify" --assignment "$ASSIGNMENT_TARGET"
499
+ ```
500
+
501
+ New step is inserted after the current in-progress step.
502
+
503
+ #### Option C: Ask the User
504
+
505
+ If uncertain, ask the user whether to retry, add a fix step, or abort.
506
+
507
+ ### 8. Repeat
508
+
509
+ Check status again:
510
+ - If there is a next step, continue the loop from step 1
511
+ - If all steps are `done`, proceed to Completion
512
+ - If assignment has failed steps and no fix is planned, report to user
513
+
514
+ ## Completion
515
+
516
+ When `ace-assign status` shows all steps as `done`:
517
+
518
+ ```bash
519
+ ace-assign status --assignment "$ASSIGNMENT_TARGET"
520
+ ```
521
+
522
+ Example output:
523
+ ```
524
+ Assignment: work-on-task-123 (8or5kx)
525
+
526
+ Step Status Name
527
+ 010 done onboard
528
+ 020 done work-on-task
529
+ 030 done finalize
530
+
531
+ All steps complete!
532
+ ```
533
+
534
+ Summarize the assignment results to the user:
535
+ - What was accomplished
536
+ - Any artifacts created (PRs, commits, etc.)
537
+ - Next steps or follow-up actions
538
+
539
+ ## Skill Invocation Pattern
540
+
541
+ When executing a step with a `skill:` field:
542
+
543
+ 1. **Read step instructions** - Understand context and parameters
544
+ 2. **Extract parameters** - Get task IDs, PR numbers from instructions
545
+ 3. **Invoke skill** - Run the referenced skill command
546
+ 4. **Follow skill workflow** - Complete the skill's process
547
+ 5. **Report completion** - Use `ace-assign finish --message` with results
548
+
549
+ ### Common Skill References
550
+
551
+ | Skill | Invocation | Purpose |
552
+ |-------|-----------|---------|
553
+ | `onboard` | `/as-onboard` | Load project context |
554
+ | `ace:task-work` | `/as-task-work <taskref>` | Implement task changes |
555
+ | `ace:github-pr-create` | `/as-github-pr-create` | Create pull request |
556
+ | `ace:review-pr` | `/as-review-pr [pr#]` | Review code changes |
557
+ | `ace:git-commit` | `/as-git-commit` | Generate commit message |
558
+ | `ace:github-pr-update` | `/as-github-pr-update` | Update PR description |
559
+
560
+ ## Error Handling
561
+
562
+ | Scenario | Action |
563
+ |----------|--------|
564
+ | No active assignment | Create an assignment first via `/as-assign-create` |
565
+ | All steps done | Report completion to user |
566
+ | Step fails | Attempt first, then use `fail` with command/error evidence; decide retry/add/ask |
567
+ | Skill not found | Execute instructions directly without skill |
568
+ | Unclear instructions | Ask user for clarification |
569
+ | Provider/tool unavailable | For fork steps: see Provider-Unavailability Recovery. For inline steps: attempt with alternate model, then fail with evidence |
570
+
571
+ ## Assignment State Reference
572
+
573
+ ### Step Status Values
574
+
575
+ | Status | Meaning | Next Action |
576
+ |--------|---------|-------------|
577
+ | `pending` | Step not started | Cannot execute (wait for queue) |
578
+ | `in_progress` | Step is active | Execute this step |
579
+ | `done` | Step completed | Move to next step |
580
+ | `failed` | Step failed | Decide: retry, add fix, or abort |
581
+
582
+ ### Assignment Directory Structure
583
+
584
+ ```
585
+ .ace-local/assign/
586
+ ├── .latest → abc123/ # Auto-updated on any activity
587
+ ├── .current → def456/ # Explicit user selection (optional)
588
+ ├── abc123/
589
+ │ ├── assignment.yaml # Assignment metadata
590
+ │ ├── steps/ # Step files (.st.md extension)
591
+ │ │ ├── 010-init.st.md # done
592
+ │ │ ├── 020-implement.st.md # in_progress
593
+ │ │ └── 030-test.st.md # pending
594
+ │ └── reports/ # Report files (.r.md extension)
595
+ │ ├── 010-init.r.md # completed report
596
+ │ └── 020-implement.r.md # in-progress report
597
+ └── def456/
598
+ ├── assignment.yaml
599
+ ├── steps/
600
+ └── reports/
601
+ ```
602
+
603
+ Each step has:
604
+ - **Step file** (`steps/NNN-name.st.md`) - Contains step instructions and status
605
+ - **Report file** (`reports/NNN-name.r.md`) - Contains completion report (created when step is done)
606
+
607
+ ## Numbering Convention
608
+
609
+ | Pattern | Purpose | Example |
610
+ |---------|---------|---------|
611
+ | `010`, `020`, `030` | Main tasks (10-step gaps) | `010-init.st.md` |
612
+ | `010.01`, `010.02` | Subtasks | `010.01-setup.st.md` |
613
+ | `041`, `042` | Injected after existing | `041-fix.st.md` |
614
+
615
+ ## Exit Codes
616
+
617
+ | Code | Meaning |
618
+ |------|---------|
619
+ | 0 | Success |
620
+ | 1 | General error |
621
+ | 2 | No active assignment |
622
+ | 3 | File not found (report file) |
623
+ | 4 | Invalid step reference |
624
+
625
+ ## Success Criteria
626
+
627
+ - All steps processed (done or failed)
628
+ - Reports written for all completed steps
629
+ - Failed steps have clear failure reasons
630
+ - No planned step is auto-completed via skip-by-assumption behavior
631
+ - User informed of assignment completion state
632
+ - Artifacts and next steps clearly communicated
633
+
634
+ ## Example Assignment Flow
635
+
636
+ ```bash
637
+ # 0. Pin assignment for this loop
638
+ $ ASSIGNMENT_TARGET=8or5kx
639
+
640
+ # 1. Check status
641
+ $ ace-assign status --assignment "$ASSIGNMENT_TARGET"
642
+ Step 010: onboard [in_progress]
643
+
644
+ # 2. Execute step (has skill: onboard)
645
+ $ /as-onboard
646
+ [Onboarding workflow runs...]
647
+
648
+ # 3. Write report
649
+ $ ace-assign finish --message onboard-complete.md --assignment "$ASSIGNMENT_TARGET"
650
+ Step 010 marked done, advancing to 020
651
+
652
+ # 4. Check status again
653
+ $ ace-assign status --assignment "$ASSIGNMENT_TARGET"
654
+ Step 020: work-on-task [in_progress]
655
+
656
+ # 5. Execute next step (has skill: as-task-work)
657
+ $ /as-task-work 148
658
+ [Task workflow runs...]
659
+
660
+ # 6. Report and continue...
661
+ $ ace-assign finish --message task-done.md --assignment "$ASSIGNMENT_TARGET"
662
+
663
+ # 7. Eventually...
664
+ $ ace-assign status --assignment "$ASSIGNMENT_TARGET"
665
+ All steps complete!
666
+ ```