@yemi33/minions 0.1.2245 → 0.1.2247
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/slim/body.html +28 -0
- package/dashboard/slim/js/chat.js +146 -16
- package/dashboard/slim/js/command-send.js +100 -77
- package/dashboard/slim/js/modals-tiles.js +23 -0
- package/dashboard/slim/js/plans.js +550 -0
- package/dashboard/slim/js/status.js +7 -0
- package/dashboard/slim/styles.css +4 -3
- package/dashboard-build.js +1 -1
- package/docs/slim-ux/architecture-suggestions.md +10 -0
- package/docs/slim-ux/concepts.md +20 -0
- package/engine/lifecycle.js +52 -0
- package/engine/shared.js +16 -0
- package/engine.js +4 -4
- package/package.json +1 -1
package/engine/lifecycle.js
CHANGED
|
@@ -3906,12 +3906,47 @@ function _deferRetryWithCounter(meta, detection, counterField, maxCount, pending
|
|
|
3906
3906
|
if (!wiPath) return reason;
|
|
3907
3907
|
|
|
3908
3908
|
let finalStatus = WI_STATUS.PENDING;
|
|
3909
|
+
let systematicPhantom = null;
|
|
3909
3910
|
try {
|
|
3910
3911
|
mutateJsonFileLocked(wiPath, data => {
|
|
3911
3912
|
if (!Array.isArray(data)) return data;
|
|
3912
3913
|
const w = data.find(i => i.id === itemId);
|
|
3913
3914
|
if (!w) return data;
|
|
3914
3915
|
const retries = w[counterField] || 0;
|
|
3916
|
+
|
|
3917
|
+
// Systematic phantom detection: after 2+ phantom completions spanning
|
|
3918
|
+
// 2+ different agents, the failure is likely content-filter or prompt-
|
|
3919
|
+
// malformed. Mark non-retryable immediately so human can intervene.
|
|
3920
|
+
if (counterField === '_phantomRetryCount') {
|
|
3921
|
+
const phantomAgent = meta?._agentId || w.dispatched_to;
|
|
3922
|
+
if (!w._phantomAgents || typeof w._phantomAgents !== 'object' || Array.isArray(w._phantomAgents)) {
|
|
3923
|
+
w._phantomAgents = {};
|
|
3924
|
+
}
|
|
3925
|
+
if (phantomAgent) {
|
|
3926
|
+
w._phantomAgents[phantomAgent] = (w._phantomAgents[phantomAgent] || 0) + 1;
|
|
3927
|
+
}
|
|
3928
|
+
const distinctAgents = Object.keys(w._phantomAgents);
|
|
3929
|
+
if (distinctAgents.length >= 2 && retries >= 1) {
|
|
3930
|
+
w.status = WI_STATUS.FAILED;
|
|
3931
|
+
w.failReason = `Systematic phantom completion across ${distinctAgents.length} agents ` +
|
|
3932
|
+
`(${distinctAgents.join(', ')}) — likely a content filter triggered by the task description ` +
|
|
3933
|
+
`or a malformed prompt. Manual intervention required.`;
|
|
3934
|
+
w._failureClass = 'phantom-all-agents';
|
|
3935
|
+
w.failedAt = ts();
|
|
3936
|
+
delete w.completedAt;
|
|
3937
|
+
delete w.dispatched_at;
|
|
3938
|
+
delete w.dispatched_to;
|
|
3939
|
+
delete w._pendingReason;
|
|
3940
|
+
delete w._phantomCompletion;
|
|
3941
|
+
delete w._phantomBranch;
|
|
3942
|
+
finalStatus = WI_STATUS.FAILED;
|
|
3943
|
+
systematicPhantom = { distinctCount: distinctAgents.length, agents: distinctAgents };
|
|
3944
|
+
log('warn', `Work item ${itemId} systematically phantoms across ${distinctAgents.length} agents ` +
|
|
3945
|
+
`(${distinctAgents.join(', ')}) — marking non-retryable (phantom-all-agents)`);
|
|
3946
|
+
return data;
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3915
3950
|
if (retries < maxCount) {
|
|
3916
3951
|
w.status = WI_STATUS.PENDING;
|
|
3917
3952
|
w[counterField] = retries + 1;
|
|
@@ -3963,6 +3998,20 @@ function _deferRetryWithCounter(meta, detection, counterField, maxCount, pending
|
|
|
3963
3998
|
} catch (err) {
|
|
3964
3999
|
log('warn', `${pendingReason} gate: ${err.message}`);
|
|
3965
4000
|
}
|
|
4001
|
+
// Post diagnostic inbox note when systematic phantom detection fired.
|
|
4002
|
+
if (systematicPhantom) {
|
|
4003
|
+
shared.writeToInbox('engine', `phantom-all-agents-${itemId}`,
|
|
4004
|
+
`# Systematic phantom completion for ${itemId}\n\n` +
|
|
4005
|
+
`**Work item:** \`${itemId}\` — ${meta.item?.title || ''}\n` +
|
|
4006
|
+
`**Agents that all phantom-completed:** ${systematicPhantom.agents.join(', ')}\n\n` +
|
|
4007
|
+
`All ${systematicPhantom.distinctCount} agents produced phantom completions ` +
|
|
4008
|
+
`(process exited 0 but emitted no result event). This pattern is typically caused by:\n` +
|
|
4009
|
+
`- A runtime content filter triggered by credential-shaped strings in the task description\n` +
|
|
4010
|
+
`- A malformed prompt that causes the runtime to bail out silently\n\n` +
|
|
4011
|
+
`The work item has been marked non-retryable. **Manual intervention required.**\n`,
|
|
4012
|
+
null,
|
|
4013
|
+
{ sourceItem: itemId, reason: 'phantom-all-agents' });
|
|
4014
|
+
}
|
|
3966
4015
|
return reason;
|
|
3967
4016
|
}
|
|
3968
4017
|
|
|
@@ -5019,6 +5068,9 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
|
|
|
5019
5068
|
log('info', `Phantom-completion recovered for ${meta.item.id} via ls-remote + PR auto-link — no retry needed`);
|
|
5020
5069
|
} else {
|
|
5021
5070
|
skipDoneStatus = true;
|
|
5071
|
+
// Stamp agentId on meta so _deferRetryWithCounter can track
|
|
5072
|
+
// phantom completions per agent (systematic phantom detection).
|
|
5073
|
+
if (!meta._agentId) meta._agentId = agentId;
|
|
5022
5074
|
const reason = isPhantomDetection
|
|
5023
5075
|
? deferPhantomCompletion(meta, nonTerminalCompletion)
|
|
5024
5076
|
: deferNonTerminalCompletion(meta, nonTerminalCompletion);
|
package/engine/shared.js
CHANGED
|
@@ -415,6 +415,21 @@ function redactSecrets(value, options = {}) {
|
|
|
415
415
|
return value;
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
+
// Authorization header pattern broader than _BEARER_RE: catches already-redacted
|
|
419
|
+
// placeholder forms (e.g. `Authorization: Bearer <REDACTED>`) that still look
|
|
420
|
+
// credential-shaped to Copilot CLI safety filters and cause silent phantom exits.
|
|
421
|
+
const _AUTH_HEADER_RE = /\bAuthorization\s*:\s*Bearer\s+\S+/gi;
|
|
422
|
+
|
|
423
|
+
// Redactor applied to WI description text before it is injected into an agent
|
|
424
|
+
// prompt. Applies the standard log redactor (_redactString) first, then catches
|
|
425
|
+
// any remaining Authorization: Bearer header — including already-redacted forms
|
|
426
|
+
// with placeholder values — that would trigger Copilot CLI safety bail-outs.
|
|
427
|
+
function redactPromptDescription(s) {
|
|
428
|
+
if (s == null) return s;
|
|
429
|
+
if (typeof s !== 'string' || s.length === 0) return s;
|
|
430
|
+
return _redactString(s).replace(_AUTH_HEADER_RE, 'Authorization: Bearer [REDACTED-IN-DESC]');
|
|
431
|
+
}
|
|
432
|
+
|
|
418
433
|
// ── Log Buffering ──────────────────────────────────────────────────────────
|
|
419
434
|
// Buffer log entries in memory and flush to disk periodically to reduce lock
|
|
420
435
|
// contention (~139 calls/tick → 1 lock acquisition per flush).
|
|
@@ -9089,6 +9104,7 @@ module.exports = {
|
|
|
9089
9104
|
openAppendLogFd,
|
|
9090
9105
|
flushLogs,
|
|
9091
9106
|
redactSecrets,
|
|
9107
|
+
redactPromptDescription,
|
|
9092
9108
|
slugify,
|
|
9093
9109
|
getPrAutomationCauses,
|
|
9094
9110
|
hasPrAutomationCause,
|
package/engine.js
CHANGED
|
@@ -7337,9 +7337,9 @@ function renderProjectWorkItemPromptForAgent(item, workType, agentId, config, pr
|
|
|
7337
7337
|
item_id: item.id,
|
|
7338
7338
|
item_name: item.title || item.id,
|
|
7339
7339
|
item_priority: item.priority || 'medium',
|
|
7340
|
-
item_description: item.description || '',
|
|
7340
|
+
item_description: shared.redactPromptDescription(item.description || ''),
|
|
7341
7341
|
item_complexity: item.complexity || item.estimated_complexity || 'medium',
|
|
7342
|
-
task_description: item.title + (item.description ? '\n\n' + item.description : ''),
|
|
7342
|
+
task_description: shared.redactPromptDescription(item.title + (item.description ? '\n\n' + item.description : '')),
|
|
7343
7343
|
task_id: item.id,
|
|
7344
7344
|
work_type: workType,
|
|
7345
7345
|
source_plan: item.sourcePlan || '',
|
|
@@ -8575,9 +8575,9 @@ function discoverCentralWorkItems(config) {
|
|
|
8575
8575
|
item_id: item.id,
|
|
8576
8576
|
item_name: item.title || item.id,
|
|
8577
8577
|
item_priority: item.priority || 'medium',
|
|
8578
|
-
item_description: item.description || '',
|
|
8578
|
+
item_description: shared.redactPromptDescription(item.description || ''),
|
|
8579
8579
|
item_complexity: item.complexity || item.estimated_complexity || 'medium',
|
|
8580
|
-
task_description: item.title + (item.description ? '\n\n' + item.description : ''),
|
|
8580
|
+
task_description: shared.redactPromptDescription(item.title + (item.description ? '\n\n' + item.description : '')),
|
|
8581
8581
|
task_id: item.id,
|
|
8582
8582
|
work_type: workType,
|
|
8583
8583
|
additional_context: item.prompt ? `## Additional Context\n\n${item.prompt}` : '',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2247",
|
|
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"
|