@yemi33/minions 0.1.1632 → 0.1.1633
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/CHANGELOG.md +12 -2
- package/engine/copilot-models.json +1 -1
- package/engine/dispatch.js +102 -73
- package/engine/lifecycle.js +12 -0
- package/engine.js +2 -0
- package/package.json +1 -1
- package/playbooks/fix.md +17 -19
- package/playbooks/implement-shared.md +17 -16
- package/playbooks/implement.md +19 -14
- package/playbooks/shared-rules.md +11 -0
- package/playbooks/work-item.md +26 -23
- package/routing.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.1633 (2026-04-30)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- prevent completed stderr redispatch
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- yemi33/minions#1890
|
|
10
|
+
|
|
11
|
+
### Other
|
|
12
|
+
- docs: relax minions playbook contracts
|
|
13
|
+
|
|
14
|
+
## 0.1.1631 (2026-04-30)
|
|
4
15
|
|
|
5
16
|
### Features
|
|
6
|
-
- guard malformed PR context
|
|
7
17
|
- clear stale pending reason on retry
|
|
8
18
|
|
|
9
19
|
## 0.1.1629 (2026-04-29)
|
package/engine/dispatch.js
CHANGED
|
@@ -184,6 +184,22 @@ function isRetryableFailureReason(reason = '', failureClass = '') {
|
|
|
184
184
|
return !nonRetryable.some(s => r.includes(s));
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
function isCompletedWorkItemForFailure(item) {
|
|
188
|
+
return !!item && (
|
|
189
|
+
item.status === WI_STATUS.DONE ||
|
|
190
|
+
(!!item.completedAt && (!!item._pr || !!item._prUrl))
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function readLiveWorkItem(meta) {
|
|
195
|
+
const itemId = meta?.item?.id;
|
|
196
|
+
if (!itemId) return null;
|
|
197
|
+
const wiPath = lifecycle().resolveWorkItemPath(meta);
|
|
198
|
+
if (!wiPath) return null;
|
|
199
|
+
const items = safeJson(wiPath) || [];
|
|
200
|
+
return Array.isArray(items) ? items.find(i => i.id === itemId) || null : null;
|
|
201
|
+
}
|
|
202
|
+
|
|
187
203
|
// ─── Complete Dispatch ───────────────────────────────────────────────────────
|
|
188
204
|
|
|
189
205
|
function completeDispatch(id, result = DISPATCH_RESULT.SUCCESS, reason = '', resultSummary = '', opts = {}) {
|
|
@@ -225,83 +241,96 @@ function completeDispatch(id, result = DISPATCH_RESULT.SUCCESS, reason = '', res
|
|
|
225
241
|
|
|
226
242
|
// Update source work item status on failure + auto-retry with backoff
|
|
227
243
|
const retryableFailure = isRetryableFailureReason(reason, failureClass);
|
|
228
|
-
|
|
229
|
-
|
|
244
|
+
let completedWorkItemFailure = false;
|
|
230
245
|
if (processWorkItemFailure && result === DISPATCH_RESULT.ERROR && item.meta?.item?.id) {
|
|
231
|
-
|
|
246
|
+
// If the live item cannot be resolved, keep the existing retry path.
|
|
232
247
|
try {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (item.meta?.dispatchKey) {
|
|
244
|
-
try {
|
|
245
|
-
mutateDispatch((dp) => {
|
|
246
|
-
dp.completed = Array.isArray(dp.completed) ? dp.completed.filter(d => d.meta?.dispatchKey !== item.meta.dispatchKey) : [];
|
|
247
|
-
return dp;
|
|
248
|
-
});
|
|
249
|
-
} catch (e) { log('warn', 'clear dispatch for retry: ' + e.message); }
|
|
250
|
-
}
|
|
251
|
-
// Increment retry counter on the source work item
|
|
252
|
-
try {
|
|
253
|
-
const wiPath = lifecycle().resolveWorkItemPath(item.meta);
|
|
254
|
-
if (wiPath) {
|
|
255
|
-
mutateWorkItems(wiPath, items => {
|
|
256
|
-
const wi = items.find(i => i.id === item.meta.item.id);
|
|
257
|
-
if (wi && wi.status !== WI_STATUS.PAUSED && wi.status !== WI_STATUS.DONE && !wi.completedAt) {
|
|
258
|
-
wi._retryCount = retries + 1;
|
|
259
|
-
wi.status = WI_STATUS.PENDING;
|
|
260
|
-
wi._lastRetryReason = reason || '';
|
|
261
|
-
wi._lastRetryAt = ts();
|
|
262
|
-
delete wi.failReason;
|
|
263
|
-
delete wi.failedAt;
|
|
264
|
-
delete wi.dispatched_at;
|
|
265
|
-
delete wi.dispatched_to;
|
|
266
|
-
delete wi._pendingReason;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
} catch (e) { log('warn', 'increment retry counter: ' + e.message); }
|
|
248
|
+
completedWorkItemFailure = isCompletedWorkItemForFailure(readLiveWorkItem(item.meta));
|
|
249
|
+
} catch (e) { log('warn', 'read live work item before retry: ' + e.message); }
|
|
250
|
+
}
|
|
251
|
+
if (result === DISPATCH_RESULT.ERROR && item.meta?.dispatchKey && retryableFailure && !completedWorkItemFailure) {
|
|
252
|
+
setCooldownFailure(item.meta.dispatchKey);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (processWorkItemFailure && result === DISPATCH_RESULT.ERROR && item.meta?.item?.id) {
|
|
256
|
+
if (completedWorkItemFailure) {
|
|
257
|
+
log('info', `Dispatch error for ${item.meta.item.id} ignored — work item is already completed`);
|
|
271
258
|
} else {
|
|
272
|
-
|
|
273
|
-
const CLASS_LABELS = {
|
|
274
|
-
[FAILURE_CLASS.EMPTY_OUTPUT]: 'agent produced no output \u2014 likely crashed on startup',
|
|
275
|
-
[FAILURE_CLASS.BUILD_FAILURE]: 'build/test/lint failure in output',
|
|
276
|
-
[FAILURE_CLASS.MERGE_CONFLICT]: 'merge conflict',
|
|
277
|
-
[FAILURE_CLASS.MAX_TURNS]: 'reached max turn limit',
|
|
278
|
-
[FAILURE_CLASS.TIMEOUT]: 'timed out waiting for agent',
|
|
279
|
-
[FAILURE_CLASS.SPAWN_ERROR]: 'agent process failed to start',
|
|
280
|
-
[FAILURE_CLASS.NETWORK_ERROR]: 'network or API error',
|
|
281
|
-
[FAILURE_CLASS.OUT_OF_CONTEXT]: 'context window exhausted',
|
|
282
|
-
[FAILURE_CLASS.CONFIG_ERROR]: 'configuration error',
|
|
283
|
-
[FAILURE_CLASS.PERMISSION_BLOCKED]: 'permission or auth failure',
|
|
284
|
-
[FAILURE_CLASS.UNKNOWN]: 'unknown error',
|
|
285
|
-
};
|
|
286
|
-
const classLabel = failureClass ? (CLASS_LABELS[failureClass] || failureClass) : '';
|
|
287
|
-
const effectiveReason = reason || classLabel || 'Unknown error';
|
|
288
|
-
const classSuffix = failureClass ? ` [${failureClass.toUpperCase().replace(/-/g, '_')}]` : '';
|
|
289
|
-
const finalReason = !retryableFailure
|
|
290
|
-
? `Non-retryable failure: ${effectiveReason}${classSuffix}`
|
|
291
|
-
: (reason || `Failed after ${maxRetries} retries${classSuffix}`);
|
|
292
|
-
lifecycle().updateWorkItemStatus(item.meta, WI_STATUS.FAILED, finalReason);
|
|
293
|
-
// Surface blocked dependents in logs without creating failure inbox noise.
|
|
259
|
+
let retries = (item.meta.item._retryCount || 0);
|
|
294
260
|
try {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
log('
|
|
303
|
-
|
|
304
|
-
|
|
261
|
+
const wi = queries.getWorkItems().find(i => i.id === item.meta.item.id);
|
|
262
|
+
if (wi) retries = wi._retryCount || 0;
|
|
263
|
+
} catch (e) { log('warn', 'read retry count: ' + e.message); }
|
|
264
|
+
const maxRetries = ENGINE_DEFAULTS.maxRetries;
|
|
265
|
+
// Use per-class retry limits from recovery.js when failureClass is available
|
|
266
|
+
const classAllowsRetry = failureClass ? recovery().shouldRetry(failureClass, retries) : (retries < maxRetries);
|
|
267
|
+
if (retryableFailure && classAllowsRetry) {
|
|
268
|
+
log('info', `Dispatch error for ${item.meta.item.id} — auto-retry ${retries + 1}/${maxRetries}${failureClass ? ' [' + failureClass + ']' : ''}`);
|
|
269
|
+
lifecycle().updateWorkItemStatus(item.meta, WI_STATUS.PENDING, '');
|
|
270
|
+
// Remove this dispatch key from completed so dedupe doesn't block immediate redispatch.
|
|
271
|
+
if (item.meta?.dispatchKey) {
|
|
272
|
+
try {
|
|
273
|
+
mutateDispatch((dp) => {
|
|
274
|
+
dp.completed = Array.isArray(dp.completed) ? dp.completed.filter(d => d.meta?.dispatchKey !== item.meta.dispatchKey) : [];
|
|
275
|
+
return dp;
|
|
276
|
+
});
|
|
277
|
+
} catch (e) { log('warn', 'clear dispatch for retry: ' + e.message); }
|
|
278
|
+
}
|
|
279
|
+
// Increment retry counter on the source work item
|
|
280
|
+
try {
|
|
281
|
+
const wiPath = lifecycle().resolveWorkItemPath(item.meta);
|
|
282
|
+
if (wiPath) {
|
|
283
|
+
mutateWorkItems(wiPath, items => {
|
|
284
|
+
const wi = items.find(i => i.id === item.meta.item.id);
|
|
285
|
+
if (wi && wi.status !== WI_STATUS.PAUSED && wi.status !== WI_STATUS.DONE && !wi.completedAt) {
|
|
286
|
+
wi._retryCount = retries + 1;
|
|
287
|
+
wi.status = WI_STATUS.PENDING;
|
|
288
|
+
wi._lastRetryReason = reason || '';
|
|
289
|
+
wi._lastRetryAt = ts();
|
|
290
|
+
delete wi.failReason;
|
|
291
|
+
delete wi.failedAt;
|
|
292
|
+
delete wi.dispatched_at;
|
|
293
|
+
delete wi.dispatched_to;
|
|
294
|
+
delete wi._pendingReason;
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
} catch (e) { log('warn', 'increment retry counter: ' + e.message); }
|
|
299
|
+
} else {
|
|
300
|
+
// Human-readable labels for each failure class — used as fallback when reason is empty
|
|
301
|
+
const CLASS_LABELS = {
|
|
302
|
+
[FAILURE_CLASS.EMPTY_OUTPUT]: 'agent produced no output \u2014 likely crashed on startup',
|
|
303
|
+
[FAILURE_CLASS.BUILD_FAILURE]: 'build/test/lint failure in output',
|
|
304
|
+
[FAILURE_CLASS.MERGE_CONFLICT]: 'merge conflict',
|
|
305
|
+
[FAILURE_CLASS.MAX_TURNS]: 'reached max turn limit',
|
|
306
|
+
[FAILURE_CLASS.TIMEOUT]: 'timed out waiting for agent',
|
|
307
|
+
[FAILURE_CLASS.SPAWN_ERROR]: 'agent process failed to start',
|
|
308
|
+
[FAILURE_CLASS.NETWORK_ERROR]: 'network or API error',
|
|
309
|
+
[FAILURE_CLASS.OUT_OF_CONTEXT]: 'context window exhausted',
|
|
310
|
+
[FAILURE_CLASS.CONFIG_ERROR]: 'configuration error',
|
|
311
|
+
[FAILURE_CLASS.PERMISSION_BLOCKED]: 'permission or auth failure',
|
|
312
|
+
[FAILURE_CLASS.UNKNOWN]: 'unknown error',
|
|
313
|
+
};
|
|
314
|
+
const classLabel = failureClass ? (CLASS_LABELS[failureClass] || failureClass) : '';
|
|
315
|
+
const effectiveReason = reason || classLabel || 'Unknown error';
|
|
316
|
+
const classSuffix = failureClass ? ` [${failureClass.toUpperCase().replace(/-/g, '_')}]` : '';
|
|
317
|
+
const finalReason = !retryableFailure
|
|
318
|
+
? `Non-retryable failure: ${effectiveReason}${classSuffix}`
|
|
319
|
+
: (reason || `Failed after ${maxRetries} retries${classSuffix}`);
|
|
320
|
+
lifecycle().updateWorkItemStatus(item.meta, WI_STATUS.FAILED, finalReason);
|
|
321
|
+
// Surface blocked dependents in logs without creating failure inbox noise.
|
|
322
|
+
try {
|
|
323
|
+
const config = getConfig();
|
|
324
|
+
const failedId = item.meta.item.id;
|
|
325
|
+
const blockedItems = [];
|
|
326
|
+
const allItems = queries.getWorkItems(config);
|
|
327
|
+
allItems.filter(w => w.status === WI_STATUS.PENDING && (w.depends_on || []).includes(failedId))
|
|
328
|
+
.forEach(w => blockedItems.push(`- \`${w.id}\` — ${w.title}`));
|
|
329
|
+
|
|
330
|
+
log('warn', `Work item ${failedId} failed: ${finalReason}` +
|
|
331
|
+
(blockedItems.length > 0 ? `; blocked dependents: ${blockedItems.map(line => line.replace(/^- `([^`]+)`.*/, '$1')).join(', ')}` : '; no downstream items blocked'));
|
|
332
|
+
} catch (e) { log('warn', 'summarize failure dependents: ' + e.message); }
|
|
333
|
+
}
|
|
305
334
|
}
|
|
306
335
|
}
|
|
307
336
|
|
package/engine/lifecycle.js
CHANGED
|
@@ -560,10 +560,18 @@ function updateWorkItemStatus(meta, status, reason) {
|
|
|
560
560
|
const wiPath = resolveWorkItemPath(meta);
|
|
561
561
|
if (!wiPath) return;
|
|
562
562
|
|
|
563
|
+
let completionGuarded = false;
|
|
563
564
|
mutateJsonFileLocked(wiPath, (items) => {
|
|
564
565
|
if (!items || !Array.isArray(items)) return items;
|
|
565
566
|
const target = items.find(i => i.id === itemId);
|
|
566
567
|
if (!target) return items;
|
|
568
|
+
if (status !== WI_STATUS.DONE && (
|
|
569
|
+
target.status === WI_STATUS.DONE ||
|
|
570
|
+
(!!target.completedAt && (!!target._pr || !!target._prUrl))
|
|
571
|
+
)) {
|
|
572
|
+
completionGuarded = true;
|
|
573
|
+
return items;
|
|
574
|
+
}
|
|
567
575
|
|
|
568
576
|
if (meta.source === 'central-work-item-fanout') {
|
|
569
577
|
if (!target.agentResults) target.agentResults = {};
|
|
@@ -609,6 +617,10 @@ function updateWorkItemStatus(meta, status, reason) {
|
|
|
609
617
|
return items;
|
|
610
618
|
}, { defaultValue: [], skipWriteIfUnchanged: true });
|
|
611
619
|
|
|
620
|
+
if (completionGuarded) {
|
|
621
|
+
log('info', `Work item ${itemId} already completed — ignoring ${status} status update`);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
612
624
|
log('info', `Work item ${itemId} → ${status}${reason ? ': ' + reason : ''}`);
|
|
613
625
|
syncPrdItemStatus(itemId, status, meta.item?.sourcePlan);
|
|
614
626
|
}
|
package/engine.js
CHANGED
|
@@ -2411,6 +2411,7 @@ function discoverFromWorkItems(config, project) {
|
|
|
2411
2411
|
|
|
2412
2412
|
for (const item of items) {
|
|
2413
2413
|
try {
|
|
2414
|
+
if (isItemCompleted(item)) continue;
|
|
2414
2415
|
// Re-evaluate failed items: if deps have recovered, reset to pending
|
|
2415
2416
|
if (item.status === WI_STATUS.FAILED && !isItemCompleted(item) && item.failReason === 'Dependency failed — cannot proceed') {
|
|
2416
2417
|
const depStatus = areDependenciesMet(item, config);
|
|
@@ -2908,6 +2909,7 @@ function discoverCentralWorkItems(config) {
|
|
|
2908
2909
|
|
|
2909
2910
|
for (const item of items) {
|
|
2910
2911
|
try {
|
|
2912
|
+
if (isItemCompleted(item)) continue;
|
|
2911
2913
|
if (item.status !== WI_STATUS.QUEUED && item.status !== WI_STATUS.PENDING) continue;
|
|
2912
2914
|
|
|
2913
2915
|
const key = `central-work-${item.id}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1633",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|
package/playbooks/fix.md
CHANGED
|
@@ -25,33 +25,31 @@ Before starting work, run `git status` and verify the worktree is clean and on t
|
|
|
25
25
|
|
|
26
26
|
Use subagents only for genuinely parallel, independent tasks. For sequential work, single-file edits, searches, and file reads, work directly — do not spawn subagents.
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Delivery Contract
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Handle this like the PR author responding directly from a CLI:
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
- You are already in the correct worktree on branch `{{pr_branch}}`. Do NOT create additional worktrees.
|
|
33
|
+
- For each review finding, use engineering judgment:
|
|
34
|
+
- Fix it if the feedback is valid and improves correctness, safety, maintainability, or test coverage.
|
|
35
|
+
- If the current approach is intentionally correct, reply with specific rationale instead of silently changing code or ignoring the thread.
|
|
36
|
+
- Handle merge conflicts when needed, preserving the PR's intended changes while keeping the branch reviewable.
|
|
37
|
+
- Do not add unrelated cleanups or broaden the PR beyond the review feedback unless that is necessary to make the fix correct.
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
- If `git pull` or the PR shows conflicts, resolve them in the worktree
|
|
38
|
-
- Prefer the PR branch changes, commit the resolution
|
|
39
|
+
## Validation
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
Before pushing, prove the review fix did not break the branch:
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
3. If any tests fail due to your changes, fix them before pushing.
|
|
47
|
-
4. If the build fails 3 times, report the errors in your PR comment and stop.
|
|
48
|
-
5. Do NOT push code that breaks existing tests or the build.
|
|
43
|
+
- Use the project's source of truth for commands: `CLAUDE.md`, README, package scripts, Makefile, or equivalent build config.
|
|
44
|
+
- Run checks that are relevant to the addressed findings. Prefer the full suite when practical.
|
|
45
|
+
- Fix regressions you introduced. If failures are pre-existing or unrelated, capture the evidence and include it in the PR comment.
|
|
46
|
+
- Do not push code that breaks existing tests or the build because of your changes.
|
|
49
47
|
|
|
50
48
|
> ⚠️ **Long builds (Gradle, MSBuild, dotnet, fresh `npm install`)**: any command that may stay silent for more than ~4 minutes will be killed by the heartbeat monitor. Run it via `Bash(run_in_background: true)` then `Monitor` to stream stdout, OR pass an explicit `timeout` (max 600000 ms). See **Long-Running Build / Test Commands** below for the full pattern.
|
|
51
49
|
|
|
52
|
-
##
|
|
50
|
+
## Publish & Comment on PR
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
After the fix is validated or any unavoidable limitation is clearly documented, commit only relevant files and push:
|
|
55
53
|
|
|
56
54
|
```bash
|
|
57
55
|
git add <specific files>
|
|
@@ -76,7 +74,7 @@ After pushing, respond to each review comment/thread:
|
|
|
76
74
|
|
|
77
75
|
## When to Stop
|
|
78
76
|
|
|
79
|
-
Your task is complete
|
|
77
|
+
Your task is complete when each review finding has either been fixed or answered with rationale, the validation story is truthful and sufficient for review, the fix is pushed if code changed, the PR is commented, and addressed threads are resolved. Do NOT continue into unrelated improvements.
|
|
80
78
|
|
|
81
79
|
**NEVER run `gh pr merge` or any merge command on this PR.** The engine handles merging after review approval. Self-merging bypasses the review cycle and is prohibited.
|
|
82
80
|
|
|
@@ -47,29 +47,30 @@ Before starting work, run `git status` and verify the worktree is clean and on t
|
|
|
47
47
|
|
|
48
48
|
Use subagents only for genuinely parallel, independent tasks. For sequential work, single-file edits, searches, and file reads, work directly — do not spawn subagents.
|
|
49
49
|
|
|
50
|
-
##
|
|
50
|
+
## Delivery Contract
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
2. Check what prior plan items already committed on this branch (`git log {{main_branch}}..HEAD`)
|
|
54
|
-
3. Follow existing patterns exactly — check `CLAUDE.md` for conventions
|
|
55
|
-
4. Build on existing work — don't duplicate or conflict with prior commits
|
|
52
|
+
Deliver this as if the user asked you directly in a CLI, with the added constraint that this branch may already contain related work:
|
|
56
53
|
|
|
57
|
-
|
|
54
|
+
- Understand the requested behavior and how prior commits on `{{branch_name}}` affect it.
|
|
55
|
+
- Read the smallest useful set of source, tests, docs, and comparable implementations needed to make the change correctly.
|
|
56
|
+
- Follow existing project conventions from `CLAUDE.md` and nearby code.
|
|
57
|
+
- Build on previous plan-item work instead of duplicating or conflicting with it.
|
|
58
|
+
- Make the complete change required by this item; do not add unrelated cleanups or speculative improvements.
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
## Validation
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
Before publishing, prove the shared branch still works with your change included:
|
|
63
|
+
|
|
64
|
+
- Use the project's source of truth for commands: `CLAUDE.md`, README, package scripts, Makefile, or equivalent build config.
|
|
65
|
+
- Run checks that are relevant to this item and to the integrated branch state. Prefer the full suite when practical.
|
|
66
|
+
- Fix regressions you introduced. If failures are pre-existing or caused by earlier branch work, capture the evidence and say so clearly.
|
|
67
|
+
- Do not push code with a broken build or failing tests that you introduced.
|
|
67
68
|
|
|
68
69
|
> ⚠️ **Long builds (Gradle, MSBuild, dotnet, fresh `npm install`)**: any command that may stay silent for more than ~4 minutes will be killed by the heartbeat monitor. Run it via `Bash(run_in_background: true)` then `Monitor` to stream stdout, OR pass an explicit `timeout` (max 600000 ms). See **Long-Running Build / Test Commands** below for the full pattern.
|
|
69
70
|
|
|
70
|
-
##
|
|
71
|
+
## Publish
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
After the change is validated or any unavoidable limitation is clearly documented, commit only the relevant files and push to the shared branch:
|
|
73
74
|
|
|
74
75
|
```bash
|
|
75
76
|
git add <specific files>
|
|
@@ -79,7 +80,7 @@ git push origin {{branch_name}}
|
|
|
79
80
|
|
|
80
81
|
## When to Stop
|
|
81
82
|
|
|
82
|
-
Your task is complete
|
|
83
|
+
Your task is complete when the requested implementation is delivered, the validation story is truthful and sufficient for review, and your commit is pushed to the shared branch. Do NOT create a PR — the engine creates one when all plan items are done.
|
|
83
84
|
|
|
84
85
|
## Completion
|
|
85
86
|
|
package/playbooks/implement.md
CHANGED
|
@@ -38,32 +38,35 @@ Before starting work, run `git status` and verify the worktree is clean and on t
|
|
|
38
38
|
|
|
39
39
|
Use subagents only for genuinely parallel, independent tasks (e.g., editing files in unrelated modules simultaneously). For sequential work, single-file edits, searches, and file reads, work directly — do not spawn subagents.
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## Delivery Contract
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
Deliver this as if the user asked you directly in a CLI:
|
|
44
|
+
|
|
45
|
+
- Understand the requested behavior and relevant acceptance criteria before editing.
|
|
46
|
+
- Read the smallest useful set of source, tests, docs, and comparable implementations needed to make the change correctly.
|
|
47
|
+
- Follow existing project conventions, including logging, typing, error handling, and test structure.
|
|
48
|
+
- Make the complete change required by the task; do not add unrelated cleanups or speculative improvements.
|
|
49
|
+
- Keep working through failures you introduced until the implementation is either correct or honestly blocked with concrete evidence.
|
|
46
50
|
|
|
47
51
|
## Git Workflow
|
|
48
52
|
|
|
49
53
|
You are already running in a git worktree on branch `{{branch_name}}`. Do NOT create additional worktrees — the engine pre-created one for you.
|
|
50
54
|
Do NOT remove the worktree — the engine handles cleanup automatically.
|
|
51
55
|
|
|
52
|
-
##
|
|
56
|
+
## Validation
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
Before publishing, prove the change with the repo's own documented checks:
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
5. Do NOT push code with a broken build or failing tests that you introduced.
|
|
60
|
+
- Use the project's source of truth for commands: `CLAUDE.md`, README, package scripts, Makefile, or equivalent build config.
|
|
61
|
+
- Run the checks that are relevant to this task, including tests that cover the changed behavior. Prefer the full suite when practical.
|
|
62
|
+
- Fix regressions you introduced. If failures are pre-existing or outside the task, capture the evidence and make that explicit in the PR.
|
|
63
|
+
- Do not publish changes with a broken build or failing tests that you introduced.
|
|
61
64
|
|
|
62
65
|
> ⚠️ **Long builds (Gradle, MSBuild, dotnet, fresh `npm install`)**: any command that may stay silent for more than ~4 minutes will be killed by the heartbeat monitor. Run it via `Bash(run_in_background: true)` then `Monitor` to stream stdout, OR pass an explicit `timeout` (max 600000 ms). See **Long-Running Build / Test Commands** below for the full pattern.
|
|
63
66
|
|
|
64
|
-
##
|
|
67
|
+
## Publish
|
|
65
68
|
|
|
66
|
-
|
|
69
|
+
After the change is validated or any unavoidable limitation is clearly documented, commit only the relevant files and push this branch:
|
|
67
70
|
|
|
68
71
|
```bash
|
|
69
72
|
git add <specific files>
|
|
@@ -73,10 +76,12 @@ git push -u origin {{branch_name}}
|
|
|
73
76
|
|
|
74
77
|
{{pr_section}}
|
|
75
78
|
|
|
79
|
+
PR creation is MANDATORY for implement tasks because the engine tracks review and completion from the PR.
|
|
80
|
+
|
|
76
81
|
Include build/test status and run instructions in the PR description. If the project has a runnable app, include the localhost URL.
|
|
77
82
|
|
|
78
83
|
## When to Stop
|
|
79
84
|
|
|
80
|
-
Your task is complete
|
|
85
|
+
Your task is complete when the requested implementation is delivered, the validation story is truthful and sufficient for review, the branch is pushed, and the PR exists. Your final message MUST include the PR URL so the engine can track it.
|
|
81
86
|
|
|
82
87
|
Do NOT run `gh pr merge` or any other merge command on your own PR. The engine reviews and merges PRs through a separate review cycle. Self-merging is prohibited.
|
|
@@ -17,6 +17,17 @@ Codex will review your changes — make sure your implementation is thorough and
|
|
|
17
17
|
|
|
18
18
|
Your context window may be compacted or summarized mid-task by Claude's automatic context management. This is normal and expected for long-running tasks. Do NOT interpret compacted or truncated context as a signal to stop early, wrap up prematurely, or skip remaining work. Continue working toward your stated objective regardless of context window state — re-read key files if needed to recover context.
|
|
19
19
|
|
|
20
|
+
## Delegated Task Contract
|
|
21
|
+
|
|
22
|
+
Treat a Minions assignment like the user typed the same task directly into a capable CLI agent. Preserve the user's actual task contract first; the playbook adds orchestration guardrails, not a rigid script for thinking or implementation.
|
|
23
|
+
|
|
24
|
+
- Optimize for the requested outcome, not for mechanically completing checklist steps.
|
|
25
|
+
- Use judgment to choose the smallest reliable workflow that fully satisfies the task.
|
|
26
|
+
- Read only the context needed to make correct decisions; do not perform broad archaeology unless the task requires it.
|
|
27
|
+
- Validate with the repo's own documented commands and acceptance criteria. If full validation is impossible or pre-existing failures block it, explain that precisely instead of inventing a green result.
|
|
28
|
+
- Prefer direct work over ceremony. Branches, PRs, inbox notes, completion blocks, and status comments exist for traceability; they should not change what "done" means for the user.
|
|
29
|
+
- Safety and observability rules still win: stay in the engine-created worktree, do not self-merge, do not edit engine-managed status files, do not hide failures, and leave enough evidence for the human and engine to track the result.
|
|
30
|
+
|
|
20
31
|
## Engine Rules (apply to all tasks)
|
|
21
32
|
|
|
22
33
|
**Context compaction:** Your context window may be compacted mid-task by Claude's infrastructure. If you notice your earlier conversation history appears truncated or summarized, this is normal and expected. Do not interpret compaction as a signal to stop early or wrap up. Continue working toward your task objective — all relevant instructions and state remain available.
|
package/playbooks/work-item.md
CHANGED
|
@@ -20,28 +20,31 @@ Team root: {{team_root}}
|
|
|
20
20
|
Branch format: `feat/{{item_id}}-<short-description>`
|
|
21
21
|
Keep branch names lowercase, use hyphens, max 60 chars.
|
|
22
22
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
## Delivery Contract
|
|
24
|
+
|
|
25
|
+
Treat this like the user typed the task directly into a CLI agent:
|
|
26
|
+
|
|
27
|
+
- Work in the correct project directory: `{{project_path}}`.
|
|
28
|
+
- You are already in a worktree on branch `{{branch_name}}`. Do NOT create additional worktrees.
|
|
29
|
+
- Understand the requested outcome, inspect the relevant source/tests/docs, and make the complete change needed.
|
|
30
|
+
- Follow existing repo conventions and avoid unrelated cleanups.
|
|
31
|
+
- Validate with the repo's documented build/test/check commands. Fix regressions you introduced; if failures are pre-existing or outside the task, document the evidence.
|
|
32
|
+
- Do NOT publish code with a broken build or failing tests that you introduced.
|
|
33
|
+
|
|
34
|
+
After the change is ready for review, commit only relevant files, push `{{branch_name}}`, create the PR, and post implementation notes with the validation result:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git add <specific files>
|
|
38
|
+
git commit -m "feat({{item_id}}): <description>"
|
|
39
|
+
git push -u origin {{branch_name}}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
{{pr_create_instructions}}
|
|
43
|
+
- sourceRefName: `refs/heads/feat/{{item_id}}-<short-desc>`
|
|
44
|
+
- targetRefName: `refs/heads/{{main_branch}}`
|
|
45
|
+
- title: `feat({{item_id}}): <description>`
|
|
46
|
+
|
|
47
|
+
{{pr_comment_instructions}}
|
|
45
48
|
|
|
46
49
|
Do NOT remove the worktree — the engine handles cleanup automatically.
|
|
47
50
|
|
|
@@ -59,6 +62,6 @@ If you encounter merge conflicts during push or PR creation:
|
|
|
59
62
|
|
|
60
63
|
## When to Stop
|
|
61
64
|
|
|
62
|
-
Your task is complete
|
|
65
|
+
Your task is complete when the requested work item is delivered, the validation story is truthful and sufficient for review, the branch is pushed, and the PR exists. Do NOT continue into unrelated improvements.
|
|
63
66
|
|
|
64
67
|
Do NOT run `gh pr merge` or any other merge command on your own PR. The engine reviews and merges PRs through a separate review cycle. Self-merging is prohibited.
|
package/routing.md
CHANGED
|
@@ -25,6 +25,7 @@ Notes:
|
|
|
25
25
|
- `_any_` means route to any available idle agent (lowest error rate first)
|
|
26
26
|
- `implement:large` is for items with `estimated_complexity: "large"`
|
|
27
27
|
- Engine falls back to any idle agent if both preferred and fallback are busy
|
|
28
|
+
- Routing selects an owner; it should not narrow the user's task contract. The assigned agent should behave like the user typed the same task directly into a CLI, with Minions adding only safety, status, and review guardrails.
|
|
28
29
|
|
|
29
30
|
## Rules
|
|
30
31
|
|