@yemi33/minions 0.1.1749 → 0.1.1750

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,15 +1,13 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.1749 (2026-05-06)
3
+ ## 0.1.1750 (2026-05-06)
4
4
 
5
- ### Features
6
- - lock CC/doc session writes via mutateJsonFileLocked (#2126)
7
- - lock meeting state RMW via mutateMeeting helper (#2125)
8
- - bounds-validate parseCronField min/max (#2124)
9
- - replace JSON.parse(safeRead) swallow with safeJsonArr in archiveList (#2123)
5
+ ### Fixes
6
+ - lock doc-chat into plain-response mode (no tool calls) (#2127)
7
+
8
+ ## 0.1.1748 (2026-05-06)
10
9
 
11
10
  ### Fixes
12
- - readBody aborts on >1MB and stops accumulating (P-c1read-7b3c) (#2121)
13
11
  - guard w.title.replace against null/undefined titles (#2120)
14
12
 
15
13
  ## 0.1.1746 (2026-05-06)
package/dashboard.js CHANGED
@@ -2646,8 +2646,11 @@ async function ccDocCall({ message, document, title, filePath, selection, canEdi
2646
2646
  store: 'doc', sessionKey,
2647
2647
  extraContext, label: 'doc-chat',
2648
2648
  timeout: DOC_CHAT_TIMEOUT_MS,
2649
- allowedTools: canEdit ? 'Read,Write,Edit,Glob,Grep' : 'Read,Glob,Grep',
2650
- maxTurns: canEdit ? 25 : 10,
2649
+ // Match Command Center's full tool surface and turn budget so doc-chat
2650
+ // can take action (read/write/edit/dispatch) instead of being limited
2651
+ // to Q&A. The doc-chat sysprompt still scopes orchestration to explicit
2652
+ // requests, and ---DOCUMENT--- remains the only document edit channel.
2653
+ allowedTools: 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch',
2651
2654
  skipStatePreamble: true,
2652
2655
  systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
2653
2656
  ...(model ? { model } : {}),
@@ -2702,8 +2705,10 @@ async function ccDocCallStreaming({ message, document, title, filePath, selectio
2702
2705
  store: 'doc', sessionKey,
2703
2706
  extraContext, label: 'doc-chat',
2704
2707
  timeout: DOC_CHAT_TIMEOUT_MS,
2705
- allowedTools: canEdit ? 'Read,Write,Edit,Glob,Grep' : 'Read,Glob,Grep',
2706
- maxTurns: canEdit ? 25 : 10,
2708
+ // Match Command Center's full tool surface — see ccDocCall for
2709
+ // rationale. Both wrappers must share the same policy so the streaming
2710
+ // variant doesn't diverge from the non-streaming one.
2711
+ allowedTools: 'Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch',
2707
2712
  skipStatePreamble: true,
2708
2713
  systemPrompt: DOC_CHAT_SYSTEM_PROMPT,
2709
2714
  ...(model ? { model } : {}),
@@ -5367,7 +5372,11 @@ What would you like to discuss or change? When you're happy, say "approve" and I
5367
5372
  const result = removeProject(target, { keepData: body.keepData === true, purge: body.purge === true });
5368
5373
  if (!result.ok) return jsonReply(res, result.error?.includes('No project') ? 404 : 400, result);
5369
5374
  reloadConfig();
5370
- invalidateStatusCache();
5375
+ // includeSlow: getStatus() caches the projects[] field in slow state (60s
5376
+ // TTL) — without flushing it, the removed project keeps appearing under
5377
+ // status.projects for up to a minute even though PROJECTS in memory is
5378
+ // already up to date.
5379
+ invalidateStatusCache({ includeSlow: true });
5371
5380
  return jsonReply(res, 200, result);
5372
5381
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
5373
5382
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "runtime": "copilot",
3
3
  "models": null,
4
- "cachedAt": "2026-05-06T18:54:37.862Z"
4
+ "cachedAt": "2026-05-06T20:21:49.605Z"
5
5
  }
package/engine/queries.js CHANGED
@@ -626,30 +626,32 @@ function getPullRequests(config) {
626
626
  const projectByName = new Map(projects.map(p => [p.name, p]));
627
627
  const allPrs = [];
628
628
  const seenIds = new Set();
629
- // Single pass over projects/* configured projects use their full config
630
- // (prUrlBase fill-in, _project name); unconfigured subdirs are tagged _ghost
631
- // so engine code can filter them out. Mirrors what shared.getPrLinks scans,
632
- // so PRD links and PR records stay in sync after a project is removed.
629
+ // Single pass over projects/* intersected with the configured project list.
630
+ // Filesystem dirs not in CONFIG.projects (e.g. a leftover .minions/projects/
631
+ // <removedName>/ recreated by a stale code path between archive and reload)
632
+ // are skipped so removed projects can't resurrect themselves through the
633
+ // status payload. Hidden dirs (.archived sidecar) are also skipped defensively
634
+ // — they live as siblings under projects/ and would otherwise be enumerated.
633
635
  let projectDirs = [];
634
636
  try {
635
637
  projectDirs = fs.readdirSync(path.join(MINIONS_DIR, 'projects'), { withFileTypes: true })
636
- .filter(d => d.isDirectory()).map(d => d.name);
638
+ .filter(d => d.isDirectory() && !d.name.startsWith('.')).map(d => d.name);
637
639
  } catch { /* projects dir missing */ }
638
640
  for (const dirName of projectDirs) {
639
- const project = projectByName.get(dirName) || null;
640
- const prPath = project ? projectPrPath(project) : path.join(MINIONS_DIR, 'projects', dirName, 'pull-requests.json');
641
+ const project = projectByName.get(dirName);
642
+ if (!project) continue; // unconfigured/removed don't surface
643
+ const prPath = projectPrPath(project);
641
644
  const prs = readJsonNoRestore(prPath);
642
645
  if (!Array.isArray(prs)) continue;
643
646
  shared.normalizePrRecords(prs, project);
644
- const base = project?.prUrlBase || '';
647
+ const base = project.prUrlBase || '';
645
648
  for (const pr of prs) {
646
649
  if (!pr?.id || seenIds.has(pr.id)) continue;
647
- if (project && !pr.url && base) {
650
+ if (!pr.url && base) {
648
651
  const prNumber = shared.getPrNumber(pr);
649
652
  if (prNumber != null) pr.url = base + prNumber;
650
653
  }
651
- pr._project = project ? (project.name || 'Project') : dirName;
652
- if (!project) pr._ghost = true;
654
+ pr._project = project.name || 'Project';
653
655
  allPrs.push(pr);
654
656
  seenIds.add(pr.id);
655
657
  }
package/engine/shared.js CHANGED
@@ -1499,9 +1499,22 @@ function projectRoot(project) {
1499
1499
 
1500
1500
  // All project state files live centrally in .minions/projects/{name}/
1501
1501
  // No state files in project repos — avoids worktree/git interference.
1502
+ //
1503
+ // projectStateDir is path-only (no fs side effects) — safe to call with stale
1504
+ // project references after `removeProject` archived the data dir. Write paths
1505
+ // (safeWrite, withFileLock, mutateJsonFileLocked) already mkdir the parent dir
1506
+ // at write time, so the dir is created lazily only when something is actually
1507
+ // written. Use projectStateDirEnsure() when a caller specifically needs the
1508
+ // directory to exist before doing its own fs ops.
1502
1509
  function projectStateDir(project) {
1503
1510
  const name = project.name || path.basename(project.localPath);
1504
- const dir = path.join(MINIONS_DIR, 'projects', name);
1511
+ return path.join(MINIONS_DIR, 'projects', name);
1512
+ }
1513
+
1514
+ // Same as projectStateDir() but mkdirs the directory. Use when the caller does
1515
+ // raw fs ops (writeFileSync etc.) that don't already create the parent dir.
1516
+ function projectStateDirEnsure(project) {
1517
+ const dir = projectStateDir(project);
1505
1518
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
1506
1519
  return dir;
1507
1520
  }
@@ -2860,6 +2873,7 @@ module.exports = {
2860
2873
  getProjects,
2861
2874
  projectRoot,
2862
2875
  projectStateDir,
2876
+ projectStateDirEnsure,
2863
2877
  projectWorkItemsPath,
2864
2878
  projectPrPath,
2865
2879
  resolveProjectForPrPath, // exported for testing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1749",
3
+ "version": "0.1.1750",
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"