@yemi33/minions 0.1.1838 → 0.1.1840

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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1840 (2026-05-10)
4
+
5
+ ### Other
6
+ - refactor(cc): skip describeCcProtectedPaths render when template lacks placeholder
7
+
8
+ ## 0.1.1839 (2026-05-10)
9
+
10
+ ### Other
11
+ - refactor(cc): simplify CC migration code per /simplify review
12
+
3
13
  ## 0.1.1838 (2026-05-10)
4
14
 
5
15
  ### Features
package/dashboard.js CHANGED
@@ -1592,21 +1592,20 @@ const DOC_CHAT_SYSTEM_PROMPT_RAW = (() => {
1592
1592
  }
1593
1593
  })();
1594
1594
 
1595
- const DOC_CHAT_SYSTEM_PROMPT = DOC_CHAT_SYSTEM_PROMPT_RAW
1596
- .replace(/\{\{minions_dir\}\}/g, MINIONS_DIR);
1595
+ const DOC_CHAT_SYSTEM_PROMPT = shared.renderCcSystemPrompt(DOC_CHAT_SYSTEM_PROMPT_RAW, { liveRoot: MINIONS_DIR });
1597
1596
 
1598
1597
  function renderDocChatSystemPromptForTurn(turnId) {
1599
- return DOC_CHAT_SYSTEM_PROMPT_RAW
1600
- .replace(/\{\{minions_dir\}\}/g, MINIONS_DIR)
1601
- .replace(/\{\{cc_turn_id\}\}/g, String(turnId || ''))
1602
- .replace(/\{\{dashboard_port\}\}/g, String(PORT));
1598
+ return shared.renderCcSystemPrompt(DOC_CHAT_SYSTEM_PROMPT_RAW, {
1599
+ liveRoot: MINIONS_DIR,
1600
+ turnId: turnId || '',
1601
+ dashboardPort: PORT,
1602
+ });
1603
1603
  }
1604
1604
 
1605
1605
  // Per-CC-turn correlation. CC's tool calls (Bash curl to /api/...) attach an
1606
- // X-CC-Turn-Id header; the mutating endpoints record creations into this map
1607
- // keyed by the turn ID so the CC handler can surface them as confirmation
1608
- // chips in the user's reply. Complements (and will eventually replace) the
1609
- // ===ACTIONS=== protocol — both currently active during transition.
1606
+ // X-CC-Turn-Id header; mutating endpoints record their creations into this
1607
+ // map keyed by the turn ID so the CC handler can surface them as confirmation
1608
+ // chips in the user's reply.
1610
1609
  const _ccTurnCreations = new Map();
