@yemi33/minions 0.1.831 → 0.1.833
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 +10 -89
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.833 (2026-04-11)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- stale PRD shows Regenerate PRD + Resume as-is buttons
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
- diff-aware plan-to-prd triggered by Resume, not auto-dispatch
|
|
14
14
|
|
|
15
15
|
### Other
|
|
16
|
+
- remove: /api/prd/regenerate endpoint (destructive delete + fresh gen)
|
|
17
|
+
- refactor: migrate handlePrdRegenerate and handlePlansExecute to queuePlanToPrd
|
|
16
18
|
- refactor: add PRD_ITEM_STATUS/PRD_MATERIALIZABLE constants, extract queuePlanToPrd
|
|
17
19
|
- refactor: remove dead criteria variable, DRY plan resume functions
|
|
18
20
|
|
package/dashboard.js
CHANGED
|
@@ -2362,73 +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 wiPath = path.join(MINIONS_DIR, 'work-items.json');
|
|
2406
|
-
|
|
2407
|
-
const completedContext = completedItems.length > 0
|
|
2408
|
-
? `\n\n**Previously completed items (preserve their status in the new PRD):**\n${completedItems.map(i => `- ${i.id}: ${i.name} [${i.status}]`).join('\n')}`
|
|
2409
|
-
: '';
|
|
2410
|
-
|
|
2411
|
-
const id = 'W-' + shared.uid();
|
|
2412
|
-
let alreadyQueuedId = null;
|
|
2413
|
-
mutateWorkItems(wiPath, items => {
|
|
2414
|
-
// Dedup: check if already queued
|
|
2415
|
-
const alreadyQueued = items.find(w =>
|
|
2416
|
-
w.type === 'plan-to-prd' && w.planFile === plan.source_plan && (w.status === WI_STATUS.PENDING || w.status === WI_STATUS.DISPATCHED)
|
|
2417
|
-
);
|
|
2418
|
-
if (alreadyQueued) { alreadyQueuedId = alreadyQueued.id; return; }
|
|
2419
|
-
items.push({
|
|
2420
|
-
id, title: `Regenerate PRD: ${plan.plan_summary || plan.source_plan}`,
|
|
2421
|
-
type: 'plan-to-prd', priority: 'high',
|
|
2422
|
-
description: `Plan file: plans/${plan.source_plan}\nTarget PRD filename: ${body.file}\nRegeneration requested by user after plan revision.${completedContext}`,
|
|
2423
|
-
status: WI_STATUS.PENDING, created: new Date().toISOString(), createdBy: 'dashboard:regenerate',
|
|
2424
|
-
project: plan.project || '', planFile: plan.source_plan,
|
|
2425
|
-
_targetPrdFile: body.file,
|
|
2426
|
-
});
|
|
2427
|
-
});
|
|
2428
|
-
if (alreadyQueuedId) return jsonReply(res, 200, { id: alreadyQueuedId, alreadyQueued: true });
|
|
2429
|
-
return jsonReply(res, 200, { id, file: plan.source_plan });
|
|
2430
|
-
} catch (e) { return jsonReply(res, 500, { error: e.message }); }
|
|
2431
|
-
}
|
|
2365
|
+
// handlePrdRegenerate removed — destructive delete+regen replaced by diff-aware update via /api/plans/approve
|
|
2432
2366
|
|
|
2433
2367
|
async function handlePlansExecute(req, res) {
|
|
2434
2368
|
if (checkRateLimit('plans-execute', 5)) return jsonReply(res, 429, { error: 'Rate limited — max 5 requests/minute' });
|
|
@@ -2440,28 +2374,15 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
|
|
|
2440
2374
|
const planPath = path.join(MINIONS_DIR, 'plans', body.file);
|
|
2441
2375
|
if (!fs.existsSync(planPath)) return jsonReply(res, 404, { error: 'plan file not found' });
|
|
2442
2376
|
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
const existing = items.find(w => w.type === 'plan-to-prd' && w.planFile === body.file && (w.status === WI_STATUS.PENDING || w.status === WI_STATUS.DISPATCHED));
|
|
2451
|
-
if (existing) { existingId = existing.id; return items; }
|
|
2452
|
-
items.push({
|
|
2453
|
-
id, title: 'Convert plan to PRD: ' + body.file.replace('.md', ''),
|
|
2454
|
-
type: 'plan-to-prd', priority: 'high',
|
|
2455
|
-
description: 'Plan file: plans/' + body.file,
|
|
2456
|
-
status: WI_STATUS.PENDING, created: new Date().toISOString(),
|
|
2457
|
-
createdBy: 'dashboard:execute', project: body.project || '',
|
|
2458
|
-
planFile: body.file,
|
|
2459
|
-
});
|
|
2460
|
-
return items;
|
|
2461
|
-
}, { defaultValue: [] });
|
|
2462
|
-
if (existingId) return jsonReply(res, 200, { ok: true, id: existingId, alreadyQueued: true });
|
|
2377
|
+
const queued = shared.queuePlanToPrd({
|
|
2378
|
+
planFile: body.file,
|
|
2379
|
+
title: 'Convert plan to PRD: ' + body.file.replace('.md', ''),
|
|
2380
|
+
description: 'Plan file: plans/' + body.file,
|
|
2381
|
+
project: body.project || '', createdBy: 'dashboard:execute',
|
|
2382
|
+
});
|
|
2383
|
+
if (!queued) return jsonReply(res, 200, { ok: true, alreadyQueued: true });
|
|
2463
2384
|
invalidateStatusCache();
|
|
2464
|
-
return jsonReply(res, 200, { ok: true
|
|
2385
|
+
return jsonReply(res, 200, { ok: true });
|
|
2465
2386
|
} catch (e) { return jsonReply(res, 400, { error: e.message }); }
|
|
2466
2387
|
}
|
|
2467
2388
|
|
|
@@ -4179,7 +4100,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4179
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 },
|
|
4180
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 },
|
|
4181
4102
|
{ method: 'POST', path: '/api/prd-items/remove', desc: 'Remove a PRD item from plan + cancel materialized work item', params: 'source, itemId', handler: handlePrdItemsRemove },
|
|
4182
|
-
|
|
4103
|
+
// /api/prd/regenerate removed — use /api/plans/approve which does diff-aware update
|
|
4183
4104
|
|
|
4184
4105
|
// Agents
|
|
4185
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.833",
|
|
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"
|