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,469 @@
1
+ ---
2
+ doc-type: workflow
3
+ title: Prepare Assignment Workflow
4
+ purpose: workflow instruction for preparing ace-assign job configurations
5
+ ace-docs:
6
+ last-updated: 2026-03-18
7
+ last-checked: 2026-03-21
8
+ ---
9
+
10
+ # Prepare Assignment Workflow
11
+
12
+ ## Purpose
13
+
14
+ Transform informal instructions OR preset names into a structured job.yaml file that can be used with `ace-assign create job.yaml`. This workflow bridges the gap between high-level intent and the structured work queue format.
15
+
16
+ ## Input Formats
17
+
18
+ The workflow accepts three input types:
19
+
20
+ ### 1. Preset Name Only
21
+
22
+ ```
23
+ /as-assign-prepare work-on-task --taskref 123
24
+ ```
25
+
26
+ Loads the preset and injects parameter values.
27
+
28
+ ### 2. Informal Instructions Only
29
+
30
+ ```
31
+ /as-assign-prepare "Work on task 123, create a PR, do 2 review cycles"
32
+ ```
33
+
34
+ Transforms prose into structured steps.
35
+
36
+ ### 3. Preset + Customization
37
+
38
+ ```
39
+ /as-assign-prepare work-on-task --taskref 123 "skip onboarding, add security review"
40
+ ```
41
+
42
+ Loads preset then applies modifications.
43
+
44
+ ## Available Presets
45
+
46
+ Presets are stored in `ace-assign/.ace-defaults/assign/presets/`:
47
+
48
+ | Preset | Description |
49
+ |--------|-------------|
50
+ | `work-on-task` | Unified preset for single-task (`--taskref`) and batch (`--taskrefs`) execution |
51
+
52
+ List available presets:
53
+ ```bash
54
+ ls ace-assign/.ace-defaults/assign/presets/
55
+ ```
56
+
57
+ ## Preset File Format
58
+
59
+ ### Basic Preset
60
+
61
+ ```yaml
62
+ name: preset-name
63
+ description: What this preset does
64
+
65
+ parameters:
66
+ taskref:
67
+ required: true
68
+ description: Task reference (e.g., task-123 or 123)
69
+ pr_number:
70
+ required: false
71
+ description: Optional PR number for review steps
72
+
73
+ steps:
74
+ - name: step-name
75
+ skill: ace_skill_name # Optional skill reference
76
+ instructions:
77
+ - Step instruction line one.
78
+ - "Step instruction with {{parameter}} placeholder."
79
+ ```
80
+
81
+ ### Preset with Expansion Directives
82
+
83
+ For multi-task presets, use the `expansion` section to generate hierarchical steps:
84
+
85
+ ```yaml
86
+ name: work-on-task
87
+ description: Work on multiple tasks with consolidated review
88
+
89
+ parameters:
90
+ taskrefs:
91
+ required: true
92
+ type: array # Accepts comma-separated, range, or pattern
93
+ description: Task references (e.g., "148,149,150" or "148-152")
94
+
95
+ expansion:
96
+ batch-parent:
97
+ name: batch-tasks
98
+ number: "010"
99
+ instructions: |
100
+ Batch container - auto-completes when children done.
101
+ Tasks: {{taskrefs}}
102
+
103
+ foreach: taskrefs # Parameter name to iterate over
104
+ child-template:
105
+ name: "work-on-{{item}}" # {{item}} is current iteration value
106
+ parent: "010"
107
+ context: fork # Parent split step can be forked (children stay non-fork)
108
+ instructions: |
109
+ Implement task {{item}} per specification.
110
+
111
+ steps:
112
+ # Steps after expansion are appended with their own numbers
113
+ - name: consolidated-review
114
+ number: "020"
115
+ instructions: Review all batch changes.
116
+ ```
117
+
118
+ #### Array Parameter Syntax
119
+
120
+ The `--taskrefs` parameter accepts multiple formats:
121
+
122
+ | Format | Example | Result |
123
+ |--------|---------|--------|
124
+ | Comma-separated | `148,149,150` | Tasks 148, 149, 150 |
125
+ | Range | `148-152` | Tasks 148, 149, 150, 151, 152 |
126
+ | Pattern | `240.*` | All subtasks of 240 |
127
+
128
+ #### Generated Job Structure
129
+
130
+ For `--taskrefs 148,149,150`, expansion generates:
131
+
132
+ ```
133
+ 010 batch-tasks (parent, auto-completes)
134
+ ├── 010.01 work-on-148 (fork context on split parent)
135
+ │ ├── 010.01.01 onboard (no fork marker)
136
+ │ ├── 010.01.02 plan-task (no fork marker)
137
+ │ └── 010.01.03 work-on-task (no fork marker)
138
+ ├── 010.02 work-on-149 (fork context on split parent)
139
+ └── 010.03 work-on-150 (fork context on split parent)
140
+ 020 consolidated-review
141
+ 030 finalize
142
+ ```
143
+
144
+ The hierarchical numbering enables:
145
+ - Parent auto-completion when all children are done
146
+ - Parent-only fork markers for subtree delegation
147
+ - Progress tracking per-task
148
+
149
+ ## Parameter Placeholders
150
+
151
+ Use `{{parameter}}` syntax in preset instructions:
152
+ - `{{taskrefs}}` - Task references (single-item or multi-item list)
153
+ - `{{pr_number}}` - PR number (when available)
154
+
155
+ Parameters are injected when preparing the job.yaml.
156
+
157
+ ## Transformation Rules
158
+
159
+ ### From Informal Instructions
160
+
161
+ When parsing informal instructions, identify:
162
+
163
+ 1. **Task References**: "task 123", "task-123", "#123"
164
+ 2. **Skill Keywords**: Map to known skills
165
+ - "work on task" → `ace:task-work`
166
+ - "create pr", "make pr" → `ace:github-pr-create`
167
+ - "review", "review pr" → `ace:review-pr`
168
+ - "commit" → `ace:git-commit`
169
+ - "onboard" → `onboard`
170
+ 3. **Loop Indicators**: "2 cycles", "3 iterations", "twice"
171
+ 4. **Sequence Markers**: "then", "after that", "finally"
172
+
173
+ ### Loop Expansion
174
+
175
+ Review loops expand into forked cycle parent steps with standard child sub-steps:
176
+
177
+ ```yaml
178
+ # "do 3 review cycles" becomes:
179
+ - name: review-valid-1
180
+ context: fork
181
+ sub_steps: [review-pr, apply-feedback, release]
182
+ instructions:
183
+ - "Child review-pr: use preset code-valid."
184
+ - "Focus: correctness — bugs, logic errors, missing functionality, broken contracts."
185
+
186
+ - name: review-fit-1
187
+ context: fork
188
+ sub_steps: [review-pr, apply-feedback, release]
189
+ instructions:
190
+ - "Child review-pr: use preset code-fit."
191
+ - "Focus: quality — performance, architecture, standards, test coverage."
192
+
193
+ - name: review-shine-1
194
+ context: fork
195
+ sub_steps: [review-pr, apply-feedback, release]
196
+ instructions:
197
+ - "Child review-pr: use preset code-shine."
198
+ - "Focus: polish — simplification, naming, documentation (non-blocking suggestions)."
199
+ ```
200
+
201
+ ## Process Steps
202
+
203
+ ### 1. Parse Input
204
+
205
+ Determine input type:
206
+ - If starts with known preset name → load preset
207
+ - If contains `--taskref` or similar flags → extract parameters
208
+ - If quoted string or prose → parse as informal instructions
209
+
210
+ ### 2. Load Preset (if applicable)
211
+
212
+ ```bash
213
+ # Read preset file
214
+ cat ace-assign/.ace-defaults/assign/presets/<preset-name>.yml
215
+ ```
216
+
217
+ ### 3. Extract Parameters
218
+
219
+ From command-line flags:
220
+ - `--taskref 123` → normalize to `taskrefs: ["123"]` (single task shorthand)
221
+ - `--taskrefs 148,149,150` → `taskrefs: ["148", "149", "150"]` (multi-task)
222
+ - `--taskrefs 148-152` → `taskrefs: ["148", "149", "150", "151", "152"]` (range)
223
+ - `--output custom-job.yaml` → output path
224
+
225
+ From informal instructions:
226
+ - "task 123" → `taskrefs: ["123"]`
227
+ - "tasks 148, 149, 150" → `taskrefs: ["148", "149", "150"]`
228
+ - "PR 45" → `pr_number: "45"`
229
+
230
+ ### 4. Apply Customizations (if prose provided)
231
+
232
+ Parse modifications:
233
+ - "skip onboarding" → remove onboard step
234
+ - "add security review" → insert security review step
235
+ - "only 2 cycles" → adjust loop count
236
+
237
+ ### 5. Expand and Inject Parameters
238
+
239
+ For presets with `expansion` section, use `Ace::Assign::Atoms::PresetExpander.expand()`:
240
+
241
+ ```ruby
242
+ require "ace/assign"
243
+
244
+ preset = YAML.load_file("work-on-task.yml")
245
+ params = { "taskrefs" => ["148", "149", "150"], "review_preset" => "batch" }
246
+ steps = Ace::Assign::Atoms::PresetExpander.expand(preset, params)
247
+ ```
248
+
249
+ ### 5.1 Resolve Skill `assign.source` Metadata (Deterministic Runtime Expansion)
250
+
251
+ After preset expansion, each step with a `skill:` field may declare assignment source metadata via the skill frontmatter:
252
+
253
+ ```yaml
254
+ assign:
255
+ source: wfi://task/work
256
+ ```
257
+
258
+ Resolution flow:
259
+ 1. Find `SKILL.md` by step `skill` name (e.g., `ace:task-work`)
260
+ 2. Read `assign.source` from skill frontmatter
261
+ 3. Resolve `wfi://...` to workflow file
262
+ 4. Parse workflow frontmatter `assign.sub-steps`
263
+ 5. Materialize those sub-steps into the concrete job steps
264
+
265
+ This keeps lifecycle ownership in workflow files while prepare/create remain deterministic.
266
+ Compose intentionally does not perform this metadata scan.
267
+
268
+ This generates hierarchical steps with:
269
+ - Pre-assigned numbers (010, 010.01, 010.02, etc.)
270
+ - Parent-child relationships
271
+ - All `{{placeholder}}` tokens resolved
272
+
273
+ For standard presets (no expansion), replace `{{parameter}}` placeholders:
274
+
275
+ ```yaml
276
+ # Before
277
+ instructions:
278
+ - "Work on task {{taskref}}."
279
+
280
+ # After (with taskref=123)
281
+ instructions:
282
+ - Work on task 123.
283
+ ```
284
+
285
+ ### 6. Validate Job Configuration
286
+
287
+ Check:
288
+ - [ ] Session name is set
289
+ - [ ] All required parameters have values
290
+ - [ ] No unresolved `{{placeholder}}` tokens remain
291
+ - [ ] Steps have names and instructions
292
+ - [ ] Skill references are valid (if present)
293
+
294
+ ### 7. Generate job.yaml
295
+
296
+ Write the final configuration:
297
+
298
+ ```yaml
299
+ session:
300
+ name: <preset-name>-<taskref>
301
+ description: <preset description with context>
302
+
303
+ steps:
304
+ - name: <step-name>
305
+ skill: <skill-reference> # If present in preset
306
+ instructions:
307
+ - <resolved instruction line>
308
+ # ... more steps
309
+ ```
310
+
311
+ ### 8. Output Result
312
+
313
+ Default output: `<task>/jobs/<timestamp>-job.yml` (e.g., `.ace-taskflow/v.0.9.0/tasks/229-xxx/jobs/k5abc123-job.yml`)
314
+
315
+ Custom output: Use `--output path/to/custom.yaml`
316
+
317
+ Report:
318
+ ```
319
+ Job configuration created: job.yaml
320
+
321
+ Session: work-on-task-123
322
+ Steps: 10 total
323
+ - onboard
324
+ - work-on-task
325
+ - create-pr
326
+ - review-cycle-1
327
+ - apply-feedback-1
328
+ - review-cycle-2
329
+ - apply-feedback-2
330
+ - review-cycle-3
331
+ - apply-feedback-3
332
+ - finalize
333
+
334
+ Start assignment with: ace-assign create job.yaml
335
+ ```
336
+
337
+ ## Output Format
338
+
339
+ ### job.yaml Structure
340
+
341
+ ```yaml
342
+ session:
343
+ name: work-on-task-123
344
+ description: Work on task 123 with PR and review cycles
345
+
346
+ steps:
347
+ - name: onboard
348
+ skill: as-onboard
349
+ instructions:
350
+ - Onboard yourself to the codebase.
351
+ - Load context and understand the project structure.
352
+
353
+ - name: work-on-task
354
+ skill: as-task-work
355
+ instructions:
356
+ - Work on task 123.
357
+ - Implement the required changes following project conventions.
358
+
359
+ - name: create-pr
360
+ skill: as-github-pr-create
361
+ instructions:
362
+ - Create a pull request for the changes.
363
+ - Capture the PR number for subsequent review steps.
364
+ - Update the next steps with the PR number.
365
+
366
+ # ... more steps
367
+ ```
368
+
369
+ ## Error Handling
370
+
371
+ | Scenario | Action |
372
+ |----------|--------|
373
+ | Unknown preset | List available presets, ask for selection |
374
+ | Missing required parameter | Prompt for value |
375
+ | Invalid task reference | Show expected formats |
376
+ | Unresolved placeholders | Report which parameters need values |
377
+
378
+ ## Examples
379
+
380
+ ### Example 1: Full Workflow Preset
381
+
382
+ ```
383
+ /as-assign-prepare work-on-task --taskref 148
384
+ ```
385
+
386
+ Creates job with 13 steps: onboard, work-on-task, release, create-pr, 2 review cycles (review + apply-feedback + release each), reorganize-commits, push-to-remote, update-pr-desc.
387
+
388
+ ### Example 2: Informal Instructions
389
+
390
+ ```
391
+ /as-assign-prepare "implement task 148, create pr, review twice"
392
+ ```
393
+
394
+ Parses instructions and creates job with:
395
+ - onboard
396
+ - work-on-task (148)
397
+ - create-pr
398
+ - review-valid-1 (fork subtree: review-pr → apply-feedback → release)
399
+ - review-fit-1 (fork subtree: review-pr → apply-feedback → release)
400
+ - finalize
401
+
402
+ ### Example 3: Custom Output Path
403
+
404
+ ```
405
+ /as-assign-prepare work-on-task --taskref 148 --output .cache/my-job.yaml
406
+ ```
407
+
408
+ Writes configuration to specified path.
409
+
410
+ ### Example 4: Multi-Task Batch (Comma-Separated)
411
+
412
+ ```
413
+ /as-assign-prepare work-on-task --taskrefs 148,149,150
414
+ ```
415
+
416
+ Creates job with hierarchical structure:
417
+ - batch-tasks (010) - parent container
418
+ - work-on-148 (010.01) - fork context
419
+ - work-on-149 (010.02) - fork context
420
+ - work-on-150 (010.03) - fork context
421
+ - consolidated-review (020)
422
+ - finalize (030)
423
+
424
+ ### Example 5: Multi-Task Batch (Range)
425
+
426
+ ```
427
+ /as-assign-prepare work-on-task --taskrefs 148-152
428
+ ```
429
+
430
+ Expands range to tasks 148, 149, 150, 151, 152.
431
+
432
+ ### Example 6: Multi-Task Batch (Pattern)
433
+
434
+ ```
435
+ /as-assign-prepare work-on-task --taskrefs "240.*"
436
+ ```
437
+
438
+ Expands pattern to match subtasks (requires resolution at prepare time).
439
+
440
+ ## Success Criteria
441
+
442
+ - [ ] Input correctly parsed (preset, parameters, or prose)
443
+ - [ ] Preset loaded and parameters injected
444
+ - [ ] Expansion directives processed (if present)
445
+ - [ ] Hierarchical steps numbered correctly
446
+ - [ ] Loops expanded into separate steps
447
+ - [ ] All placeholders resolved
448
+ - [ ] Valid job.yaml generated
449
+ - [ ] Clear summary provided to user
450
+
451
+ ## Next Steps
452
+
453
+ After job.yaml is created:
454
+
455
+ ```bash
456
+ # Start the assignment
457
+ /as-assign-create job.yaml
458
+
459
+ # Or directly:
460
+ ace-assign create job.yaml
461
+
462
+ # Check status
463
+ ace-assign status
464
+
465
+ # Drive execution through the workflow
466
+ /as-assign-drive
467
+ ```
468
+
469
+ **Note:** Job files created in `<task>/jobs/` stay in place when `ace-assign create` runs. Files created elsewhere are moved to `<task>/jobs/<session_id>-job.yml` for provenance. Always use `ace-assign status` to query the current assignment state.
@@ -0,0 +1,233 @@
1
+ ---
2
+ doc-type: workflow
3
+ title: Fork Recovery Workflow
4
+ purpose: Recover from fork-run failures — crash with partial completion, provider unavailability, or mixed subtree state
5
+ ace-docs:
6
+ last-updated: 2026-03-22
7
+ last-checked: 2026-03-22
8
+ ---
9
+
10
+ # Fork Recovery Workflow
11
+
12
+ ## Purpose
13
+
14
+ Recover from `fork-run` failures during assignment execution. This workflow is invoked by the driver when a fork subtree exits non-zero. It covers three scenarios: crash with partial progress, provider unavailability, and mixed subtree state after provider failure.
15
+
16
+ ## Prerequisites
17
+
18
+ - A fork subtree that exited non-zero (`fork-run` failed)
19
+ - The driver has the `ASSIGNMENT_ID` and `FORK_ROOT` pinned
20
+ - The driver has NOT started executing fork work inline (fork boundary intact)
21
+
22
+ ## Variables
23
+
24
+ - `$ASSIGNMENT_ID`: The pinned assignment identifier
25
+ - `$FORK_ROOT`: The root step number of the failed fork subtree (e.g., `020`)
26
+ - `$failed_step`: The specific step that was active when the fork crashed
27
+
28
+ ## Detection: When to Use This Workflow
29
+
30
+ Invoke this workflow when `fork-run` exits non-zero. Determine the scenario:
31
+
32
+ | Signal | Scenario | Go to |
33
+ |--------|----------|-------|
34
+ | `exit != 0` AND (`git status --short` shows changes OR mixed step status) | Crash with partial progress | Scenario 1 |
35
+ | `exit != 0` AND error indicates timeout/hang/empty response (no stack trace, no test failure) | Provider unavailability | Scenario 2 |
36
+ | `exit != 0` AND subtree has mix of done + failed + pending children after provider failure | Mixed state after provider failure | Scenario 3 |
37
+
38
+ ---
39
+
40
+ ## Scenario 1: Crash with Partial Completion
41
+
42
+ The fork crashed due to a code issue, environment error, or timeout — but made partial progress.
43
+
44
+ ### Step 1: Commit Partial Work
45
+
46
+ Stage and commit any uncommitted changes from the crashed fork:
47
+
48
+ ```bash
49
+ git add -A
50
+ ace-git-commit -i "partial: save fork progress for ${FORK_ROOT}"
51
+ ```
52
+
53
+ ### Step 2: Write Progress Report for the Active Step
54
+
55
+ Document what was accomplished and what remains:
56
+
57
+ ```bash
58
+ cat > /tmp/partial-report.md << 'EOF'
59
+ ## Partial Completion (fork crashed)
60
+
61
+ ### Completed
62
+ - [list of files created/modified]
63
+ - [tests passing: X tests, Y assertions]
64
+
65
+ ### Remaining
66
+ - [list of components not yet implemented]
67
+ - [tests not yet written]
68
+ EOF
69
+ ace-assign finish --message /tmp/partial-report.md --assignment ${ASSIGNMENT_ID}@${failed_step}
70
+ ```
71
+
72
+ ### Step 3: Inject Recovery Steps
73
+
74
+ Add two child steps inside the failed step's subtree. **Never inject as top-level siblings.**
75
+
76
+ #### Recovery Step Construction Rules
77
+
78
+ **recovery-onboard** — Must enumerate all completed subtree report paths explicitly:
79
+
80
+ ```bash
81
+ # 1. List all completed reports in the subtree
82
+ REPORT_DIR=".ace-local/assign/${ASSIGNMENT_ID}/reports"
83
+ REPORT_LIST=$(ls ${REPORT_DIR}/${FORK_ROOT}.* 2>/dev/null | sort)
84
+
85
+ # 2. Build the instruction with explicit file paths
86
+ RECOVERY_INSTRUCTIONS="Read these reports to understand completed work before continuing:
87
+ $(echo "$REPORT_LIST" | sed 's/^/- /')
88
+ Also read the failure evidence from the failed step."
89
+
90
+ # 3. Inject the step
91
+ ace-assign add "recovery-onboard" --after ${failed_step} --child \
92
+ --assignment ${ASSIGNMENT_ID}@${FORK_ROOT} \
93
+ -i "$RECOVERY_INSTRUCTIONS"
94
+ ```
95
+
96
+ The recovery-onboard instructions MUST list every report file path — not semantic references like "read the plan-task report". A forked recovery agent starts with zero context and cannot infer the directory structure.
97
+
98
+ **continue-work** — Must be a verbatim copy of the original failed step's instructions:
99
+
100
+ ```bash
101
+ # 1. Read the original failed step file
102
+ STEP_FILE=$(ls .ace-local/assign/${ASSIGNMENT_ID}/steps/${failed_step}-*.st.md)
103
+
104
+ # 2. Extract the instruction body (everything after YAML frontmatter)
105
+ ORIGINAL_INSTRUCTIONS=$(sed '1,/^---$/{ /^---$/!d; /^---$/d }' "$STEP_FILE" | sed '1,/^---$/d')
106
+
107
+ # 3. Inject continue-work with the SAME instructions
108
+ ace-assign add "continue-work" --after recovery-onboard --child \
109
+ --assignment ${ASSIGNMENT_ID}@${FORK_ROOT} \
110
+ -i "$ORIGINAL_INSTRUCTIONS"
111
+ ```
112
+
113
+ The continue-work step IS the restart of the same work — it needs the same execution rules, principles, conventions, and done criteria that the original agent had. Do NOT compress or summarize the instructions. Only the recovery-onboard step gets special "catch up" instructions.
114
+
115
+ ### Step 4: Reset Downstream Steps
116
+
117
+ If any steps after the failed step were completed during a prior (incorrect) recovery attempt, reset them:
118
+
119
+ - Set their status back to `pending` in the step file frontmatter
120
+ - Delete their report files from `.ace-local/assign/${ASSIGNMENT_ID}/reports/`
121
+
122
+ ### Step 5: Re-Fork
123
+
124
+ The injected recovery steps are pending, so `fork-run` will pick them up:
125
+
126
+ ```bash
127
+ ace-assign fork-run --assignment ${ASSIGNMENT_ID}@${FORK_ROOT}
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Scenario 2: Provider Unavailability
133
+
134
+ The fork failed because the LLM provider timed out, hung, or returned no output — not because of a code bug. Re-forking would crash the same way.
135
+
136
+ ### Step 1: Confirm Provider Failure
137
+
138
+ Read the fork's last message and failed step error. Look for:
139
+ - Model timeout or API unavailability
140
+ - Empty or truncated response
141
+ - Connection reset or socket hangup
142
+ - Tool hang with no output
143
+
144
+ NOT provider failure: stack traces, test failures, syntax errors — those are code bugs (use Scenario 1).
145
+
146
+ ### Step 2: Classify the Failed Step
147
+
148
+ | Step Type | Description | Example Steps |
149
+ |-----------|-------------|---------------|
150
+ | **LLM-tool step** | Invokes an LLM-backed tool as its primary action | `ace-review`, `ace-lint`, audit, summarize |
151
+ | **Code step** | Produces or modifies source code | implement, fix, refactor, work-on-task |
152
+
153
+ ### Step 3: Fork-Side Action (if still inside fork)
154
+
155
+ The fork MUST only fail and exit. It must NEVER inject steps:
156
+
157
+ ```bash
158
+ # Mark the crashed step as failed with evidence, then exit
159
+ ace-assign fail --message "Provider unavailable: <error details>" \
160
+ --assignment ${ASSIGNMENT_ID}@${failed_step}
161
+ # EXIT — do not add steps, do not retry, do not modify the assignment tree
162
+ ```
163
+
164
+ **Forks NEVER inject steps outside their subtree scope. Recovery decisions belong to the driver.**
165
+
166
+ ### Step 4: Driver-Side Recovery
167
+
168
+ After detecting the fork failure, the driver classifies and recovers:
169
+
170
+ **LLM-tool steps** → execute equivalent work inline at driver level:
171
+
172
+ ```bash
173
+ # Option A: Execute inline (for LLM-tool steps only)
174
+ # Read changed files, analyze each, write review report directly
175
+
176
+ # Option B: Add retry as a child of the failed step's parent
177
+ ace-assign add "retry-<step-name>" --after <failed_step> --child \
178
+ --assignment ${ASSIGNMENT_ID}@${FORK_ROOT} \
179
+ -i "Provider was unavailable for forked <step-name>. Execute equivalent work inline: <specific instructions>"
180
+ ```
181
+
182
+ **Code steps** → do NOT execute inline. Wait for provider recovery or escalate:
183
+
184
+ ```bash
185
+ # Ask user whether to wait and retry later
186
+ # Do NOT attempt the code work inline — context isolation is required
187
+ ```
188
+
189
+ **Inline execution constraint**: Only LLM-tool steps may go inline during provider unavailability. Code-producing steps always require a fork for context isolation — wait for recovery or ask the user.
190
+
191
+ ---
192
+
193
+ ## Scenario 3: Re-Fork After Partial Provider Failure
194
+
195
+ The fork subtree has a mix of done, failed, and pending children after a provider failure. The driver recovers by re-forking — not by absorbing remaining work inline.
196
+
197
+ ### Protocol
198
+
199
+ 1. **Inject retry as a child** of the failed step's parent subtree (never as a top-level sibling):
200
+
201
+ ```bash
202
+ ace-assign add "retry-<step-name>" --after ${failed_child} --child \
203
+ --assignment ${ASSIGNMENT_ID}@${FORK_ROOT} \
204
+ -i "Retry <step-name> after provider recovery."
205
+ ```
206
+
207
+ 2. **Re-fork the subtree** — fork-run re-enters and picks up pending/retry children:
208
+
209
+ ```bash
210
+ ace-assign fork-run --assignment "${ASSIGNMENT_ID}@${FORK_ROOT}"
211
+ ```
212
+
213
+ 3. **Do NOT inject steps as top-level siblings** — retry steps must be children of the original subtree root, never top-level steps like `101` or `121`.
214
+
215
+ **Anti-pattern**: Driver sees subtree 110 with 110.01 failed, 110.02 and 110.03 pending. Driver executes 110.02 and 110.03 inline. This defeats context isolation and violates the fork-delegation constraint.
216
+
217
+ ---
218
+
219
+ ## Key Principles
220
+
221
+ 1. **Never execute fork work inline** — except for LLM-tool steps during provider unavailability. The fork boundary exists for context isolation.
222
+ 2. **Recovery steps are always children, never top-level siblings** — injecting at the top level breaks subtree scope and causes downstream steps to run without prerequisite work.
223
+ 3. **Recovery-onboard lists explicit file paths** — never semantic references. The recovery agent has zero context.
224
+ 4. **Continue-work copies original instructions verbatim** — the restart needs the same rules as the original. Only recovery-onboard gets special instructions.
225
+ 5. **Reset downstream steps after incorrect recovery** — if steps ran without their prerequisite work, they must be reset to pending with their reports deleted.
226
+
227
+ ## Success Criteria
228
+
229
+ - Failed fork subtree is recovered without breaking fork isolation
230
+ - Recovery children are injected inside the correct subtree scope
231
+ - Recovery agent receives explicit report paths and complete original instructions
232
+ - Re-fork picks up pending recovery steps and completes the subtree
233
+ - No fork work is absorbed into the driver (except LLM-tool inline during provider unavailability)