@yemi33/minions 0.1.325 → 0.1.327

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.327 (2026-04-03)
4
+
5
+ ### Fixes
6
+ - eliminate all legacy done-status writers, add CANCELLED to WI_STATUS
7
+ - stop writing legacy done aliases, add migration, keep read compat
8
+
3
9
  ## 0.1.325 (2026-04-03)
4
10
 
5
11
  ### Fixes
package/engine/cleanup.js CHANGED
@@ -431,17 +431,17 @@ function runCleanup(config, verbose = false) {
431
431
  }
432
432
  } catch (e) { log('warn', 'KB watchdog check: ' + e.message); }
433
433
 
434
- // 6. Migrate legacy work-item statuses to canonical values
434
+ // 6. Migrate legacy work-item statuses to canonical 'done'
435
435
  // in-pr, implemented, complete → done (one-time correction per item)
436
- const LEGACY_DONE_STATUSES = shared.DONE_STATUSES;
436
+ const LEGACY_DONE_ALIASES = new Set(['in-pr', 'implemented', 'complete']);
437
437
  for (const project of projects) {
438
438
  try {
439
439
  const wiPath = projectWorkItemsPath(project);
440
440
  const items = safeJson(wiPath) || [];
441
441
  let migrated = 0;
442
442
  for (const item of items) {
443
- if (LEGACY_DONE_STATUSES.has(item.status)) {
444
- item.status = 'done';
443
+ if (LEGACY_DONE_ALIASES.has(item.status)) {
444
+ item.status = shared.WI_STATUS.DONE;
445
445
  delete item._pendingReason;
446
446
  migrated++;
447
447
  }
@@ -458,8 +458,8 @@ function runCleanup(config, verbose = false) {
458
458
  const centralItems = safeJson(centralPath) || [];
459
459
  let migrated = 0;
460
460
  for (const item of centralItems) {
461
- if (LEGACY_DONE_STATUSES.has(item.status)) {
462
- item.status = 'done';
461
+ if (LEGACY_DONE_ALIASES.has(item.status)) {
462
+ item.status = shared.WI_STATUS.DONE;
463
463
  delete item._pendingReason;
464
464
  migrated++;
465
465
  }
@@ -485,8 +485,8 @@ function runCleanup(config, verbose = false) {
485
485
  if (!prd?.missing_features) continue;
486
486
  let migrated = 0;
487
487
  for (const feat of prd.missing_features) {
488
- if (LEGACY_DONE_STATUSES.has(feat.status)) {
489
- feat.status = 'done';
488
+ if (LEGACY_DONE_ALIASES.has(feat.status)) {
489
+ feat.status = shared.WI_STATUS.DONE;
490
490
  migrated++;
491
491
  }
492
492
  }
@@ -789,13 +789,13 @@ async function handlePostMerge(pr, project, config, newStatus) {
789
789
  const plan = safeJson(path.join(prdDir, pf));
790
790
  if (!plan?.missing_features) continue;
791
791
  const feature = plan.missing_features.find(f => f.id === mergedItemId);
792
- if (feature && feature.status !== 'implemented') {
793
- feature.status = 'implemented';
792
+ if (feature && feature.status !== WI_STATUS.DONE) {
793
+ feature.status = WI_STATUS.DONE;
794
794
  shared.safeWrite(path.join(prdDir, pf), plan);
795
795
  updated++;
796
796
  }
797
797
  }
798
- if (updated > 0) log('info', `Post-merge: marked ${mergedItemId} as implemented for ${pr.id}`);
798
+ if (updated > 0) log('info', `Post-merge: marked ${mergedItemId} as done for ${pr.id}`);
799
799
  } catch (err) { log('warn', `Post-merge PRD update: ${err.message}`); }
800
800
 
801
801
  // Mark work item as done
@@ -806,9 +806,9 @@ async function handlePostMerge(pr, project, config, newStatus) {
806
806
  const items = safeJson(wiPath);
807
807
  if (!items) continue;
808
808
  const item = items.find(i => i.id === mergedItemId);
809
- if (item && item.status !== 'done') {
809
+ if (item && item.status !== WI_STATUS.DONE) {
810
810
  log('info', `Post-merge: marking work item ${mergedItemId} as done (was ${item.status}) for ${pr.id}`);
811
- item.status = 'done';
811
+ item.status = WI_STATUS.DONE;
812
812
  item.completedAt = ts();
813
813
  item._mergedVia = pr.id;
814
814
  shared.safeWrite(wiPath, items);
@@ -1070,7 +1070,7 @@ function handleDecompositionResult(stdout, meta, config) {
1070
1070
  if (!parent) continue;
1071
1071
 
1072
1072
  // Mark parent as decomposed
1073
- parent.status = 'decomposed';
1073
+ parent.status = WI_STATUS.DECOMPOSED;
1074
1074
  parent._decomposed = true;
1075
1075
  delete parent._decomposing;
1076
1076
  parent._subItemIds = subItems.map(s => s.id);
package/engine/shared.js CHANGED
@@ -393,9 +393,12 @@ const ENGINE_DEFAULTS = {
393
393
 
394
394
  const WI_STATUS = {
395
395
  PENDING: 'pending', DISPATCHED: 'dispatched', DONE: 'done', FAILED: 'failed',
396
- PAUSED: 'paused', QUEUED: 'queued', NEEDS_REVIEW: 'needs-human-review', DECOMPOSED: 'decomposed',
396
+ PAUSED: 'paused', QUEUED: 'queued', NEEDS_REVIEW: 'needs-human-review',
397
+ DECOMPOSED: 'decomposed', CANCELLED: 'cancelled',
397
398
  };
398
- const DONE_STATUSES = new Set([WI_STATUS.DONE, 'in-pr', 'implemented', 'complete']); // includes legacy aliases
399
+ // Read-side: accept legacy aliases for backward compat with old data/clients.
400
+ // Write-side: only WI_STATUS.DONE is written (cleanup.js migrates old values on each run).
401
+ const DONE_STATUSES = new Set([WI_STATUS.DONE, 'in-pr', 'implemented', 'complete']);
399
402
  const WORK_TYPE = {
400
403
  IMPLEMENT: 'implement', IMPLEMENT_LARGE: 'implement:large', FIX: 'fix', REVIEW: 'review',
401
404
  VERIFY: 'verify', PLAN: 'plan', PLAN_TO_PRD: 'plan-to-prd', DECOMPOSE: 'decompose',
package/engine.js CHANGED
@@ -1182,7 +1182,7 @@ function materializePlansAsWorkItems(config) {
1182
1182
  for (const wi of existingItems) {
1183
1183
  if (wi.status !== WI_STATUS.PENDING || wi.sourcePlan !== file) continue;
1184
1184
  if (!currentPrdIds.has(wi.id)) {
1185
- wi.status = 'cancelled';
1185
+ wi.status = WI_STATUS.CANCELLED;
1186
1186
  wi.cancelledAt = ts();
1187
1187
  wi.cancelReason = `PRD item removed from ${file}`;
1188
1188
  cancelled++;
@@ -1504,7 +1504,7 @@ function discoverFromWorkItems(config, project) {
1504
1504
  const cpCount = (item._checkpointCount || 0) + 1;
1505
1505
  if (cpCount > 3) {
1506
1506
  log('warn', `Work item ${item.id} exceeded 3 checkpoint-resumes — marking as needs-human-review`);
1507
- item.status = 'needs-human-review';
1507
+ item.status = WI_STATUS.NEEDS_REVIEW;
1508
1508
  item._checkpointCount = cpCount;
1509
1509
  needsWrite = true;
1510
1510
  continue;
@@ -1918,7 +1918,7 @@ function discoverCentralWorkItems(config) {
1918
1918
  const cpCount = (item._checkpointCount || 0) + 1;
1919
1919
  if (cpCount > 3) {
1920
1920
  log('warn', `Work item ${item.id} exceeded 3 checkpoint-resumes — marking as needs-human-review`);
1921
- item.status = 'needs-human-review';
1921
+ item.status = WI_STATUS.NEEDS_REVIEW;
1922
1922
  item._checkpointCount = cpCount;
1923
1923
  continue;
1924
1924
  }
@@ -2425,7 +2425,7 @@ async function tickInner() {
2425
2425
  const wi = items.find(i => i.id === item.meta.item.id);
2426
2426
  if (wi && wi.status === WI_STATUS.DISPATCHED) {
2427
2427
  // completeDispatch didn't update the work item — re-queue manually
2428
- wi.status = 'pending';
2428
+ wi.status = WI_STATUS.PENDING;
2429
2429
  wi._retryCount = (wi._retryCount || 0) + 1;
2430
2430
  wi._lastRetryReason = 'spawnAgent returned null';
2431
2431
  wi._lastRetryAt = ts();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.325",
3
+ "version": "0.1.327",
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"