1611
1610
  const CC_TURN_CREATION_TTL_MS = (() => {
1612
1611
  const env = parseInt(process.env.CC_TURN_CREATION_TTL_MS || '', 10);
@@ -1649,10 +1648,17 @@ function _readCcTurnIdHeader(req) {
1649
1648
  return trimmed;
1650
1649
  }
1651
1650
 
1652
- // Build synthetic action results from the turn map so the existing renderer
1653
- // (_ccActionContextSuffix in dashboard/js/command-center.js) shows the same
1654
- // "Dispatched: <id>" chip whether the work item was created by a direct CC API
1655
- // call or by the (now-removed) ===ACTIONS=== executor.
1651
+ // Mutating endpoint helper: records the creation under the request's CC turn
1652
+ // ID if one was sent, otherwise no-ops. Keeps the wiring at each handler down
1653
+ // to a single line.
1654
+ function recordCcTurnIfPresent(req, entry) {
1655
+ const turnId = _readCcTurnIdHeader(req);
1656
+ if (turnId) _recordCcTurnCreation(turnId, entry);
1657
+ }
1658
+
1659
+ // Build action results from the turn map so the existing renderer
1660
+ // (_ccActionContextSuffix in dashboard/js/command-center.js) shows a
1661
+ // "Dispatched: <id>" chip for each direct CC API call.
1656
1662
  function _buildSyntheticActionResultsForTurn(turnId, message, requestedAt) {
1657
1663
  const entries = _consumeCcTurnCreations(turnId);
1658
1664
  if (entries.length === 0) return { actions: [], results: [] };
@@ -1693,22 +1699,23 @@ function _buildSyntheticActionResultsForTurn(turnId, message, requestedAt) {
1693
1699
  return { actions, results };
1694
1700
  }
1695
1701
 
1696
- // Cheap mtime+size snapshot used by doc-chat to detect whether CC's `Edit` /
1697
- // `Write` tool calls actually changed the target file during a turn. A diff
1698
- // triggers a "Document saved" chip via the same _ccTurnCreations surface used
1699
- // by mutating /api/* endpoints.
1702
+ // mtime+size snapshot used by doc-chat to detect whether CC's Edit/Write
1703
+ // tool calls actually changed the target file during a turn. Null sentinel
1704
+ // distinguishes "file present" from "file absent" so deletions don't fire
1705
+ // a "Document saved" chip.
1700
1706
  function _snapshotDocFile(fullPath) {
1701
1707
  if (!fullPath) return null;
1702
1708
  try {
1703
1709
  const st = fs.statSync(fullPath);
1704
1710
  return { mtimeMs: st.mtimeMs, size: st.size };
1705
- } catch { return { mtimeMs: 0, size: 0 }; } // missing file → all changes look like edits
1711
+ } catch { return null; }
1706
1712
  }
1707
1713
 
1708
1714
  function _docFileChanged(before, fullPath) {
1709
1715
  if (!fullPath) return false;
1710
1716
  const after = _snapshotDocFile(fullPath);
1711
- if (!before || !after) return false;
1717
+ if (!after) return false;
1718
+ if (!before) return true;
1712
1719
  return before.mtimeMs !== after.mtimeMs || before.size !== after.size;
1713
1720
  }
1714
1721
 
@@ -2893,11 +2900,10 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
2893
2900
  return _docChatFailureResponse('doc-chat', filePath, result, sessionPreserved);
2894
2901
  }
2895
2902
 
2896
- // No more ===ACTIONS=== / ---DOCUMENT--- parsing CC's text answer is the
2897
- // visible reply; file edits land via Edit/Write tools (validated in
2898
- // _finalizeDocChatEdit by re-reading disk); state mutations land via direct
2899
- // /api/* calls (correlated by X-CC-Turn-Id, surfaced as synthetic chips
2900
- // server-side).
2903
+ // CC's text answer is the visible reply. File edits land via the Edit/Write
2904
+ // tools (verified by _finalizeDocChatEdit re-reading disk); state mutations
2905
+ // land via direct /api/* calls (correlated by X-CC-Turn-Id, surfaced as
2906
+ // chips server-side).
2901
2907
  return { answer: result.text, toolUses: Array.isArray(result.toolUses) ? result.toolUses : [] };
2902
2908
  }
2903
2909
 
@@ -2955,11 +2961,10 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
2955
2961
  return _docChatFailureResponse('doc-chat-stream', filePath, result, sessionPreserved);
2956
2962
  }
2957
2963
 
2958
- // No more ===ACTIONS=== / ---DOCUMENT--- parsing CC's text answer is the
2959
- // visible reply; file edits land via Edit/Write tools (validated in
2960
- // _finalizeDocChatEdit by re-reading disk); state mutations land via direct
2961
- // /api/* calls (correlated by X-CC-Turn-Id, surfaced as synthetic chips
2962
- // server-side).
2964
+ // CC's text answer is the visible reply. File edits land via the Edit/Write
2965
+ // tools (verified by _finalizeDocChatEdit re-reading disk); state mutations
2966
+ // land via direct /api/* calls (correlated by X-CC-Turn-Id, surfaced as
2967
+ // chips server-side).
2963
2968
  return { answer: result.text, toolUses: Array.isArray(result.toolUses) ? result.toolUses : [] };
2964
2969
  }
2965
2970
 
