@yemi33/minions 0.1.2151 → 0.1.2152
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/engine/lifecycle.js +89 -0
- package/package.json +1 -1
package/engine/lifecycle.js
CHANGED
|
@@ -546,6 +546,64 @@ function resolveWorkItemPath(meta) {
|
|
|
546
546
|
return null;
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
+
function getWorkItemPaths(config) {
|
|
550
|
+
const paths = [path.join(MINIONS_DIR, 'work-items.json')];
|
|
551
|
+
for (const p of shared.getProjects(config || {})) {
|
|
552
|
+
if (p && p.name) paths.push(shared.projectWorkItemsPath(p));
|
|
553
|
+
}
|
|
554
|
+
return paths;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function findWorkItemRecord(itemId, config) {
|
|
558
|
+
if (!itemId) return null;
|
|
559
|
+
for (const wiPath of getWorkItemPaths(config)) {
|
|
560
|
+
try {
|
|
561
|
+
const items = readOptionalJsonStrict(wiPath, 'work-items', Array.isArray) || [];
|
|
562
|
+
const item = items.find(i => i && i.id === itemId);
|
|
563
|
+
if (item) return { item, path: wiPath };
|
|
564
|
+
} catch { /* best-effort lineage lookup */ }
|
|
565
|
+
}
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function resolveWorkItemScheduleContext(item, config) {
|
|
570
|
+
if (!item || typeof item !== 'object') return {};
|
|
571
|
+
const seen = new Set();
|
|
572
|
+
let current = item;
|
|
573
|
+
let scheduleId = current._scheduleId || current._sourceScheduleId || '';
|
|
574
|
+
let scheduleWorkItemId = current._scheduleId ? current.id : (current._scheduleWorkItemId || '');
|
|
575
|
+
let projectName = current.project || '';
|
|
576
|
+
let parentItemId = current.parent_id || current.parentId || '';
|
|
577
|
+
|
|
578
|
+
while ((!scheduleId || !projectName) && parentItemId && !seen.has(parentItemId)) {
|
|
579
|
+
seen.add(parentItemId);
|
|
580
|
+
const found = findWorkItemRecord(parentItemId, config);
|
|
581
|
+
if (!found?.item) break;
|
|
582
|
+
current = found.item;
|
|
583
|
+
if (!scheduleId && (current._scheduleId || current._sourceScheduleId)) {
|
|
584
|
+
scheduleId = current._scheduleId || current._sourceScheduleId;
|
|
585
|
+
scheduleWorkItemId = current._scheduleId ? current.id : (current._scheduleWorkItemId || current.id);
|
|
586
|
+
}
|
|
587
|
+
if (!projectName && current.project) projectName = current.project;
|
|
588
|
+
parentItemId = current.parent_id || current.parentId || '';
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return {
|
|
592
|
+
scheduleId: scheduleId || '',
|
|
593
|
+
scheduleWorkItemId: scheduleWorkItemId || '',
|
|
594
|
+
projectName: projectName || '',
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function applyScheduleContextToPrEntry(entry, item, config) {
|
|
599
|
+
const ctx = resolveWorkItemScheduleContext(item, config);
|
|
600
|
+
if (ctx.scheduleId) {
|
|
601
|
+
entry._sourceScheduleId = ctx.scheduleId;
|
|
602
|
+
if (ctx.scheduleWorkItemId) entry._scheduleWorkItemId = ctx.scheduleWorkItemId;
|
|
603
|
+
}
|
|
604
|
+
return entry;
|
|
605
|
+
}
|
|
606
|
+
|
|
549
607
|
/** Check if a work item is in a terminal completed state. */
|
|
550
608
|
function isItemCompleted(item) {
|
|
551
609
|
if (!item || typeof item !== 'object') return false;
|
|
@@ -920,6 +978,7 @@ function syncPrsFromOutput(output, agentId, meta, config, opts = {}) {
|
|
|
920
978
|
sourcePlan: meta?.item?.sourcePlan || '',
|
|
921
979
|
itemType: meta?.item?.itemType || ''
|
|
922
980
|
};
|
|
981
|
+
applyScheduleContextToPrEntry(entry, meta?.item, config);
|
|
923
982
|
// Issue #1772: one-off dispatches (e.g. human-initiated "review this PR" via CC)
|
|
924
983
|
// must not enroll the discovered PR into the auto eval loop. Tag _contextOnly so
|
|
925
984
|
// discoverFromPrs skips it for review/fix dispatch (still polled for status/comments).
|
|
@@ -1318,6 +1377,11 @@ function resolvePrFallbackProject(meta, config) {
|
|
|
1318
1377
|
const match = shared.resolveProjectSource(meta.item.project, projects, { allowCentral: false }).project;
|
|
1319
1378
|
if (match) return match;
|
|
1320
1379
|
}
|
|
1380
|
+
const scheduleContext = resolveWorkItemScheduleContext(meta?.item, config);
|
|
1381
|
+
if (scheduleContext.projectName) {
|
|
1382
|
+
const match = shared.resolveProjectSource(scheduleContext.projectName, projects, { allowCentral: false }).project;
|
|
1383
|
+
if (match) return match;
|
|
1384
|
+
}
|
|
1321
1385
|
return projects.length === 1 ? projects[0] : null;
|
|
1322
1386
|
}
|
|
1323
1387
|
|
|
@@ -1488,6 +1552,7 @@ function _attachFoundPrToWi(found, meta, agentId, resultSummary, config) {
|
|
|
1488
1552
|
sourcePlan: meta.item?.sourcePlan || '',
|
|
1489
1553
|
itemType: meta.item?.itemType || '',
|
|
1490
1554
|
};
|
|
1555
|
+
applyScheduleContextToPrEntry(entry, meta?.item, config);
|
|
1491
1556
|
shared.upsertPullRequestRecord(shared.projectPrPath(found.project), entry, {
|
|
1492
1557
|
project: found.project,
|
|
1493
1558
|
itemId: meta.item.id,
|
|
@@ -4184,6 +4249,9 @@ function processCompletionFollowups(completion, agentId, dispatchItem, config) {
|
|
|
4184
4249
|
}
|
|
4185
4250
|
if (raw.length === 0) return [];
|
|
4186
4251
|
const wiId = dispatchItem?.meta?.item?.id || 'N/A';
|
|
4252
|
+
const parentItem = dispatchItem?.meta?.item || null;
|
|
4253
|
+
const parentProject = dispatchItem?.meta?.project?.name || parentItem?.project || '';
|
|
4254
|
+
const parentSchedule = resolveWorkItemScheduleContext(parentItem, config);
|
|
4187
4255
|
let existingIds = null;
|
|
4188
4256
|
function loadExistingIds() {
|
|
4189
4257
|
if (existingIds !== null) return existingIds;
|
|
@@ -4217,6 +4285,27 @@ function processCompletionFollowups(completion, agentId, dispatchItem, config) {
|
|
|
4217
4285
|
if (allIds.size > 0 && !allIds.has(followupWiId)) {
|
|
4218
4286
|
log('warn', `Followup audit (${agentId || 'unknown'} wi=${wiId}): claimed followup ${followupWiId} not found in any work-items.json — dispatch may have been deduped, reverted, or never landed`);
|
|
4219
4287
|
}
|
|
4288
|
+
if (parentItem && (parentSchedule.scheduleId || parentProject)) {
|
|
4289
|
+
let stamped = false;
|
|
4290
|
+
for (const wiPath of getWorkItemPaths(config)) {
|
|
4291
|
+
mutateWorkItems(wiPath, items => {
|
|
4292
|
+
const target = Array.isArray(items) ? items.find(i => i && i.id === followupWiId) : null;
|
|
4293
|
+
if (!target) return items;
|
|
4294
|
+
if (!target.parent_id && target.id !== wiId) target.parent_id = wiId;
|
|
4295
|
+
if (!target.project && parentProject) target.project = parentProject;
|
|
4296
|
+
if (parentSchedule.scheduleId) {
|
|
4297
|
+
if (!target._sourceScheduleId) target._sourceScheduleId = parentSchedule.scheduleId;
|
|
4298
|
+
if (!target._scheduleWorkItemId) target._scheduleWorkItemId = parentSchedule.scheduleWorkItemId || wiId;
|
|
4299
|
+
}
|
|
4300
|
+
stamped = true;
|
|
4301
|
+
return items;
|
|
4302
|
+
});
|
|
4303
|
+
if (stamped) break;
|
|
4304
|
+
}
|
|
4305
|
+
if (stamped && parentSchedule.scheduleId) {
|
|
4306
|
+
log('info', `Followup audit (${agentId || 'unknown'} wi=${wiId}): linked ${followupWiId} to schedule ${parentSchedule.scheduleId}`);
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4220
4309
|
accepted.push({
|
|
4221
4310
|
wi_id: followupWiId,
|
|
4222
4311
|
title,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2152",
|
|
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"
|