@yemi33/minions 0.1.1757 → 0.1.1759

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.1759 (2026-05-07)
4
+
5
+ ### Fixes
6
+ - isolate meeting tests, kill rename-live-dir antipattern (#2142)
7
+ - honor no-op completions in PR attachment contract (#2141)
8
+
3
9
  ## 0.1.1757 (2026-05-06)
4
10
 
5
11
  ### Other
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-06T23:51:41.530Z"
4
+ "cachedAt": "2026-05-07T00:36:52.041Z"
5
5
  }
@@ -542,6 +542,16 @@ function updateWorkItemStatus(meta, status, reason) {
542
542
  target.completedAt = ts();
543
543
  // Restore agent info from dispatch metadata (cleared on retry reset)
544
544
  if (meta._agentId && !target.dispatched_to) target.dispatched_to = meta._agentId;
545
+ // No-op marker (set by runPostCompletionHooks when the agent honored a
546
+ // verify-already-shipped / no-op-fix-review skill). Surfaces the
547
+ // rationale on the dashboard instead of marking the WI as failed.
548
+ if (meta._noopReason) {
549
+ target._noop = true;
550
+ target._noopReason = meta._noopReason;
551
+ } else {
552
+ delete target._noop;
553
+ delete target._noopReason;
554
+ }
545
555
  } else if (status === WI_STATUS.FAILED) {
546
556
  if (reason) target.failReason = reason;
547
557
  target.failedAt = ts();
@@ -2510,6 +2520,38 @@ function parseCompletionBoolean(value) {
2510
2520
  return undefined;
2511
2521
  }
2512
2522
 
2523
+ // Detect a deliberate no-op completion — the agent correctly declined to make
2524
+ // changes (work was already shipped, dispatch premise was wrong, self-authored
2525
+ // review with no actionable feedback, etc.) and should NOT be flagged as a
2526
+ // silent failure for missing a PR. Honored signals:
2527
+ // - completion.noop === true (canonical, primary)
2528
+ // - completion.result === 'noop' OR completion.result.type === 'noop'
2529
+ // Returns the no-op rationale string (for surfacing in WI metadata) when
2530
+ // detected, or null otherwise. The status must be a successful terminal state
2531
+ // — a failed/partial/in-progress completion that also claims `noop` is a
2532
+ // contradiction and falls through to the normal contract.
2533
+ function parseCompletionNoop(completion) {
2534
+ if (!completion || typeof completion !== 'object') return null;
2535
+ const explicit = parseCompletionBoolean(completion.noop);
2536
+ let resultIsNoop = false;
2537
+ if (typeof completion.result === 'string') {
2538
+ resultIsNoop = completion.result.trim().toLowerCase() === 'noop';
2539
+ } else if (completion.result && typeof completion.result === 'object') {
2540
+ resultIsNoop = String(completion.result.type || '').trim().toLowerCase() === 'noop';
2541
+ }
2542
+ if (explicit !== true && !resultIsNoop) return null;
2543
+ const status = normalizeCompletionStatus(completion.status);
2544
+ if (status && status !== 'success' && status !== 'done' && status !== 'complete') return null;
2545
+ const reason = String(
2546
+ completion.noopReason
2547
+ || completion.noop_reason
2548
+ || completion.summary
2549
+ || completion.reason
2550
+ || ''
2551
+ ).trim();
2552
+ return reason || 'no-op completion';
2553
+ }
2554
+
2513
2555
  function normalizeReviewVerdict(verdict) {
2514
2556
  const value = String(verdict || '').trim().toLowerCase().replace(/[\s-]+/g, '_');
2515
2557
  if (value === 'approve' || value === 'approved') return 'approved';
@@ -2867,7 +2909,17 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
2867
2909
  }
2868
2910
  }
2869
2911
 
2870
- if (effectiveSuccess && meta?.item?.id && !skipDoneStatus) {
2912
+ // No-op signal: agent declared the work was correctly NOT done (already
2913
+ // shipped, dispatch premise wrong, self-authored review, etc.). Skip the PR
2914
+ // attachment contract — a missing PR is intentional, not a silent failure.
2915
+ const noopRationale = (effectiveSuccess && meta?.item?.id && !skipDoneStatus)
2916
+ ? parseCompletionNoop(structuredCompletion)
2917
+ : null;
2918
+ if (noopRationale) {
2919
+ log('info', `No-op completion for ${meta.item.id}: ${noopRationale.slice(0, 200)}`);
2920
+ }
2921
+
2922
+ if (effectiveSuccess && meta?.item?.id && !skipDoneStatus && !noopRationale) {
2871
2923
  completionContractFailure = await enforcePrAttachmentContract(type, meta, agentId, config, resultSummary, stdout);
2872
2924
  if (completionContractFailure?.severity === 'hard' || completionContractFailure?.nonTerminal) {
2873
2925
  skipDoneStatus = true;
@@ -2876,6 +2928,9 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
2876
2928
 
2877
2929
  if (effectiveSuccess && meta?.item?.id && !skipDoneStatus) {
2878
2930
  meta._agentId = agentId;
2931
+ if (noopRationale) {
2932
+ meta._noopReason = noopRationale.slice(0, 500);
2933
+ }
2879
2934
  updateWorkItemStatus(meta, WI_STATUS.DONE, '');
2880
2935
  }
2881
2936
  // Failure retry is handled by completeDispatch in dispatch.js — not duplicated here.
@@ -3238,6 +3293,7 @@ module.exports = {
3238
3293
  isReviewBailout,
3239
3294
  parseStructuredCompletion,
3240
3295
  parseCompletionFieldSummary,
3296
+ parseCompletionNoop,
3241
3297
  detectNonTerminalResultSummary,
3242
3298
  parseCompletionReportFile,
3243
3299
  persistCompletionReport,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1757",
3
+ "version": "0.1.1759",
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"
@@ -72,6 +72,8 @@ The engine provides a completion report path in the prompt and in `MINIONS_COMPL
72
72
 
73
73
  Use `status: "failed"` plus an accurate `failure_class`, `retryable`, and `needs_rerun` when the task could not be completed. For PR reviews, set `verdict` to `approved` or `changes-requested`. Include every durable artifact you created or updated in `artifacts` (PRs, notes, plans, PRDs, important files) so the dashboard can display them. Fenced `completion` blocks are still accepted as a fallback, but the JSON report is the primary signal.
74
74
 
75
+ **No-op completions:** when you correctly decline to do the work — the change was already shipped on master, the dispatch premise is wrong, the flagged review comment is your own author-notes, etc. — write `status: "success"`, `pr: "N/A"`, AND add `"noop": true`. The engine treats `noop: true` as the canonical signal that no PR was expected, marks the work item done with the rationale surfaced in `_noopReason` for the dashboard, and skips the missing-PR-attachment failure. Without `noop: true`, an empty PR will still be flagged as a silent failure and auto-retried up to `maxRetries` times.
76
+
75
77
  ## Long-Running Commands
76
78
 
77
79
  Builds, dependency installs, tests, and local servers can be quiet for long periods. Run the repo's normal CLI commands and let them finish; do not add artificial progress output, heartbeat loops, or command-specific workarounds just to keep Minions active.