|
| 1 | +--- |
| 2 | +description: Loop-engineering workflow patterns and implementation guidance for gh-aw workflows. |
| 3 | +--- |
| 4 | + |
| 5 | +# Loop Engineering Patterns |
| 6 | + |
| 7 | +Use as a playbook for long-running iterative workflows. |
| 8 | + |
| 9 | +## What “loop engineering” means |
| 10 | + |
| 11 | +A loop workflow repeatedly: |
| 12 | + |
| 13 | +1. selects exactly one work item, |
| 14 | +2. makes one bounded improvement step, |
| 15 | +3. verifies with concrete evidence, |
| 16 | +4. preserves accepted progress, |
| 17 | +5. records durable state for the next run. |
| 18 | + |
| 19 | +Design for reliability across repeated runs, merges, CI failures, and human steering. |
| 20 | + |
| 21 | +## Shared architecture across Autoloop, Goal, and Crane |
| 22 | + |
| 23 | +### 1) Single-item scheduler |
| 24 | + |
| 25 | +All three select one item per run: |
| 26 | + |
| 27 | +- Autoloop: one program |
| 28 | +- Goal: one goal issue |
| 29 | +- Crane: one migration |
| 30 | + |
| 31 | +This bounds run cost and preserves round-robin fairness. |
| 32 | + |
| 33 | +### 2) Canonical long-running branch + single PR |
| 34 | + |
| 35 | +Each item owns one stable branch and one draft PR: |
| 36 | + |
| 37 | +- `autoloop/<program>` |
| 38 | +- `goal/<issue>-<slug>` |
| 39 | +- `crane/<migration>` |
| 40 | + |
| 41 | +Accumulate accepted commits on that same PR over time. |
| 42 | + |
| 43 | +### 3) Ratcheting acceptance |
| 44 | + |
| 45 | +A change is accepted only when it improves the tracked metric (or advances the contract) and passes CI/verification gates. |
| 46 | + |
| 47 | +If improvement fails, discard the change and still record the run. |
| 48 | + |
| 49 | +### 4) Durable state in repo-memory |
| 50 | + |
| 51 | +Persist state as markdown in a dedicated memory branch: |
| 52 | + |
| 53 | +- `memory/autoloop` |
| 54 | +- `memory/goal` |
| 55 | +- `memory/crane` |
| 56 | + |
| 57 | +Keep state machine-readable and human-editable. |
| 58 | + |
| 59 | +### 5) Human control-plane issue |
| 60 | + |
| 61 | +Each item has one canonical issue with: |
| 62 | + |
| 63 | +- a durable status comment sentinel (`<!-- ...:STATUS -->`), |
| 64 | +- one per-run log comment, |
| 65 | +- human steering directives. |
| 66 | + |
| 67 | +### 6) Explicit no-progress and pause semantics |
| 68 | + |
| 69 | +When blocked or stuck, pause with a concrete reason. Do not retry forever. |
| 70 | + |
| 71 | +## Pattern inventory |
| 72 | + |
| 73 | +### Pattern A — Item selection and fairness |
| 74 | + |
| 75 | +Use a deterministic pre-step scheduler that writes a compact selection artifact (for example `/tmp/gh-aw/autoloop.json` in gh-aw runners; match the file name to your workflow) with: |
| 76 | + |
| 77 | +- selected item, |
| 78 | +- deferred items, |
| 79 | +- due/not-due flags, |
| 80 | +- existing PR/branch metadata. |
| 81 | + |
| 82 | +Do not discover candidates ad hoc in-prompt. |
| 83 | + |
| 84 | +### Pattern B — Canonical branch invariants |
| 85 | + |
| 86 | +Branch names must be deterministic and suffix-free. |
| 87 | + |
| 88 | +Always use ahead/behind logic against default branch: |
| 89 | + |
| 90 | +- `ahead=0, behind>0`: fast-forward/reset branch to default, |
| 91 | +- `ahead>0, behind>0`: merge default into branch, |
| 92 | +- else: checkout as-is. |
| 93 | + |
| 94 | +When a force-push is required by your branch-sync strategy, use `--force-with-lease` (not `--force`). |
| 95 | +Still keep canonical branches single-writer (the workflow) to minimize push conflicts. |
| 96 | + |
| 97 | +### Pattern C — One PR per item |
| 98 | + |
| 99 | +Never create multiple active PRs for the same item. |
| 100 | + |
| 101 | +Resolve in order: |
| 102 | + |
| 103 | +1. scheduler-provided `existing_pr`, |
| 104 | +2. state-file PR fallback, |
| 105 | +3. create exactly one PR if none exists. |
| 106 | + |
| 107 | +### Pattern D — Improve → push → gate → accept |
| 108 | + |
| 109 | +Use a three-phase accept path: |
| 110 | + |
| 111 | +1. metric/contract improvement check, |
| 112 | +2. push and wait for CI/checks, |
| 113 | +3. accept only on green. |
| 114 | + |
| 115 | +This avoids sandbox-only false positives. |
| 116 | + |
| 117 | +### Pattern E — CI fix loop with circuit breakers |
| 118 | + |
| 119 | +When CI fails after an improved change: |
| 120 | + |
| 121 | +- collect failing jobs and error signatures, |
| 122 | +- attempt bounded fix retries, |
| 123 | +- stop on repeated identical signature, |
| 124 | +- pause with structured reason (`ci-fix-exhausted`, `stuck`, `ci-timeout`). |
| 125 | + |
| 126 | +### Pattern F — Structured state file |
| 127 | + |
| 128 | +Keep a stable state layout with: |
| 129 | + |
| 130 | +- machine-state table (iteration count, last run, best metric, pause/completion fields), |
| 131 | +- current focus/checkpoint, |
| 132 | +- lessons learned, |
| 133 | +- foreclosed avenues/blockers, |
| 134 | +- iteration history (newest first). |
| 135 | + |
| 136 | +This preserves continuity and deterministic scheduling. |
| 137 | + |
| 138 | +### Pattern G — Setup guard and safety rails |
| 139 | + |
| 140 | +Use sentinel-based configuration checks before first real run: |
| 141 | + |
| 142 | +- Autoloop: `<!-- AUTOLOOP:UNCONFIGURED -->` |
| 143 | +- Crane: `<!-- CRANE:UNCONFIGURED -->` |
| 144 | + |
| 145 | +If unconfigured, create/refresh setup issue and skip execution. |
| 146 | + |
| 147 | +### Pattern H — Direction-aware metrics |
| 148 | + |
| 149 | +Support both optimization directions: |
| 150 | + |
| 151 | +- `higher` is better (default), |
| 152 | +- `lower` is better. |
| 153 | + |
| 154 | +Use direction in: |
| 155 | + |
| 156 | +- improvement test, |
| 157 | +- signed delta reporting, |
| 158 | +- target-metric completion check. |
| 159 | + |
| 160 | +### Pattern I — Completion by evidence, not intent |
| 161 | + |
| 162 | +Completion requires explicit evidence gates. |
| 163 | + |
| 164 | +- Goal enforces issue-defined completion contracts. |
| 165 | +- Crane separates reaching target metric from deterministic completion-gate pass. |
| 166 | +- Autoloop supports target-metric completion with explicit label transition. |
| 167 | + |
| 168 | +Never mark complete on belief alone. |
| 169 | + |
| 170 | +### Pattern J — Unified run reporting |
| 171 | + |
| 172 | +On every run (accepted/rejected/error/blocked): |
| 173 | + |
| 174 | +- update durable status comment, |
| 175 | +- append per-run summary comment, |
| 176 | +- include run URL, checkpoint, evidence, result, next step. |
| 177 | + |
| 178 | +This creates an auditable run narrative. |
| 179 | + |
| 180 | +## Comparative notes by project |
| 181 | + |
| 182 | +| Project | Primary loop unit | Unique strength | Key reusable pattern | |
| 183 | +|---|---|---|---| |
| 184 | +| Autoloop | Program | General metric-driven optimization with rich iteration memory | Improvement ratchet + CI-gated accept/reject | |
| 185 | +| Goal | Goal-labeled issue | Contract-first execution and definition-quality gating | “Needs action” path before implementation | |
| 186 | +| Crane | Migration | Milestone plan + strategy selection (`in-place` vs `greenfield`) | iteration 0 planning commit and migration-specific completion gate | |
| 187 | + |
| 188 | +## Implementation blueprint for new loop workflows in gh-aw |
| 189 | + |
| 190 | +When creating a new loop workflow, implement in this order: |
| 191 | + |
| 192 | +1. **Define the loop unit** (issue/program/migration/task). |
| 193 | +2. **Add scheduler pre-step** that selects one item and emits JSON context. |
| 194 | +3. **Define canonical branch and single-PR invariant**. |
| 195 | +4. **Add durable state schema** in repo-memory. |
| 196 | +5. **Implement run phases**: read state → choose checkpoint → change → verify. |
| 197 | +6. **Add accept/reject logic** with direction-aware metric handling. |
| 198 | +7. **Gate acceptance on CI/check health**. |
| 199 | +8. **Add bounded fix loop** with failure-signature no-progress guard. |
| 200 | +9. **Implement completion semantics** with explicit evidence gate. |
| 201 | +10. **Add status + per-run issue comments** for observability. |
| 202 | +11. **Add pause/recovery policy** for blocked or repeated failures. |
| 203 | +12. **Document command-mode overrides** (slash command steering). |
| 204 | + |
| 205 | +## Minimal loop run-state model |
| 206 | + |
| 207 | +Use these conceptual states: |
| 208 | + |
| 209 | +- `active` |
| 210 | +- `accepted` |
| 211 | +- `rejected` |
| 212 | +- `error` |
| 213 | +- `needs_action` |
| 214 | +- `blocked` |
| 215 | +- `paused` |
| 216 | +- `completed` |
| 217 | + |
| 218 | +Transitions must be deterministic and evidence-backed. |
| 219 | + |
| 220 | +## Common failure modes to avoid |
| 221 | + |
| 222 | +- Branch name drift (suffixes/hashes/run IDs) |
| 223 | +- Multiple PRs per item |
| 224 | +- Marking completion without deterministic evidence |
| 225 | +- Repeating the same failed CI signature without pause |
| 226 | +- Losing long-term context by storing state only in ephemeral run logs |
| 227 | +- Unbounded scope growth per iteration |
| 228 | + |
| 229 | +## Practical guidance for prompt authors |
| 230 | + |
| 231 | +For loop prompts, explicitly require: |
| 232 | + |
| 233 | +- one checkpoint per run, |
| 234 | +- smallest useful change, |
| 235 | +- explicit evidence command output, |
| 236 | +- explicit `noop`/blocked behavior, |
| 237 | +- state updates every run, |
| 238 | +- strict branch/PR invariants. |
| 239 | + |
| 240 | +Keep prompts short. Move durable policy to state + structured workflow rules. |
| 241 | + |
| 242 | +## Reusable checklist |
| 243 | + |
| 244 | +- [ ] One selected item per run |
| 245 | +- [ ] Canonical branch name with no suffix |
| 246 | +- [ ] Single draft PR per item |
| 247 | +- [ ] Durable state file updated every run |
| 248 | +- [ ] Improvement criterion defined (direction-aware) |
| 249 | +- [ ] Acceptance gated on CI/checks |
| 250 | +- [ ] Fix-loop retry cap and signature-based stop |
| 251 | +- [ ] Explicit blocked/paused handling |
| 252 | +- [ ] Deterministic completion gate |
| 253 | +- [ ] Status comment + per-run comment updated |
0 commit comments