@yemi33/minions 0.1.2299 → 0.1.2301

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.
@@ -134,7 +134,7 @@ const RENDER_VERSIONS = {
134
134
  prdProgress: 2,
135
135
  prdPrs: 1,
136
136
  inbox: 2,
137
- projects: 3,
137
+ projects: 4,
138
138
  notes: 1,
139
139
  prd: 3,
140
140
  prs: 3,
@@ -91,9 +91,18 @@ function _renderProjectBranch(p) {
91
91
  // unset → 'worktree'). Live is the riskier/special mode (capped to one mutating
92
92
  // dispatch per project, refuses on a dirty tree) so it gets a more prominent
93
93
  // color than the muted worktree pill.
94
+ //
95
+ // Hybrid live-validation: when checkoutMode is 'live' AND p.liveValidationType
96
+ // is set, coding WIs author in isolated worktrees and only the named validation
97
+ // type runs in-place on the live checkout. This is a materially different
98
+ // dispatch profile from full-live, so it gets its own pill.
94
99
  function _renderWorktreeModePill(p) {
95
100
  if (!p) return '';
96
101
  if (p.checkoutMode === 'live') {
102
+ if (p.liveValidationType) {
103
+ const vt = escapeHtml(p.liveValidationType);
104
+ return ' <span class="project-mode-pill project-mode-hybrid" title="Hybrid live-validation — coding work items author in isolated worktrees; only the &quot;' + vt + '&quot; validation type runs in-place on the live checkout (capped to one mutating dispatch, refused on a dirty tree)">⚡ Hybrid · ' + vt + '</span>';
105
+ }
97
106
  return ' <span class="project-mode-pill project-mode-live" title="Live-checkout dispatch mode — agents run in-place inside the project working tree (no isolated worktree); capped to one mutating dispatch and refused on a dirty tree">⚡ Live checkout</span>';
98
107
  }
99
108
  return ' <span class="project-mode-pill project-mode-isolated" title="Worktree dispatch mode (default) — each agent runs in its own git worktree">Worktrees</span>';
@@ -1286,6 +1286,7 @@
1286
1286
  }
1287
1287
  .project-mode-isolated { background: var(--surface); color: var(--muted); border: 1px solid var(--border); }
1288
1288
  .project-mode-live { background: rgba(210,153,34,0.15); color: var(--yellow); border: 1px solid var(--yellow); }
1289
+ .project-mode-hybrid { background: rgba(88,166,255,0.15); color: var(--blue); border: 1px solid var(--blue); }
1289
1290
 
1290
1291
  /* QA tab (W-mpeiwz6k0005bf34-d) — targets / runbooks / runs sections.
1291
1292
  * Reuses surface/border/text tokens defined in :root so the QA page
package/dashboard.js CHANGED
@@ -2719,6 +2719,14 @@ function _buildStatusSlowState() {
2719
2719
  // pill. resolveCheckoutMode honors the legacy worktreeMode field and
2720
2720
  // defaults to 'worktree' when unset (matches engine spawn behavior).
2721
2721
  checkoutMode: shared.resolveCheckoutMode(p),
2722
+ // Surface the hybrid live-validation type (when configured) so the
2723
+ // Projects view can render a distinct "Hybrid" pill: coding WIs author
2724
+ // in isolated worktrees while only the named validation type runs
2725
+ // in-place on the live checkout. Only meaningful when checkoutMode is
2726
+ // 'live'; null otherwise (full-live or worktree projects).
2727
+ liveValidationType: (shared.resolveCheckoutMode(p) === 'live' && p.liveValidation && p.liveValidation.type)
2728
+ ? p.liveValidation.type
2729
+ : null,
2722
2730
  };
2723
2731
  }),
2724
2732
  autoMode: {
@@ -577,7 +577,7 @@ function isRetryableFailureReason(reason = '', failureClass = '') {
577
577
  FAILURE_CLASS.INVALID_MANAGED_SPAWN, // W-mpbhxg3b000u8411 — managed-spawn.json failed validation; re-running with the same wrong file won't fix it
578
578
  FAILURE_CLASS.MANAGED_SPAWN_HEALTHCHECK_FAILED, // W-mpbhxg3b000u8411 — healthcheck timed out; agent must fix the spec or the service it spawned
579
579
  FAILURE_CLASS.INJECTION_FLAGGED, // F5 (W-mpeklod3000we69c) — agent spotted a prompt-injection attempt in spliced untrusted content; a human must review the source before re-dispatch
580
- FAILURE_CLASS.LIVE_CHECKOUT_DIRTY, // P-a3f9b204 — live-checkout refused to spawn because operator localPath is dirty; mechanical retry won't fix it (operator must commit/stash/discard)
580
+ FAILURE_CLASS.LIVE_CHECKOUT_DIRTY, // P-a3f9b204 — live-checkout refused to spawn because operator localPath is dirty; mechanical retry won't fix it (operator must commit/stash/discard). NOTE (W-mqzmkoqt000hbca2): engine.js#spawnAgent ALWAYS passes an explicit `agentRetryable` for this class, so this Set entry is never the actual gate — when auto-cleanup (liveCheckoutAutoReset/AutoStash) is enabled the engine overrides to retryable. Kept as a defensive safety net for any caller that omits the explicit override.
581
581
  FAILURE_CLASS.LIVE_CHECKOUT_MID_OPERATION, // P-a7f3c1d9 — live-checkout refused to spawn because the operator tree is mid-operation (in-progress merge/rebase/cherry-pick/bisect or detached HEAD); mechanical retry won't fix it (operator must finish/abort the op or checkout a branch)
582
582
  FAILURE_CLASS.LIVE_CHECKOUT_BLOB_FETCH, // PL-live-checkout-reliability-hardening — live-checkout `git checkout <existing-branch>` failed hydrating the tree through the auth-less GVFS cache server (blobless partial clone, headless); deterministic, so mechanical retry just reproduces it (operator must hydrate the branch with their own creds, then re-dispatch)
583
583
  FAILURE_CLASS.OUTPUT_TRUNCATED, // P-8e4c2a17 — agent stdout exceeded the hard capture cap before the terminal result event; mechanical retry just reproduces the overflow (agent must reduce output volume or the task must be split)
package/engine.js CHANGED
@@ -2437,8 +2437,21 @@ async function spawnAgent(dispatchItem, config) {
2437
2437
  // burned all maxRetries. The dedicated counter is touched ONLY here (on a
2438
2438
  // dirty failure) and cleared on a successful prepareLiveCheckout below;
2439
2439
  // neither discovery nor the retry re-queue clears it.
2440
+ //
2441
+ // W-mqzmkoqt000hbca2 — AUTO-CLEANUP EXCEPTION: the two-strike cap assumes
2442
+ // the dirty tree is operator-owned and only a human can clear it. But when
2443
+ // `liveCheckoutAutoReset` or `liveCheckoutAutoStash` is configured (per-project
2444
+ // or fleet-wide), the engine itself re-cleans the tree on every dispatch
2445
+ // attempt, so a recurring dirty failure (e.g. a transiently failing
2446
+ // auto-reset/stash) is NOT operator-owned. In that case we skip the
2447
+ // two-strike cap and stay retryable — the next attempt re-runs auto-cleanup.
2448
+ // The normal `maxRetries` cap in dispatch.js still bounds the retries.
2440
2449
  const _priorDirtyAttempts = Number(dispatchItem.meta?.item?._liveCheckoutDirtyAttempts) || 0;
2441
2450
  const _alreadyDirtyFailed = _priorDirtyAttempts >= 1;
2451
+ const _autoCleanupEnabled =
2452
+ shared.resolveLiveCheckoutAutoReset(project, engineConfig) ||
2453
+ (typeof _liveCheckout.resolveLiveCheckoutAutoStash === 'function' &&
2454
+ !!_liveCheckout.resolveLiveCheckoutAutoStash({ project, engine: engineConfig }));
2442
2455
  const _alertBody = [
2443
2456
  '# Live-checkout refused: dirty worktree',
2444
2457
  '',
@@ -2457,9 +2470,11 @@ async function spawnAgent(dispatchItem, config) {
2457
2470
  ...(_dirtyFiles.length > 0 ? _dirtyFiles : ['(none reported)']),
2458
2471
  '```',
2459
2472
  '',
2460
- _alreadyDirtyFailed
2461
- ? 'Recovery: dirty state persisted across retries commit, stash, or discard the changes in the project checkout, then re-dispatch the work item.'
2462
- : 'This dispatch will be retried once automatically in case the dirty state is transient. If dirty again on retry, commit, stash, or discard the changes, then re-dispatch.',
2473
+ _autoCleanupEnabled
2474
+ ? 'Auto-cleanup (`liveCheckoutAutoReset`/`liveCheckoutAutoStash`) is active the engine re-cleans the tree on each attempt, so this dispatch will be retried automatically (subject to the normal retry cap).'
2475
+ : (_alreadyDirtyFailed
2476
+ ? 'Recovery: dirty state persisted across retries — commit, stash, or discard the changes in the project checkout, then re-dispatch the work item.'
2477
+ : 'This dispatch will be retried once automatically in case the dirty state is transient. If dirty again on retry, commit, stash, or discard the changes, then re-dispatch.'),
2463
2478
  ].join('\n');
2464
2479
  try { writeInboxAlert(`live-checkout-dirty-${_wiIdForAlert}`, _alertBody); }
2465
2480
  catch (e) { log('warn', `live-checkout: writeInboxAlert failed: ${e.message}`); }
@@ -2487,10 +2502,12 @@ async function spawnAgent(dispatchItem, config) {
2487
2502
  id,
2488
2503
  DISPATCH_RESULT.ERROR,
2489
2504
  _dirtyMsg.slice(0, 800),
2490
- _alreadyDirtyFailed
2491
- ? 'Live-checkout dirty state persisted across retriesoperator must commit/stash/discard before re-dispatch.'
2492
- : 'Live-checkout dirty tree retried once automatically; if dirty persists, operator must commit/stash/discard.',
2493
- { failureClass: FAILURE_CLASS.LIVE_CHECKOUT_DIRTY, agentRetryable: !_alreadyDirtyFailed },
2505
+ _autoCleanupEnabled
2506
+ ? 'Live-checkout dirty tree with auto-cleanup activewill retry (engine re-cleans each attempt; normal retry cap applies).'
2507
+ : (_alreadyDirtyFailed
2508
+ ? 'Live-checkout dirty state persisted across retries — operator must commit/stash/discard before re-dispatch.'
2509
+ : 'Live-checkout dirty tree retried once automatically; if dirty persists, operator must commit/stash/discard.'),
2510
+ { failureClass: FAILURE_CLASS.LIVE_CHECKOUT_DIRTY, agentRetryable: _autoCleanupEnabled || !_alreadyDirtyFailed },
2494
2511
  );
2495
2512
  cleanupTempAgent(agentId);
2496
2513
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.2299",
3
+ "version": "0.1.2301",
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"