opencodekit 0.17.8 → 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.
@@ -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
- PROGRESS +
87
- TODO PERSIST
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencodekit",
3
- "version": "0.17.8",
3
+ "version": "0.17.10",
4
4
  "description": "CLI tool for bootstrapping and managing OpenCodeKit projects",
5
5
  "keywords": ["agents", "cli", "mcp", "opencode", "opencodekit", "template"],
6
6
  "license": "MIT",
@@ -35,16 +35,16 @@
35
35
  "format:check": "oxfmt --check"
36
36
  },
37
37
  "dependencies": {
38
- "@ai-sdk/provider": "^3.0.6",
39
- "@ai-sdk/provider-utils": "^4.0.11",
38
+ "@ai-sdk/provider": "^3.0.8",
39
+ "@ai-sdk/provider-utils": "^4.0.15",
40
40
  "@clack/prompts": "^0.7.0",
41
- "@opencode-ai/plugin": "^1.1.12",
42
- "@opentui/core": "^0.1.72",
43
- "@opentui/solid": "^0.1.72",
41
+ "@opencode-ai/plugin": "^1.2.6",
42
+ "@opentui/core": "^0.1.80",
43
+ "@opentui/solid": "^0.1.80",
44
44
  "cac": "^6.7.14",
45
45
  "cli-table3": "^0.6.5",
46
46
  "diff": "^8.0.3",
47
- "ora": "^9.0.0",
47
+ "ora": "^9.3.0",
48
48
  "picocolors": "^1.1.1",
49
49
  "solid-js": "1.9.9",
50
50
  "zod": "^3.25.76"
@@ -53,9 +53,9 @@
53
53
  "@biomejs/biome": "^1.9.4",
54
54
  "@types/bun": "latest",
55
55
  "@types/diff": "^8.0.0",
56
- "@types/node": "^22.19.5",
56
+ "@types/node": "^22.19.11",
57
57
  "oxfmt": "^0.23.0",
58
- "oxlint": "^1.38.0",
58
+ "oxlint": "^1.48.0",
59
59
  "typescript": "^5.9.3"
60
60
  },
61
61
  "engines": {