@yemi33/minions 0.1.2353 → 0.1.2355

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.
@@ -1485,7 +1485,10 @@ async function restoreLiveCheckoutAtDispatchEnd(opts = {}) {
1485
1485
  * and the per-agent cli/model override pattern):
1486
1486
  * 1. If `project.liveCheckoutAutoStash` is an explicit boolean, use it.
1487
1487
  * 2. Else if `engine.liveCheckoutAutoStash` is an explicit boolean, use it.
1488
- * 3. Else default false.
1488
+ * 3. Else fall back to `shared.ENGINE_DEFAULTS.liveCheckoutAutoStash`
1489
+ * (default true as of W-mrawiym8000c42c9 — non-destructive, recoverable
1490
+ * via `git stash pop`, and now the first line of defense in the
1491
+ * dirty-tree recovery flow now that `liveCheckoutAutoReset` defaults off).
1489
1492
  *
1490
1493
  * Pure — no I/O. Tested in test/unit/live-checkout-auto-stash.test.js.
1491
1494
  *
@@ -1500,7 +1503,7 @@ function resolveLiveCheckoutAutoStash(opts = {}) {
1500
1503
  if (engine && typeof engine.liveCheckoutAutoStash === 'boolean') {
1501
1504
  return engine.liveCheckoutAutoStash;
1502
1505
  }
1503
- return false;
1506
+ return shared.ENGINE_DEFAULTS.liveCheckoutAutoStash;
1504
1507
  }
1505
1508
 
1506
1509
  /**
@@ -1570,11 +1573,29 @@ async function performLiveCheckoutAutoStash(opts = {}) {
1570
1573
  *
1571
1574
  * Returns a discriminated outcome the caller acts on:
1572
1575
  * - `{ outcome:'unchanged', liveResult }` — not dirty, disabled, or stash failed
1573
- * (caller falls through to the existing retry-once-then-fail dirty handling).
1576
+ * (caller falls through to the existing retry-once-then-fail dirty handling,
1577
+ * or — W-mrawgw4q000a6bff — to an explicit `liveCheckoutAutoReset` fallback
1578
+ * when that policy also resolves true; see engine.js spawnAgent).
1574
1579
  * - `{ outcome:'stashed', liveResult }` — stashed + re-preflighted; proceed.
1575
1580
  * - `{ outcome:'threw', error }` — the re-preflight threw; caller must
1576
1581
  * fail the dispatch as LIVE_CHECKOUT_FAILED (engine-specific completion).
1577
1582
  *
1583
+ * W-mrawgw4q000a6bff — stash-before-reset ordering + no auto-sync-to-origin.
1584
+ * The re-preflight (step 2) is called with `autoReset:false` so a still-dirty
1585
+ * tree after a successful stash NEVER silently falls through to a destructive
1586
+ * reset here — reset is only ever triggered explicitly by the caller as a
1587
+ * documented last-resort fallback. Also, by design, this function does NOT
1588
+ * follow up a successful stash with a `git merge --ff-only origin/<mainRef>`
1589
+ * to re-sync the branch: `liveCheckoutAutoStash`'s contract (see
1590
+ * `resolveLiveCheckoutAutoStash` above) has only ever been "park the dirty
1591
+ * changes so dispatch can proceed", never "keep the branch in sync with
1592
+ * origin" — that stronger guarantee is what `liveCheckoutAutoReset` is for,
1593
+ * and it is still available as an explicit opt-in for dispatches that need it
1594
+ * (with stash getting first crack at the tree, non-destructively, per the new
1595
+ * ordering). Adding an implicit ff-only sync here would blur that line and
1596
+ * risk a "successful" stash silently leaving a merge commit or a still-dirty
1597
+ * tree if the ff fails — so it was deliberately left out.
1598
+ *
1578
1599
  * @param {object} opts
1579
1600
  * @returns {Promise<{outcome:'unchanged'|'stashed'|'threw', liveResult?:object, error?:Error}>}
1580
1601
  */
@@ -1583,6 +1604,7 @@ async function applyLiveCheckoutAutoStash(opts = {}) {
1583
1604
  liveResult, project, engine, localPath, branchName, mainRef,
1584
1605
  gitOpts, dispatchId, wiId, log,
1585
1606
  clearDirtyStamp, writeStashNote,
1607
+ _git, // private injection for testing — forwarded to performLiveCheckoutAutoStash + the re-preflight prepareLiveCheckout call
1586
1608
  } = opts;
