@yemi33/minions 0.1.156 → 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 +12 -0
- package/engine/ado.js +1 -13
- package/engine/github.js +2 -14
- package/engine/shared.js +23 -12
- package/engine.js +8 -11
- package/package.json +1 -1
- package/pipelines/daily-standup.json +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
3
15
|
## 0.1.156 (2026-04-02)
|
|
4
16
|
|
|
5
17
|
### Engine
|
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,7 +517,7 @@ 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
|
-
// Derive from PR.prdItems (single source of truth)
|
|
520
|
+
// Derive from PR.prdItems (single source of truth)
|
|
505
521
|
const links = {};
|
|
506
522
|
try {
|
|
507
523
|
const projects = getProjects();
|
|
@@ -514,22 +530,15 @@ function getPrLinks() {
|
|
|
514
530
|
}
|
|
515
531
|
}
|
|
516
532
|
} catch { /* optional */ }
|
|
517
|
-
// Merge legacy pr-links.json for items not yet in PR.prdItems
|
|
518
|
-
try {
|
|
519
|
-
const legacy = JSON.parse(require('fs').readFileSync(PR_LINKS_PATH, 'utf8'));
|
|
520
|
-
for (const [prId, itemId] of Object.entries(legacy)) {
|
|
521
|
-
if (!links[prId]) links[prId] = itemId;
|
|
522
|
-
}
|
|
523
|
-
} catch { /* optional */ }
|
|
524
533
|
return links;
|
|
525
534
|
}
|
|
526
535
|
|
|
527
536
|
function addPrLink(prId, itemId) {
|
|
528
537
|
if (!prId || !itemId) return;
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
538
|
+
try {
|
|
539
|
+
const projects = getProjects();
|
|
540
|
+
for (const project of projects) { linkPrToItem(project, prId, itemId); }
|
|
541
|
+
} catch { /* optional */ }
|
|
533
542
|
}
|
|
534
543
|
|
|
535
544
|
/**
|
|
@@ -592,7 +601,9 @@ module.exports = {
|
|
|
592
601
|
getProjects,
|
|
593
602
|
projectRoot,
|
|
594
603
|
projectStateDir,
|
|
604
|
+
CENTRAL_WI_PATH,
|
|
595
605
|
projectWorkItemsPath,
|
|
606
|
+
resolveWiPath,
|
|
596
607
|
projectPrPath,
|
|
597
608
|
getPrLinks,
|
|
598
609
|
addPrLink,
|
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 ──────────────────────────────────────────────────────────────────
|
|
@@ -879,7 +879,7 @@ const { COOLDOWN_PATH, dispatchCooldowns, loadCooldowns, saveCooldowns,
|
|
|
879
879
|
// Auto-clean pending/failed work items for a PRD so they re-materialize with updated plan data
|
|
880
880
|
function autoCleanPrdWorkItems(prdFile, config) {
|
|
881
881
|
const allProjects = getProjects(config);
|
|
882
|
-
const wiPaths = [
|
|
882
|
+
const wiPaths = [CENTRAL_WI_PATH];
|
|
883
883
|
for (const proj of allProjects) wiPaths.push(projectWorkItemsPath(proj));
|
|
884
884
|
const deletedIds = [];
|
|
885
885
|
for (const wiPath of wiPaths) {
|
|
@@ -1001,8 +1001,7 @@ function materializePlansAsWorkItems(config) {
|
|
|
1001
1001
|
const allProjects = getProjects(config);
|
|
1002
1002
|
const targetProject = allProjects.find(p => p.name?.toLowerCase() === projectName.toLowerCase()) || allProjects[0];
|
|
1003
1003
|
if (targetProject) {
|
|
1004
|
-
const
|
|
1005
|
-
const centralItems = safeJson(centralWiPath) || [];
|
|
1004
|
+
const centralItems = safeJson(CENTRAL_WI_PATH) || [];
|
|
1006
1005
|
const alreadyQueued = centralItems.some(w =>
|
|
1007
1006
|
w.type === 'plan-to-prd' && w.planFile === plan.source_plan && (w.status === 'pending' || w.status === 'dispatched')
|
|
1008
1007
|
);
|
|
@@ -1070,7 +1069,7 @@ function materializePlansAsWorkItems(config) {
|
|
|
1070
1069
|
}
|
|
1071
1070
|
}
|
|
1072
1071
|
// Also check central work-items.json
|
|
1073
|
-
for (const w of (safeJson(
|
|
1072
|
+
for (const w of (safeJson(CENTRAL_WI_PATH) || [])) {
|
|
1074
1073
|
if (w.id) allExistingWiIds.add(w.id);
|
|
1075
1074
|
}
|
|
1076
1075
|
const items = plan.missing_features.filter(f =>
|
|
@@ -1115,7 +1114,7 @@ function materializePlansAsWorkItems(config) {
|
|
|
1115
1114
|
|
|
1116
1115
|
let totalCreated = 0;
|
|
1117
1116
|
for (const [projName, { project, items: projItems }] of itemsByProject) {
|
|
1118
|
-
const wiPath = project ? projectWorkItemsPath(project) :
|
|
1117
|
+
const wiPath = project ? projectWorkItemsPath(project) : CENTRAL_WI_PATH;
|
|
1119
1118
|
const existingItems = safeJson(wiPath) || [];
|
|
1120
1119
|
let created = 0;
|
|
1121
1120
|
const newlyCreatedIds = new Set(); // tracks IDs created in this pass for reconciliation scoping
|
|
@@ -1768,7 +1767,7 @@ function extractSpecInfo(filePath, projectRoot_) {
|
|
|
1768
1767
|
* Uses the shared work-item.md playbook with multi-project context injected.
|
|
1769
1768
|
*/
|
|
1770
1769
|
function discoverCentralWorkItems(config) {
|
|
1771
|
-
const centralPath =
|
|
1770
|
+
const centralPath = CENTRAL_WI_PATH;
|
|
1772
1771
|
const items = safeJson(centralPath) || [];
|
|
1773
1772
|
const projects = getProjects(config);
|
|
1774
1773
|
const newWork = [];
|
|
@@ -2080,7 +2079,7 @@ function discoverWork(config) {
|
|
|
2080
2079
|
const { discoverScheduledWork } = require('./engine/scheduler');
|
|
2081
2080
|
const scheduledWork = discoverScheduledWork(config);
|
|
2082
2081
|
if (scheduledWork.length > 0) {
|
|
2083
|
-
const centralPath =
|
|
2082
|
+
const centralPath = CENTRAL_WI_PATH;
|
|
2084
2083
|
const items = safeJson(centralPath) || [];
|
|
2085
2084
|
let added = 0;
|
|
2086
2085
|
for (const item of scheduledWork) {
|
|
@@ -2411,9 +2410,7 @@ async function tickInner() {
|
|
|
2411
2410
|
// Defensive: ensure the work item is re-queued if completeDispatch didn't fire
|
|
2412
2411
|
if (item.meta?.item?.id) {
|
|
2413
2412
|
try {
|
|
2414
|
-
const wiPath = item.meta
|
|
2415
|
-
? path.join(ENGINE_DIR, '..', 'work-items.json')
|
|
2416
|
-
: item.meta.project?.name ? projectWorkItemsPath({ name: item.meta.project.name, localPath: item.meta.project.localPath }) : null;
|
|
2413
|
+
const wiPath = resolveWiPath(item.meta);
|
|
2417
2414
|
if (wiPath) {
|
|
2418
2415
|
const items = safeJson(wiPath) || [];
|
|
2419
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
|
+
}
|