@@ -3641,13 +3646,7 @@ const server = http.createServer(async (req, res) => {
3641
3646
  const duplicateId = createResult.duplicateOf || createResult.item?.id;
3642
3647
  return jsonReply(res, 200, { ok: true, id: duplicateId, duplicate: true, duplicateOf: duplicateId });
3643
3648
  }
3644
- // CC turn-ID correlation: record direct API creations so the CC handler
3645
- // can surface a "Dispatched: <id>" chip in the assistant reply without
3646
- // CC needing to also emit an ===ACTIONS=== block.
3647
- const _ccTurn = _readCcTurnIdHeader(req);
3648
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, {
3649
- kind: 'work-item', id, title: item.title, project: item.project || null,
3650
- });
3649
+ recordCcTurnIfPresent(req, { kind: 'work-item', id, title: item.title, project: item.project || null });
3651
3650
  return jsonReply(res, 200, { ok: true, id });
3652
3651
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
3653
3652
  }
@@ -3704,8 +3703,7 @@ const server = http.createServer(async (req, res) => {
3704
3703
  const content = `# ${body.title}\n\n**By:** ${author}\n**Date:** ${today}\n\n${body.what}\n${body.why ? '\n**Why:** ' + body.why + '\n' : ''}`;
3705
3704
  safeWrite(shared.uniquePath(path.join(inboxDir, filename)), content);
3706
3705
  invalidateStatusCache();
3707
- const _ccTurn = _readCcTurnIdHeader(req);
3708
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, { kind: 'note', title: body.title.trim() });
3706
+ recordCcTurnIfPresent(req, { kind: 'note', title: body.title.trim() });
3709
3707
  return jsonReply(res, 200, { ok: true });
3710
3708
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
3711
3709
  }
