@yemi33/minions 0.1.520 → 0.1.522
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 +7 -1
- package/engine/cleanup.js +24 -1
- package/engine/lifecycle.js +4 -2
- package/engine/llm.js +3 -2
- package/engine/shared.js +1 -1
- package/engine.js +11 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.522 (2026-04-07)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- test isolation — tests no longer pollute production data
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- reconcile failed work items that have attached PRs (#407) (#430)
|
|
4
10
|
|
|
5
11
|
### Other
|
|
6
12
|
- perf: reduce curl timeout to 5s, cache getDispatch() reads
|
package/engine/cleanup.js
CHANGED
|
@@ -431,7 +431,30 @@ function runCleanup(config, verbose = false) {
|
|
|
431
431
|
}
|
|
432
432
|
} catch (e) { log('warn', 'KB watchdog check: ' + e.message); }
|
|
433
433
|
|
|
434
|
-
//
|
|
434
|
+
// 6a. Reconcile failed work items that have an attached PR (#407)
|
|
435
|
+
// If a work item is 'failed' but already has _pr, it should be 'done'.
|
|
436
|
+
for (const project of projects) {
|
|
437
|
+
try {
|
|
438
|
+
const wiPath = projectWorkItemsPath(project);
|
|
439
|
+
const items = safeJson(wiPath) || [];
|
|
440
|
+
let reconciled = 0;
|
|
441
|
+
for (const item of items) {
|
|
442
|
+
if (item.status === shared.WI_STATUS.FAILED && item._pr) {
|
|
443
|
+
item.status = shared.WI_STATUS.DONE;
|
|
444
|
+
if (item.failReason) delete item.failReason;
|
|
445
|
+
if (item.failedAt) delete item.failedAt;
|
|
446
|
+
if (!item.completedAt) item.completedAt = shared.ts();
|
|
447
|
+
reconciled++;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (reconciled > 0) {
|
|
451
|
+
safeWrite(wiPath, items);
|
|
452
|
+
log('info', `Reconciled ${reconciled} failed-with-PR item(s) → done in ${project.name}`);
|
|
453
|
+
}
|
|
454
|
+
} catch (e) { log('warn', 'reconcile failed-with-PR: ' + e.message); }
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// 6b. Migrate legacy work-item statuses to canonical 'done'
|
|
435
458
|
// in-pr, implemented, complete → done (one-time correction per item)
|
|
436
459
|
const LEGACY_DONE_ALIASES = new Set(['in-pr', 'implemented', 'complete']);
|
|
437
460
|
for (const project of projects) {
|
package/engine/lifecycle.js
CHANGED
|
@@ -1012,6 +1012,7 @@ function createReviewFeedbackForAuthor(reviewerAgentId, pr, config) {
|
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
1014
1014
|
function updateMetrics(agentId, dispatchItem, result, taskUsage, prsCreatedCount, model) {
|
|
1015
|
+
if (!agentId || agentId.startsWith('temp-') || agentId === 'agent1' || agentId === 'reviewer' || agentId.startsWith('_test')) return;
|
|
1015
1016
|
|
|
1016
1017
|
const metricsPath = path.join(ENGINE_DIR, 'metrics.json');
|
|
1017
1018
|
mutateJsonFileLocked(metricsPath, metrics => {
|
|
@@ -1371,7 +1372,8 @@ function syncPrdFromPrs(config) {
|
|
|
1371
1372
|
for (const project of allProjects) {
|
|
1372
1373
|
const wiPath = shared.projectWorkItemsPath(project);
|
|
1373
1374
|
const items = safeJson(wiPath) || [];
|
|
1374
|
-
const hasReconcilable = items.some(wi =>
|
|
1375
|
+
const hasReconcilable = items.some(wi =>
|
|
1376
|
+
(wi.status === WI_STATUS.PENDING && !wi._pr) || wi.status === WI_STATUS.FAILED);
|
|
1375
1377
|
if (!hasReconcilable) continue;
|
|
1376
1378
|
let reconciled = 0;
|
|
1377
1379
|
const reconciledItems = mutateJsonFileLocked(wiPath, data => {
|
|
@@ -1388,7 +1390,7 @@ function syncPrdFromPrs(config) {
|
|
|
1388
1390
|
}
|
|
1389
1391
|
}
|
|
1390
1392
|
if (totalReconciled > 0) {
|
|
1391
|
-
log('info', `PR sync: reconciled ${totalReconciled}
|
|
1393
|
+
log('info', `PR sync: reconciled ${totalReconciled} work item(s) to done`);
|
|
1392
1394
|
}
|
|
1393
1395
|
} catch (err) {
|
|
1394
1396
|
// Non-fatal — log and continue
|
package/engine/llm.js
CHANGED
|
@@ -7,11 +7,12 @@ const path = require('path');
|
|
|
7
7
|
const shared = require('./shared');
|
|
8
8
|
const { safeWrite, safeUnlink, uid, runFile, cleanChildEnv, parseStreamJsonOutput, mutateJsonFileLocked } = shared;
|
|
9
9
|
|
|
10
|
-
const MINIONS_DIR =
|
|
11
|
-
const ENGINE_DIR =
|
|
10
|
+
const MINIONS_DIR = shared.MINIONS_DIR;
|
|
11
|
+
const ENGINE_DIR = path.join(MINIONS_DIR, 'engine');
|
|
12
12
|
|
|
13
13
|
function trackEngineUsage(category, usage) {
|
|
14
14
|
if (!usage) return;
|
|
15
|
+
if (category && (category.startsWith('_test') || category.startsWith('test-'))) return;
|
|
15
16
|
try {
|
|
16
17
|
const metricsPath = path.join(ENGINE_DIR, 'metrics.json');
|
|
17
18
|
mutateJsonFileLocked(metricsPath, (metrics) => {
|
package/engine/shared.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
|
-
const MINIONS_DIR = path.resolve(__dirname, '..');
|
|
9
|
+
const MINIONS_DIR = process.env.MINIONS_TEST_DIR || path.resolve(__dirname, '..');
|
|
10
10
|
const PR_LINKS_PATH = path.join(MINIONS_DIR, 'engine', 'pr-links.json');
|
|
11
11
|
const LOG_PATH = path.join(__dirname, 'log.json');
|
|
12
12
|
|
package/engine.js
CHANGED
|
@@ -878,6 +878,16 @@ function reconcileItemsWithPrs(items, allPrs, { onlyIds } = {}) {
|
|
|
878
878
|
if (wi.status !== WI_STATUS.PENDING && wi.status !== WI_STATUS.FAILED) continue;
|
|
879
879
|
if (onlyIds && !onlyIds.has(wi.id)) continue;
|
|
880
880
|
|
|
881
|
+
// Short-circuit: failed item already has a PR attached — mark done directly (#407)
|
|
882
|
+
if (wi.status === WI_STATUS.FAILED && wi._pr) {
|
|
883
|
+
wi.status = WI_STATUS.DONE;
|
|
884
|
+
if (wi.failReason) delete wi.failReason;
|
|
885
|
+
if (wi.failedAt) delete wi.failedAt;
|
|
886
|
+
if (!wi.completedAt) wi.completedAt = ts();
|
|
887
|
+
reconciled++;
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
|
|
881
891
|
let exactPr = allPrs.find(pr => (pr.prdItems || []).includes(wi.id));
|
|
882
892
|
if (!exactPr) {
|
|
883
893
|
const linkedPrId = Object.keys(prLinks).find(prId => prLinks[prId] === wi.id);
|
|
@@ -893,7 +903,7 @@ function reconcileItemsWithPrs(items, allPrs, { onlyIds } = {}) {
|
|
|
893
903
|
// Clear failure artifacts if reconciling a previously failed item
|
|
894
904
|
if (wi.failReason) delete wi.failReason;
|
|
895
905
|
if (wi.failedAt) delete wi.failedAt;
|
|
896
|
-
if (!wi.completedAt) wi.completedAt =
|
|
906
|
+
if (!wi.completedAt) wi.completedAt = ts();
|
|
897
907
|
reconciled++;
|
|
898
908
|
}
|
|
899
909
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.522",
|
|
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"
|