@yemi33/minions 0.1.1815 → 0.1.1817
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 +10 -0
- package/dashboard/js/command-center.js +34 -4
- package/dashboard.js +116 -4
- package/engine/cli.js +6 -0
- package/engine/copilot-models.json +1 -1
- package/engine/shared.js +4 -0
- package/package.json +1 -1
- package/prompts/cc-system.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1817 (2026-05-09)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- suppress duplicate inline ask dispatch (#2256)
|
|
7
|
+
- correlate CC action failures (#2254)
|
|
8
|
+
|
|
9
|
+
### Other
|
|
10
|
+
- test(shared): add unit tests for project resolution and path comparison helpers (#2268)
|
|
11
|
+
- test(cli): add unit tests for pid/dispatch helpers and help formatter (#2267)
|
|
12
|
+
|
|
3
13
|
## 0.1.1815 (2026-05-09)
|
|
4
14
|
|
|
5
15
|
### Features
|
|
@@ -826,11 +826,15 @@ async function _ccDoSend(message, skipUserMsg, forceTabId, intentMetadata) {
|
|
|
826
826
|
var failures = evt.actionResults.filter(function(r) { return r && r.error; });
|
|
827
827
|
var warnings = evt.actionResults.filter(function(r) { return r && r.warning; });
|
|
828
828
|
if (failures.length > 0) {
|
|
829
|
-
var failHtml = failures.map(function(r) {
|
|
829
|
+
var failHtml = failures.map(function(r) {
|
|
830
|
+
return '<li>' + escHtml(r.type || (r.actionContext && r.actionContext.type) || 'action') + ': ' + escHtml(r.error) + _ccActionContextSuffix(r.actionContext) + '</li>';
|
|
831
|
+
}).join('');
|
|
830
832
|
addMsg('system', '<div style="padding:6px 12px;font-size:11px;color:var(--red);background:var(--surface2);border-radius:6px;margin:4px 0">⚠️ ' + failures.length + ' action' + (failures.length > 1 ? 's' : '') + ' failed:<ul style="margin:4px 0 0 16px;padding:0">' + failHtml + '</ul></div>', false, activeTabId);
|
|
831
833
|
}
|
|
832
834
|
if (warnings.length > 0) {
|
|
833
|
-
var warnHtml = warnings.map(function(r) {
|
|
835
|
+
var warnHtml = warnings.map(function(r) {
|
|
836
|
+
return '<li>' + escHtml(r.type || (r.actionContext && r.actionContext.type) || 'action') + ': ' + escHtml(r.warning) + _ccActionContextSuffix(r.actionContext) + '</li>';
|
|
837
|
+
}).join('');
|
|
834
838
|
addMsg('system', '<div style="padding:6px 12px;font-size:11px;color:var(--orange);background:var(--surface2);border-radius:6px;margin:4px 0">ℹ️ ' + warnings.length + ' action' + (warnings.length > 1 ? '' : '') + ' completed with warnings:<ul style="margin:4px 0 0 16px;padding:0">' + warnHtml + '</ul></div>', false, activeTabId);
|
|
835
839
|
}
|
|
836
840
|
}
|
|
@@ -1012,6 +1016,28 @@ async function _ccFetch(url, body, method) {
|
|
|
1012
1016
|
return res;
|
|
1013
1017
|
}
|
|
1014
1018
|
|
|
1019
|
+
var CC_ACTION_CONTEXT_STALE_MS = 2 * 60 * 1000;
|
|
1020
|
+
function _ccActionContextIsStale(ctx, nowMs) {
|
|
1021
|
+
if (!ctx || !ctx.requestedAt) return false;
|
|
1022
|
+
var ts = Date.parse(ctx.requestedAt);
|
|
1023
|
+
if (!Number.isFinite(ts)) return false;
|
|
1024
|
+
var now = Number.isFinite(nowMs) ? nowMs : Date.now();
|
|
1025
|
+
return now - ts > CC_ACTION_CONTEXT_STALE_MS;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
function _ccActionContextSuffix(ctx, nowMs) {
|
|
1029
|
+
if (!ctx || typeof ctx !== 'object') return '';
|
|
1030
|
+
var parts = [];
|
|
1031
|
+
if (ctx.title) parts.push('action "' + escHtml(ctx.title) + '"');
|
|
1032
|
+
if (ctx.request) parts.push('request "' + escHtml(ctx.request) + '"');
|
|
1033
|
+
if (ctx.requestedAt) parts.push('started ' + escHtml(ctx.requestedAt));
|
|
1034
|
+
if (parts.length === 0) return '';
|
|
1035
|
+
var stale = _ccActionContextIsStale(ctx, nowMs)
|
|
1036
|
+
? ' <strong style="color:var(--orange)">possibly stale</strong>'
|
|
1037
|
+
: '';
|
|
1038
|
+
return '<div style="font-size:10px;color:var(--muted);margin-top:2px">Context: ' + parts.join(' | ') + stale + '</div>';
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1015
1041
|
// Tag actions that the server already executed so ccExecuteAction skips the API call
|
|
1016
1042
|
function _tagServerExecuted(actions, actionResults) {
|
|
1017
1043
|
if (!actionResults || !Array.isArray(actionResults)) return;
|
|
@@ -1022,10 +1048,12 @@ function _tagServerExecuted(actions, actionResults) {
|
|
|
1022
1048
|
if (r.id) actions[i]._serverId = r.id;
|
|
1023
1049
|
if (r.warning) actions[i]._serverWarning = r.warning;
|
|
1024
1050
|
if (r.duplicate) actions[i]._serverDuplicate = true;
|
|
1051
|
+
if (r.actionContext) actions[i]._serverContext = r.actionContext;
|
|
1025
1052
|
if (r.reusedFromAction !== undefined) actions[i]._serverHidden = true;
|
|
1026
1053
|
} else if (r && r.error) {
|
|
1027
1054
|
actions[i]._serverExecuted = true;
|
|
1028
1055
|
actions[i]._serverError = r.error;
|
|
1056
|
+
if (r.actionContext) actions[i]._serverContext = r.actionContext;
|
|
1029
1057
|
}
|
|
1030
1058
|
// clientExecuted: false means server didn't handle it — frontend must execute
|
|
1031
1059
|
}
|
|
@@ -1040,7 +1068,8 @@ async function ccExecuteAction(action, targetTabId) {
|
|
|
1040
1068
|
if (action._serverExecuted) {
|
|
1041
1069
|
if (action._serverHidden) return;
|
|
1042
1070
|
if (action._serverError) {
|
|
1043
|
-
status.innerHTML = '✗ ' + escHtml(action.type) + ' failed: ' + escHtml(action._serverError)
|
|
1071
|
+
status.innerHTML = '✗ ' + escHtml(action.type) + ' failed: ' + escHtml(action._serverError) +
|
|
1072
|
+
_ccActionContextSuffix(action._serverContext);
|
|
1044
1073
|
status.style.color = 'var(--red)';
|
|
1045
1074
|
} else {
|
|
1046
1075
|
var label = action._serverId ? escHtml(action._serverId) : escHtml(action.title || action.type);
|
|
@@ -1048,7 +1077,8 @@ async function ccExecuteAction(action, targetTabId) {
|
|
|
1048
1077
|
var successLabel = serverActionType === 'dispatch' ? 'Dispatched' : serverActionType;
|
|
1049
1078
|
status.innerHTML = '✓ ' + escHtml(successLabel) + ': <strong>' + label + '</strong>' +
|
|
1050
1079
|
(action._serverDuplicate ? '<div style="font-size:10px;color:var(--orange);margin-top:2px">Already existed from a previous request; no duplicate work item was created.</div>' : '') +
|
|
1051
|
-
(action._serverWarning ? '<div style="font-size:10px;color:var(--muted);margin-top:2px">' + escHtml(action._serverWarning) + '</div>' : '')
|
|
1080
|
+
(action._serverWarning ? '<div style="font-size:10px;color:var(--muted);margin-top:2px">' + escHtml(action._serverWarning) + '</div>' : '') +
|
|
1081
|
+
_ccActionContextSuffix(action._serverContext);
|
|
1052
1082
|
status.style.color = 'var(--green)';
|
|
1053
1083
|
}
|
|
1054
1084
|
ccAddMessage('action', status.outerHTML, false, targetTabId);
|
package/dashboard.js
CHANGED
|
@@ -2163,7 +2163,8 @@ function _ccFallbackMissingTargetError(intent) {
|
|
|
2163
2163
|
|
|
2164
2164
|
function _actionsWithIntentFallback(actions, opts = {}) {
|
|
2165
2165
|
const { message = '', intentMetadata = null, source = 'command-center', filePath = null, title: docTitle = null, answerText = '', toolUses = [] } = opts;
|
|
2166
|
-
const existing = Array.isArray(actions) ? actions.map(normalizeCCAction) : []
|
|
2166
|
+
const existing = (Array.isArray(actions) ? actions.map(normalizeCCAction) : [])
|
|
2167
|
+
.filter(action => !_ccShouldSuppressAnsweredAskDispatch(action, { message, source, answerText, toolUses }));
|
|
2167
2168
|
if (_messageRequestsDirectHandling(message)) return existing.filter(a => normalizeCCAction(a)?.type !== 'dispatch');
|
|
2168
2169
|
if (existing.some(a => normalizeCCAction(a)?.type === 'dispatch')) return existing;
|
|
2169
2170
|
if (existing.length > 0) return existing;
|
|
@@ -2199,9 +2200,38 @@ function _actionsWithIntentFallback(actions, opts = {}) {
|
|
|
2199
2200
|
...common,
|
|
2200
2201
|
};
|
|
2201
2202
|
if (!hasTarget) action._intentFallbackError = _ccFallbackMissingTargetError(intent);
|
|
2203
|
+
if (_ccShouldSuppressAnsweredAskDispatch(action, { message, source, answerText, toolUses })) return existing;
|
|
2202
2204
|
return [action];
|
|
2203
2205
|
}
|
|
2204
2206
|
|
|
2207
|
+
function _ccActionContextValue(action) {
|
|
2208
|
+
if (!action || typeof action !== 'object') return '';
|
|
2209
|
+
const candidates = [action.title, action.id, action.file, action.target, action.pr, action.endpoint];
|
|
2210
|
+
for (const value of candidates) {
|
|
2211
|
+
const cleaned = _ccCleanIntentString(value, 160);
|
|
2212
|
+
if (cleaned) return cleaned;
|
|
2213
|
+
}
|
|
2214
|
+
return '';
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
function _annotateCCActionResults(actions, actionResults, opts = {}) {
|
|
2218
|
+
if (!Array.isArray(actionResults)) return actionResults;
|
|
2219
|
+
const requestedAt = _ccCleanIntentString(opts.requestedAt || new Date().toISOString(), 80);
|
|
2220
|
+
const request = _ccCleanIntentString(opts.message, 180);
|
|
2221
|
+
return actionResults.map((result, idx) => {
|
|
2222
|
+
if (!result || typeof result !== 'object') return result;
|
|
2223
|
+
const action = Array.isArray(actions) ? normalizeCCAction(actions[idx]) : null;
|
|
2224
|
+
const context = {
|
|
2225
|
+
type: _ccCleanIntentString(result.type || action?.type || 'action', 80) || 'action',
|
|
2226
|
+
};
|
|
2227
|
+
const title = _ccActionContextValue(action);
|
|
2228
|
+
if (title) context.title = title;
|
|
2229
|
+
if (request) context.request = request;
|
|
2230
|
+
if (requestedAt) context.requestedAt = requestedAt;
|
|
2231
|
+
return { ...result, actionContext: context };
|
|
2232
|
+
});
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2205
2235
|
function parseCCActions(text) {
|
|
2206
2236
|
let actions = [];
|
|
2207
2237
|
let displayText = stripCCActionsForDisplay(text);
|
|
@@ -2258,6 +2288,18 @@ function parseCCActions(text) {
|
|
|
2258
2288
|
}
|
|
2259
2289
|
|
|
2260
2290
|
const DELEGATION_ACTION_TERMS = ['dispatch', 'delegate', 'assign', 'queue', 'enqueue'];
|
|
2291
|
+
const DELEGATION_REQUEST_PREFIX_TERMS = ['please', 'can', 'could', 'would', 'will', 'should', 'you', 'cc', 'minions', 'minion'];
|
|
2292
|
+
const DELEGATION_PERSON_ACTION_TERMS = ['ask', 'tell', 'have'];
|
|
2293
|
+
// Subset of delegation action terms that double as common nouns in status
|
|
2294
|
+
// questions (e.g. "queue status", "dispatch contents"). When followed by a
|
|
2295
|
+
// status-noun follow-on these are noun usage, not imperative delegation.
|
|
2296
|
+
const DELEGATION_AMBIGUOUS_NOUN_TERMS = new Set(['dispatch', 'queue']);
|
|
2297
|
+
const DELEGATION_NON_VERB_FOLLOW_ONS = new Set([
|
|
2298
|
+
'status', 'contents', 'content', 'state', 'count', 'list', 'items', 'item',
|
|
2299
|
+
'size', 'length', 'depth', 'health', 'info', 'order', 'queue', 'history',
|
|
2300
|
+
'log', 'logs', 'summary', 'overview', 'report', 'is', 'was', 'are', 'were',
|
|
2301
|
+
'has', 'have', 'looks', 'shows',
|
|
2302
|
+
]);
|
|
2261
2303
|
const DELEGATION_MINIONS_PHRASES = ['have minions', 'ask minions', 'tell minions', 'hand off', 'hand it off', 'hand this off', 'send to agent', 'send it to agent', 'send this to agent'];
|
|
2262
2304
|
const MEDIUM_INVESTIGATION_TERMS = ['audit', 'investigate', 'research', 'explore', 'analyze', 'analyse'];
|
|
2263
2305
|
const MEDIUM_INVESTIGATION_PHRASES = ['deep dive', 'root cause'];
|
|
@@ -2288,6 +2330,15 @@ const DIRECT_HANDLING_PHRASES = [
|
|
|
2288
2330
|
'no dispatch', 'no delegate', 'no delegation', 'no work item',
|
|
2289
2331
|
'without dispatching', 'without delegating', 'without creating work item',
|
|
2290
2332
|
];
|
|
2333
|
+
const ANSWERED_ASK_MIN_CHARS = 80;
|
|
2334
|
+
const ANSWERED_ASK_INCOMPLETE_PHRASES = [
|
|
2335
|
+
'i will dispatch', 'ill dispatch', 'i will delegate', 'ill delegate',
|
|
2336
|
+
'i will ask', 'ill ask', 'need to dispatch', 'needs to dispatch',
|
|
2337
|
+
'need to delegate', 'needs to delegate', 'need an agent', 'needs an agent',
|
|
2338
|
+
'hand off', 'hand this off', 'deeper investigation', 'further investigation',
|
|
2339
|
+
'cannot answer', 'cant answer', 'could not answer', 'couldnt answer',
|
|
2340
|
+
'not enough information',
|
|
2341
|
+
];
|
|
2291
2342
|
|
|
2292
2343
|
function _isIntentWordChar(ch) {
|
|
2293
2344
|
const code = ch.charCodeAt(0);
|
|
@@ -2373,6 +2424,37 @@ function _messageHasDelegationIntent(message) {
|
|
|
2373
2424
|
return _intentHasAnyPhrase(normalized, DELEGATION_MINIONS_PHRASES);
|
|
2374
2425
|
}
|
|
2375
2426
|
|
|
2427
|
+
function _delegationTokenIsImperativeVerb(tokens, idx) {
|
|
2428
|
+
const term = tokens[idx];
|
|
2429
|
+
if (!term) return false;
|
|
2430
|
+
if (!DELEGATION_AMBIGUOUS_NOUN_TERMS.has(term)) return true;
|
|
2431
|
+
const next = tokens[idx + 1];
|
|
2432
|
+
if (!next) return true;
|
|
2433
|
+
return !DELEGATION_NON_VERB_FOLLOW_ONS.has(next);
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
function _messageExplicitlyRequestsDelegation(message) {
|
|
2437
|
+
const normalized = _normalizeIntentText(message);
|
|
2438
|
+
const tokens = _intentTokens(normalized);
|
|
2439
|
+
if (!tokens.length) return false;
|
|
2440
|
+
if (_intentHasAnyPhrase(normalized, DELEGATION_MINIONS_PHRASES)) return true;
|
|
2441
|
+
if (_intentHasPhrase(normalized, 'work item') && _intentHasAnyToken(normalized, ['create', 'open', 'add'])) return true;
|
|
2442
|
+
|
|
2443
|
+
let i = 0;
|
|
2444
|
+
while (DELEGATION_REQUEST_PREFIX_TERMS.includes(tokens[i])) i++;
|
|
2445
|
+
if (DELEGATION_ACTION_TERMS.includes(tokens[i]) && _delegationTokenIsImperativeVerb(tokens, i)) return true;
|
|
2446
|
+
if (DELEGATION_PERSON_ACTION_TERMS.includes(tokens[i])) {
|
|
2447
|
+
return tokens.slice(i + 1, i + 7).includes('to');
|
|
2448
|
+
}
|
|
2449
|
+
for (let j = 0; j < tokens.length && j <= 6; j++) {
|
|
2450
|
+
if (!DELEGATION_ACTION_TERMS.includes(tokens[j])) continue;
|
|
2451
|
+
if (!_delegationTokenIsImperativeVerb(tokens, j)) continue;
|
|
2452
|
+
const prefix = tokens.slice(0, j);
|
|
2453
|
+
if (prefix.includes('you') || prefix.includes('minions') || prefix.includes('minion')) return true;
|
|
2454
|
+
}
|
|
2455
|
+
return false;
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2376
2458
|
function _messageRequestsDirectHandling(message) {
|
|
2377
2459
|
const normalized = _normalizeIntentText(message);
|
|
2378
2460
|
if (!normalized.trim()) return false;
|
|
@@ -2412,6 +2494,24 @@ function _inferDelegatedWorkType(message) {
|
|
|
2412
2494
|
return 'ask';
|
|
2413
2495
|
}
|
|
2414
2496
|
|
|
2497
|
+
function _ccAnswerLooksCompleteForAsk(answerText, toolUses = []) {
|
|
2498
|
+
if (!Array.isArray(toolUses) || toolUses.length === 0) return false;
|
|
2499
|
+
const answer = _collapseWhitespace(stripCCActionSyntax(answerText || ''));
|
|
2500
|
+
if (answer.length < ANSWERED_ASK_MIN_CHARS) return false;
|
|
2501
|
+
const normalized = _normalizeIntentText(answer);
|
|
2502
|
+
if (_intentHasAnyPhrase(normalized, ANSWERED_ASK_INCOMPLETE_PHRASES)) return false;
|
|
2503
|
+
if (_intentHasVerbObject(normalized, ['need', 'needs', 'require', 'requires'], ['agent', 'delegation', 'investigation', 'research'])) return false;
|
|
2504
|
+
return true;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
function _ccShouldSuppressAnsweredAskDispatch(action, opts = {}) {
|
|
2508
|
+
const normalized = normalizeCCAction(action);
|
|
2509
|
+
if (normalized?.type !== 'dispatch') return false;
|
|
2510
|
+
if (String(normalized.workType || '').trim().toLowerCase() !== 'ask') return false;
|
|
2511
|
+
if (_messageExplicitlyRequestsDelegation(opts.message)) return false;
|
|
2512
|
+
return _ccAnswerLooksCompleteForAsk(opts.answerText, opts.toolUses);
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2415
2515
|
function _collapseWhitespace(text) {
|
|
2416
2516
|
let out = '';
|
|
2417
2517
|
let lastWasSpace = true;
|
|
@@ -2504,11 +2604,13 @@ function _inferDelegationActionFromMessage(message, { source = 'command-center',
|
|
|
2504
2604
|
}
|
|
2505
2605
|
|
|
2506
2606
|
function _ensureDelegationForIntent(actions, opts = {}) {
|
|
2507
|
-
const list = Array.isArray(actions) ? actions.map(normalizeCCAction) : []
|
|
2607
|
+
const list = (Array.isArray(actions) ? actions.map(normalizeCCAction) : [])
|
|
2608
|
+
.filter(action => !_ccShouldSuppressAnsweredAskDispatch(action, opts));
|
|
2508
2609
|
if (_messageRequestsDirectHandling(opts.message)) return list.filter(a => normalizeCCAction(a)?.type !== 'dispatch');
|
|
2509
2610
|
if (list.some(a => normalizeCCAction(a)?.type === 'dispatch')) return list;
|
|
2510
2611
|
if (list.length > 0) return list;
|
|
2511
2612
|
const inferred = _inferDelegationActionFromMessage(opts.message, opts);
|
|
2613
|
+
if (_ccShouldSuppressAnsweredAskDispatch(inferred, opts)) return list;
|
|
2512
2614
|
return inferred ? [...list, inferred] : list;
|
|
2513
2615
|
}
|
|
2514
2616
|
|
|
@@ -7100,6 +7202,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7100
7202
|
try {
|
|
7101
7203
|
const body = await readBody(req);
|
|
7102
7204
|
if (!body.message) return jsonReply(res, 400, { error: 'message required' });
|
|
7205
|
+
const actionRequestedAt = new Date().toISOString();
|
|
7103
7206
|
|
|
7104
7207
|
// Per-tab concurrency guard
|
|
7105
7208
|
tabId = body.tabId || 'default';
|
|
@@ -7155,7 +7258,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7155
7258
|
{ message: body.message, intentMetadata: body.intentMetadata, source: 'command-center', answerText: parsed.text, toolUses }
|
|
7156
7259
|
);
|
|
7157
7260
|
if (parsed.actions.length > 0) {
|
|
7158
|
-
parsed.actionResults =
|
|
7261
|
+
parsed.actionResults = _annotateCCActionResults(
|
|
7262
|
+
parsed.actions,
|
|
7263
|
+
await executeCCActions(parsed.actions),
|
|
7264
|
+
{ message: body.message, requestedAt: actionRequestedAt }
|
|
7265
|
+
);
|
|
7159
7266
|
}
|
|
7160
7267
|
// Mirror only user-facing text to Teams; never send the internal action block.
|
|
7161
7268
|
if (!tabId.startsWith('teams-')) {
|
|
@@ -7259,6 +7366,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7259
7366
|
const body = await readBody(req);
|
|
7260
7367
|
if (!body.message && !body.reconnect) { res.statusCode = 400; res.end('message required'); return; }
|
|
7261
7368
|
tabId = body.tabId || 'default';
|
|
7369
|
+
const actionRequestedAt = new Date().toISOString();
|
|
7262
7370
|
if (body.reconnect) {
|
|
7263
7371
|
const live = _getCcLiveStream(tabId);
|
|
7264
7372
|
if (!live) { res.statusCode = 409; res.end('No live command-center response to reconnect'); return; }
|
|
@@ -7487,7 +7595,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
7487
7595
|
);
|
|
7488
7596
|
let actionResults;
|
|
7489
7597
|
if (actions.length > 0) {
|
|
7490
|
-
actionResults =
|
|
7598
|
+
actionResults = _annotateCCActionResults(
|
|
7599
|
+
actions,
|
|
7600
|
+
await executeCCActions(actions),
|
|
7601
|
+
{ message: body.message, requestedAt: actionRequestedAt }
|
|
7602
|
+
);
|
|
7491
7603
|
}
|
|
7492
7604
|
const donePayload = { type: 'done', text: displayText, actions, actionResults, sessionId: responseSessionId, newSession: !wasResume };
|
|
7493
7605
|
// Issue #1834: surface action JSON parse failures so the UI can warn
|
package/engine/cli.js
CHANGED
|
@@ -1531,4 +1531,10 @@ module.exports = {
|
|
|
1531
1531
|
_controlBelongsToOwner: controlBelongsToOwner,
|
|
1532
1532
|
_markControlStoppingForOwner: markControlStoppingForOwner,
|
|
1533
1533
|
_markControlStoppedForOwner: markControlStoppedForOwner,
|
|
1534
|
+
_isPidAlive: isPidAlive,
|
|
1535
|
+
_summarizeActiveDispatchPids: summarizeActiveDispatchPids,
|
|
1536
|
+
_dispatchSafeId: dispatchSafeId,
|
|
1537
|
+
_readDispatchPid: readDispatchPid,
|
|
1538
|
+
_normalizeSessionBranch: normalizeSessionBranch,
|
|
1539
|
+
_dispatchSessionBranch: dispatchSessionBranch,
|
|
1534
1540
|
};
|
package/engine/shared.js
CHANGED
|
@@ -3451,6 +3451,10 @@ module.exports = {
|
|
|
3451
3451
|
legacyProjectStatePath,
|
|
3452
3452
|
ensureProjectStateFiles,
|
|
3453
3453
|
sameResolvedPath,
|
|
3454
|
+
projectStateRecordKey, // exported for testing
|
|
3455
|
+
mergeProjectStateArrays, // exported for testing
|
|
3456
|
+
realPathForComparison, // exported for testing
|
|
3457
|
+
prPathComparisonCandidates, // exported for testing
|
|
3454
3458
|
resolveProjectForPrPath, // exported for testing
|
|
3455
3459
|
getPrLinks,
|
|
3456
3460
|
addPrLink,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1817",
|
|
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"
|
package/prompts/cc-system.md
CHANGED
|
@@ -98,6 +98,7 @@ I'll dispatch dallas to fix that bug.
|
|
|
98
98
|
Core action types:
|
|
99
99
|
- **dispatch**: title (REQUIRED), workType, priority (low/medium/high), agents[] or agent (optional — both shapes accepted), project (REQUIRED when multi-project unless `pr` resolves to a tracked PR), description, pr (optional PR number/id/url for work that targets an existing PR), scope (`"fan-out"` only when the user explicitly asks to fan out to all agents). Do not emit `type:"fix"` or `type:"implement"`; emit `type:"dispatch"` with `workType:"fix"` or emit `type:"dispatch"` with `workType:"implement"`.
|
|
100
100
|
workTypes: `explore` (research/report only, NO PR), `ask` (answer/report, NO PR), `implement` (new code, PR REQUIRED), `fix` (standalone bug fix creates a PR; include `pr` when fixing review comments/build failures on an existing PR), `review` (code review, NO PR), `test` (tests, PR if new), `verify` (merge/build/maintenance, NO PR)
|
|
101
|
+
Do not dispatch an `ask` work item for a question you already answered inline in the same turn, especially after using tools. If the answer needs deeper investigation, give a brief handoff note and dispatch; do not both provide a complete answer and queue an agent to repeat it.
|
|
101
102
|
If the user wants a design/architecture artifact committed through a PR, dispatch `implement` or `docs` rather than `explore`.
|
|
102
103
|
When the user names a specific agent ("assign this to lambert"), put exactly that one name in `agents` (e.g. `"agents": ["lambert"]`). A single-agent assignment is hard-pinned by the server — it will queue for that agent only and skip the routing table. If the user explicitly asks for fan-out/all agents, set `scope: "fan-out"`.
|
|
103
104
|
After emitting a dispatch-like action, return immediately; do not poll, monitor, watch, wait, or check until completion, and do not add follow-up status actions. Only create a watch, monitor, poll, or periodically check when the human explicitly asks for monitoring, watching, periodic checks, or notification on completion.
|