@yemi33/minions 0.1.832 → 0.1.834
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 +3 -1
- package/dashboard.js +2 -56
- package/engine.js +3 -36
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.834 (2026-04-11)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- stale PRD shows Regenerate PRD + Resume as-is buttons
|
|
7
7
|
|
|
8
8
|
### Fixes
|
|
9
|
+
- engine only flags stale on plan revision, never auto-regenerates
|
|
9
10
|
- only 'updated' re-opens done work items, remove 'planned' status
|
|
10
11
|
- revert doc-chat MAX_HEIGHT to 500px
|
|
11
12
|
- hide plan card action buttons when stale banner is showing
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
- diff-aware plan-to-prd triggered by Resume, not auto-dispatch
|
|
14
15
|
|
|
15
16
|
### Other
|
|
17
|
+
- remove: /api/prd/regenerate endpoint (destructive delete + fresh gen)
|
|
16
18
|
- refactor: migrate handlePrdRegenerate and handlePlansExecute to queuePlanToPrd
|
|
17
19
|
- refactor: add PRD_ITEM_STATUS/PRD_MATERIALIZABLE constants, extract queuePlanToPrd
|
|
18
20
|
- refactor: remove dead criteria variable, DRY plan resume functions
|
package/dashboard.js
CHANGED
|
@@ -2362,61 +2362,7 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
|
|
|
2362
2362
|
} catch (e) { return jsonReply(res, 400, { error: e.message }); }
|
|
2363
2363
|
}
|
|
2364
2364
|
|
|
2365
|
-
|
|
2366
|
-
try {
|
|
2367
|
-
const body = await readBody(req);
|
|
2368
|
-
if (!body.file) return jsonReply(res, 400, { error: 'file is required' });
|
|
2369
|
-
shared.sanitizePath(body.file, PRD_DIR);
|
|
2370
|
-
|
|
2371
|
-
const prdPath = path.join(PRD_DIR, body.file);
|
|
2372
|
-
const plan = safeJson(prdPath);
|
|
2373
|
-
if (!plan) return jsonReply(res, 404, { error: 'PRD file not found' });
|
|
2374
|
-
if (!plan.source_plan) return jsonReply(res, 400, { error: 'PRD has no source_plan — cannot regenerate' });
|
|
2375
|
-
|
|
2376
|
-
const sourcePlanPath = path.join(PLANS_DIR, plan.source_plan);
|
|
2377
|
-
if (!fs.existsSync(sourcePlanPath)) return jsonReply(res, 400, { error: `Source plan not found: ${plan.source_plan}` });
|
|
2378
|
-
|
|
2379
|
-
// Collect completed item IDs from the old PRD to carry over
|
|
2380
|
-
const completedStatuses = new Set(['done', 'in-pr', 'implemented']); // in-pr kept for backward compat
|
|
2381
|
-
const completedItems = (plan.missing_features || [])
|
|
2382
|
-
.filter(f => completedStatuses.has(f.status))
|
|
2383
|
-
.map(f => ({ id: f.id, name: f.name, status: f.status }));
|
|
2384
|
-
|
|
2385
|
-
// Clean pending/failed work items from old PRD (keep done items)
|
|
2386
|
-
const { getProjects, projectWorkItemsPath } = shared;
|
|
2387
|
-
const config = queries.getConfig();
|
|
2388
|
-
for (const p of getProjects(config)) {
|
|
2389
|
-
const projWiPath = projectWorkItemsPath(p);
|
|
2390
|
-
try {
|
|
2391
|
-
mutateWorkItems(projWiPath, items => {
|
|
2392
|
-
const filtered = items.filter(w => {
|
|
2393
|
-
if (w.sourcePlan !== body.file) return true; // different plan, keep
|
|
2394
|
-
return completedStatuses.has(w.status); // keep completed, remove pending/failed
|
|
2395
|
-
});
|
|
2396
|
-
if (filtered.length < items.length) return filtered;
|
|
2397
|
-
});
|
|
2398
|
-
} catch { /* project may not have work items */ }
|
|
2399
|
-
}
|
|
2400
|
-
|
|
2401
|
-
// Delete old PRD — agent will write replacement at same path
|
|
2402
|
-
try { fs.unlinkSync(prdPath); } catch { /* cleanup */ }
|
|
2403
|
-
|
|
2404
|
-
// Queue plan-to-prd regeneration with instructions to preserve completed items
|
|
2405
|
-
const completedContext = completedItems.length > 0
|
|
2406
|
-
? `\n\n**Previously completed items (preserve their status in the new PRD):**\n${completedItems.map(i => `- ${i.id}: ${i.name} [${i.status}]`).join('\n')}`
|
|
2407
|
-
: '';
|
|
2408
|
-
|
|
2409
|
-
const queued = shared.queuePlanToPrd({
|
|
2410
|
-
planFile: plan.source_plan, prdFile: body.file,
|
|
2411
|
-
title: `Regenerate PRD: ${plan.plan_summary || plan.source_plan}`,
|
|
2412
|
-
description: `Plan file: plans/${plan.source_plan}\nTarget PRD filename: ${body.file}\nRegeneration requested by user after plan revision.${completedContext}`,
|
|
2413
|
-
project: plan.project || '', createdBy: 'dashboard:regenerate',
|
|
2414
|
-
extra: { _targetPrdFile: body.file },
|
|
2415
|
-
});
|
|
2416
|
-
if (!queued) return jsonReply(res, 200, { alreadyQueued: true });
|
|
2417
|
-
return jsonReply(res, 200, { ok: true, file: plan.source_plan });
|
|
2418
|
-
} catch (e) { return jsonReply(res, 500, { error: e.message }); }
|
|
2419
|
-
}
|
|
2365
|
+
// handlePrdRegenerate removed — destructive delete+regen replaced by diff-aware update via /api/plans/approve
|
|
2420
2366
|
|
|
2421
2367
|
async function handlePlansExecute(req, res) {
|
|
2422
2368
|
if (checkRateLimit('plans-execute', 5)) return jsonReply(res, 429, { error: 'Rate limited — max 5 requests/minute' });
|
|
@@ -4154,7 +4100,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4154
4100
|
{ method: 'POST', path: '/api/prd-items', desc: 'Create a PRD item as a plan file in prd/ (auto-approved)', params: 'name, description?, priority?, estimated_complexity?, project?, id?', handler: handlePrdItemsCreate },
|
|
4155
4101
|
{ method: 'POST', path: '/api/prd-items/update', desc: 'Edit a PRD item in its source plan JSON', params: 'source, itemId, name?, description?, priority?, estimated_complexity?, status?', handler: handlePrdItemsUpdate },
|
|
4156
4102
|
{ method: 'POST', path: '/api/prd-items/remove', desc: 'Remove a PRD item from plan + cancel materialized work item', params: 'source, itemId', handler: handlePrdItemsRemove },
|
|
4157
|
-
|
|
4103
|
+
// /api/prd/regenerate removed — use /api/plans/approve which does diff-aware update
|
|
4158
4104
|
|
|
4159
4105
|
// Agents
|
|
4160
4106
|
{ method: 'POST', path: '/api/pull-requests/link', desc: 'Manually link an external PR for tracking', params: 'url, title?, project?, autoObserve?, context?', handler: async (req, res) => {
|
package/engine.js
CHANGED
|
@@ -1331,43 +1331,10 @@ function materializePlansAsWorkItems(config) {
|
|
|
1331
1331
|
// Handle PRD based on current status
|
|
1332
1332
|
const prdStatus = plan.status || (plan.requires_approval ? 'awaiting-approval' : null);
|
|
1333
1333
|
|
|
1334
|
-
//
|
|
1335
|
-
if (prdStatus
|
|
1334
|
+
// Flag stale for all statuses — user decides when to regenerate/resume from dashboard
|
|
1335
|
+
if (prdStatus) {
|
|
1336
1336
|
plan.planStale = true;
|
|
1337
|
-
log('info', `PRD ${file} flagged as stale (plan revised while ${prdStatus}) — user can
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
// Awaiting-approval PRDs: auto-regenerate (no work started yet, safe to replace)
|
|
1341
|
-
if (prdStatus === 'awaiting-approval') {
|
|
1342
|
-
log('info', `PRD ${file} invalidated (was awaiting-approval) — queuing regeneration from revised plan`);
|
|
1343
|
-
|
|
1344
|
-
const completedStatuses = new Set(['done', 'in-pr', 'implemented']);
|
|
1345
|
-
const completedItems = (plan.missing_features || [])
|
|
1346
|
-
.filter(f => completedStatuses.has(f.status))
|
|
1347
|
-
.map(f => ({ id: f.id, name: f.name, status: f.status }));
|
|
1348
|
-
|
|
1349
|
-
const completedContext = completedItems.length > 0
|
|
1350
|
-
? `\nPreviously completed items (preserve their status in the new PRD):\n${completedItems.map(i => `- ${i.id}: ${i.name} [${i.status}]`).join('\n')}`
|
|
1351
|
-
: '';
|
|
1352
|
-
|
|
1353
|
-
try { fs.unlinkSync(path.join(PRD_DIR, file)); } catch { /* cleanup */ }
|
|
1354
|
-
|
|
1355
|
-
const planContent = safeRead(path.join(PLANS_DIR, plan.source_plan));
|
|
1356
|
-
if (planContent) {
|
|
1357
|
-
const projectName = plan.project || file.replace(/-\d{4}-\d{2}-\d{2}\.json$/, '');
|
|
1358
|
-
const allProjects = getProjects(config);
|
|
1359
|
-
const targetProject = allProjects.find(p => p.name?.toLowerCase() === projectName.toLowerCase()) || allProjects[0];
|
|
1360
|
-
if (targetProject) {
|
|
1361
|
-
const queued = shared.queuePlanToPrd({
|
|
1362
|
-
planFile: plan.source_plan, prdFile: file,
|
|
1363
|
-
title: `Generate PRD from plan: ${plan.source_plan}`,
|
|
1364
|
-
description: `Plan file: plans/${plan.source_plan}\nSource plan was updated while PRD was awaiting approval — generating fresh PRD.${completedContext}`,
|
|
1365
|
-
project: targetProject.name, createdBy: 'engine:plan-revision',
|
|
1366
|
-
});
|
|
1367
|
-
if (queued) log('info', `Queued plan-to-prd regeneration for revised plan ${plan.source_plan} (${completedItems.length} completed items to carry over)`);
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
continue; // Old PRD deleted — skip safeWrite below
|
|
1337
|
+
log('info', `PRD ${file} flagged as stale (plan revised while ${prdStatus}) — user can regenerate from dashboard`);
|
|
1371
1338
|
}
|
|
1372
1339
|
|
|
1373
1340
|
safeWrite(path.join(PRD_DIR, file), plan);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.834",
|
|
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"
|