@yemi33/minions 0.1.741 → 0.1.743
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 +3 -1
- package/engine/lifecycle.js +25 -9
- package/engine/queries.js +2 -0
- package/engine/shared.js +4 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.743 (2026-04-09)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- add prNumber field to pull-requests.json records (#711)
|
|
7
7
|
|
|
8
8
|
### Fixes
|
|
9
|
+
- link plan files as artifacts on plan/plan-to-prd work items
|
|
10
|
+
- escalate failed plan items instead of blocking indefinitely (closes #722) (#733)
|
|
9
11
|
- handle NUL pseudo-file in Windows worktree cleanup (#731)
|
|
10
12
|
|
|
11
13
|
## 0.1.739 (2026-04-09)
|
package/engine/lifecycle.js
CHANGED
|
@@ -8,7 +8,7 @@ const path = require('path');
|
|
|
8
8
|
const os = require('os');
|
|
9
9
|
const shared = require('./shared');
|
|
10
10
|
const { safeRead, safeJson, safeWrite, mutateJsonFileLocked, mutateWorkItems, execSilent, projectPrPath, getPrLinks, addPrLink,
|
|
11
|
-
log, ts, dateStamp, WI_STATUS, DONE_STATUSES, WORK_TYPE, PLAN_STATUS, PR_STATUS, DISPATCH_RESULT,
|
|
11
|
+
log, ts, dateStamp, WI_STATUS, DONE_STATUSES, PLAN_TERMINAL_STATUSES, WORK_TYPE, PLAN_STATUS, PR_STATUS, DISPATCH_RESULT,
|
|
12
12
|
ENGINE_DEFAULTS, DEFAULT_AGENT_METRICS, FAILURE_CLASS } = shared;
|
|
13
13
|
const { trackEngineUsage } = require('./llm');
|
|
14
14
|
const queries = require('./queries');
|
|
@@ -34,7 +34,7 @@ function checkPlanCompletion(meta, config) {
|
|
|
34
34
|
const planItems = allWorkItems.filter(w => w.sourcePlan === planFile && w.itemType !== 'pr' && w.itemType !== 'verify');
|
|
35
35
|
if (planItems.length === 0) return;
|
|
36
36
|
|
|
37
|
-
// Hard completion gate: every PRD feature ID must have a corresponding work item in
|
|
37
|
+
// Hard completion gate: every PRD feature ID must have a corresponding work item in a terminal state.
|
|
38
38
|
const planFeatureIds = new Set((plan.missing_features || []).map(f => f.id).filter(Boolean));
|
|
39
39
|
const workItemById = {};
|
|
40
40
|
for (const w of planItems) { if (w.id) workItemById[w.id] = w; }
|
|
@@ -51,20 +51,36 @@ function checkPlanCompletion(meta, config) {
|
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// Check 2: every feature
|
|
55
|
-
|
|
54
|
+
// Check 2: every feature must be in a terminal state (done, failed, or cancelled).
|
|
55
|
+
// Failed/cancelled items are unrecoverable — waiting on them blocks the plan indefinitely.
|
|
56
|
+
const notTerminal = [...planFeatureIds].filter(id => {
|
|
56
57
|
const w = workItemById[id];
|
|
57
|
-
if (w &&
|
|
58
|
+
if (w && PLAN_TERMINAL_STATUSES.has(w.status)) return false;
|
|
58
59
|
const prdItem = (plan.missing_features || []).find(f => f.id === id);
|
|
59
|
-
return !(prdItem &&
|
|
60
|
+
return !(prdItem && PLAN_TERMINAL_STATUSES.has(prdItem.status));
|
|
60
61
|
});
|
|
61
|
-
if (
|
|
62
|
-
log('info', `Plan ${planFile}: waiting for
|
|
62
|
+
if (notTerminal.length > 0) {
|
|
63
|
+
log('info', `Plan ${planFile}: waiting for ${notTerminal.length}/${planFeatureIds.size} item(s) to reach terminal state: ${notTerminal.join(', ')}`);
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
const doneItems = planItems.filter(w => DONE_STATUSES.has(w.status));
|
|
67
|
-
const failedItems = planItems.filter(w => w.status === WI_STATUS.FAILED);
|
|
68
|
+
const failedItems = planItems.filter(w => w.status === WI_STATUS.FAILED || w.status === WI_STATUS.CANCELLED);
|
|
69
|
+
|
|
70
|
+
// Escalate failed/cancelled items to human — write inbox alert (deduped by slug)
|
|
71
|
+
if (failedItems.length > 0) {
|
|
72
|
+
const alertSlug = `plan-failure-escalation-${planFile.replace('.json', '')}`;
|
|
73
|
+
const failDetails = failedItems.map(w =>
|
|
74
|
+
`- \`${w.id}\`: ${w.title || 'Unknown'} — ${w.failReason || w.status}`
|
|
75
|
+
).join('\n');
|
|
76
|
+
shared.writeToInbox('engine', alertSlug,
|
|
77
|
+
`# Plan Items Failed: ${plan.plan_summary || planFile}\n\n` +
|
|
78
|
+
`**${failedItems.length}** of ${planFeatureIds.size} item(s) failed or were cancelled:\n\n${failDetails}\n\n` +
|
|
79
|
+
`The plan is completing with partial results (${doneItems.length} done, ${failedItems.length} failed).\n` +
|
|
80
|
+
`Review failed items and re-dispatch manually if needed.\n`
|
|
81
|
+
);
|
|
82
|
+
log('warn', `Plan ${planFile}: ${failedItems.length} item(s) failed/cancelled — escalating to human: ${failedItems.map(w => w.id).join(', ')}`);
|
|
83
|
+
}
|
|
68
84
|
|
|
69
85
|
// 1. Mark plan as completed
|
|
70
86
|
plan.status = PLAN_STATUS.COMPLETED;
|
package/engine/queries.js
CHANGED
|
@@ -754,6 +754,8 @@ function getWorkItems(config) {
|
|
|
754
754
|
}
|
|
755
755
|
if (item.branch || item.featureBranch) arts.branch = item.branch || item.featureBranch;
|
|
756
756
|
if (item.sourcePlan) arts.sourcePlan = item.sourcePlan;
|
|
757
|
+
if (item._planFileName) arts.plan = item._planFileName;
|
|
758
|
+
else if (item.planFile) arts.plan = item.planFile;
|
|
757
759
|
if (item._pr) arts.pr = item._pr;
|
|
758
760
|
if (Object.keys(arts).length > 0) item._artifacts = arts;
|
|
759
761
|
}
|
package/engine/shared.js
CHANGED
|
@@ -562,6 +562,9 @@ const WI_STATUS = {
|
|
|
562
562
|
// Read-side: accept legacy aliases for backward compat with old data/clients.
|
|
563
563
|
// Write-side: only WI_STATUS.DONE is written (cleanup.js migrates old values on each run).
|
|
564
564
|
const DONE_STATUSES = new Set([WI_STATUS.DONE, 'in-pr', 'implemented', 'complete']);
|
|
565
|
+
// Terminal statuses for plan completion — item won't progress further (done, failed, cancelled).
|
|
566
|
+
// Used by checkPlanCompletion to unblock the gate when items are in an unrecoverable state.
|
|
567
|
+
const PLAN_TERMINAL_STATUSES = new Set([...DONE_STATUSES, WI_STATUS.FAILED, WI_STATUS.CANCELLED]);
|
|
565
568
|
const WORK_TYPE = {
|
|
566
569
|
IMPLEMENT: 'implement', IMPLEMENT_LARGE: 'implement:large', FIX: 'fix', REVIEW: 'review',
|
|
567
570
|
VERIFY: 'verify', PLAN: 'plan', PLAN_TO_PRD: 'plan-to-prd', DECOMPOSE: 'decompose',
|
|
@@ -989,7 +992,7 @@ module.exports = {
|
|
|
989
992
|
KB_CATEGORIES,
|
|
990
993
|
classifyInboxItem,
|
|
991
994
|
ENGINE_DEFAULTS,
|
|
992
|
-
WI_STATUS, DONE_STATUSES, WORK_TYPE, PLAN_STATUS, PR_STATUS, DISPATCH_RESULT,
|
|
995
|
+
WI_STATUS, DONE_STATUSES, PLAN_TERMINAL_STATUSES, WORK_TYPE, PLAN_STATUS, PR_STATUS, DISPATCH_RESULT,
|
|
993
996
|
PIPELINE_STATUS, STAGE_TYPE, MEETING_STATUS, AGENT_STATUS,
|
|
994
997
|
FAILURE_CLASS, ESCALATION_POLICY, COMPLETION_FIELDS,
|
|
995
998
|
DEFAULT_AGENT_METRICS,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.743",
|
|
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"
|