@yemi33/minions 0.1.2120 → 0.1.2121

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/engine/shared.js CHANGED
@@ -2242,6 +2242,7 @@ const ENGINE_DEFAULTS = {
2242
2242
  autoFixHumanComments: true, // auto-dispatch fix agents for actionable human PR comments
2243
2243
  autoConsolidateMemory: false, // opt-in: periodically spawn engine/kb-sweep-runner.js from the tick loop (4h cadence). Inbox→notes consolidation already runs every tick via consolidateInbox; this flag only controls the KB sweep.
2244
2244
  prNoOpFixPauseAttempts: 2, // pause one PR automation cause after repeated no-op fixes for unchanged evidence
2245
+ quarantineAutoRecoveryMax: 2, // #2996 follow-up: cap on auto-flipping WORKTREE_DIRTY/WORKTREE_DIVERGENT failures back to pending (the quarantine is self-healing so the next dispatch starts clean; the cap prevents infinite loops if quarantine itself keeps failing).
2245
2246
  completionReportRetentionDays: 90, // retain completion report sidecars beyond capped dispatch history
2246
2247
  completionReportMaxFiles: 5000, // hard cap for completion report sidecars during cleanup
2247
2248
  // P-bfa2c-cors-wildcard: extra Origins permitted to receive an
package/engine.js CHANGED
@@ -5807,6 +5807,52 @@ function discoverFromWorkItems(config, project) {
5807
5807
  }
5808
5808
  }
5809
5809
 
5810
+ // #2996 follow-up: auto-recover from WORKTREE_DIRTY / WORKTREE_DIVERGENT quarantines.
5811
+ // The quarantine is self-healing (dir renamed away, ref backed up, branch reset to
5812
+ // origin), so the next dispatch starts from a clean worktree. Auto-flip to pending up
5813
+ // to ENGINE_DEFAULTS.quarantineAutoRecoveryMax times so WIs without downstream deps and
5814
+ // no human watching don't rot in `failed`. _failureClass is stamped on the WI only by
5815
+ // the force-demote path (engine/dispatch.js); the standard non-retryable path leaves
5816
+ // it on the dispatch record but embeds the class name in failReason — so detection
5817
+ // covers both shapes.
5818
+ if (item.status === WI_STATUS.FAILED && !isItemCompleted(item)) {
5819
+ const fr = String(item.failReason || '');
5820
+ const isQuarantineFail = item._failureClass === FAILURE_CLASS.WORKTREE_DIRTY
5821
+ || item._failureClass === FAILURE_CLASS.WORKTREE_DIVERGENT
5822
+ || /\bWORKTREE_DIRTY\b/.test(fr)
5823
+ || /\bWORKTREE_DIVERGENT\b/.test(fr);
5824
+ if (isQuarantineFail) {
5825
+ item._quarantineRecoveryCount = (item._quarantineRecoveryCount || 0) + 1;
5826
+ const cap = ENGINE_DEFAULTS.quarantineAutoRecoveryMax || 2;
5827
+ if (item._quarantineRecoveryCount <= cap) {
5828
+ const prevReason = item.failReason;
5829
+ item.status = WI_STATUS.PENDING;
5830
+ delete item.failReason;
5831
+ delete item.failedAt;
5832
+ delete item._failureClass;
5833
+ delete item._lastDispatchResult;
5834
+ delete item.dispatched_at;
5835
+ delete item.dispatched_to;
5836
+ delete item._pendingReason;
5837
+ log('info', `Quarantine auto-recovery: ${item.id} → pending (attempt ${item._quarantineRecoveryCount}/${cap}, was: ${prevReason})`);
5838
+ needsWrite = true;
5839
+ // Intentionally do NOT `continue` — fall through to the normal dispatch path
5840
+ // (self-heal of stale completed dedupe + cooldown + dispatch evaluation) just
5841
+ // like the dependency-failed recovery block above. The dedupe + cooldown gates
5842
+ // still throttle how often the next dispatch fires.
5843
+ } else {
5844
+ // Cap hit: leave failed, log once via the gave-up flag so the warn doesn't
5845
+ // fire every tick. _retriesByAgent is untouched — quarantine failures are
5846
+ // environmental, not agent failures.
5847
+ if (!item._quarantineRecoveryGaveUp) {
5848
+ log('warn', `Quarantine auto-recovery: ${item.id} hit cap (${cap}) — leaving failed for human intervention`);
5849
+ item._quarantineRecoveryGaveUp = true;
5850
+ needsWrite = true;
5851
+ }
5852
+ }
5853
+ }
5854
+ }
5855
+
5810
5856
  if (item.status !== WI_STATUS.QUEUED && item.status !== WI_STATUS.PENDING) continue;
5811
5857
 
5812
5858
  // Dependency gate: skip items whose depends_on are not yet met; propagate failure
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.2120",
3
+ "version": "0.1.2121",
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"