@yemi33/minions 0.1.329 → 0.1.331
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/dashboard/js/render-prs.js +1 -1
- package/dashboard.js +1 -1
- package/engine/ado.js +2 -2
- package/engine/github.js +2 -2
- package/engine/lifecycle.js +144 -55
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.331 (2026-04-03)
|
|
4
4
|
|
|
5
5
|
### Fixes
|
|
6
|
+
- standardize PR created field to ISO format
|
|
7
|
+
|
|
8
|
+
## 0.1.330 (2026-04-03)
|
|
9
|
+
|
|
10
|
+
### Fixes
|
|
11
|
+
- resolve all 25 lifecycle.js test failures
|
|
6
12
|
- remove orphan statuses, add validation, replace in-progress with dispatched
|
|
7
13
|
|
|
8
14
|
## 0.1.328 (2026-04-03)
|
|
@@ -27,7 +27,7 @@ function prRow(pr) {
|
|
|
27
27
|
'<td>' + (sq.reviewer && sq.status !== 'waiting' ? '<span class="pr-agent" title="' + escHtml(sq.note || '') + '">' + escHtml(sq.reviewer) + '</span>' : sq.reviewer && sq.status === 'waiting' ? '<span class="pr-agent" style="color:var(--muted)" title="Vote pending confirmation">' + escHtml(sq.reviewer) + '…</span>' : pr.reviewedBy && pr.reviewedBy.length ? '<span class="pr-agent">' + escHtml(pr.reviewedBy.join(', ')) + '</span>' : '<span style="color:var(--muted);font-size:11px">—</span>') + '</td>' +
|
|
28
28
|
'<td><span class="pr-badge ' + buildClass + '">' + escHtml(buildLabel) + '</span></td>' +
|
|
29
29
|
'<td><span class="pr-badge ' + statusClass + '">' + escHtml(statusLabel) + '</span></td>' +
|
|
30
|
-
'<td><span class="pr-date">' + escHtml(pr.created || '—') + '</span></td>' +
|
|
30
|
+
'<td><span class="pr-date">' + escHtml((pr.created || '—').slice(0, 10)) + '</span></td>' +
|
|
31
31
|
'</tr>';
|
|
32
32
|
}
|
|
33
33
|
|
package/dashboard.js
CHANGED
|
@@ -3458,7 +3458,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
3458
3458
|
branch: '',
|
|
3459
3459
|
reviewStatus: autoObserve ? 'pending' : 'none',
|
|
3460
3460
|
status: autoObserve ? 'active' : 'linked',
|
|
3461
|
-
created: new Date().toISOString()
|
|
3461
|
+
created: new Date().toISOString(),
|
|
3462
3462
|
url,
|
|
3463
3463
|
prdItems: [],
|
|
3464
3464
|
_manual: true,
|
package/engine/ado.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const shared = require('./shared');
|
|
8
|
-
const { exec, getAdoOrgBase, addPrLink, log, dateStamp, PR_STATUS } = shared;
|
|
8
|
+
const { exec, getAdoOrgBase, addPrLink, log, ts, dateStamp, PR_STATUS } = shared;
|
|
9
9
|
const { getPrs } = require('./queries');
|
|
10
10
|
|
|
11
11
|
// Lazy require to avoid circular dependency — only needed for engine().handlePostMerge
|
|
@@ -389,7 +389,7 @@ async function reconcilePrs(config) {
|
|
|
389
389
|
branch,
|
|
390
390
|
reviewStatus: 'pending',
|
|
391
391
|
status: 'active',
|
|
392
|
-
created:
|
|
392
|
+
created: adoPr.creationDate || ts(),
|
|
393
393
|
url: prUrl,
|
|
394
394
|
prdItems: confirmedItemId ? [confirmedItemId] : [],
|
|
395
395
|
});
|
package/engine/github.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const shared = require('./shared');
|
|
8
|
-
const { exec, getProjects, projectPrPath, projectWorkItemsPath, safeJson, safeWrite, MINIONS_DIR, addPrLink, getPrLinks, log, dateStamp, PR_STATUS } = shared;
|
|
8
|
+
const { exec, getProjects, projectPrPath, projectWorkItemsPath, safeJson, safeWrite, MINIONS_DIR, addPrLink, getPrLinks, log, ts, dateStamp, PR_STATUS } = shared;
|
|
9
9
|
const { getPrs } = require('./queries');
|
|
10
10
|
const path = require('path');
|
|
11
11
|
|
|
@@ -373,7 +373,7 @@ async function reconcilePrs(config) {
|
|
|
373
373
|
branch,
|
|
374
374
|
reviewStatus: 'pending',
|
|
375
375
|
status: 'active',
|
|
376
|
-
created:
|
|
376
|
+
created: ghPr.created_at || ts(),
|
|
377
377
|
url: prUrl,
|
|
378
378
|
prdItems: confirmedItemId ? [confirmedItemId] : [],
|
|
379
379
|
});
|
package/engine/lifecycle.js
CHANGED
|
@@ -137,16 +137,28 @@ function checkPlanCompletion(meta, config) {
|
|
|
137
137
|
].filter(Boolean).join('\n');
|
|
138
138
|
|
|
139
139
|
// Write summary to notes/inbox
|
|
140
|
-
const
|
|
141
|
-
shared.
|
|
142
|
-
log('info', `PRD completion summary written to notes/inbox/${
|
|
140
|
+
const summarySlug = `prd-completion-${planFile.replace('.json', '')}`;
|
|
141
|
+
shared.writeToInbox('engine', summarySlug, summary);
|
|
142
|
+
log('info', `PRD completion summary written to notes/inbox/${summarySlug}`);
|
|
143
|
+
|
|
144
|
+
// Persist completed status + _completionNotified via file lock
|
|
145
|
+
mutateJsonFileLocked(planPath, (data) => {
|
|
146
|
+
data.status = PLAN_STATUS.COMPLETED;
|
|
147
|
+
data.completedAt = plan.completedAt;
|
|
148
|
+
data._completionNotified = true;
|
|
149
|
+
return data;
|
|
150
|
+
});
|
|
143
151
|
|
|
144
152
|
// Resolve the primary project for writing new work items (PR, verify)
|
|
145
153
|
const projectName = plan.project;
|
|
146
154
|
const primaryProject = projectName
|
|
147
155
|
? projects.find(p => p.name?.toLowerCase() === projectName?.toLowerCase()) : projects[0];
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
if (!primaryProject) {
|
|
157
|
+
log('warn', `Plan ${planFile}: no primary project found — skipping PR/verify creation`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const wiPath = shared.projectWorkItemsPath(primaryProject);
|
|
161
|
+
const workItems = safeJson(wiPath) || [];
|
|
150
162
|
|
|
151
163
|
// 3. For shared-branch plans, create PR work item
|
|
152
164
|
if (plan.branch_strategy === 'shared-branch' && plan.feature_branch && wiPath) {
|
|
@@ -262,47 +274,94 @@ function checkPlanCompletion(meta, config) {
|
|
|
262
274
|
log('info', `Created verification work item ${verifyId} for plan ${planFile}`);
|
|
263
275
|
}
|
|
264
276
|
|
|
265
|
-
//
|
|
277
|
+
// Archive deferred until verify completes
|
|
278
|
+
|
|
279
|
+
log('info', `PRD ${planFile} completed: ${doneItems.length} done, ${failedItems.length} failed, runtime ${runtimeMin}m`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ─── Archive Plan ───────────────────────────────────────────────────────────
|
|
283
|
+
function archivePlan(planFile, plan, projects, config) {
|
|
284
|
+
const planPath = path.join(PRD_DIR, planFile);
|
|
285
|
+
|
|
286
|
+
// Archive PRD .json to prd/archive/
|
|
266
287
|
const prdArchiveDir = path.join(PRD_DIR, 'archive');
|
|
267
288
|
if (!fs.existsSync(prdArchiveDir)) fs.mkdirSync(prdArchiveDir, { recursive: true });
|
|
268
|
-
shared.safeWrite(planPath, plan); // save completed status first
|
|
269
289
|
try {
|
|
270
|
-
fs.
|
|
271
|
-
|
|
290
|
+
if (fs.existsSync(planPath)) {
|
|
291
|
+
fs.renameSync(planPath, path.join(prdArchiveDir, planFile));
|
|
292
|
+
log('info', `Archived completed PRD: prd/archive/${planFile}`);
|
|
293
|
+
}
|
|
272
294
|
} catch (err) {
|
|
273
295
|
log('warn', `Failed to archive PRD ${planFile}: ${err.message}`);
|
|
274
|
-
shared.safeWrite(planPath, plan);
|
|
275
296
|
}
|
|
276
297
|
|
|
277
|
-
//
|
|
298
|
+
// Archive the source .md plan if it exists
|
|
299
|
+
const projectName = plan.project;
|
|
278
300
|
const planArchiveDir = path.join(PLANS_DIR, 'archive');
|
|
279
301
|
if (!fs.existsSync(planArchiveDir)) fs.mkdirSync(planArchiveDir, { recursive: true });
|
|
280
302
|
try {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
303
|
+
// Direct match by source_plan field or planFile-derived name
|
|
304
|
+
const sourcePlanName = plan.source_plan || planFile.replace(/\.json$/, '.md');
|
|
305
|
+
if (sourcePlanName && fs.existsSync(path.join(PLANS_DIR, sourcePlanName))) {
|
|
306
|
+
try {
|
|
307
|
+
fs.renameSync(path.join(PLANS_DIR, sourcePlanName), path.join(planArchiveDir, sourcePlanName));
|
|
308
|
+
log('info', `Archived source plan: plans/archive/${sourcePlanName}`);
|
|
309
|
+
} catch (err) { log('warn', `Failed to archive plan ${sourcePlanName}: ${err.message}`); }
|
|
310
|
+
} else {
|
|
311
|
+
// Fallback: match by content
|
|
312
|
+
const mdFiles = fs.readdirSync(PLANS_DIR).filter(f => f.endsWith('.md'));
|
|
313
|
+
for (const md of mdFiles) {
|
|
314
|
+
const mdContent = shared.safeRead(path.join(PLANS_DIR, md)) || '';
|
|
315
|
+
if (mdContent.includes(projectName) || mdContent.includes(plan.plan_summary?.slice(0, 40) || '___nomatch___')) {
|
|
316
|
+
try {
|
|
317
|
+
fs.renameSync(path.join(PLANS_DIR, md), path.join(planArchiveDir, md));
|
|
318
|
+
log('info', `Archived source plan: plans/archive/${md}`);
|
|
319
|
+
} catch (err) { log('warn', `Failed to archive plan ${md}: ${err.message}`); }
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
291
322
|
}
|
|
292
323
|
}
|
|
293
324
|
} catch (err) { log('warn', `Plan archive scan: ${err.message}`); }
|
|
294
325
|
|
|
295
|
-
//
|
|
326
|
+
// Clean up ALL worktrees created for this plan's work items (shared-branch + per-item)
|
|
296
327
|
try {
|
|
297
|
-
// Collect all branch slugs: shared-branch + per-item branches + item IDs
|
|
298
328
|
const branchSlugs = new Set();
|
|
299
329
|
if (plan.feature_branch) branchSlugs.add(shared.sanitizeBranch(plan.feature_branch).toLowerCase());
|
|
330
|
+
|
|
331
|
+
// Collect work items for this plan
|
|
332
|
+
let allWorkItems = [];
|
|
333
|
+
for (const p of projects) {
|
|
334
|
+
try {
|
|
335
|
+
const wi = safeJson(shared.projectWorkItemsPath(p)) || [];
|
|
336
|
+
allWorkItems = allWorkItems.concat(wi);
|
|
337
|
+
} catch { /* optional */ }
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const central = safeJson(path.join(MINIONS_DIR, 'work-items.json')) || [];
|
|
341
|
+
for (const w of central) {
|
|
342
|
+
if (!allWorkItems.some(existing => existing.id === w.id)) allWorkItems.push(w);
|
|
343
|
+
}
|
|
344
|
+
} catch { /* optional */ }
|
|
345
|
+
const planItems = allWorkItems.filter(w => w.sourcePlan === planFile);
|
|
346
|
+
const doneItems = planItems.filter(w => DONE_STATUSES.has(w.status));
|
|
347
|
+
|
|
300
348
|
for (const w of doneItems) {
|
|
301
349
|
if (w.branch) branchSlugs.add(shared.sanitizeBranch(w.branch).toLowerCase());
|
|
302
350
|
if (w.id) branchSlugs.add(w.id.toLowerCase());
|
|
303
351
|
}
|
|
304
|
-
|
|
305
|
-
|
|
352
|
+
|
|
353
|
+
// Collect PR branches
|
|
354
|
+
for (const p of projects) {
|
|
355
|
+
try {
|
|
356
|
+
const prs = safeJson(shared.projectPrPath(p)) || [];
|
|
357
|
+
const prLinks = getPrLinks();
|
|
358
|
+
for (const pr of prs) {
|
|
359
|
+
const linkedId = prLinks[pr.id];
|
|
360
|
+
if (linkedId && doneItems.find(w => w.id === linkedId) && pr.branch) {
|
|
361
|
+
branchSlugs.add(shared.sanitizeBranch(pr.branch).toLowerCase());
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
} catch { /* optional */ }
|
|
306
365
|
}
|
|
307
366
|
|
|
308
367
|
let cleanedWt = 0;
|
|
@@ -323,10 +382,8 @@ function checkPlanCompletion(meta, config) {
|
|
|
323
382
|
}
|
|
324
383
|
}
|
|
325
384
|
}
|
|
326
|
-
if (cleanedWt > 0) log('info', `
|
|
385
|
+
if (cleanedWt > 0) log('info', `Archive: cleaned ${cleanedWt} worktree(s)`);
|
|
327
386
|
} catch (err) { log('warn', `Worktree cleanup: ${err.message}`); }
|
|
328
|
-
|
|
329
|
-
log('info', `PRD ${planFile} completed: ${doneItems.length} done, ${failedItems.length} failed, runtime ${runtimeMin}m`);
|
|
330
387
|
}
|
|
331
388
|
|
|
332
389
|
// ─── Plan → PRD Chaining ─────────────────────────────────────────────────────
|
|
@@ -385,6 +442,10 @@ function chainPlanToPrd(dispatchItem, meta, config) {
|
|
|
385
442
|
|
|
386
443
|
const projectName = meta?.item?.project || meta?.project?.name;
|
|
387
444
|
const projects = shared.getProjects(config);
|
|
445
|
+
if (projects.length === 0) {
|
|
446
|
+
log('error', 'Plan chaining: no projects configured');
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
388
449
|
const targetProject = projectName
|
|
389
450
|
? projects.find(p => p.name === projectName) || projects[0]
|
|
390
451
|
: projects[0];
|
|
@@ -397,7 +458,10 @@ function chainPlanToPrd(dispatchItem, meta, config) {
|
|
|
397
458
|
log('info', `Plan chaining: queuing plan-to-prd for next tick (chained from ${dispatchItem.id})`);
|
|
398
459
|
const wiPath = path.join(MINIONS_DIR, 'work-items.json');
|
|
399
460
|
let items = [];
|
|
400
|
-
try { items = JSON.parse(fs.readFileSync(wiPath, 'utf8')); } catch {
|
|
461
|
+
try { items = JSON.parse(fs.readFileSync(wiPath, 'utf8')); } catch (err) {
|
|
462
|
+
log('warn', `Failed to parse ${wiPath}: ${err.message}`);
|
|
463
|
+
try { fs.copyFileSync(wiPath, wiPath + '.bak'); } catch {}
|
|
464
|
+
}
|
|
401
465
|
items.push({
|
|
402
466
|
id: 'W-' + shared.uid(),
|
|
403
467
|
title: `Convert plan to PRD: ${meta?.item?.title || planFile.name}`,
|
|
@@ -549,6 +613,7 @@ function syncPrsFromOutput(output, agentId, meta, config) {
|
|
|
549
613
|
if (prMatches.size === 0) return 0;
|
|
550
614
|
|
|
551
615
|
const projects = shared.getProjects(config);
|
|
616
|
+
if (projects.length === 0 && !meta?.project?.name) return 0;
|
|
552
617
|
const defaultProject = (meta?.project?.name && projects.find(p => p.name === meta.project.name)) || projects[0];
|
|
553
618
|
const useCentral = !defaultProject;
|
|
554
619
|
|
|
@@ -577,8 +642,9 @@ function syncPrsFromOutput(output, agentId, meta, config) {
|
|
|
577
642
|
const agentName = config.agents?.[agentId]?.name || agentId;
|
|
578
643
|
let added = 0;
|
|
579
644
|
const centralPrPath = path.join(MINIONS_DIR, 'pull-requests.json');
|
|
580
|
-
|
|
581
|
-
|
|
645
|
+
|
|
646
|
+
// Group new PRs by target file path
|
|
647
|
+
const newPrsByPath = new Map(); // prPath -> [{ prId, newEntry }]
|
|
582
648
|
|
|
583
649
|
for (const prId of prMatches) {
|
|
584
650
|
const fullId = `PR-${prId}`;
|
|
@@ -586,38 +652,47 @@ function syncPrsFromOutput(output, agentId, meta, config) {
|
|
|
586
652
|
const targetName = targetProject ? targetProject.name : '_central';
|
|
587
653
|
const prPath = targetProject ? shared.projectPrPath(targetProject) : centralPrPath;
|
|
588
654
|
|
|
589
|
-
// Load PRs for this target (cache per target)
|
|
590
|
-
if (!dirtyTargets.has(targetName)) {
|
|
591
|
-
dirtyTargets.set(targetName, { prs: safeJson(prPath) || [], prPath });
|
|
592
|
-
}
|
|
593
|
-
const entry = dirtyTargets.get(targetName);
|
|
594
|
-
if (entry.prs.some(p => p.id === fullId || String(p.id).includes(prId))) continue;
|
|
595
|
-
|
|
596
655
|
let title = meta?.item?.title || '';
|
|
597
656
|
const titleMatch = output.match(new RegExp(`${prId}[^\\n]*?[—–-]\\s*([^\\n]+)`, 'i'));
|
|
598
657
|
if (titleMatch) title = titleMatch[1].trim();
|
|
599
658
|
if (title.includes('session_id') || title.includes('is_error') || title.includes('uuid') || title.length > 120) {
|
|
600
659
|
title = meta?.item?.title || '';
|
|
601
660
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
661
|
+
|
|
662
|
+
if (!newPrsByPath.has(prPath)) newPrsByPath.set(prPath, { name: targetName, entries: [] });
|
|
663
|
+
newPrsByPath.get(prPath).entries.push({
|
|
664
|
+
prId, fullId,
|
|
665
|
+
entry: {
|
|
666
|
+
id: fullId,
|
|
667
|
+
title: (title || `PR created by ${agentName}`).slice(0, 120),
|
|
668
|
+
agent: agentName,
|
|
669
|
+
branch: meta?.branch || '',
|
|
670
|
+
reviewStatus: 'pending',
|
|
671
|
+
status: PR_STATUS.ACTIVE,
|
|
672
|
+
created: ts(),
|
|
673
|
+
url: extractPrUrl(prId),
|
|
674
|
+
prdItems: meta?.item?.id ? [meta.item.id] : [],
|
|
675
|
+
sourcePlan: meta?.item?.sourcePlan || '',
|
|
676
|
+
itemType: meta?.item?.itemType || ''
|
|
677
|
+
}
|
|
614
678
|
});
|
|
615
|
-
if (meta?.item?.id) addPrLink(fullId, meta.item.id);
|
|
616
|
-
added++;
|
|
617
679
|
}
|
|
618
680
|
|
|
619
|
-
for (const [name,
|
|
620
|
-
|
|
681
|
+
for (const [prPath, { name, entries }] of newPrsByPath) {
|
|
682
|
+
mutateJsonFileLocked(prPath, (data) => {
|
|
683
|
+
const prs = Array.isArray(data) ? data : [];
|
|
684
|
+
// Normalize legacy YYYY-MM-DD created dates to ISO
|
|
685
|
+
for (const p of prs) {
|
|
686
|
+
if (p.created && p.created.length === 10) p.created = p.created + 'T00:00:00.000Z';
|
|
687
|
+
}
|
|
688
|
+
for (const { prId, fullId, entry } of entries) {
|
|
689
|
+
if (prs.some(p => p.id === fullId || String(p.id) === String(prId))) continue;
|
|
690
|
+
prs.push(entry);
|
|
691
|
+
if (meta?.item?.id) addPrLink(fullId, meta.item.id);
|
|
692
|
+
added++;
|
|
693
|
+
}
|
|
694
|
+
return prs;
|
|
695
|
+
});
|
|
621
696
|
log('info', `Synced PR(s) from ${agentName}'s output to ${name === '_central' ? 'central' : name}/pull-requests.json`);
|
|
622
697
|
}
|
|
623
698
|
return added;
|
|
@@ -662,7 +737,7 @@ function updatePrAfterReview(agentId, pr, project) {
|
|
|
662
737
|
}
|
|
663
738
|
|
|
664
739
|
shared.safeWrite(project ? shared.projectPrPath(project) : path.join(path.resolve(MINIONS_DIR, '..'), '.minions', 'pull-requests.json'), prs);
|
|
665
|
-
log('info', `Updated ${pr.id} → minions review: ${
|
|
740
|
+
log('info', `Updated ${pr.id} → minions review: ${target.reviewStatus} by ${reviewerName}`);
|
|
666
741
|
createReviewFeedbackForAuthor(agentId, { ...pr, ...target }, config);
|
|
667
742
|
}
|
|
668
743
|
|
|
@@ -1137,6 +1212,19 @@ function runPostCompletionHooks(dispatchItem, agentId, code, stdout, config) {
|
|
|
1137
1212
|
let prsCreatedCount = 0;
|
|
1138
1213
|
if (isSuccess) prsCreatedCount = syncPrsFromOutput(stdout, agentId, meta, config) || 0;
|
|
1139
1214
|
|
|
1215
|
+
// After verify completes, archive the plan
|
|
1216
|
+
if (isSuccess && meta?.item?.itemType === 'verify' && meta?.item?.sourcePlan) {
|
|
1217
|
+
try {
|
|
1218
|
+
const vPlanFile = meta.item.sourcePlan;
|
|
1219
|
+
const vPlanPath = path.join(PRD_DIR, vPlanFile);
|
|
1220
|
+
const vPlan = safeJson(vPlanPath);
|
|
1221
|
+
if (vPlan) {
|
|
1222
|
+
const vProjects = shared.getProjects(config);
|
|
1223
|
+
archivePlan(vPlanFile, vPlan, vProjects, config);
|
|
1224
|
+
}
|
|
1225
|
+
} catch (err) { log('warn', `Verify archive: ${err.message}`); }
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1140
1228
|
// Clean up worktree for non-shared-branch tasks after completion
|
|
1141
1229
|
if (meta?.branch && meta?.branchStrategy !== 'shared-branch') {
|
|
1142
1230
|
try {
|
|
@@ -1263,6 +1351,7 @@ function syncPrdFromPrs(config) {
|
|
|
1263
1351
|
|
|
1264
1352
|
module.exports = {
|
|
1265
1353
|
checkPlanCompletion,
|
|
1354
|
+
archivePlan,
|
|
1266
1355
|
updateWorkItemStatus,
|
|
1267
1356
|
syncPrdItemStatus,
|
|
1268
1357
|
syncPrsFromOutput,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.331",
|
|
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"
|