1587
1609
  const logFn = (typeof log === 'function') ? log : () => {};
1588
1610
  const reason = (liveResult && liveResult.ok === false) ? liveResult.reason : null;
@@ -1591,7 +1613,7 @@ async function applyLiveCheckoutAutoStash(opts = {}) {
1591
1613
  }
1592
1614
  let stashResult;
1593
1615
  try {
1594
- stashResult = await performLiveCheckoutAutoStash({ localPath, dispatchId, gitOpts, log });
1616
+ stashResult = await performLiveCheckoutAutoStash({ localPath, dispatchId, gitOpts, log, _git });
1595
1617
  } catch (stashErr) {
1596
1618
  stashResult = { ok: false, error: stashErr && stashErr.message };
1597
1619
  }
@@ -1601,7 +1623,10 @@ async function applyLiveCheckoutAutoStash(opts = {}) {
1601
1623
  }
1602
1624
  let newLive;
1603
1625
  try {
1604
- newLive = await prepareLiveCheckout({ localPath, branchName, mainRef, gitOpts, dispatchId, wiId, log });
1626
+ // autoReset:false see the function doc above; a still-dirty tree after a
1627
+ // successful stash must never silently fall through to a destructive reset
1628
+ // inside this re-preflight.
1629
+ newLive = await prepareLiveCheckout({ localPath, branchName, mainRef, gitOpts, dispatchId, wiId, log, autoReset: false, _git });
1605
1630
  } catch (stashLiveErr) {
1606
1631
  return { outcome: 'threw', error: stashLiveErr };
1607
1632
  }
@@ -307,6 +307,7 @@ const PLAYBOOK_OPTIONAL_VARS = new Set([
307
307
  'references', // only set when item.references has entries
308
308
  'acceptance_criteria', // only set when item.acceptanceCriteria has entries
309
309
  'checkpoint_context', // only set when resuming from a prior timeout
310
+ 'retry_context', // only set when retrying after a validation-gate failure (#893)
310
311
  // Host-specific identifiers — always one of {ado_*, github_*} is empty
311
312
  // (project is either ADO or GitHub, never both). Keeping them as warns
312
313
  // produces ~96 noise lines per day on a single-host project.
@@ -85,16 +85,20 @@ const PR_ACTION_FOLLOWUPS = Object.freeze([
85
85
  { kind: 'track-auto-fix', label: 'Track for auto-fix' },
86
86
  ]);
87
87
 
88
- /** Canonical `host:slug#number` id for a record/ref, or '' when unknowable. */
88
+ /**
89
+ * Canonical `host:slug#number` id for a record/ref, or '' when unknowable.
90
+ *
91
+ * Thin wrapper over prResolve.prIdFromRef: normalizes the heterogeneous
92
+ * record shapes buildPrActionFollowups is called with — an explicit
93
+ * `record.prId`, a `record.ref` ref object, or a bare ref-shaped object
94
+ * (`{host, slug, number}`/`{id}`) — into the ref shape prIdFromRef expects,
95
+ * then delegates so the `host:slug#number` template literal has one owner.
96
+ */
89
97
  function _prIdForRecord(record) {
90
98
  if (!record) return '';
91
99
  if (record.prId) return record.prId;
92
100
  const ref = record.ref || record;
93
- if (ref && ref.id) return ref.id;
94
- if (ref && ref.host && ref.slug && (ref.number || ref.number === 0)) {
95
- return `${ref.host}:${ref.slug}#${ref.number}`;
96
- }
97
- return '';
101
+ return prResolve.prIdFromRef(ref) || '';
98
102
  }
99
103
 
100
104
  /**
@@ -364,7 +368,8 @@ function buildPrActionPrompt(action, payload) {
364
368
  number: payload && payload.number,
365
369
  id: payload && payload.prId,
366
370
  };
367
- const prId = ref.id || (ref.host && ref.slug && ref.number ? `${ref.host}:${ref.slug}#${ref.number}` : (payload && payload.slug ? `${payload.slug}#${payload.number}` : 'the pull request'));
371
+ const prId = prResolve.prIdFromRef(ref)
372
+ || (payload && payload.slug ? `${payload.slug}#${payload.number}` : 'the pull request');
368
373
  const guidance = PR_ACTION_GUIDANCE[act] || PR_ACTION_GUIDANCE.review;
369
374
 
370
375
  const sections = [