opencodekit 0.17.9 → 0.17.10
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.
- package/dist/index.js +12 -12
- package/dist/template/.opencode/opencode.json +54 -44
- package/dist/template/.opencode/package.json +1 -1
- package/dist/template/.opencode/skill/beads/SKILL.md +96 -0
- package/dist/template/.opencode/skill/context-engineering/SKILL.md +104 -0
- package/dist/template/.opencode/skill/executing-plans/SKILL.md +70 -0
- package/dist/template/.opencode/skill/finishing-a-development-branch/SKILL.md +101 -0
- package/dist/template/.opencode/skill/swarm-coordination/SKILL.md +365 -10
- package/dist/template/.opencode/skill/writing-plans/SKILL.md +112 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -759,7 +759,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
759
759
|
// package.json
|
|
760
760
|
var package_default = {
|
|
761
761
|
name: "opencodekit",
|
|
762
|
-
version: "0.17.
|
|
762
|
+
version: "0.17.10",
|
|
763
763
|
description: "CLI tool for bootstrapping and managing OpenCodeKit projects",
|
|
764
764
|
keywords: ["agents", "cli", "mcp", "opencode", "opencodekit", "template"],
|
|
765
765
|
license: "MIT",
|
|
@@ -9244,21 +9244,21 @@ async function copyOpenCodeOnly(templateRoot, targetDir) {
|
|
|
9244
9244
|
}
|
|
9245
9245
|
var MODEL_PRESETS = {
|
|
9246
9246
|
free: {
|
|
9247
|
-
model: "opencode/
|
|
9247
|
+
model: "opencode/glm-5-free",
|
|
9248
9248
|
agents: {
|
|
9249
|
-
build: "opencode/
|
|
9250
|
-
plan: "opencode/
|
|
9249
|
+
build: "opencode/minimax-m2.5-free",
|
|
9250
|
+
plan: "opencode/minimax-m2.5-free",
|
|
9251
9251
|
review: "opencode/minimax-m2.5-free",
|
|
9252
|
-
explore: "opencode/
|
|
9253
|
-
general: "opencode/
|
|
9254
|
-
looker: "opencode/
|
|
9255
|
-
vision: "opencode/
|
|
9256
|
-
scout: "opencode/
|
|
9257
|
-
painter: "opencode/
|
|
9252
|
+
explore: "opencode/glm-5-free",
|
|
9253
|
+
general: "opencode/glm-5-free",
|
|
9254
|
+
looker: "opencode/minimax-m2.5-free",
|
|
9255
|
+
vision: "opencode/minimax-m2.5-free",
|
|
9256
|
+
scout: "opencode/glm-5-free",
|
|
9257
|
+
painter: "opencode/minimax-m2.5-free"
|
|
9258
9258
|
}
|
|
9259
9259
|
},
|
|
9260
9260
|
recommend: {
|
|
9261
|
-
model: "opencode/
|
|
9261
|
+
model: "opencode/minimax-m2.5-free",
|
|
9262
9262
|
agents: {
|
|
9263
9263
|
build: "github-copilot/claude-opus-4.6",
|
|
9264
9264
|
plan: "openai/gpt-5.3-codex",
|
|
@@ -9266,7 +9266,7 @@ var MODEL_PRESETS = {
|
|
|
9266
9266
|
explore: "proxypal/gemini-3-flash",
|
|
9267
9267
|
general: "github-copilot/gpt-5.2-codex",
|
|
9268
9268
|
looker: "proxypal/gemini-3-flash",
|
|
9269
|
-
vision: "proxypal/gemini-3-pro-high",
|
|
9269
|
+
vision: "proxypal/gemini-3.1-pro-high",
|
|
9270
9270
|
scout: "proxypal/claude-sonnet-4-6",
|
|
9271
9271
|
painter: "proxypal/gemini-3-pro-image"
|
|
9272
9272
|
}
|
|
@@ -157,6 +157,10 @@
|
|
|
157
157
|
"models": {
|
|
158
158
|
"claude-haiku-4.5": {
|
|
159
159
|
"attachment": true,
|
|
160
|
+
"limit": {
|
|
161
|
+
"context": 200000,
|
|
162
|
+
"output": 64000
|
|
163
|
+
},
|
|
160
164
|
"options": {
|
|
161
165
|
"thinking_budget": 10000,
|
|
162
166
|
"type": "enabled"
|
|
@@ -181,6 +185,10 @@
|
|
|
181
185
|
},
|
|
182
186
|
"claude-opus-4.5": {
|
|
183
187
|
"attachment": true,
|
|
188
|
+
"limit": {
|
|
189
|
+
"context": 200000,
|
|
190
|
+
"output": 64000
|
|
191
|
+
},
|
|
184
192
|
"options": {
|
|
185
193
|
"thinking_budget": 10000
|
|
186
194
|
},
|
|
@@ -203,7 +211,7 @@
|
|
|
203
211
|
"claude-opus-4.6": {
|
|
204
212
|
"attachment": true,
|
|
205
213
|
"limit": {
|
|
206
|
-
"context":
|
|
214
|
+
"context": 200000,
|
|
207
215
|
"output": 64000
|
|
208
216
|
},
|
|
209
217
|
"options": {
|
|
@@ -248,8 +256,8 @@
|
|
|
248
256
|
"claude-sonnet-4.6": {
|
|
249
257
|
"attachment": true,
|
|
250
258
|
"limit": {
|
|
251
|
-
"context":
|
|
252
|
-
"output":
|
|
259
|
+
"context": 200000,
|
|
260
|
+
"output": 64000
|
|
253
261
|
},
|
|
254
262
|
"options": {
|
|
255
263
|
"thinking": {
|
|
@@ -292,6 +300,10 @@
|
|
|
292
300
|
},
|
|
293
301
|
"claude-sonnet-4.5": {
|
|
294
302
|
"attachment": true,
|
|
303
|
+
"limit": {
|
|
304
|
+
"context": 200000,
|
|
305
|
+
"output": 64000
|
|
306
|
+
},
|
|
295
307
|
"options": {
|
|
296
308
|
"thinking_budget": 10000
|
|
297
309
|
},
|
|
@@ -313,6 +325,10 @@
|
|
|
313
325
|
},
|
|
314
326
|
"gpt-5.2": {
|
|
315
327
|
"attachment": true,
|
|
328
|
+
"limit": {
|
|
329
|
+
"context": 400000,
|
|
330
|
+
"output": 128000
|
|
331
|
+
},
|
|
316
332
|
"options": {
|
|
317
333
|
"reasoningEffort": "medium",
|
|
318
334
|
"reasoningSummary": "auto",
|
|
@@ -339,6 +355,10 @@
|
|
|
339
355
|
},
|
|
340
356
|
"gpt-5.2-codex": {
|
|
341
357
|
"attachment": true,
|
|
358
|
+
"limit": {
|
|
359
|
+
"context": 400000,
|
|
360
|
+
"output": 128000
|
|
361
|
+
},
|
|
342
362
|
"options": {
|
|
343
363
|
"reasoningEffort": "medium",
|
|
344
364
|
"reasoningSummary": "auto",
|
|
@@ -472,6 +492,37 @@
|
|
|
472
492
|
"fast": {
|
|
473
493
|
"disabled": true
|
|
474
494
|
},
|
|
495
|
+
"xhigh": {
|
|
496
|
+
"include": ["reasoning.encrypted_content"],
|
|
497
|
+
"reasoningEffort": "xhigh",
|
|
498
|
+
"reasoningSummary": "auto",
|
|
499
|
+
"textVerbosity": "low"
|
|
500
|
+
},
|
|
501
|
+
"high": {
|
|
502
|
+
"include": ["reasoning.encrypted_content"],
|
|
503
|
+
"reasoningEffort": "high",
|
|
504
|
+
"reasoningSummary": "auto",
|
|
505
|
+
"textVerbosity": "low"
|
|
506
|
+
},
|
|
507
|
+
"medium": {
|
|
508
|
+
"include": ["reasoning.encrypted_content"],
|
|
509
|
+
"reasoningEffort": "medium",
|
|
510
|
+
"reasoningSummary": "auto",
|
|
511
|
+
"textVerbosity": "low"
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
"gpt-5.3-codex": {
|
|
516
|
+
"variants": {
|
|
517
|
+
"fast": {
|
|
518
|
+
"disabled": true
|
|
519
|
+
},
|
|
520
|
+
"xhigh": {
|
|
521
|
+
"include": ["reasoning.encrypted_content"],
|
|
522
|
+
"reasoningEffort": "xhigh",
|
|
523
|
+
"reasoningSummary": "auto",
|
|
524
|
+
"textVerbosity": "low"
|
|
525
|
+
},
|
|
475
526
|
"high": {
|
|
476
527
|
"include": ["reasoning.encrypted_content"],
|
|
477
528
|
"reasoningEffort": "high",
|
|
@@ -498,47 +549,6 @@
|
|
|
498
549
|
"top_p": 0.95
|
|
499
550
|
},
|
|
500
551
|
"reasoning": true
|
|
501
|
-
},
|
|
502
|
-
"kimi-k2.5-free": {
|
|
503
|
-
"limit": {
|
|
504
|
-
"context": 262144,
|
|
505
|
-
"output": 32768
|
|
506
|
-
},
|
|
507
|
-
"options": {
|
|
508
|
-
"interleaved": {
|
|
509
|
-
"field": "reasoning_content"
|
|
510
|
-
},
|
|
511
|
-
"thinking": {
|
|
512
|
-
"budgetTokens": 8192,
|
|
513
|
-
"reasoning_effort": "high",
|
|
514
|
-
"type": "enabled"
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
"reasoning": true,
|
|
518
|
-
"temperature": true,
|
|
519
|
-
"tool_call": true,
|
|
520
|
-
"variants": {
|
|
521
|
-
"high": {
|
|
522
|
-
"interleaved": {
|
|
523
|
-
"field": "reasoning_content"
|
|
524
|
-
},
|
|
525
|
-
"options": {
|
|
526
|
-
"reasoning_effort": "high",
|
|
527
|
-
"thinkingBudget": 16384,
|
|
528
|
-
"type": "enabled"
|
|
529
|
-
}
|
|
530
|
-
},
|
|
531
|
-
"max": {
|
|
532
|
-
"interleaved": {
|
|
533
|
-
"field": "reasoning_content"
|
|
534
|
-
},
|
|
535
|
-
"options": {
|
|
536
|
-
"reasoning_effort": "high",
|
|
537
|
-
"thinkingBudget": 32768,
|
|
538
|
-
"type": "enabled"
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
552
|
}
|
|
543
553
|
}
|
|
544
554
|
},
|
|
@@ -348,6 +348,102 @@ swarm({ operation: "sync", action: "pull" });
|
|
|
348
348
|
3. **One task per session** - Restart after `br close`
|
|
349
349
|
4. **Always sync and commit** - `br sync --flush-only` then `git add .beads/ && git commit`
|
|
350
350
|
5. **Write notes for future agents** - Assume zero conversation context
|
|
351
|
+
6. **Claim file paths before editing** - Use reserve to declare ownership (multi-agent only)
|
|
352
|
+
|
|
353
|
+
## File Path Claiming (Multi-Agent Safety)
|
|
354
|
+
|
|
355
|
+
At multi-agent scale, agents editing the same files cause merge conflicts. File path claiming prevents this by making ownership explicit before any edit happens.
|
|
356
|
+
|
|
357
|
+
### When to Use
|
|
358
|
+
|
|
359
|
+
- **Single agent**: Optional — no conflicts possible
|
|
360
|
+
- **2-10 agents**: Recommended for files touched by multiple tasks
|
|
361
|
+
- **10+ agents**: Required — every file must be claimed before editing
|
|
362
|
+
|
|
363
|
+
### The Claim/Edit/Release Cycle
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
# 1. CLAIM: Declare intent to edit before touching the file
|
|
367
|
+
br reserve <bead-id> --files "src/auth/service.ts,src/auth/types.ts"
|
|
368
|
+
# → Marks files as owned by this bead
|
|
369
|
+
# → Other agents see the reservation and must wait
|
|
370
|
+
|
|
371
|
+
# 2. EDIT: Make your changes
|
|
372
|
+
# (edit files as normal)
|
|
373
|
+
|
|
374
|
+
# 3. VERIFY: Run gates before releasing
|
|
375
|
+
npm run typecheck && npm run lint
|
|
376
|
+
|
|
377
|
+
# 4. CLOSE: Release ownership when done
|
|
378
|
+
br close <bead-id> --reason "Auth service implemented. Gates passed."
|
|
379
|
+
# → Ownership released automatically on close
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Checking for Conflicts Before Claiming
|
|
383
|
+
|
|
384
|
+
Before claiming, check if another bead already owns the file:
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
# See all reserved files across active beads
|
|
388
|
+
br list --status in_progress --json | jq '.[].reserved_files'
|
|
389
|
+
|
|
390
|
+
# If conflict detected:
|
|
391
|
+
# → Wait for the other bead to close
|
|
392
|
+
# → Or coordinate with the agent owning that bead
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Claiming in Delegation Packets
|
|
396
|
+
|
|
397
|
+
Workers MUST declare file claims in their delegation packet:
|
|
398
|
+
|
|
399
|
+
```markdown
|
|
400
|
+
# Delegation Packet
|
|
401
|
+
|
|
402
|
+
- TASK: task-1 - Implement auth service
|
|
403
|
+
- FILES TO CLAIM BEFORE EDITING:
|
|
404
|
+
- src/auth/service.ts
|
|
405
|
+
- src/auth/types.ts
|
|
406
|
+
- src/auth/middleware.ts
|
|
407
|
+
- MUST NOT EDIT (owned by other tasks):
|
|
408
|
+
- src/db/schema.ts (owned by task-0)
|
|
409
|
+
- src/config.ts (owned by task-2)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Conflict Resolution Protocol
|
|
413
|
+
|
|
414
|
+
When two agents want the same file:
|
|
415
|
+
|
|
416
|
+
| Scenario | Resolution |
|
|
417
|
+
| ------------------------------------ | ----------------------------------------------- |
|
|
418
|
+
| File not claimed | Claim it and proceed |
|
|
419
|
+
| File claimed by completed bead | Safe to claim (no active owner) |
|
|
420
|
+
| File claimed by in_progress bead | Wait for bead to close, then claim |
|
|
421
|
+
| Urgent: same file, different workers | Escalate to lead agent to split the file change |
|
|
422
|
+
|
|
423
|
+
### Anti-Pattern: Claiming After Editing
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
# WRONG — edit first, claim after → conflict already happened
|
|
427
|
+
edit src/auth/service.ts
|
|
428
|
+
br reserve bead-1 --files "src/auth/service.ts"
|
|
429
|
+
|
|
430
|
+
# RIGHT — claim first, then edit
|
|
431
|
+
br reserve bead-1 --files "src/auth/service.ts"
|
|
432
|
+
edit src/auth/service.ts
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Quick Reference: File Claiming
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
BEFORE EDITING (multi-agent):
|
|
439
|
+
br reserve <id> --files "src/file.ts"
|
|
440
|
+
|
|
441
|
+
CHECK OWNERSHIP:
|
|
442
|
+
br list --status in_progress --json | jq '.[].reserved_files'
|
|
443
|
+
|
|
444
|
+
RELEASE:
|
|
445
|
+
br close <id> --reason "..." ← auto-releases files
|
|
446
|
+
```
|
|
351
447
|
|
|
352
448
|
## Best Practices
|
|
353
449
|
|
|
@@ -59,3 +59,107 @@ Extend it by:
|
|
|
59
59
|
❌ Keeping old file reads after editing complete
|
|
60
60
|
❌ Reading entire files when you only need a function
|
|
61
61
|
❌ Ignoring AGENTS.md hierarchy
|
|
62
|
+
|
|
63
|
+
## Static vs Runtime Context (Longshot Pattern)
|
|
64
|
+
|
|
65
|
+
At scale (10+ agents), the difference between **static context** and **runtime context** is the difference between a coherent swarm and chaos.
|
|
66
|
+
|
|
67
|
+
### Definitions
|
|
68
|
+
|
|
69
|
+
| Type | What It Is | When Loaded | Example |
|
|
70
|
+
| ------------------- | ------------------------------------------------------------ | ---------------------- | --------------------------------------- |
|
|
71
|
+
| **Static Context** | Always-on knowledge — invariants, constraints, project shape | Always (auto-injected) | AGENTS.md, tech-stack.md, user.md |
|
|
72
|
+
| **Runtime Context** | Per-task injections — what THIS task needs right now | Per-task | Delegation packet, task spec, file list |
|
|
73
|
+
|
|
74
|
+
### Why the Split Matters
|
|
75
|
+
|
|
76
|
+
Without separation, context becomes soup:
|
|
77
|
+
|
|
78
|
+
- Agent loads everything → hits token limit → degrades
|
|
79
|
+
- Agents share stale context → conflicting decisions
|
|
80
|
+
- No clear source of truth for "what is the objective"
|
|
81
|
+
|
|
82
|
+
With separation:
|
|
83
|
+
|
|
84
|
+
- Static = immune to session pollution (always fresh)
|
|
85
|
+
- Runtime = scoped to task (cleaned up when done)
|
|
86
|
+
- Result: agents stay coherent at 200-agent scale
|
|
87
|
+
|
|
88
|
+
### Task Packet Format
|
|
89
|
+
|
|
90
|
+
Every task dispatched to a worker agent MUST include an explicit context block:
|
|
91
|
+
|
|
92
|
+
```markdown
|
|
93
|
+
## Task Packet
|
|
94
|
+
|
|
95
|
+
### Static Context (always available)
|
|
96
|
+
|
|
97
|
+
- Project rules: AGENTS.md
|
|
98
|
+
- Tech stack: .opencode/memory/project/tech-stack.md
|
|
99
|
+
- Gotchas: .opencode/memory/project/gotchas.md
|
|
100
|
+
|
|
101
|
+
### Runtime Context (this task only)
|
|
102
|
+
|
|
103
|
+
- Objective: [one sentence]
|
|
104
|
+
- Scope: [files this task may touch]
|
|
105
|
+
- Constraints: [must_do / must_not_do]
|
|
106
|
+
- Dependencies: [what was produced by prior tasks]
|
|
107
|
+
- Verification: [acceptance commands]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Injection Pattern
|
|
111
|
+
|
|
112
|
+
When spawning workers, always inject runtime context explicitly:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// WRONG: Vague prompt — agent guesses context
|
|
116
|
+
Task({ prompt: "Implement auth service" });
|
|
117
|
+
|
|
118
|
+
// RIGHT: Explicit static + runtime context split
|
|
119
|
+
Task({
|
|
120
|
+
prompt: `## Static Context
|
|
121
|
+
AGENTS.md governs all decisions. Tech stack: Bun, TypeScript strict mode.
|
|
122
|
+
|
|
123
|
+
## Runtime Context
|
|
124
|
+
Objective: Implement JWT auth service in src/auth/service.ts.
|
|
125
|
+
Scope: Only modify src/auth/ directory.
|
|
126
|
+
Dependencies: Schema defined in src/db/schema.ts (from task-1).
|
|
127
|
+
Constraints:
|
|
128
|
+
MUST DO: Use zod for input validation
|
|
129
|
+
MUST NOT DO: Add new dependencies without approval
|
|
130
|
+
Verification:
|
|
131
|
+
npm run typecheck && npm run lint && bun test src/auth/`,
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Context Pollution Anti-Patterns
|
|
136
|
+
|
|
137
|
+
| Anti-Pattern | Problem | Fix |
|
|
138
|
+
| ------------------------------------------- | --------------------------------- | ------------------------------------- |
|
|
139
|
+
| Passing entire AGENTS.md as runtime context | Bloats token budget on every task | Load via static injection only |
|
|
140
|
+
| Runtime state persisting across waves | Stale context poisons next wave | Clear runtime state between waves |
|
|
141
|
+
| No objective in task packet | Agent drifts from goal | Always include one-sentence objective |
|
|
142
|
+
| Injection without scope | Agent modifies wrong files | Always declare file scope |
|
|
143
|
+
|
|
144
|
+
### Static Context Files (Always Inject)
|
|
145
|
+
|
|
146
|
+
These files are the project's invariant layer. Always available, never stale:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
.opencode/memory/project/
|
|
150
|
+
├── user.md # User preferences, workflow rules
|
|
151
|
+
├── tech-stack.md # Frameworks, constraints
|
|
152
|
+
├── gotchas.md # Footguns, warnings
|
|
153
|
+
└── project.md # Vision, success criteria
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Runtime Context Files (Per-Task)
|
|
157
|
+
|
|
158
|
+
These are created fresh per task and cleaned up after:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
.beads/artifacts/<task-id>/
|
|
162
|
+
├── delegation.md # Task-specific instructions
|
|
163
|
+
├── spec.md # Technical requirements
|
|
164
|
+
└── progress.txt # Task state (append-only)
|
|
165
|
+
```
|
|
@@ -56,6 +56,13 @@ If concerns: Wait for human to decide and resubmit
|
|
|
56
56
|
|
|
57
57
|
**Default: First 3 tasks**
|
|
58
58
|
|
|
59
|
+
**Before starting a batch**: create a wave-start git tag for safe rollback:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Tag the safe point before this batch/wave
|
|
63
|
+
git tag wave-${BATCH_NUMBER}-start
|
|
64
|
+
```
|
|
65
|
+
|
|
59
66
|
For each task:
|
|
60
67
|
|
|
61
68
|
1. Mark as in_progress
|
|
@@ -63,12 +70,20 @@ For each task:
|
|
|
63
70
|
3. Run verifications as specified
|
|
64
71
|
4. Mark as completed
|
|
65
72
|
|
|
73
|
+
**After batch passes all gates**: create a wave-complete tag:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Seal the completed wave - confirms all gates passed
|
|
77
|
+
git tag wave-${BATCH_NUMBER}-complete
|
|
78
|
+
```
|
|
79
|
+
|
|
66
80
|
### Step 3: Report
|
|
67
81
|
|
|
68
82
|
When batch complete:
|
|
69
83
|
|
|
70
84
|
- Show what was implemented
|
|
71
85
|
- Show verification output
|
|
86
|
+
- Show wave tag created (e.g., `wave-1-complete`)
|
|
72
87
|
- Say: "Ready for feedback."
|
|
73
88
|
|
|
74
89
|
### Step 4: Continue
|
|
@@ -87,6 +102,61 @@ After all tasks complete and verified:
|
|
|
87
102
|
- **REQUIRED SUB-SKILL:** Use skill({ name: "finishing-a-development-branch" })
|
|
88
103
|
- Follow that skill to verify tests, present options, execute choice
|
|
89
104
|
|
|
105
|
+
## Wave-Level Rollback with Git Tags
|
|
106
|
+
|
|
107
|
+
Git tags act as checkpoints between waves. If a wave fails irrecoverably, roll back to the last known-good state.
|
|
108
|
+
|
|
109
|
+
### Tag Protocol
|
|
110
|
+
|
|
111
|
+
| When | Command | Purpose |
|
|
112
|
+
| ---------------------------- | ------------------------------- | ------------------------- |
|
|
113
|
+
| Before starting any batch | `git tag wave-N-start` | Mark rollback point |
|
|
114
|
+
| After batch passes all gates | `git tag wave-N-complete` | Seal confirmed-good state |
|
|
115
|
+
| On irrecoverable failure | `git reset --hard wave-N-start` | Restore to pre-wave state |
|
|
116
|
+
| Listing all wave checkpoints | `git tag --list "wave-*"` | Audit trail of execution |
|
|
117
|
+
|
|
118
|
+
### When to Rollback
|
|
119
|
+
|
|
120
|
+
Roll back (with user confirmation) when:
|
|
121
|
+
|
|
122
|
+
- Build gates fail twice consecutively in the same wave
|
|
123
|
+
- Unexpected destructive changes were made
|
|
124
|
+
- Drift check detects unrecoverable scope creep
|
|
125
|
+
- Tests were broken and the cause is unclear
|
|
126
|
+
|
|
127
|
+
**Always ask the user before running `git reset --hard`** - it discards uncommitted changes irreversibly.
|
|
128
|
+
|
|
129
|
+
### Rollback Steps
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# 1. Identify safe point
|
|
133
|
+
git tag --list "wave-*"
|
|
134
|
+
# e.g.: wave-1-complete wave-2-start wave-2-complete wave-3-start
|
|
135
|
+
|
|
136
|
+
# 2. Confirm with user: rollback to which tag?
|
|
137
|
+
# e.g.: git reset --hard wave-2-complete (last known good)
|
|
138
|
+
|
|
139
|
+
# 3. Execute rollback (ONLY after user confirms)
|
|
140
|
+
git reset --hard wave-2-complete
|
|
141
|
+
|
|
142
|
+
# 4. Verify state is clean
|
|
143
|
+
npm run typecheck && npm run lint
|
|
144
|
+
|
|
145
|
+
# 5. Re-plan the failed batch with new approach
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Tag Naming Convention
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
wave-1-start # Before batch 1 starts
|
|
152
|
+
wave-1-complete # After batch 1 passes all gates
|
|
153
|
+
wave-2-start # Before batch 2 starts
|
|
154
|
+
wave-2-complete # After batch 2 passes all gates
|
|
155
|
+
...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Use numeric batch numbers, not task names, for predictable reference.
|
|
159
|
+
|
|
90
160
|
## When to Stop and Ask for Help
|
|
91
161
|
|
|
92
162
|
**STOP executing immediately when:**
|
|
@@ -175,6 +175,107 @@ git worktree remove <worktree-path>
|
|
|
175
175
|
| 3. Keep as-is | - | - | ✓ | - |
|
|
176
176
|
| 4. Discard | - | - | - | ✓ (force) |
|
|
177
177
|
|
|
178
|
+
## Mandatory Build Gates (Longshot Pattern)
|
|
179
|
+
|
|
180
|
+
**Build gates are non-optional before any merge/PR/close.** Advisory verification has failed at scale — gates must be enforced as hard blockers.
|
|
181
|
+
|
|
182
|
+
### Gate Sequence
|
|
183
|
+
|
|
184
|
+
Every bead MUST pass all three gates in order. No exceptions.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Gate 1: Typecheck
|
|
188
|
+
npm run typecheck
|
|
189
|
+
# Must exit 0. If fails → STOP. Fix types first.
|
|
190
|
+
|
|
191
|
+
# Gate 2: Lint
|
|
192
|
+
npm run lint
|
|
193
|
+
# Must exit 0. If fails → STOP. Run npm run lint:fix, then fix remaining.
|
|
194
|
+
|
|
195
|
+
# Gate 3: Tests
|
|
196
|
+
bun test
|
|
197
|
+
# Must exit 0. If fails → STOP. Fix failing tests first.
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Gate Enforcement Script
|
|
201
|
+
|
|
202
|
+
Run before every merge, PR creation, or bead close:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
#!/bin/bash
|
|
206
|
+
# Run mandatory gates — all must pass
|
|
207
|
+
|
|
208
|
+
echo "Gate 1/3: Typecheck..."
|
|
209
|
+
npm run typecheck || { echo "FAILED: Fix type errors before proceeding."; exit 1; }
|
|
210
|
+
|
|
211
|
+
echo "Gate 2/3: Lint..."
|
|
212
|
+
npm run lint || {
|
|
213
|
+
echo "Attempting auto-fix..."
|
|
214
|
+
npm run lint:fix
|
|
215
|
+
npm run lint || { echo "FAILED: Fix lint errors before proceeding."; exit 1; }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
echo "Gate 3/3: Tests..."
|
|
219
|
+
bun test || { echo "FAILED: Fix failing tests before proceeding."; exit 1; }
|
|
220
|
+
|
|
221
|
+
echo "All gates passed. Safe to merge/PR/close."
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Gate Failure Response
|
|
225
|
+
|
|
226
|
+
| Gate Failure | First Action | If Still Failing |
|
|
227
|
+
| ------------ | -------------------------------- | --------------------------- |
|
|
228
|
+
| Typecheck | Fix type errors at reported line | Use LSP hover for type info |
|
|
229
|
+
| Lint | Run `npm run lint:fix` | Fix remaining manually |
|
|
230
|
+
| Tests | Read failing test output | Fix implementation or test |
|
|
231
|
+
|
|
232
|
+
### Hard Rules
|
|
233
|
+
|
|
234
|
+
**NEVER:**
|
|
235
|
+
|
|
236
|
+
- Close a bead without passing all 3 gates
|
|
237
|
+
- Create a PR without passing all 3 gates
|
|
238
|
+
- Merge locally without passing all 3 gates on merged result
|
|
239
|
+
- Skip gates "because the change is small"
|
|
240
|
+
|
|
241
|
+
**ALWAYS:**
|
|
242
|
+
|
|
243
|
+
- Run gates after EVERY non-trivial file change
|
|
244
|
+
- Re-run gates after fixing gate failures (to catch regressions)
|
|
245
|
+
- Run gates on the merged result, not just the branch
|
|
246
|
+
|
|
247
|
+
### Integration with Bead Workflow
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Before closing any bead:
|
|
251
|
+
npm run typecheck && npm run lint && bun test
|
|
252
|
+
|
|
253
|
+
# If all pass:
|
|
254
|
+
br close <id> --reason "Implementation complete. All gates passed."
|
|
255
|
+
br sync --flush-only
|
|
256
|
+
|
|
257
|
+
# If any fail:
|
|
258
|
+
# STOP. Fix. Re-run gates. Then close.
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Gate State in Delegation Packets
|
|
262
|
+
|
|
263
|
+
Workers must include gate results in their completion report:
|
|
264
|
+
|
|
265
|
+
```markdown
|
|
266
|
+
## Completion Report
|
|
267
|
+
|
|
268
|
+
### Gate Results
|
|
269
|
+
|
|
270
|
+
- [ ] typecheck: PASS / FAIL (error: ...)
|
|
271
|
+
- [ ] lint: PASS / FAIL (error: ...)
|
|
272
|
+
- [ ] tests: PASS / FAIL (N failed, N passed)
|
|
273
|
+
|
|
274
|
+
### Gate Command Used
|
|
275
|
+
|
|
276
|
+
`npm run typecheck && npm run lint && bun test`
|
|
277
|
+
```
|
|
278
|
+
|
|
178
279
|
## Common Mistakes
|
|
179
280
|
|
|
180
281
|
**Skipping test verification**
|
|
@@ -15,10 +15,11 @@ Coordinate multiple agents working on independent tasks in parallel using Kimi K
|
|
|
15
15
|
|
|
16
16
|
## Overview
|
|
17
17
|
|
|
18
|
-
**Swarm = Leader + Workers + Progress Tracking + Todo Persistence**
|
|
18
|
+
**Swarm = Leader + Workers + Reconciler + Progress Tracking + Todo Persistence**
|
|
19
19
|
|
|
20
20
|
- **Leader (build agent)**: Orchestrates the swarm - analyzes tasks, spawns workers, monitors progress, synthesizes results
|
|
21
21
|
- **Workers (general/explore/review/plan agents)**: Execute independent tasks - read delegation, make changes, report progress
|
|
22
|
+
- **Reconciler**: Watches for CI failures, detects broken builds, auto-spawns fix tasks - this is the self-healing mechanism
|
|
22
23
|
- **Progress Tracker (swarm-progress.jsonl)**: Real-time progress updates with TUI visualization
|
|
23
24
|
- **Todo Persistence (swarm-todos.json)**: Cross-session recovery for interrupted swarms
|
|
24
25
|
|
|
@@ -68,8 +69,8 @@ Coordinate multiple agents working on independent tasks in parallel using Kimi K
|
|
|
68
69
|
│ - Monitors progress via swarm tool │
|
|
69
70
|
│ - Synthesizes final results │
|
|
70
71
|
└─────────────────────────────────────────────────────────────────┘
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
│ │ │
|
|
73
|
+
▼ ▼ ▼
|
|
73
74
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
74
75
|
│ WORKER-1 │ │ WORKER-2 │ │ WORKER-3 │
|
|
75
76
|
│ (general) │ │ (general) │ │ (general) │
|
|
@@ -79,15 +80,288 @@ Coordinate multiple agents working on independent tasks in parallel using Kimi K
|
|
|
79
80
|
│ - Execute │ │ - Execute │ │ - Execute │
|
|
80
81
|
│ - Report │ │ - Report │ │ - Report │
|
|
81
82
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
│ │ │
|
|
84
|
+
└────────────────────┼────────────────────┘
|
|
85
|
+
▼
|
|
86
|
+
┌─────────────────┐
|
|
87
|
+
│ RECONCILER │
|
|
88
|
+
│ │
|
|
89
|
+
│ - Watch CI │
|
|
90
|
+
│ - Detect broken │
|
|
91
|
+
│ - Spawn fixes │
|
|
92
|
+
└─────────────────┘
|
|
93
|
+
│
|
|
94
|
+
▼
|
|
95
|
+
┌─────────────────┐
|
|
96
|
+
│ PROGRESS + │
|
|
97
|
+
│ TODO PERSIST │
|
|
98
|
+
└─────────────────┘
|
|
89
99
|
```
|
|
90
100
|
|
|
101
|
+
## Reconciler Agent Pattern (Self-Healing)
|
|
102
|
+
|
|
103
|
+
The reconciler is the key to scaling beyond 50+ agents. Without reconciliation, broken builds cascade and the swarm collapses. The reconciler provides **continuous self-healing** by watching for failures and spawning targeted fix tasks.
|
|
104
|
+
|
|
105
|
+
### When to Use Reconciler
|
|
106
|
+
|
|
107
|
+
- **50+ agents** running in parallel → **REQUIRED**
|
|
108
|
+
- **10-50 agents** → Recommended
|
|
109
|
+
- **<10 agents** → Optional (leader can handle)
|
|
110
|
+
|
|
111
|
+
### Reconciler Responsibilities
|
|
112
|
+
|
|
113
|
+
1. **Watch CI/Build Status**: Monitor build gates continuously
|
|
114
|
+
2. **Detect Failures**: Identify which worker caused the failure
|
|
115
|
+
3. **Analyze Root Cause**: Determine if it's a merge conflict, test failure, or type error
|
|
116
|
+
4. **Spawn Fix Tasks**: Create targeted fix tasks with context about what failed
|
|
117
|
+
5. **Verify Fix**: Wait for fix to pass gates before continuing
|
|
118
|
+
|
|
119
|
+
### Reconciler vs Leader
|
|
120
|
+
|
|
121
|
+
| Aspect | Leader | Reconciler |
|
|
122
|
+
| -------------- | ----------------------------- | ----------------------------- |
|
|
123
|
+
| Focus | Orchestration, spawning | Recovery, fixing |
|
|
124
|
+
| Runs | At swarm start, between waves | Continuously during execution |
|
|
125
|
+
| On failure | Spawns workers | Spawns fix tasks |
|
|
126
|
+
| Failure impact | Can't start work | Wave can't complete |
|
|
127
|
+
|
|
128
|
+
### Implementing Reconciler
|
|
129
|
+
|
|
130
|
+
The reconciler runs in a loop during swarm execution:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// Reconciler runs in background during swarm execution
|
|
134
|
+
async function runReconciler(teamName: string, buildCommand: string) {
|
|
135
|
+
while (swarmActive) {
|
|
136
|
+
// 1. Check build status
|
|
137
|
+
const status = await swarm({
|
|
138
|
+
operation: "monitor",
|
|
139
|
+
operation: "status",
|
|
140
|
+
team_name: teamName,
|
|
141
|
+
});
|
|
142
|
+
const stats = JSON.parse(status).summary;
|
|
143
|
+
|
|
144
|
+
// 2. If there are errors, investigate
|
|
145
|
+
if (stats.errors > 0) {
|
|
146
|
+
// 3. Get error details
|
|
147
|
+
const errors = await getWorkerErrors(teamName);
|
|
148
|
+
|
|
149
|
+
for (const error of errors) {
|
|
150
|
+
// 4. Analyze root cause
|
|
151
|
+
const cause = await analyzeError(error);
|
|
152
|
+
|
|
153
|
+
// 5. Spawn fix task
|
|
154
|
+
const fixBead = await br create({
|
|
155
|
+
title: `Fix: ${cause.summary}`,
|
|
156
|
+
type: "bug",
|
|
157
|
+
description: `Detected by reconciler: ${error.message}. Root cause: ${cause.rootCause}. Suggested fix: ${cause.suggestion}`,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// 6. Assign to targeted worker
|
|
161
|
+
await Task({
|
|
162
|
+
subagent_type: "general",
|
|
163
|
+
description: `Fix ${error.worker}`,
|
|
164
|
+
prompt: `Fix the error in ${error.file}.
|
|
165
|
+
|
|
166
|
+
Error: ${error.message}
|
|
167
|
+
Root cause: ${cause.rootCause}
|
|
168
|
+
Suggested fix: ${cause.suggestion}
|
|
169
|
+
|
|
170
|
+
Run: ${buildCommand}
|
|
171
|
+
Verify: npm run typecheck && npm run lint`,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Wait before next check
|
|
177
|
+
await sleep(30000); // Check every 30 seconds
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Error Analysis Patterns
|
|
183
|
+
|
|
184
|
+
The reconciler categorizes errors:
|
|
185
|
+
|
|
186
|
+
| Error Type | Detection | Fix Strategy |
|
|
187
|
+
| -------------- | -------------------------------- | ---------------------------- |
|
|
188
|
+
| Merge conflict | "CONFLICT" in output, git status | Re-base, resolve, force push |
|
|
189
|
+
| Type error | "typecheck failed" | Fix types, run typecheck |
|
|
190
|
+
| Test failure | "test failed", "expect" mismatch | Fix test or implementation |
|
|
191
|
+
| Lint error | "lint failed", formatting issues | Run lint:fix |
|
|
192
|
+
| Build error | "build failed", bundler errors | Fix imports, dependencies |
|
|
193
|
+
|
|
194
|
+
### Spawning Fix Tasks
|
|
195
|
+
|
|
196
|
+
When the reconciler spawns a fix task, it includes:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Create fix task with full context
|
|
200
|
+
await br create({
|
|
201
|
+
title: `Fix: ${error.type} in ${error.file}`,
|
|
202
|
+
type: "bug",
|
|
203
|
+
description: `## Error Detected
|
|
204
|
+
- Worker: ${error.worker}
|
|
205
|
+
- File: ${error.file}
|
|
206
|
+
- Error: ${error.message}
|
|
207
|
+
- Timestamp: ${error.timestamp}
|
|
208
|
+
|
|
209
|
+
## Root Cause Analysis
|
|
210
|
+
${cause.explanation}
|
|
211
|
+
|
|
212
|
+
## Suggested Fix
|
|
213
|
+
${cause.suggestion}
|
|
214
|
+
|
|
215
|
+
## Verification
|
|
216
|
+
Run: ${buildCommand}
|
|
217
|
+
Must pass before wave can complete.`,
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Reconciler in Wave Execution
|
|
222
|
+
|
|
223
|
+
Add reconciler monitoring to each wave:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// Execute wave with reconciler
|
|
227
|
+
async function executeWaveWithReconciler(wave, teamName) {
|
|
228
|
+
// Start reconciler in background
|
|
229
|
+
const reconciler = runReconciler(teamName, "npm run typecheck && npm run lint");
|
|
230
|
+
|
|
231
|
+
// Execute workers in this wave
|
|
232
|
+
await Promise.all(wave.tasks.map(spawnWorker));
|
|
233
|
+
|
|
234
|
+
// Wait for all workers + reconciler to complete
|
|
235
|
+
await reconciler;
|
|
236
|
+
|
|
237
|
+
// Verify wave output before proceeding
|
|
238
|
+
await bash("npm run typecheck && npm run lint");
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Example: Full Swarm with Reconciler
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// Full swarm execution with reconciler
|
|
246
|
+
async function runSwarmWithReconciler(tasks, teamName) {
|
|
247
|
+
// 1. Analyze and create waves
|
|
248
|
+
const waves = createWaves(tasks);
|
|
249
|
+
|
|
250
|
+
// 2. Execute each wave with reconciler
|
|
251
|
+
for (const wave of waves) {
|
|
252
|
+
console.log(`Executing wave ${wave.number} with ${wave.tasks.length} tasks`);
|
|
253
|
+
|
|
254
|
+
// Start reconciler for this wave
|
|
255
|
+
const reconcilerPromise = runReconciler(teamName, "npm run typecheck && npm run lint");
|
|
256
|
+
|
|
257
|
+
// Spawn workers
|
|
258
|
+
await Promise.all(wave.tasks.map((task) => spawnWorker(task, teamName)));
|
|
259
|
+
|
|
260
|
+
// Wait for reconciler to finish fixing any errors
|
|
261
|
+
await reconcilerPromise;
|
|
262
|
+
|
|
263
|
+
// Verify wave output
|
|
264
|
+
const result = await bash("npm run typecheck && npm run lint");
|
|
265
|
+
if (!result.success) {
|
|
266
|
+
throw new Error(`Wave ${wave.number} failed gates`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
console.log(`Wave ${wave.number} complete`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Drift Check After Each Wave
|
|
275
|
+
|
|
276
|
+
After every wave completes and before starting the next, run a **drift check** to verify the codebase has not deviated from the intended state. Accumulated drift between waves is the primary cause of cascading failures in large swarms.
|
|
277
|
+
|
|
278
|
+
**Drift** = any difference between actual codebase state and the plan's expected state at a wave boundary.
|
|
279
|
+
|
|
280
|
+
### What to Check
|
|
281
|
+
|
|
282
|
+
| Check | Command | Passing Condition |
|
|
283
|
+
| ----------------- | -------------------------------------------------- | ------------------------------ |
|
|
284
|
+
| Build gates | `npm run typecheck && npm run lint` | Zero errors |
|
|
285
|
+
| Unexpected files | `git diff --name-only HEAD` | Only planned files modified |
|
|
286
|
+
| Missing artifacts | Verify expected files exist | All declared outputs present |
|
|
287
|
+
| Scope adherence | Compare `git status` vs wave's declared file scope | No out-of-scope files modified |
|
|
288
|
+
|
|
289
|
+
### Drift Check Protocol
|
|
290
|
+
|
|
291
|
+
Run after every wave, before spawning the next:
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
async function driftCheckAfterWave(wave: Wave, expectedFiles: string[]) {
|
|
295
|
+
console.log(`\n=== DRIFT CHECK: Wave ${wave.number} ===`);
|
|
296
|
+
|
|
297
|
+
// 1. Build gates must pass
|
|
298
|
+
const gates = await bash("npm run typecheck && npm run lint");
|
|
299
|
+
if (!gates.success) {
|
|
300
|
+
throw new Error(`Wave ${wave.number} drift: build gates failed\n${gates.output}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 2. Detect unexpected file modifications
|
|
304
|
+
const changedFiles = await bash("git diff --name-only HEAD");
|
|
305
|
+
const actualFiles = changedFiles.output.trim().split("\n").filter(Boolean);
|
|
306
|
+
const unexpected = actualFiles.filter((f) => !expectedFiles.includes(f));
|
|
307
|
+
|
|
308
|
+
if (unexpected.length > 0) {
|
|
309
|
+
console.warn(`⚠️ Unexpected files modified in wave ${wave.number}:`);
|
|
310
|
+
unexpected.forEach((f) => console.warn(` - ${f}`));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// 3. Verify declared artifacts exist
|
|
314
|
+
for (const artifact of wave.expectedArtifacts ?? []) {
|
|
315
|
+
const exists = await bash(`test -f ${artifact} && echo "ok" || echo "missing"`);
|
|
316
|
+
if (exists.output.trim() === "missing") {
|
|
317
|
+
throw new Error(`Wave ${wave.number} drift: expected artifact missing: ${artifact}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
console.log(`✓ Drift check passed: Wave ${wave.number}`);
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Integration in Wave Execution
|
|
326
|
+
|
|
327
|
+
Call drift check between every wave:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
for (let i = 0; i < waves.length; i++) {
|
|
331
|
+
const wave = waves[i];
|
|
332
|
+
const reconciler = runReconciler(teamName, "npm run typecheck && npm run lint");
|
|
333
|
+
|
|
334
|
+
await Promise.all(wave.tasks.map((task) => spawnWorker(task, teamName)));
|
|
335
|
+
await reconciler;
|
|
336
|
+
|
|
337
|
+
// MANDATORY: Drift check before next wave
|
|
338
|
+
await driftCheckAfterWave(
|
|
339
|
+
wave,
|
|
340
|
+
wave.tasks.flatMap((t) => t.assignedFiles),
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
console.log(`✓ Wave ${i + 1}/${waves.length} complete and verified`);
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Drift Response Protocol
|
|
348
|
+
|
|
349
|
+
| Drift Type | Severity | Action |
|
|
350
|
+
| ------------------------ | -------- | ------------------------------------------------ |
|
|
351
|
+
| Build gate failure | Critical | Stop swarm, run reconciler, fix before next wave |
|
|
352
|
+
| Unexpected file modified | Warning | Review change, revert if out of scope |
|
|
353
|
+
| Missing artifact | Critical | Re-run failed worker task, verify output |
|
|
354
|
+
| Scope creep | Warning | Escalate to user if >3 unexpected files changed |
|
|
355
|
+
|
|
356
|
+
### When Drift Is Unrecoverable
|
|
357
|
+
|
|
358
|
+
If drift check fails twice in a row on the same wave:
|
|
359
|
+
|
|
360
|
+
1. **Stop the swarm** - don't start next wave
|
|
361
|
+
2. **Report to user**: exact drift details, failing gate output, list of unexpected files
|
|
362
|
+
3. **Rollback option**: use `git reset --hard <wave-N-start-tag>` (see `executing-plans` skill)
|
|
363
|
+
4. **Never paper over drift** - proceeding with known drift compounds into cascading failure
|
|
364
|
+
|
|
91
365
|
## Swarm Launch Flow - PARL Pattern (7 Steps)
|
|
92
366
|
|
|
93
367
|
### Step 0: Task Analysis (Anti-Serial-Collapse + Dependency Graph)
|
|
@@ -706,3 +980,84 @@ This renders the beautiful TUI block and shows:
|
|
|
706
980
|
7. **Use dependency graph** - Spawn workers in parallelizable_groups order
|
|
707
981
|
8. **Graceful shutdown** - Leader waits for all workers, syncs back to Beads
|
|
708
982
|
9. **Use tmux for visibility** - Enable visual monitoring when available
|
|
983
|
+
10. **Use reconciler at scale** - Required for 50+ agents, recommended for 10+
|
|
984
|
+
11. **Reconciler watches continuously** - Spawns fix tasks on detected failures
|
|
985
|
+
|
|
986
|
+
## Tier Enforcement (Longshot Pattern)
|
|
987
|
+
|
|
988
|
+
For multi-agent execution at scale (10+ agents), enforce explicit tier hierarchy. This is the Longshot pattern that enabled 200 agents to build Minecraft.
|
|
989
|
+
|
|
990
|
+
### Tier System
|
|
991
|
+
|
|
992
|
+
| Tier | Role | Swarm Equivalent | Responsibility |
|
|
993
|
+
| --------------- | --------------------- | ---------------- | -------------------------------------------------------------- |
|
|
994
|
+
| **planner** | Lead orchestrator | Build agent | Analyzes scope, decomposes into sub-tasks, coordinates workers |
|
|
995
|
+
| **sub-planner** | Mid-level coordinator | N/A | Takes planner output, further decomposes, assigns to workers |
|
|
996
|
+
| **worker** | Execution agent | Worker agents | Executes assigned work, reports progress |
|
|
997
|
+
|
|
998
|
+
### When Tiers Are Required
|
|
999
|
+
|
|
1000
|
+
- **<10 agents**: Optional - flat decomposition works
|
|
1001
|
+
- **10-50 agents**: Recommended - planner + workers
|
|
1002
|
+
- **50+ agents**: Required - planner + sub-planners + workers
|
|
1003
|
+
|
|
1004
|
+
### Enforcing Tier Boundaries
|
|
1005
|
+
|
|
1006
|
+
The swarm leader enforces tier boundaries:
|
|
1007
|
+
|
|
1008
|
+
```typescript
|
|
1009
|
+
// Tier enforcement in swarm execution
|
|
1010
|
+
async function enforceTiers(waves, tierConfig) {
|
|
1011
|
+
// Wave 1: Planner tasks only
|
|
1012
|
+
const planners = waves.filter((w) => w.tier === "planner");
|
|
1013
|
+
await executeWave(planners);
|
|
1014
|
+
|
|
1015
|
+
// Wave 2: Sub-planner tasks (if any)
|
|
1016
|
+
const subPlanners = waves.filter((w) => w.tier === "sub-planner");
|
|
1017
|
+
await executeWave(subPlanners);
|
|
1018
|
+
|
|
1019
|
+
// Wave 3+: Worker tasks
|
|
1020
|
+
const workers = waves.filter((w) => w.tier === "worker");
|
|
1021
|
+
await executeWave(workers);
|
|
1022
|
+
}
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
### Handoff Contracts Between Tiers
|
|
1026
|
+
|
|
1027
|
+
Each tier must declare handoff contracts:
|
|
1028
|
+
|
|
1029
|
+
```typescript
|
|
1030
|
+
// Planner declares what it produces for sub-planners
|
|
1031
|
+
const plannerHandoff = {
|
|
1032
|
+
produces: [
|
|
1033
|
+
{ artifact: "docs/auth-design.md", format: "markdown" },
|
|
1034
|
+
{ artifact: "tasks/auth-tasks.json", format: "json" },
|
|
1035
|
+
],
|
|
1036
|
+
consumedBy: ["sub-planner-auth"],
|
|
1037
|
+
};
|
|
1038
|
+
|
|
1039
|
+
// Worker declares what it consumes from sub-planners
|
|
1040
|
+
const workerHandoff = {
|
|
1041
|
+
consumes: [{ artifact: "tasks/auth-tasks.json", format: "json" }],
|
|
1042
|
+
produces: [{ artifact: "src/auth/service.ts", format: "typescript" }],
|
|
1043
|
+
};
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
### Anti-Pattern: Flat Decomposition at Scale
|
|
1047
|
+
|
|
1048
|
+
Without tiers, 20 agents get 20 flat tasks → chaos:
|
|
1049
|
+
|
|
1050
|
+
- Workers step on each other
|
|
1051
|
+
- No coordination between related work
|
|
1052
|
+
- Merge conflicts everywhere
|
|
1053
|
+
- No clear ownership
|
|
1054
|
+
|
|
1055
|
+
With tiers (Longshot pattern):
|
|
1056
|
+
|
|
1057
|
+
```
|
|
1058
|
+
Lead Planner → Sub-planner A → Worker 1, 2, 3
|
|
1059
|
+
→ Sub-planner B → Worker 4, 5, 6
|
|
1060
|
+
Sub-planner C → Worker 7, 8, 9
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
This mirrors real engineering orgs: lead → tech lead → IC. The architecture is the differentiator.
|
|
@@ -90,10 +90,119 @@ Task C (User API): needs Task A, creates src/api/users.ts
|
|
|
90
90
|
Wave 1: A, B (parallel)
|
|
91
91
|
Wave 2: C (after Wave 1)
|
|
92
92
|
|
|
93
|
+
````
|
|
94
|
+
|
|
95
|
+
## Tiered Task Hierarchy
|
|
96
|
+
|
|
97
|
+
For multi-agent execution at scale (10+ agents), use explicit tier declarations. This prevents flat decomposition that fails when many agents work in parallel.
|
|
98
|
+
|
|
99
|
+
### Tier Definitions
|
|
100
|
+
|
|
101
|
+
| Tier | Role | Description | Example |
|
|
102
|
+
|------|------|-------------|---------|
|
|
103
|
+
| **planner** | Lead orchestrator | Analyzes scope, decomposes into sub-tasks, coordinates workers | "Design auth system" |
|
|
104
|
+
| **sub-planner** | Mid-level coordinator | Takes planner output, further decomposes, assigns to workers | "Break auth into API, model, middleware" |
|
|
105
|
+
| **worker** | Execution agent | Executes assigned work, reports progress | "Implement auth service" |
|
|
106
|
+
|
|
107
|
+
### When to Use Tiers
|
|
108
|
+
|
|
109
|
+
- **<10 agents**: Optional - flat decomposition works
|
|
110
|
+
- **10-50 agents**: Recommended - planner + workers
|
|
111
|
+
- **50+ agents**: Required - planner + sub-planners + workers
|
|
112
|
+
|
|
113
|
+
### Tier Declaration Format
|
|
114
|
+
|
|
115
|
+
Add tier metadata to each task:
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
### Task 1: Design Auth System
|
|
119
|
+
|
|
120
|
+
**Tier:** planner
|
|
121
|
+
|
|
122
|
+
**Files:**
|
|
123
|
+
- Create: `docs/auth-design.md`
|
|
124
|
+
|
|
125
|
+
This task decomposes the auth feature into sub-tasks for implementation.
|
|
126
|
+
````
|
|
127
|
+
|
|
128
|
+
### Handoff Contracts
|
|
129
|
+
|
|
130
|
+
Tasks must declare what they produce for downstream tasks:
|
|
131
|
+
|
|
132
|
+
```markdown
|
|
133
|
+
### Handoff Contract
|
|
134
|
+
|
|
135
|
+
**Produces:**
|
|
136
|
+
|
|
137
|
+
- `docs/auth-design.md` - Architecture decision document
|
|
138
|
+
|
|
139
|
+
**Consumed By:**
|
|
140
|
+
|
|
141
|
+
- Task 2: Implement Auth Service
|
|
142
|
+
- Task 3: Add Auth Tests
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Tier Enforcement in Plans
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
# [Feature Name] Implementation Plan
|
|
149
|
+
|
|
150
|
+
> **Tier Structure:**
|
|
151
|
+
>
|
|
152
|
+
> - **Planners (2):** Task 1, Task 5
|
|
153
|
+
> - **Workers (6):** Tasks 2,3,4,6,7,8
|
|
154
|
+
|
|
155
|
+
## Task Hierarchy
|
|
156
|
+
|
|
157
|
+
### Tier 1: Planner Tasks (Orchestration)
|
|
158
|
+
|
|
159
|
+
### Task 1: [Planner] Design Auth System
|
|
160
|
+
|
|
161
|
+
### Task 5: [Planner] Design API Layer
|
|
162
|
+
|
|
163
|
+
### Tier 2: Worker Tasks (Execution)
|
|
164
|
+
|
|
165
|
+
### Task 2: [Worker] Implement Auth Service
|
|
166
|
+
|
|
167
|
+
### Task 3: [Worker] Add Auth Middleware
|
|
168
|
+
|
|
169
|
+
### Task 4: [Worker] Write Auth Tests
|
|
93
170
|
```
|
|
94
171
|
|
|
172
|
+
### Wave Execution with Tiers
|
|
173
|
+
|
|
174
|
+
When executing with tiers:
|
|
175
|
+
|
|
176
|
+
1. **Planner waves** execute first (scope definition)
|
|
177
|
+
2. **Worker waves** execute after planner output is ready
|
|
178
|
+
3. **Sub-planners** sit between, bridging planner → worker
|
|
179
|
+
|
|
180
|
+
```markdown
|
|
181
|
+
Wave 1 (Planners): Task 1, Task 5
|
|
182
|
+
Wave 2 (Workers): Tasks 2, 3, 4 (after Task 1)
|
|
183
|
+
Wave 3 (Workers): Tasks 6, 7, 8 (after Task 5)
|
|
95
184
|
```
|
|
96
185
|
|
|
186
|
+
### Anti-Pattern: Flat Decomposition at Scale
|
|
187
|
+
|
|
188
|
+
Without tiers, 20 agents get 20 flat tasks → chaos:
|
|
189
|
+
|
|
190
|
+
- Workers step on each other
|
|
191
|
+
- No coordination between related work
|
|
192
|
+
- Merge conflicts everywhere
|
|
193
|
+
|
|
194
|
+
With tiers, the structure emerges:
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
Planner → Sub-planner A → Worker 1, 2, 3
|
|
198
|
+
→ Worker 4, 5
|
|
199
|
+
Sub-planner B → Worker 6, 7
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
This mirrors real engineering orgs: lead → tech lead → IC.
|
|
203
|
+
|
|
204
|
+
`````
|
|
205
|
+
|
|
97
206
|
## Context Budget
|
|
98
207
|
|
|
99
208
|
Target: ~50% context per plan execution
|
|
@@ -130,7 +239,8 @@ Maximum: 2-3 tasks per plan
|
|
|
130
239
|
def test_specific_behavior():
|
|
131
240
|
result = function(input)
|
|
132
241
|
assert result == expected
|
|
133
|
-
|
|
242
|
+
`````
|
|
243
|
+
|
|
134
244
|
````
|
|
135
245
|
|
|
136
246
|
**Step 2: Run test to verify it fails**
|
|
@@ -187,3 +297,4 @@ After saving the plan, offer execution choice:
|
|
|
187
297
|
- Guide them to open new session in worktree
|
|
188
298
|
- **REQUIRED SUB-SKILL:** New session uses skill({ name: "executing-plans" })
|
|
189
299
|
```
|
|
300
|
+
````
|
package/package.json
CHANGED