@yemi33/minions 0.1.1860 → 0.1.1861

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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1861 (2026-05-10)
4
+
5
+ ### Fixes
6
+ - surface phantom-completion as the failReason instead of "no PR detected"
7
+
3
8
  ## 0.1.1860 (2026-05-10)
4
9
 
5
10
  ### Fixes
@@ -1098,6 +1098,21 @@ function _outputContainsPrUrl(output) {
1098
1098
  return prUrlPattern.test(output);
1099
1099
  }
1100
1100
 
1101
+ // Detects the phantom-completion signature in the raw runtime output: the
1102
+ // runtime's terminating `{"type":"result"}` event never landed. When this is
1103
+ // true and the PR-attachment contract is about to hard-fail for "no PR
1104
+ // detected," it's far more accurate to say "runtime crashed before emitting a
1105
+ // result event" — the agent didn't fail silently, the runtime CLI did. Used by
1106
+ // enforcePrAttachmentContract to pick a truthful failReason.
1107
+ function _outputHasRuntimeResultEvent(output) {
1108
+ if (!output || typeof output !== 'string') return false;
1109
+ // Both Claude and Copilot emit a top-level `{"type":"result"…}` JSONL line as
1110
+ // the conversation terminator. A literal substring match is enough; the
1111
+ // captured streams are JSONL so the brace pattern can't legitimately appear
1112
+ // mid-field-value without the prefix.
1113
+ return /"type":\s*"result"/.test(output);
1114
+ }
1115
+
1101
1116
  function markMissingPrAttachment(meta, agentId, reason, resultSummary, severity) {
1102
1117
  const noPrWiPath = resolveWorkItemPath(meta);
1103
1118
  const isHard = severity !== 'soft';
@@ -1239,9 +1254,20 @@ async function enforcePrAttachmentContract(type, meta, agentId, config, resultSu
1239
1254
  // was designed to catch) from "agent claimed a PR but engine couldn't attach
1240
1255
  // it canonically" (soft — verification gap, not a failure).
1241
1256
  const severity = _outputContainsPrUrl(output) ? 'soft' : 'hard';
1242
- const reason = severity === 'hard'
1243
- ? `${meta.item.id} completed but no PR URL was detected in the agent's output. Expected a PR verify the agent didn't fail silently. (Branch: ${meta.branch || '(none)'}, agent: ${agentId})`
1244
- : `${meta.item.id} completed and a PR URL was found in the agent's output, but it couldn't be canonically attached. The work likely succeeded verify by checking the PR list. (Branch: ${meta.branch || '(none)'}, agent: ${agentId})`;
1257
+ // Hard-fail messaging: if the runtime never emitted its terminating result
1258
+ // event, the failure is a phantom completion (runtime CLI crashed), not the
1259
+ // agent silently skipping work. Surface that truthfully so operators don't
1260
+ // chase "the agent didn't open a PR" when the real cause is "the runtime
1261
+ // process died mid-conversation." Soft cases keep the original wording —
1262
+ // they imply the runtime DID finish and a URL is in the stream.
1263
+ let reason;
1264
+ if (severity === 'hard') {
1265
+ reason = _outputHasRuntimeResultEvent(output)
1266
+ ? `${meta.item.id} completed but no PR URL was detected in the agent's output. Expected a PR — verify the agent didn't fail silently. (Branch: ${meta.branch || '(none)'}, agent: ${agentId})`
1267
+ : `${meta.item.id} runtime exited without emitting a terminating result event — likely a phantom completion (the runtime CLI crashed mid-conversation, not a true agent failure). No PR was created. (Branch: ${meta.branch || '(none)'}, agent: ${agentId})`;
1268
+ } else {
1269
+ reason = `${meta.item.id} completed and a PR URL was found in the agent's output, but it couldn't be canonically attached. The work likely succeeded — verify by checking the PR list. (Branch: ${meta.branch || '(none)'}, agent: ${agentId})`;
1270
+ }
1245
1271
  markMissingPrAttachment(meta, agentId, reason, resultSummary, severity);
1246
1272
  log(severity === 'hard' ? 'warn' : 'info', reason);
1247
1273
  return { reason, itemId: meta.item.id, severity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1860",
3
+ "version": "0.1.1861",
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"