@yemi33/minions 0.1.155 → 0.1.157
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 +25 -0
- package/dashboard/js/render-plans.js +44 -4
- package/dashboard/js/render-prd.js +1 -1
- package/engine/ado.js +1 -13
- package/engine/github.js +2 -14
- package/engine/shared.js +65 -5
- package/engine.js +25 -15
- package/package.json +1 -1
- package/pipelines/daily-standup.json +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.157 (2026-04-02)
|
|
4
|
+
|
|
5
|
+
### Engine
|
|
6
|
+
- engine.js
|
|
7
|
+
- engine/ado.js
|
|
8
|
+
- engine/github.js
|
|
9
|
+
- engine/shared.js
|
|
10
|
+
|
|
11
|
+
### Other
|
|
12
|
+
- pipelines/daily-standup.json
|
|
13
|
+
- test/unit.test.js
|
|
14
|
+
|
|
15
|
+
## 0.1.156 (2026-04-02)
|
|
16
|
+
|
|
17
|
+
### Engine
|
|
18
|
+
- engine.js
|
|
19
|
+
- engine/shared.js
|
|
20
|
+
|
|
21
|
+
### Dashboard
|
|
22
|
+
- dashboard/js/render-plans.js
|
|
23
|
+
- dashboard/js/render-prd.js
|
|
24
|
+
|
|
25
|
+
### Other
|
|
26
|
+
- test/unit.test.js
|
|
27
|
+
|
|
3
28
|
## 0.1.155 (2026-04-02)
|
|
4
29
|
|
|
5
30
|
### Engine
|
|
@@ -66,9 +66,7 @@ function derivePlanStatus(prdFile, mdFile, prdJsonStatus, workItems) {
|
|
|
66
66
|
const implementWi = wi.filter(w => w.type !== 'plan-to-prd' && w.type !== 'verify');
|
|
67
67
|
const hasPendingPrd = wi.some(w => w.type === 'plan-to-prd' && (w.status === 'pending' || w.status === 'dispatched'));
|
|
68
68
|
const hasActiveWork = implementWi.some(w => w.status === 'pending' || w.status === 'dispatched');
|
|
69
|
-
const allDone = implementWi.length > 0 && implementWi.every(w =>
|
|
70
|
-
w.status === 'done'
|
|
71
|
-
);
|
|
69
|
+
const allDone = implementWi.length > 0 && implementWi.every(w => w.status === 'done');
|
|
72
70
|
const hasFailed = implementWi.some(w => w.status === 'failed');
|
|
73
71
|
|
|
74
72
|
// User-set statuses take priority when no work has started
|
|
@@ -304,6 +302,48 @@ function openArchivedPlansModal() {
|
|
|
304
302
|
document.getElementById('modal').classList.add('open');
|
|
305
303
|
}
|
|
306
304
|
|
|
305
|
+
// Disable all PRD action buttons to prevent double-clicks
|
|
306
|
+
function qaDisablePrdButtons() {
|
|
307
|
+
const container = document.getElementById('qa-generate-prd-btn');
|
|
308
|
+
if (container) container.querySelectorAll('button').forEach(b => { b.disabled = true; b.style.opacity = '0.5'; });
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Show plan version action buttons (Run alongside / Replace / Just save)
|
|
312
|
+
function showPlanVersionActions(thread, newFile, originalFile) {
|
|
313
|
+
const esc = newFile.replace(/'/g, "\\'");
|
|
314
|
+
// Look up existing PRD for the original plan's project
|
|
315
|
+
const allPlans = window._lastStatus?.plans || [];
|
|
316
|
+
const origPlan = allPlans.find(p => p.file === originalFile);
|
|
317
|
+
const project = origPlan?.project || '';
|
|
318
|
+
const existingPrd = allPlans.find(p => p.file.endsWith('.json') && p.project === project && p.status !== 'completed');
|
|
319
|
+
|
|
320
|
+
const btn = document.createElement('div');
|
|
321
|
+
btn.id = 'qa-generate-prd-btn';
|
|
322
|
+
btn.style.cssText = 'margin:8px 0;padding:8px 12px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:6px;display:flex;flex-wrap:wrap;align-items:center;gap:8px';
|
|
323
|
+
|
|
324
|
+
if (existingPrd) {
|
|
325
|
+
btn.innerHTML = '<span style="color:var(--green);font-weight:600;font-size:12px;width:100%">New plan version created — existing PRD running</span>' +
|
|
326
|
+
'<button onclick="qaNewPrd(\'' + esc + '\')" style="background:var(--green);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer" title="Execute this plan as a separate PRD alongside the current one">Run alongside</button>' +
|
|
327
|
+
'<button onclick="qaReplacePrd(\'' + esc + '\')" style="background:var(--orange);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer" title="Pause existing PRD, clean pending items, execute this plan instead">Replace old PRD</button>' +
|
|
328
|
+
'<button onclick="qaJustSave(this)" style="background:var(--surface2);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:4px 12px;font-size:11px;cursor:pointer" title="Keep the new version saved without dispatching any work">Just save</button>' +
|
|
329
|
+
'<span style="color:var(--muted);font-size:10px;width:100%">Run alongside keeps current work going. Replace pauses it and starts fresh.</span>';
|
|
330
|
+
} else {
|
|
331
|
+
btn.innerHTML = '<span style="color:var(--green);font-weight:600;font-size:12px;width:100%">New plan version created</span>' +
|
|
332
|
+
'<button onclick="qaNewPrd(\'' + esc + '\')" style="background:var(--green);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer">Execute plan</button>' +
|
|
333
|
+
'<button onclick="qaJustSave(this)" style="background:var(--surface2);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:4px 12px;font-size:11px;cursor:pointer">Just save</button>' +
|
|
334
|
+
'<span style="color:var(--muted);font-size:10px">Execute dispatches an agent to create PRD items from this plan</span>';
|
|
335
|
+
}
|
|
336
|
+
// Remove any previous action buttons
|
|
337
|
+
const old = thread.querySelector('#qa-generate-prd-btn');
|
|
338
|
+
if (old) old.remove();
|
|
339
|
+
thread.appendChild(btn);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function qaJustSave(el) {
|
|
343
|
+
const container = el.closest('#qa-generate-prd-btn');
|
|
344
|
+
if (container) container.innerHTML = '<span style="color:var(--muted);font-size:11px">Saved. No work dispatched.</span>';
|
|
345
|
+
}
|
|
346
|
+
|
|
307
347
|
async function planExecute(file, project, btn) {
|
|
308
348
|
if (btn) { btn.textContent = 'Executing...'; btn.disabled = true; btn.style.color = 'var(--blue)'; }
|
|
309
349
|
try {
|
|
@@ -694,4 +734,4 @@ async function planUnarchive(file, btn) {
|
|
|
694
734
|
} catch (e) { resetBtn(); alert('Error: ' + e.message); }
|
|
695
735
|
}
|
|
696
736
|
|
|
697
|
-
window.MinionsPlans = { openCreatePlanModal, refreshPlans, derivePlanStatus, renderPlans, openArchivedPlansModal, planExecute, planSubmitRevise, planShowRevise, planHideRevise, planView, planApprove, planArchive, planUnarchive, planDelete, planPause, planReject, planDiscuss, planOpenInDocChat, planRegeneratePRD, openVerifyGuide, triggerVerify };
|
|
737
|
+
window.MinionsPlans = { openCreatePlanModal, refreshPlans, derivePlanStatus, renderPlans, openArchivedPlansModal, qaDisablePrdButtons, showPlanVersionActions, qaJustSave, planExecute, planSubmitRevise, planShowRevise, planHideRevise, planView, planApprove, planArchive, planUnarchive, planDelete, planPause, planReject, planDiscuss, planOpenInDocChat, planRegeneratePRD, openVerifyGuide, triggerVerify };
|
|
@@ -116,7 +116,7 @@ function renderPrdProgress(prog) {
|
|
|
116
116
|
'failed': 'background:rgba(248,81,73,0.15);color:var(--red)',
|
|
117
117
|
'paused': 'background:rgba(139,148,158,0.15);color:var(--muted)',
|
|
118
118
|
};
|
|
119
|
-
const labels = { 'done': 'DONE', 'in-progress': 'WIP', 'failed': 'FAIL', 'paused': 'PAUSED', 'missing': '
|
|
119
|
+
const labels = { 'done': 'DONE', 'in-progress': 'WIP', 'failed': 'FAIL', 'paused': 'PAUSED', 'missing': '\u2014' };
|
|
120
120
|
const style = styles[s] || 'background:var(--surface);color:var(--muted)';
|
|
121
121
|
const label = labels[s] || '—';
|
|
122
122
|
return '<span style="font-size:9px;font-weight:700;padding:2px 6px;border-radius:3px;letter-spacing:0.5px;white-space:nowrap;' + style + '">' + label + '</span>';
|
package/engine/ado.js
CHANGED
|
@@ -386,19 +386,7 @@ async function reconcilePrs(config) {
|
|
|
386
386
|
log('info', `PR reconciliation: added ${prId} (branch: ${branch}${confirmedItemId ? ', linked to ' + confirmedItemId : ''}) to ${project.name}`);
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
|
|
390
|
-
const prLinks = shared.getPrLinks();
|
|
391
|
-
let backfilled = 0;
|
|
392
|
-
for (const pr of existingPrs) {
|
|
393
|
-
const linked = prLinks[pr.id];
|
|
394
|
-
if (linked && !(pr.prdItems || []).includes(linked)) {
|
|
395
|
-
pr.prdItems = Array.isArray(pr.prdItems) ? pr.prdItems : [];
|
|
396
|
-
pr.prdItems.push(linked);
|
|
397
|
-
backfilled++;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (projectAdded > 0 || projectUpdated > 0 || backfilled > 0) {
|
|
389
|
+
if (projectAdded > 0 || projectUpdated > 0) {
|
|
402
390
|
shared.safeWrite(prPath, existingPrs);
|
|
403
391
|
totalAdded += projectAdded;
|
|
404
392
|
if (projectUpdated > 0) log('info', `PR reconciliation: linked ${projectUpdated} existing PR(s) to PRD items in ${project.name}`);
|
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,
|
|
8
|
+
const { exec, getProjects, projectPrPath, projectWorkItemsPath, safeJson, safeWrite, MINIONS_DIR, addPrLink, log, dateStamp } = shared;
|
|
9
9
|
const { getPrs } = require('./queries');
|
|
10
10
|
const path = require('path');
|
|
11
11
|
|
|
@@ -371,19 +371,7 @@ async function reconcilePrs(config) {
|
|
|
371
371
|
log('info', `GitHub PR reconciliation: added ${prId} (branch: ${branch}${confirmedItemId ? ', linked to ' + confirmedItemId : ''}) to ${project.name}`);
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
-
|
|
375
|
-
const prLinks = getPrLinks();
|
|
376
|
-
let backfilled = 0;
|
|
377
|
-
for (const pr of existingPrs) {
|
|
378
|
-
const linked = prLinks[pr.id];
|
|
379
|
-
if (linked && !(pr.prdItems || []).includes(linked)) {
|
|
380
|
-
pr.prdItems = Array.isArray(pr.prdItems) ? pr.prdItems : [];
|
|
381
|
-
pr.prdItems.push(linked);
|
|
382
|
-
backfilled++;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (projectAdded > 0 || backfilled > 0) {
|
|
374
|
+
if (projectAdded > 0) {
|
|
387
375
|
safeWrite(prPath, existingPrs);
|
|
388
376
|
totalAdded += projectAdded;
|
|
389
377
|
}
|
package/engine/shared.js
CHANGED
|
@@ -404,10 +404,26 @@ function projectStateDir(project) {
|
|
|
404
404
|
return dir;
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
+
const CENTRAL_WI_PATH = path.join(MINIONS_DIR, 'work-items.json');
|
|
408
|
+
|
|
407
409
|
function projectWorkItemsPath(project) {
|
|
408
410
|
return path.join(projectStateDir(project), 'work-items.json');
|
|
409
411
|
}
|
|
410
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Resolve work-items.json path from dispatch meta.
|
|
415
|
+
* Central items → CENTRAL_WI_PATH; project items → projects/<name>/work-items.json.
|
|
416
|
+
*/
|
|
417
|
+
function resolveWiPath(meta) {
|
|
418
|
+
if (meta.source === 'central-work-item' || meta.source === 'central-work-item-fanout') {
|
|
419
|
+
return CENTRAL_WI_PATH;
|
|
420
|
+
}
|
|
421
|
+
if (meta.project?.name) {
|
|
422
|
+
return path.join(MINIONS_DIR, 'projects', meta.project.name, 'work-items.json');
|
|
423
|
+
}
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
|
|
411
427
|
function projectPrPath(project) {
|
|
412
428
|
return path.join(projectStateDir(project), 'pull-requests.json');
|
|
413
429
|
}
|
|
@@ -501,15 +517,55 @@ function parseSkillFrontmatter(content, filename) {
|
|
|
501
517
|
// Never touched by polling loops — only written when a PR is first linked to a PRD item.
|
|
502
518
|
|
|
503
519
|
function getPrLinks() {
|
|
504
|
-
|
|
520
|
+
// Derive from PR.prdItems (single source of truth)
|
|
521
|
+
const links = {};
|
|
522
|
+
try {
|
|
523
|
+
const projects = getProjects();
|
|
524
|
+
for (const project of projects) {
|
|
525
|
+
const prs = safeJson(projectPrPath(project)) || [];
|
|
526
|
+
for (const pr of prs) {
|
|
527
|
+
for (const itemId of (pr.prdItems || [])) {
|
|
528
|
+
if (!links[pr.id]) links[pr.id] = itemId;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
} catch { /* optional */ }
|
|
533
|
+
return links;
|
|
505
534
|
}
|
|
506
535
|
|
|
507
536
|
function addPrLink(prId, itemId) {
|
|
508
537
|
if (!prId || !itemId) return;
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
538
|
+
try {
|
|
539
|
+
const projects = getProjects();
|
|
540
|
+
for (const project of projects) { linkPrToItem(project, prId, itemId); }
|
|
541
|
+
} catch { /* optional */ }
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Locked mutation of a project's pull-requests.json.
|
|
546
|
+
* Single source of truth for PR data including prdItems links.
|
|
547
|
+
*/
|
|
548
|
+
function mutatePrs(project, mutateFn) {
|
|
549
|
+
const prPath = projectPrPath(project);
|
|
550
|
+
return mutateJsonFileLocked(prPath, (prs) => {
|
|
551
|
+
return mutateFn(Array.isArray(prs) ? prs : []);
|
|
552
|
+
}, { defaultValue: [] });
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Link a PR to a work item via PR.prdItems (single source of truth).
|
|
557
|
+
* Uses file-locked mutation to prevent race conditions.
|
|
558
|
+
*/
|
|
559
|
+
function linkPrToItem(project, prId, itemId) {
|
|
560
|
+
if (!prId || !itemId) return;
|
|
561
|
+
mutatePrs(project, (prs) => {
|
|
562
|
+
const pr = prs.find(p => p.id === prId);
|
|
563
|
+
if (pr) {
|
|
564
|
+
pr.prdItems = Array.isArray(pr.prdItems) ? pr.prdItems : [];
|
|
565
|
+
if (!pr.prdItems.includes(itemId)) pr.prdItems.push(itemId);
|
|
566
|
+
}
|
|
567
|
+
return prs;
|
|
568
|
+
});
|
|
513
569
|
}
|
|
514
570
|
|
|
515
571
|
module.exports = {
|
|
@@ -545,10 +601,14 @@ module.exports = {
|
|
|
545
601
|
getProjects,
|
|
546
602
|
projectRoot,
|
|
547
603
|
projectStateDir,
|
|
604
|
+
CENTRAL_WI_PATH,
|
|
548
605
|
projectWorkItemsPath,
|
|
606
|
+
resolveWiPath,
|
|
549
607
|
projectPrPath,
|
|
550
608
|
getPrLinks,
|
|
551
609
|
addPrLink,
|
|
610
|
+
mutatePrs,
|
|
611
|
+
linkPrToItem,
|
|
552
612
|
nextWorkItemId,
|
|
553
613
|
getAdoOrgBase,
|
|
554
614
|
sanitizePath,
|
package/engine.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
const fs = require('fs');
|
|
25
25
|
const path = require('path');
|
|
26
26
|
const shared = require('./engine/shared');
|
|
27
|
-
const { exec, execSilent, runFile, ENGINE_DEFAULTS: DEFAULTS } = shared;
|
|
27
|
+
const { exec, execSilent, runFile, ENGINE_DEFAULTS: DEFAULTS, CENTRAL_WI_PATH, resolveWiPath } = shared;
|
|
28
28
|
const queries = require('./engine/queries');
|
|
29
29
|
|
|
30
30
|
// ─── Paths ──────────────────────────────────────────────────────────────────
|
|
@@ -307,7 +307,7 @@ function spawnAgent(dispatchItem, config) {
|
|
|
307
307
|
|
|
308
308
|
if (isSharedBranch) {
|
|
309
309
|
log('info', `Creating worktree for shared branch: ${worktreePath} on ${branchName}`);
|
|
310
|
-
try { exec(`git fetch origin "${branchName}"`, { ..._gitOpts, cwd: rootDir }); } catch (e) { log('warn', 'git: ' + e.message); }
|
|
310
|
+
try { exec(`git fetch origin "${branchName}"`, { ..._gitOpts, cwd: rootDir }); } catch (e) { log('warn', 'git fetch: ' + e.message); }
|
|
311
311
|
try {
|
|
312
312
|
runWorktreeAdd(rootDir, worktreePath, `"${branchName}"`, _worktreeGitOpts, worktreeCreateRetries);
|
|
313
313
|
} catch (eShared) {
|
|
@@ -317,6 +317,11 @@ function spawnAgent(dispatchItem, config) {
|
|
|
317
317
|
log('info', `Shared branch ${branchName} already checked out at ${existingWtPath} — reusing`);
|
|
318
318
|
worktreePath = existingWtPath;
|
|
319
319
|
} else { throw eShared; }
|
|
320
|
+
} else if (eShared.message?.includes('invalid reference') || eShared.message?.includes('not a valid branch')) {
|
|
321
|
+
// Branch doesn't exist yet — create it from main
|
|
322
|
+
log('info', `Shared branch ${branchName} not found — creating from ${project.mainBranch || 'main'}`);
|
|
323
|
+
const mainRef = sanitizeBranch(project.mainBranch || 'main');
|
|
324
|
+
runWorktreeAdd(rootDir, worktreePath, `-b "${branchName}" ${mainRef}`, _worktreeGitOpts, worktreeCreateRetries);
|
|
320
325
|
} else { throw eShared; }
|
|
321
326
|
}
|
|
322
327
|
} else {
|
|
@@ -874,7 +879,7 @@ const { COOLDOWN_PATH, dispatchCooldowns, loadCooldowns, saveCooldowns,
|
|
|
874
879
|
// Auto-clean pending/failed work items for a PRD so they re-materialize with updated plan data
|
|
875
880
|
function autoCleanPrdWorkItems(prdFile, config) {
|
|
876
881
|
const allProjects = getProjects(config);
|
|
877
|
-
const wiPaths = [
|
|
882
|
+
const wiPaths = [CENTRAL_WI_PATH];
|
|
878
883
|
for (const proj of allProjects) wiPaths.push(projectWorkItemsPath(proj));
|
|
879
884
|
const deletedIds = [];
|
|
880
885
|
for (const wiPath of wiPaths) {
|
|
@@ -996,8 +1001,7 @@ function materializePlansAsWorkItems(config) {
|
|
|
996
1001
|
const allProjects = getProjects(config);
|
|
997
1002
|
const targetProject = allProjects.find(p => p.name?.toLowerCase() === projectName.toLowerCase()) || allProjects[0];
|
|
998
1003
|
if (targetProject) {
|
|
999
|
-
const
|
|
1000
|
-
const centralItems = safeJson(centralWiPath) || [];
|
|
1004
|
+
const centralItems = safeJson(CENTRAL_WI_PATH) || [];
|
|
1001
1005
|
const alreadyQueued = centralItems.some(w =>
|
|
1002
1006
|
w.type === 'plan-to-prd' && w.planFile === plan.source_plan && (w.status === 'pending' || w.status === 'dispatched')
|
|
1003
1007
|
);
|
|
@@ -1065,7 +1069,7 @@ function materializePlansAsWorkItems(config) {
|
|
|
1065
1069
|
}
|
|
1066
1070
|
}
|
|
1067
1071
|
// Also check central work-items.json
|
|
1068
|
-
for (const w of (safeJson(
|
|
1072
|
+
for (const w of (safeJson(CENTRAL_WI_PATH) || [])) {
|
|
1069
1073
|
if (w.id) allExistingWiIds.add(w.id);
|
|
1070
1074
|
}
|
|
1071
1075
|
const items = plan.missing_features.filter(f =>
|
|
@@ -1110,7 +1114,7 @@ function materializePlansAsWorkItems(config) {
|
|
|
1110
1114
|
|
|
1111
1115
|
let totalCreated = 0;
|
|
1112
1116
|
for (const [projName, { project, items: projItems }] of itemsByProject) {
|
|
1113
|
-
const wiPath = project ? projectWorkItemsPath(project) :
|
|
1117
|
+
const wiPath = project ? projectWorkItemsPath(project) : CENTRAL_WI_PATH;
|
|
1114
1118
|
const existingItems = safeJson(wiPath) || [];
|
|
1115
1119
|
let created = 0;
|
|
1116
1120
|
const newlyCreatedIds = new Set(); // tracks IDs created in this pass for reconciliation scoping
|
|
@@ -1190,9 +1194,17 @@ function materializePlansAsWorkItems(config) {
|
|
|
1190
1194
|
const root = path.resolve(firstProject.localPath);
|
|
1191
1195
|
const mainBranch = firstProject.mainBranch || 'main';
|
|
1192
1196
|
const branch = sanitizeBranch(plan.feature_branch);
|
|
1193
|
-
// Create branch from main
|
|
1194
|
-
|
|
1195
|
-
|
|
1197
|
+
// Create branch from main — verify it actually succeeded
|
|
1198
|
+
try {
|
|
1199
|
+
exec(`git branch "${branch}" "${mainBranch}"`, { cwd: root, stdio: 'pipe', windowsHide: true });
|
|
1200
|
+
} catch (e) {
|
|
1201
|
+
// Branch may already exist — that's fine
|
|
1202
|
+
if (!e.message?.includes('already exists')) throw e;
|
|
1203
|
+
}
|
|
1204
|
+
// Push to remote (best-effort — may not have a remote)
|
|
1205
|
+
try {
|
|
1206
|
+
exec(`git push -u origin "${branch}"`, { cwd: root, stdio: 'pipe', windowsHide: true, timeout: 15000 });
|
|
1207
|
+
} catch { /* no remote or push failed — branch still exists locally */ }
|
|
1196
1208
|
log('info', `Shared branch pre-created: ${branch} for plan ${file}`);
|
|
1197
1209
|
} catch (err) {
|
|
1198
1210
|
log('warn', `Failed to pre-create shared branch for ${file}: ${err.message}`);
|
|
@@ -1755,7 +1767,7 @@ function extractSpecInfo(filePath, projectRoot_) {
|
|
|
1755
1767
|
* Uses the shared work-item.md playbook with multi-project context injected.
|
|
1756
1768
|
*/
|
|
1757
1769
|
function discoverCentralWorkItems(config) {
|
|
1758
|
-
const centralPath =
|
|
1770
|
+
const centralPath = CENTRAL_WI_PATH;
|
|
1759
1771
|
const items = safeJson(centralPath) || [];
|
|
1760
1772
|
const projects = getProjects(config);
|
|
1761
1773
|
const newWork = [];
|
|
@@ -2067,7 +2079,7 @@ function discoverWork(config) {
|
|
|
2067
2079
|
const { discoverScheduledWork } = require('./engine/scheduler');
|
|
2068
2080
|
const scheduledWork = discoverScheduledWork(config);
|
|
2069
2081
|
if (scheduledWork.length > 0) {
|
|
2070
|
-
const centralPath =
|
|
2082
|
+
const centralPath = CENTRAL_WI_PATH;
|
|
2071
2083
|
const items = safeJson(centralPath) || [];
|
|
2072
2084
|
let added = 0;
|
|
2073
2085
|
for (const item of scheduledWork) {
|
|
@@ -2398,9 +2410,7 @@ async function tickInner() {
|
|
|
2398
2410
|
// Defensive: ensure the work item is re-queued if completeDispatch didn't fire
|
|
2399
2411
|
if (item.meta?.item?.id) {
|
|
2400
2412
|
try {
|
|
2401
|
-
const wiPath = item.meta
|
|
2402
|
-
? path.join(ENGINE_DIR, '..', 'work-items.json')
|
|
2403
|
-
: item.meta.project?.name ? projectWorkItemsPath({ name: item.meta.project.name, localPath: item.meta.project.localPath }) : null;
|
|
2413
|
+
const wiPath = resolveWiPath(item.meta);
|
|
2404
2414
|
if (wiPath) {
|
|
2405
2415
|
const items = safeJson(wiPath) || [];
|
|
2406
2416
|
const wi = items.find(i => i.id === item.meta.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.157",
|
|
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"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "daily-standup",
|
|
3
|
+
"title": "Daily Squad Stand-up",
|
|
4
|
+
"stages": [
|
|
5
|
+
{
|
|
6
|
+
"id": "standup",
|
|
7
|
+
"type": "meeting",
|
|
8
|
+
"title": "Daily Squad Stand-up � 2026-04-01",
|
|
9
|
+
"agenda": "Daily weekday meeting for all agents to review squad setup improvements and discuss progress on agentic harness engineering.\n\n1. What shipped since yesterday's meeting (Track A/B/C progress)?\n2. Any blockers on current work items?\n3. Review recent agentic harness engineering best practices � are there new Anthropic articles or model improvements that change our assumptions?\n4. Propose 1 concrete improvement each agent wants to make to the squad harness this week.\n5. Agree on today's priorities and any re-sequencing needed.\n\nOutput: a bulleted list of decisions made, action items with owners, and any updated priorities.",
|
|
10
|
+
"participants": [
|
|
11
|
+
"all"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"trigger": {
|
|
16
|
+
"cron": "0 9 1,2,3,4,5"
|
|
17
|
+
},
|
|
18
|
+
"enabled": true
|
|
19
|
+
}
|