@@ -3719,8 +3717,7 @@ const server = http.createServer(async (req, res) => {
3719
3717
  // Write as a work item with type 'plan' — user must explicitly execute plan-to-prd after reviewing
3720
3718
  const wiPath = path.join(MINIONS_DIR, 'work-items.json');
3721
3719
  mutateWorkItems(wiPath, items => { items.push(planWorkItem.item); });
3722
- const _ccTurn = _readCcTurnIdHeader(req);
3723
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, {
3720
+ recordCcTurnIfPresent(req, {
3724
3721
  kind: 'plan', id: planWorkItem.id, title: planWorkItem.item?.title || body.title.trim(), project: planWorkItem.item?.project || null,
3725
3722
  });
3726
3723
  return jsonReply(res, 200, { ok: true, id: planWorkItem.id, agent: body.agent || '' });
@@ -5669,10 +5666,9 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5669
5666
  }
5670
5667
  const wasResume = !!(body.sessionId && body.sessionId === ccSession.sessionId && ccSessionValid());
5671
5668
 
5672
- // Per-turn correlation: CC includes X-CC-Turn-Id when calling /api/*
5673
- // mutating endpoints; the turn map collects creations so we can surface
5674
- // them as confirmation chips alongside any (now-legacy) ===ACTIONS===
5675
- // results.
5669
+ // Per-turn correlation: CC includes X-CC-Turn-Id on its /api/* tool
5670
+ // calls; the turn map collects creations so we surface them as
5671
+ // confirmation chips in the assistant reply.
5676
5672
  const ccTurnId = 'cct-' + shared.uid();
5677
5673
  const turnSystemPrompt = renderCcSystemPromptForTurn(ccTurnId);
5678
5674
  const result = await ccCall(body.message, { store: 'cc', transcript: body.transcript, systemPrompt: turnSystemPrompt });
@@ -5928,9 +5924,8 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5928
5924
  const streamModel = CONFIG.engine?.ccModel || shared.ENGINE_DEFAULTS.ccModel;
5929
5925
  const streamEffort = CONFIG.engine?.ccEffort || shared.ENGINE_DEFAULTS.ccEffort;
5930
5926
  const ccMaxTurns = CONFIG.engine?.ccMaxTurns || shared.ENGINE_DEFAULTS.ccMaxTurns;
5931
- // Per-turn correlation header: CC threads X-CC-Turn-Id when calling
5932
- // /api/* endpoints; matching creations get surfaced as confirmation
5933
- // chips alongside any (legacy) ===ACTIONS=== executor results.
5927
+ // Per-turn correlation header: CC threads X-CC-Turn-Id on its /api/*
5928
+ // tool calls; matching creations get surfaced as confirmation chips.
5934
5929
  const ccTurnId = 'cct-' + shared.uid();
5935
5930
  const turnSystemPrompt = renderCcSystemPromptForTurn(ccTurnId);
5936
5931
  let toolUses = [];
@@ -6279,8 +6274,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
6279
6274
  try {
6280
6275
  const watch = watchesMod.createWatch({ target, targetType, condition, interval, owner, description, project, notify, stopAfter, onNotMet });
6281
6276
  invalidateStatusCache();
6282
- const _ccTurn = _readCcTurnIdHeader(req);
6283
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, {
6277
+ recordCcTurnIfPresent(req, {
6284
6278
  kind: 'watch', id: watch?.id || null, title: `Watch ${target}` + (condition ? ` (${condition})` : ''), project: project || null,
6285
6279
  });
6286
6280
  return jsonReply(res, 200, { ok: true, watch });
@@ -7237,8 +7231,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
7237
7231
  safeWrite(filePath, header + content);
7238
7232
  queries.invalidateKnowledgeBaseCache();
7239
7233
  invalidateStatusCache();
7240
- const _ccTurn = _readCcTurnIdHeader(req);
7241
- if (_ccTurn) _recordCcTurnCreation(_ccTurn, { kind: 'knowledge', title, path: filePath });
7234
+ recordCcTurnIfPresent(req, { kind: 'knowledge', title, path: filePath });
7242
7235
  return jsonReply(res, 200, { ok: true, path: filePath });
7243
7236
  }},
7244
7237
  { method: 'POST', path: '/api/knowledge/sweep', desc: 'Trigger async KB sweep (returns 202)', handler: handleKnowledgeSweep },
@@ -7671,7 +7664,7 @@ module.exports = {
7671
7664
  _inferDocChatProject,
7672
7665
  _linkPullRequestForTracking: linkPullRequestForTracking,
7673
7666
  _resolveSkillReadPath,
7674
- // Per-CC-turn correlation surface (replaces ===ACTIONS=== protocol)
7667
+ // Per-CC-turn correlation surface
7675
7668
  _ccTurnCreations,
7676
7669
  _recordCcTurnCreation,
7677
7670
  _consumeCcTurnCreations,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-10T02:49:08.142Z"
4
+ "cachedAt": "2026-05-10T03:02:09.205Z"
5
5
  }
package/engine/shared.js CHANGED
@@ -2163,9 +2163,14 @@ function renderCcSystemPrompt(raw, opts) {
2163
2163
  const turnId = (opts && typeof opts.turnId === 'string') ? opts.turnId : '';
2164
2164
  const dashboardPort = (opts && opts.dashboardPort !== undefined && opts.dashboardPort !== null && opts.dashboardPort !== '')
2165
2165
  ? String(opts.dashboardPort) : '7331';
2166
- return String(raw || '')
2167
- .replace(/\{\{minions_dir\}\}/g, liveRoot)
2168
- .replace(/\{\{cc_protected_paths\}\}/g, describeCcProtectedPaths(liveRoot))
2166
+ let out = String(raw || '').replace(/\{\{minions_dir\}\}/g, liveRoot);
2167
+ // describeCcProtectedPaths builds a ~250-byte string from three array
2168
+ // joins — skip it when the template doesn't actually need the rule
2169
+ // (e.g. doc-chat-system.md), which otherwise burns the work per turn.
2170
+ if (out.includes('{{cc_protected_paths}}')) {
2171
+ out = out.replace(/\{\{cc_protected_paths\}\}/g, describeCcProtectedPaths(liveRoot));
2172
+ }
2173
+ return out
2169
2174
  .replace(/\{\{cc_turn_id\}\}/g, turnId)
2170
2175
  .replace(/\{\{dashboard_port\}\}/g, dashboardPort);
2171
2176
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1838",
3
+ "version": "0.1.1840",
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"