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.
- checksums.yaml +7 -0
- data/.ace-defaults/assign/catalog/composition-rules.yml +211 -0
- data/.ace-defaults/assign/catalog/recipes/batch-tasks.recipe.yml +44 -0
- data/.ace-defaults/assign/catalog/recipes/documentation.recipe.yml +35 -0
- data/.ace-defaults/assign/catalog/recipes/fix-and-review.recipe.yml +32 -0
- data/.ace-defaults/assign/catalog/recipes/implement-simple.recipe.yml +29 -0
- data/.ace-defaults/assign/catalog/recipes/implement-with-pr.recipe.yml +48 -0
- data/.ace-defaults/assign/catalog/recipes/release-only.recipe.yml +34 -0
- data/.ace-defaults/assign/catalog/steps/apply-feedback.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/commit.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/create-pr.step.yml +28 -0
- data/.ace-defaults/assign/catalog/steps/create-retro.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/fix-tests.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/lint.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/mark-task-done.step.yml +57 -0
- data/.ace-defaults/assign/catalog/steps/onboard-base.step.yml +19 -0
- data/.ace-defaults/assign/catalog/steps/onboard.step.yml +19 -0
- data/.ace-defaults/assign/catalog/steps/plan-task.step.yml +17 -0
- data/.ace-defaults/assign/catalog/steps/pre-commit-review.step.yml +34 -0
- data/.ace-defaults/assign/catalog/steps/push-to-remote.step.yml +28 -0
- data/.ace-defaults/assign/catalog/steps/rebase-with-main.step.yml +28 -0
- data/.ace-defaults/assign/catalog/steps/reflect-and-refactor.step.yml +57 -0
- data/.ace-defaults/assign/catalog/steps/release-minor.step.yml +23 -0
- data/.ace-defaults/assign/catalog/steps/release.step.yml +23 -0
- data/.ace-defaults/assign/catalog/steps/reorganize-commits.step.yml +28 -0
- data/.ace-defaults/assign/catalog/steps/research.step.yml +19 -0
- data/.ace-defaults/assign/catalog/steps/review-pr.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/security-audit.step.yml +22 -0
- data/.ace-defaults/assign/catalog/steps/split-subtree-root.step.yml +25 -0
- data/.ace-defaults/assign/catalog/steps/squash-changelog.step.yml +28 -0
- data/.ace-defaults/assign/catalog/steps/task-load.step.yml +29 -0
- data/.ace-defaults/assign/catalog/steps/update-docs.step.yml +38 -0
- data/.ace-defaults/assign/catalog/steps/update-pr-desc.step.yml +28 -0
- data/.ace-defaults/assign/catalog/steps/verify-e2e.step.yml +42 -0
- data/.ace-defaults/assign/catalog/steps/verify-test-suite.step.yml +48 -0
- data/.ace-defaults/assign/catalog/steps/verify-test.step.yml +36 -0
- data/.ace-defaults/assign/catalog/steps/work-on-task.step.yml +23 -0
- data/.ace-defaults/assign/config.yml +48 -0
- data/.ace-defaults/assign/presets/fix-bug.yml +65 -0
- data/.ace-defaults/assign/presets/quick-implement.yml +41 -0
- data/.ace-defaults/assign/presets/release-only.yml +35 -0
- data/.ace-defaults/assign/presets/work-on-docs.yml +41 -0
- data/.ace-defaults/assign/presets/work-on-task.yml +179 -0
- data/.ace-defaults/nav/protocols/skill-sources/ace-assign.yml +19 -0
- data/.ace-defaults/nav/protocols/wfi-sources/ace-assign.yml +19 -0
- data/CHANGELOG.md +1415 -0
- data/README.md +87 -0
- data/Rakefile +16 -0
- data/docs/exit-codes.md +61 -0
- data/docs/getting-started.md +121 -0
- data/docs/handbook.md +40 -0
- data/docs/usage.md +224 -0
- data/exe/ace-assign +16 -0
- data/handbook/guides/fork-context.g.md +231 -0
- data/handbook/skills/as-assign-compose/SKILL.md +24 -0
- data/handbook/skills/as-assign-create/SKILL.md +23 -0
- data/handbook/skills/as-assign-drive/SKILL.md +24 -0
- data/handbook/skills/as-assign-prepare/SKILL.md +23 -0
- data/handbook/skills/as-assign-recover-fork/SKILL.md +22 -0
- data/handbook/skills/as-assign-run-in-batches/SKILL.md +23 -0
- data/handbook/skills/as-assign-start/SKILL.md +25 -0
- data/handbook/workflow-instructions/assign/compose.wf.md +256 -0
- data/handbook/workflow-instructions/assign/create.wf.md +215 -0
- data/handbook/workflow-instructions/assign/drive.wf.md +666 -0
- data/handbook/workflow-instructions/assign/prepare.wf.md +469 -0
- data/handbook/workflow-instructions/assign/recover-fork.wf.md +233 -0
- data/handbook/workflow-instructions/assign/run-in-batches.wf.md +212 -0
- data/handbook/workflow-instructions/assign/start.wf.md +46 -0
- data/lib/ace/assign/atoms/assign_frontmatter_parser.rb +173 -0
- data/lib/ace/assign/atoms/catalog_loader.rb +101 -0
- data/lib/ace/assign/atoms/composition_rules.rb +219 -0
- data/lib/ace/assign/atoms/number_generator.rb +110 -0
- data/lib/ace/assign/atoms/preset_expander.rb +277 -0
- data/lib/ace/assign/atoms/step_file_parser.rb +207 -0
- data/lib/ace/assign/atoms/step_numbering.rb +227 -0
- data/lib/ace/assign/atoms/step_sorter.rb +66 -0
- data/lib/ace/assign/atoms/tree_formatter.rb +106 -0
- data/lib/ace/assign/cli/commands/add.rb +102 -0
- data/lib/ace/assign/cli/commands/assignment_target.rb +55 -0
- data/lib/ace/assign/cli/commands/create.rb +63 -0
- data/lib/ace/assign/cli/commands/fail.rb +43 -0
- data/lib/ace/assign/cli/commands/finish.rb +88 -0
- data/lib/ace/assign/cli/commands/fork_run.rb +229 -0
- data/lib/ace/assign/cli/commands/list.rb +166 -0
- data/lib/ace/assign/cli/commands/retry_cmd.rb +42 -0
- data/lib/ace/assign/cli/commands/select.rb +45 -0
- data/lib/ace/assign/cli/commands/start.rb +40 -0
- data/lib/ace/assign/cli/commands/status.rb +407 -0
- data/lib/ace/assign/cli.rb +144 -0
- data/lib/ace/assign/models/assignment.rb +107 -0
- data/lib/ace/assign/models/assignment_info.rb +66 -0
- data/lib/ace/assign/models/queue_state.rb +326 -0
- data/lib/ace/assign/models/step.rb +197 -0
- data/lib/ace/assign/molecules/assignment_discoverer.rb +57 -0
- data/lib/ace/assign/molecules/assignment_manager.rb +276 -0
- data/lib/ace/assign/molecules/fork_session_launcher.rb +102 -0
- data/lib/ace/assign/molecules/queue_scanner.rb +130 -0
- data/lib/ace/assign/molecules/skill_assign_source_resolver.rb +376 -0
- data/lib/ace/assign/molecules/step_renumberer.rb +227 -0
- data/lib/ace/assign/molecules/step_writer.rb +246 -0
- data/lib/ace/assign/organisms/assignment_executor.rb +1299 -0
- data/lib/ace/assign/version.rb +7 -0
- data/lib/ace/assign.rb +141 -0
- 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
|
+
```
|