@yemi33/minions 0.1.1800 → 0.1.1802

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/dashboard.js CHANGED
@@ -1929,16 +1929,52 @@ function fencedUntrustedBlock(label, content) {
1929
1929
  return `### ${label}\n${fence}text\n${value}\n${fence}`;
1930
1930
  }
1931
1931
 
1932
+ function _messageExplicitlyRequestsMonitoring(message) {
1933
+ const text = String(message || '').toLowerCase();
1934
+ if (!text.trim()) return false;
1935
+ if (/\b(?:do\s+not|don't|dont|never|without|no\s+need\s+to)\s+(?:monitor(?:ing)?|watch(?:ing)?|poll(?:ing)?|check(?:ing)?|notify(?:ing)?|ping(?:ing)?|keep(?:ing)?\s+an\s+eye)\b/.test(text)) {
1936
+ return false;
1937
+ }
1938
+ return [
1939
+ /\bmonitor(?:ing)?\b/,
1940
+ /\bwatch(?:ing)?\b/,
1941
+ /\bkeep(?:ing)?\s+an\s+eye\s+on\b/,
1942
+ /\bcheck(?:ing)?\s+(?:it|this|that|[^.?!\n]+)\s+periodically\b/,
1943
+ /\bperiodically\s+check\b/,
1944
+ /\bcheck(?:ing)?\s+[^.?!\n]+\bevery\s+\d+\s*(?:s|sec|seconds?|m|min|minutes?|h|hr|hours?)\b/,
1945
+ /\bevery\s+\d+\s*(?:s|sec|seconds?|m|min|minutes?|h|hr|hours?)\b[^.?!\n]+\b(?:check|poll|monitor|watch)\b/,
1946
+ /\bping\s+(?:me\s+)?(?:on|when|after)\b/,
1947
+ /\bping\s+on\s+completion\b/,
1948
+ /\bnotify\s+(?:me\s+)?(?:on|when|after)\b/,
1949
+ /\blet\s+me\s+know\s+(?:when|once|if)\b/,
1950
+ /\bpoll(?:ing)?\b/,
1951
+ ].some(pattern => pattern.test(text));
1952
+ }
1953
+
1954
+ function _isDispatchLikeCCAction(action) {
1955
+ const type = String(action?.type || '').trim().toLowerCase();
1956
+ return type === 'dispatch' || ['fix', 'explore', 'review', 'test'].includes(type);
1957
+ }
1958
+
1959
+ function _filterImplicitPostDispatchActions(actions, humanMessage) {
1960
+ if (!Array.isArray(actions) || actions.length === 0) return [];
1961
+ if (_messageExplicitlyRequestsMonitoring(humanMessage)) return actions;
1962
+ const dispatchIdx = actions.findIndex(_isDispatchLikeCCAction);
1963
+ if (dispatchIdx < 0) return actions;
1964
+ return actions.slice(0, dispatchIdx + 1);
1965
+ }
1966
+
1932
1967
  // ── /loop → create-watch safety net ──────────────────────────────────────────
1933
1968
  // CC sometimes invokes the /loop skill instead of emitting a create-watch action.
1934
1969
  // This pure function detects /loop invocation in CC response text and synthesizes
1935
1970
  // a create-watch action as a fallback. Returns null if no conversion needed.
1936
1971
 
1937
- function _detectLoopInvocation(text, actions, toolUses) {
1972
+ function _detectLoopInvocation(text, actions, toolUses, humanMessage) {
1938
1973
  const observedToolUses = Array.isArray(toolUses) ? toolUses : [];
1939
1974
  if (!text && observedToolUses.length === 0) return null;
1940
1975
  // If a create-watch action was already emitted, no fallback needed
1941
1976
  if (actions && actions.some(a => a.type === 'create-watch')) return null;
1977
+ if (humanMessage !== undefined && !_messageExplicitlyRequestsMonitoring(humanMessage)) return null;
1942
1978
 
1943
1979
  function _extractTargetFromValue(value, keyHint) {
1944
1980
  if (value == null) return null;
@@ -6509,12 +6545,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6509
6545
  const parsed = parseCCActions(result.text);
6510
6546
  const toolUses = Array.isArray(result.toolUses) ? result.toolUses : _extractToolUsesFromRaw(result.raw);
6511
6547
  // Safety net: detect /loop invocation and convert to create-watch
6512
- const _loopWatch = _detectLoopInvocation(parsed.text, parsed.actions, toolUses);
6548
+ const _loopWatch = _detectLoopInvocation(parsed.text, parsed.actions, toolUses, body.message);
6513
6549
  if (_loopWatch) {
6514
6550
  parsed.actions.push(_loopWatch);
6515
6551
  console.warn('[CC] /loop invocation detected — converted to create-watch');
6516
6552
  try { shared.log('warn', '/loop invocation detected in CC response — auto-converted to create-watch'); } catch {}
6517
6553
  }
6554
+ parsed.actions = _filterImplicitPostDispatchActions(parsed.actions, body.message);
6518
6555
  if (parsed.actions.length > 0) {
6519
6556
  parsed.actionResults = await executeCCActions(parsed.actions);
6520
6557
  }
@@ -6834,14 +6871,15 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6834
6871
  }
6835
6872
 
6836
6873
  // Send final result with actions — execute server-side first
6837
- const { text: displayText, actions, _actionParseError } = parseCCActions(result.text);
6874
+ let { text: displayText, actions, _actionParseError } = parseCCActions(result.text);
6838
6875
  // Safety net: detect /loop invocation and convert to create-watch
6839
- const _loopWatch = _detectLoopInvocation(displayText, actions, toolUses);
6876
+ const _loopWatch = _detectLoopInvocation(displayText, actions, toolUses, body.message);
6840
6877
  if (_loopWatch) {
6841
6878
  actions.push(_loopWatch);
6842
6879
  console.warn('[CC] /loop invocation detected — converted to create-watch');
6843
6880
  try { shared.log('warn', '/loop invocation detected in CC response — auto-converted to create-watch'); } catch {}
6844
6881
  }
6882
+ actions = _filterImplicitPostDispatchActions(actions, body.message);
6845
6883
  let actionResults;
6846
6884
  if (actions.length > 0) {
6847
6885
  actionResults = await executeCCActions(actions);
@@ -8471,6 +8509,8 @@ module.exports = {
8471
8509
  _resolveSkillReadPath,
8472
8510
  DOC_CHAT_DOCUMENT_DELIMITER,
8473
8511
  _ccValidateAction,
8512
+ _messageExplicitlyRequestsMonitoring,
8513
+ _filterImplicitPostDispatchActions,
8474
8514
  _findDuplicateWorkItemCreate: findDuplicateWorkItemCreate,
8475
8515
  _createWorkItemWithDedup: createWorkItemWithDedup,
8476
8516
  _resolveWorkItemsCreateTarget: resolveWorkItemsCreateTarget,
package/engine/cli.js CHANGED
@@ -1079,14 +1079,14 @@ const commands = {
1079
1079
  return;
1080
1080
  }
1081
1081
  const dispatch = getDispatch();
1082
- const found = (dispatch.active || []).some(d => d.id === id);
1083
- if (!found) {
1082
+ const item = (dispatch.active || []).find(d => d.id === id);
1083
+ if (!item) {
1084
1084
  console.log(` Dispatch "${id}" not found in active queue.`);
1085
1085
  const pending = (dispatch.pending || []).some(d => d.id === id);
1086
1086
  if (pending) console.log(' (It is in pending — it hasn\'t started yet.)');
1087
1087
  return;
1088
1088
  }
1089
- engine().completeDispatch(id, 'success');
1089
+ engine().completeDispatch(id, DISPATCH_RESULT.SUCCESS, '', '', { processWorkItemSuccess: true });
1090
1090
  console.log(` Marked ${id} as completed.`);
1091
1091
  },
1092
1092
 
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-08T16:56:04.298Z"
4
+ "cachedAt": "2026-05-08T17:22:37.672Z"
5
5
  }
@@ -322,12 +322,45 @@ function writeFailedAgentReport(item, reason, resultSummary, failureClass) {
322
322
  shared.writeToInbox(agentId, `agent-failure-${item.id}`, content, null, metadata);
323
323
  }
324
324
 
325
+ function markCompletedSourceWorkItem(item) {
326
+ const meta = item?.meta;
327
+ const itemId = meta?.item?.id;
328
+ if (!itemId) return false;
329
+ const wiPath = lifecycle().resolveWorkItemPath(meta);
330
+ if (!wiPath) return false;
331
+ let found = false;
332
+ let terminal = false;
333
+ mutateWorkItems(wiPath, items => {
334
+ if (!Array.isArray(items)) return items;
335
+ const wi = items.find(i => i.id === itemId);
336
+ if (!wi) return items;
337
+ found = true;
338
+ if (wi.status === WI_STATUS.DONE) {
339
+ terminal = true;
340
+ return items;
341
+ }
342
+ wi.status = WI_STATUS.DONE;
343
+ delete wi.failReason;
344
+ delete wi.failedAt;
345
+ delete wi._retryCount;
346
+ if (!wi.completedAt) wi.completedAt = ts();
347
+ if (item.agent && !wi.dispatched_to) wi.dispatched_to = item.agent;
348
+ terminal = true;
349
+ return items;
350
+ });
351
+ if (!found) {
352
+ throw new Error(`source work item ${itemId} not found`);
353
+ }
354
+ return terminal;
355
+ }
356
+
325
357
  // ─── Complete Dispatch ───────────────────────────────────────────────────────
326
358
 
327
359
  function completeDispatch(id, result = DISPATCH_RESULT.SUCCESS, reason = '', resultSummary = '', opts = {}) {
328
- const { processWorkItemFailure = true, failureClass } = opts;
360
+ const { processWorkItemFailure = true, processWorkItemSuccess = false, failureClass } = opts;
329
361
  const agentRetryable = normalizeRetryableDecision(opts.agentRetryable ?? opts.retryable);
330
362
  let item = null;
363
+ let completedSourceWorkItem = false;
331
364
 
332
365
  mutateDispatch((dispatch) => {
333
366
  // Check active list first
@@ -356,6 +389,10 @@ function completeDispatch(id, result = DISPATCH_RESULT.SUCCESS, reason = '', res
356
389
  item.meta.completionReportPath = opts.structuredCompletion._path;
357
390
  }
358
391
  }
392
+ if (processWorkItemSuccess && result === DISPATCH_RESULT.SUCCESS && item.meta?.item?.id) {
393
+ if (item.agent) item.meta._agentId = item.agent;
394
+ completedSourceWorkItem = markCompletedSourceWorkItem(item);
395
+ }
359
396
  // Drop prompt (and sidecar file, if any) — completed entries don't need
360
397
  // replayable content and it would accumulate forever (#1167).
361
398
  try { deleteDispatchPromptSidecar(item); } catch { /* best-effort */ }
@@ -469,6 +506,13 @@ function completeDispatch(id, result = DISPATCH_RESULT.SUCCESS, reason = '', res
469
506
  }
470
507
  }
471
508
 
509
+ if (completedSourceWorkItem) {
510
+ try {
511
+ lifecycle().syncPrdItemStatus(item.meta.item.id, WI_STATUS.DONE, item.meta.item?.sourcePlan);
512
+ log('info', `Work item ${item.meta.item.id} → ${WI_STATUS.DONE}`);
513
+ } catch (e) { log('warn', 'manual completion PRD sync: ' + e.message); }
514
+ }
515
+
472
516
  // Restore pendingFix on failed human-feedback fix so engine re-dispatches on next tick
473
517
  if (result === DISPATCH_RESULT.ERROR && item.meta?.source === 'pr-human-feedback') {
474
518
  const prId = item.meta.pr?.id;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1800",
3
+ "version": "0.1.1802",
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"