@yemi33/minions 0.1.2448 → 0.1.2449

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.
Files changed (315) hide show
  1. package/bin/cli-api-client.js +1 -1
  2. package/bin/install-internal-minions.js +1382 -44
  3. package/bin/install-layout.js +150 -0
  4. package/bin/minions.js +460 -167
  5. package/dashboard/docs/typography.md +65 -12
  6. package/dashboard/js/command-center.js +58 -4
  7. package/dashboard/js/detail-panel.js +36 -0
  8. package/dashboard/js/memory-panel.js +59 -12
  9. package/dashboard/js/qa.js +179 -20
  10. package/dashboard/js/refresh.js +148 -12
  11. package/dashboard/js/render-dispatch.js +3 -4
  12. package/dashboard/js/render-inbox.js +2 -2
  13. package/dashboard/js/render-other.js +3 -3
  14. package/dashboard/js/render-pipelines.js +14 -0
  15. package/dashboard/js/render-plans.js +57 -9
  16. package/dashboard/js/render-prd.js +132 -23
  17. package/dashboard/js/render-prs.js +195 -166
  18. package/dashboard/js/render-schedules.js +63 -3
  19. package/dashboard/js/render-utils.js +3 -3
  20. package/dashboard/js/render-watches.js +19 -3
  21. package/dashboard/js/render-work-items.js +238 -30
  22. package/dashboard/js/settings.js +205 -54
  23. package/dashboard/js/utils.js +51 -1
  24. package/dashboard/pages/home.html +1 -1
  25. package/dashboard/pages/qa.html +1 -16
  26. package/dashboard/pages/work.html +40 -0
  27. package/dashboard/shared/cc-limits.js +79 -0
  28. package/dashboard/shared/pr-filters.js +21 -38
  29. package/dashboard/shared/project-git-summary.js +1 -1
  30. package/dashboard/shared/record-filters.js +169 -0
  31. package/dashboard/shared/watches-source.js +1 -1
  32. package/dashboard/shared/welcome-popup.js +1 -1
  33. package/dashboard/shared/wi-filters.js +302 -0
  34. package/dashboard/slim/body.html +1 -0
  35. package/dashboard/slim/js/command-send.js +26 -0
  36. package/dashboard/slim/js/modals-tiles.js +380 -39
  37. package/dashboard/slim/js/status.js +13 -21
  38. package/dashboard/slim/layout.html +1 -0
  39. package/dashboard/slim/panel-bootstrap.js +6 -2
  40. package/dashboard/slim/styles.css +38 -0
  41. package/dashboard/styles.css +159 -55
  42. package/dashboard-build.js +13 -2
  43. package/dashboard.js +956 -423
  44. package/docs/README.md +11 -6
  45. package/docs/api-errors.md +2 -2
  46. package/docs/architecture-review-2026-07-09.md +1 -1
  47. package/docs/architecture.excalidraw +2 -2
  48. package/docs/auto-discovery.md +18 -9
  49. package/docs/branch-derivation.md +4 -4
  50. package/docs/capture-demos.js +39 -2
  51. package/docs/ci-runner-canary.md +123 -0
  52. package/docs/claude-md-propagation.md +2 -2
  53. package/docs/cloud-agent-dispatch.md +204 -0
  54. package/docs/command-center.md +7 -7
  55. package/docs/completion-reports.md +43 -20
  56. package/docs/constants.md +10 -3
  57. package/docs/constellation-bridge.md +134 -6
  58. package/docs/constellation-style-telemetry.md +4 -4
  59. package/docs/contracts/capability-protocol.v1.json +165 -0
  60. package/docs/cooldown-merge-semantics.md +12 -12
  61. package/docs/copilot-cli-schema.md +7 -7
  62. package/docs/cross-repo-plans.md +10 -10
  63. package/docs/dead-code-audit-retractions.md +5 -5
  64. package/docs/default-branch-ci.md +173 -0
  65. package/docs/deprecated.json +31 -31
  66. package/docs/design-inbox-entries-schema.md +3 -3
  67. package/docs/design-language.md +1051 -0
  68. package/docs/design-state-storage.md +11 -11
  69. package/docs/diagnostics-crash-reports.md +9 -9
  70. package/docs/diagnostics-memory.md +5 -5
  71. package/docs/documentation-audit-2026-07-09.md +7 -7
  72. package/docs/engine-restart.md +90 -5
  73. package/docs/harness-mode.md +1 -1
  74. package/docs/internal-install.md +338 -39
  75. package/docs/kb-dedup-duplicate-pair-investigation.md +5 -5
  76. package/docs/kb-pr3223-cascade-archiving.md +1 -1
  77. package/docs/kb-pr696-merge-conflict-docs.md +6 -6
  78. package/docs/kb-sweep.md +35 -35
  79. package/docs/keep-processes.md +1 -1
  80. package/docs/live-checkout-mode.md +30 -30
  81. package/docs/managed-spawn.md +18 -14
  82. package/docs/named-agents.md +7 -7
  83. package/docs/plan-lifecycle.md +69 -2
  84. package/docs/pr-author-identity.md +114 -0
  85. package/docs/pr-auto-fix-dispatch.md +19 -4
  86. package/docs/pr-comment-followup.md +6 -6
  87. package/docs/pr-review-fix-loop.md +59 -10
  88. package/docs/process-termination.md +40 -0
  89. package/docs/proposals/repo-pool-for-live-checkout.md +13 -13
  90. package/docs/qa-runbook-lifecycle.md +367 -17
  91. package/docs/qa-runbooks.md +3 -3
  92. package/docs/rfc-completion-json.md +18 -18
  93. package/docs/runtime-adapters.md +26 -21
  94. package/docs/security.md +6 -6
  95. package/docs/self-improvement.md +4 -4
  96. package/docs/shared-lifecycle-module-map.md +473 -472
  97. package/docs/skills.md +52 -3
  98. package/docs/slim-ux/concepts.md +121 -116
  99. package/docs/specs/agent-configurability.md +18 -18
  100. package/docs/specs/agent-rename.md +18 -18
  101. package/docs/team-memory.md +38 -21
  102. package/docs/timeouts-and-liveness.md +118 -10
  103. package/docs/tutorials/01-install-and-connect.md +1 -1
  104. package/docs/watches.md +40 -39
  105. package/docs/workspace-manifests.md +4 -4
  106. package/docs/worktree-lifecycle.md +293 -14
  107. package/engine/README.md +46 -0
  108. package/engine/{ado-comment.js → ado/comment.js} +8 -8
  109. package/engine/{ado-git-auth.js → ado/git-auth.js} +4 -4
  110. package/engine/{ado.js → ado/index.js} +417 -63
  111. package/engine/{ado-status.js → ado/status.js} +6 -8
  112. package/engine/{ado-token.js → ado/token.js} +1 -1
  113. package/engine/{acp-transport.js → agents/acp-transport.js} +62 -22
  114. package/engine/{agent-worker-pool.js → agents/agent-worker-pool.js} +17 -8
  115. package/engine/{cc-worker-pool.js → agents/cc-worker-pool.js} +16 -6
  116. package/engine/{claude-md-context.js → agents/claude-md-context.js} +5 -5
  117. package/engine/{harness-context.js → agents/harness-context.js} +5 -5
  118. package/engine/{harness.js → agents/harness.js} +3 -3
  119. package/engine/{llm.js → agents/llm.js} +18 -14
  120. package/engine/{model-discovery.js → agents/model-discovery.js} +2 -2
  121. package/engine/{playbook.js → agents/playbook.js} +155 -22
  122. package/engine/{pooled-agent-process.js → agents/pooled-agent-process.js} +14 -12
  123. package/engine/{preflight.js → agents/preflight.js} +29 -10
  124. package/engine/{spawn-agent.js → agents/spawn-agent.js} +25 -14
  125. package/engine/{spawn-phase-watchdog.js → agents/spawn-phase-watchdog.js} +16 -7
  126. package/engine/{steering.js → agents/steering.js} +5 -5
  127. package/engine/{tools-inventory.js → agents/tools-inventory.js} +2 -2
  128. package/engine/{agent-api-validation.js → api/agent-api-validation.js} +2 -2
  129. package/engine/{api-validation.js → api/api-validation.js} +1 -1
  130. package/engine/api/bridge.js +787 -0
  131. package/engine/{cc-api-validation.js → api/cc-api-validation.js} +1 -1
  132. package/engine/api/companion.js +560 -0
  133. package/engine/{content-api-validation.js → api/content-api-validation.js} +2 -2
  134. package/engine/{pr-issue-validation.js → api/pr-issue-validation.js} +33 -6
  135. package/engine/{settings-validation.js → api/settings-validation.js} +32 -4
  136. package/engine/api-contracts/agent-content.js +4 -4
  137. package/engine/api-contracts/capability-manifest.js +236 -0
  138. package/engine/api-contracts/capability-protocol.js +333 -0
  139. package/engine/api-contracts/cc-ops.js +1 -1
  140. package/engine/api-contracts/config-runtime.js +5 -0
  141. package/engine/api-contracts/core.js +28 -1
  142. package/engine/api-contracts/index.js +100 -0
  143. package/engine/api-contracts/orchestration.js +18 -5
  144. package/engine/api-contracts/pull-requests.js +37 -6
  145. package/engine/api-contracts/qa-process.js +29 -6
  146. package/engine/api-contracts/work-plan-prd.js +21 -1
  147. package/engine/cloud/contract.js +212 -0
  148. package/engine/cloud/index.js +159 -0
  149. package/engine/{execution-model.js → core/execution-model.js} +1 -1
  150. package/engine/{features.js → core/features.js} +4 -4
  151. package/engine/{operator-identity.js → core/operator-identity.js} +1 -1
  152. package/engine/{queries.js → core/queries.js} +201 -36
  153. package/engine/{safe-expr.js → core/safe-expr.js} +1 -1
  154. package/engine/{shared.js → core/shared.js} +1637 -175
  155. package/engine/{stdio-timestamps.js → core/stdio-timestamps.js} +1 -1
  156. package/engine/{untrusted-fence.js → core/untrusted-fence.js} +3 -3
  157. package/engine/db/index.js +11 -2
  158. package/engine/db/migrations/002-dispatches.js +3 -3
  159. package/engine/db/migrations/003-work-items.js +1 -1
  160. package/engine/db/migrations/004-pull-requests.js +1 -1
  161. package/engine/db/migrations/006-metrics.js +1 -1
  162. package/engine/db/migrations/007-watches.js +2 -2
  163. package/engine/db/migrations/008-small-state.js +1 -1
  164. package/engine/db/migrations/009-qa.js +1 -1
  165. package/engine/db/migrations/010-pr-links.js +1 -1
  166. package/engine/db/migrations/011-remaining-state.js +1 -1
  167. package/engine/db/migrations/012-steering-deliveries.js +2 -2
  168. package/engine/db/migrations/013-backfill-broken-note-links.js +1 -1
  169. package/engine/db/migrations/014-pr-fix-target-prefs.js +2 -2
  170. package/engine/db/migrations/015-plans-prds.js +0 -0
  171. package/engine/db/migrations/018-sql-only-cutover.js +2 -2
  172. package/engine/db/migrations/021-archived-work-items.js +1 -1
  173. package/engine/db/migrations/022-global-cc-session.js +1 -1
  174. package/engine/db/migrations/023-engine-state.js +1 -1
  175. package/engine/db/migrations/025-malformed-work-item-phantoms.js +1 -1
  176. package/engine/db/migrations/027-review-learning-lifecycle.js +1 -1
  177. package/engine/db/migrations/029-repair-reused-versions.js +20 -0
  178. package/engine/db/migrations/031-pr-author-identity.js +137 -0
  179. package/engine/{consolidation.js → memory/consolidation.js} +6 -6
  180. package/engine/{kb-sweep-runner.js → memory/kb-sweep-runner.js} +2 -2
  181. package/engine/{kb-sweep.js → memory/kb-sweep.js} +9 -7
  182. package/engine/{memory-retrieval.js → memory/memory-retrieval.js} +46 -4
  183. package/engine/{memory-store.js → memory/memory-store.js} +3 -3
  184. package/engine/{promotion.js → memory/promotion.js} +3 -3
  185. package/engine/{review-learning-backfill.js → memory/review-learning-backfill.js} +6 -6
  186. package/engine/{review-learning.js → memory/review-learning.js} +10 -5
  187. package/engine/{diagnostics-memory.js → observability/diagnostics-memory.js} +1 -1
  188. package/engine/{logs-store.js → observability/logs-store.js} +5 -5
  189. package/engine/{metrics-store.js → observability/metrics-store.js} +4 -4
  190. package/engine/{check-status.js → operations/check-status.js} +3 -3
  191. package/engine/{cli.js → operations/cli.js} +271 -113
  192. package/engine/{distribution.js → operations/distribution.js} +5 -6
  193. package/engine/{cleanup.js → orchestration/cleanup.js} +72 -45
  194. package/engine/{cooldown.js → orchestration/cooldown.js} +5 -5
  195. package/engine/{dispatch-events.js → orchestration/dispatch-events.js} +2 -2
  196. package/engine/{dispatch.js → orchestration/dispatch.js} +129 -36
  197. package/engine/orchestration/failed-scheduled-cleanup.js +274 -0
  198. package/engine/{lifecycle.js → orchestration/lifecycle.js} +198 -90
  199. package/engine/{meeting.js → orchestration/meeting.js} +6 -16
  200. package/engine/{pipeline.js → orchestration/pipeline.js} +12 -12
  201. package/engine/{pre-dispatch-eval.js → orchestration/pre-dispatch-eval.js} +10 -9
  202. package/engine/{routing.js → orchestration/routing.js} +3 -3
  203. package/engine/{schedule-bootstrap.js → orchestration/schedule-bootstrap.js} +4 -4
  204. package/engine/{scheduler.js → orchestration/scheduler.js} +38 -8
  205. package/engine/{timeout.js → orchestration/timeout.js} +158 -109
  206. package/engine/{db-events.js → persistence/db-events.js} +2 -2
  207. package/engine/{dispatch-store.js → persistence/dispatch-store.js} +7 -7
  208. package/engine/{inbox-store.js → persistence/inbox-store.js} +2 -2
  209. package/engine/{note-link-backfill.js → persistence/note-link-backfill.js} +4 -4
  210. package/engine/{pr-fix-target-store.js → persistence/pr-fix-target-store.js} +8 -8
  211. package/engine/{pull-requests-store.js → persistence/pull-requests-store.js} +21 -7
  212. package/engine/{small-state-store.js → persistence/small-state-store.js} +31 -31
  213. package/engine/persistence/state-operations.js +350 -0
  214. package/engine/{steering-store.js → persistence/steering-store.js} +6 -6
  215. package/engine/{issues.js → planning/issues.js} +2 -2
  216. package/engine/{plan-prd-validation.js → planning/plan-prd-validation.js} +8 -2
  217. package/engine/planning/prd-result-sidecar.js +190 -0
  218. package/engine/{prd-store.js → planning/prd-store.js} +17 -17
  219. package/engine/{project-discovery.js → planning/project-discovery.js} +5 -5
  220. package/engine/{projects.js → planning/projects.js} +10 -10
  221. package/engine/{resolve-area.js → planning/resolve-area.js} +1 -1
  222. package/engine/{work-item-validation.js → planning/work-item-validation.js} +39 -3
  223. package/engine/{work-items-store.js → planning/work-items-store.js} +29 -21
  224. package/engine/{keep-process-sweep.js → processes/keep-process-sweep.js} +57 -17
  225. package/engine/{managed-spawn-launcher.js → processes/managed-spawn-launcher.js} +3 -3
  226. package/engine/{managed-spawn.js → processes/managed-spawn.js} +97 -46
  227. package/engine/{process-utils.js → processes/process-utils.js} +599 -55
  228. package/engine/{abandoned-pr-reconciliation.js → providers/abandoned-pr-reconciliation.js} +17 -7
  229. package/engine/{comment-classifier.js → providers/comment-classifier.js} +85 -17
  230. package/engine/{comment-format.js → providers/comment-format.js} +5 -5
  231. package/engine/{gh-comment.js → providers/gh-comment.js} +15 -15
  232. package/engine/{gh-token.js → providers/gh-token.js} +4 -4
  233. package/engine/{github.js → providers/github.js} +131 -54
  234. package/engine/{pr-action.js → providers/pr-action.js} +13 -12
  235. package/engine/{pr-clone-keep.js → providers/pr-clone-keep.js} +7 -7
  236. package/engine/{pr-devbox.js → providers/pr-devbox.js} +6 -6
  237. package/engine/{pr-fix-target.js → providers/pr-fix-target.js} +13 -13
  238. package/engine/{pr-remote-patch.js → providers/pr-remote-patch.js} +4 -4
  239. package/engine/{pr-resolve.js → providers/pr-resolve.js} +7 -7
  240. package/engine/{pr-temp-clone.js → providers/pr-temp-clone.js} +5 -5
  241. package/engine/{pr-track.js → providers/pr-track.js} +11 -13
  242. package/engine/{shared-branch-pr-reconcile.js → providers/shared-branch-pr-reconcile.js} +4 -4
  243. package/engine/qa/auto-prd-qa.js +313 -0
  244. package/engine/{qa-from-prd.js → qa/from-prd.js} +42 -12
  245. package/engine/qa/prd-session.js +240 -0
  246. package/engine/{qa-process-validation.js → qa/process-validation.js} +14 -9
  247. package/engine/{qa-runbooks.js → qa/runbooks.js} +1 -1
  248. package/engine/{qa-runs.js → qa/runs.js} +286 -15
  249. package/engine/{qa-sessions.js → qa/sessions.js} +595 -49
  250. package/engine/qa/visual-journey.js +654 -0
  251. package/engine/{qa-runners.js → qa-runners/index.js} +7 -7
  252. package/engine/qa-runners/maestro.js +3 -3
  253. package/engine/qa-runners/playwright.js +2 -2
  254. package/engine/{restart-health.js → recovery/restart-health.js} +48 -4
  255. package/engine/recovery/stop-stack.js +607 -0
  256. package/engine/{supervisor.js → recovery/supervisor.js} +105 -175
  257. package/engine/{watchdog.js → recovery/watchdog.js} +136 -13
  258. package/engine/runtimes/claude.js +14 -12
  259. package/engine/runtimes/codex.js +8 -6
  260. package/engine/runtimes/copilot.js +17 -16
  261. package/engine/{watch-actions.js → watches/actions.js} +13 -13
  262. package/engine/{watches.js → watches/index.js} +43 -32
  263. package/engine/{watches-store.js → watches/store.js} +4 -4
  264. package/engine/{create-pr-worktree.js → worktrees/create-pr.js} +1 -1
  265. package/engine/{worktree-gc.js → worktrees/gc.js} +70 -22
  266. package/engine/worktrees/inventory.js +671 -0
  267. package/engine/{live-checkout.js → worktrees/live-checkout.js} +4 -4
  268. package/engine/{worktree-pool.js → worktrees/pool.js} +2 -2
  269. package/engine/{worktree-preflight.js → worktrees/preflight.js} +1 -0
  270. package/engine/worktrees/quarantine-refs.js +173 -0
  271. package/engine.js +1137 -208
  272. package/minions.js +147 -77
  273. package/package.json +10 -6
  274. package/playbooks/_pr-description-audit.md +110 -78
  275. package/playbooks/build-fix-complex.md +2 -0
  276. package/playbooks/fix.md +16 -12
  277. package/playbooks/implement-shared.md +2 -0
  278. package/playbooks/implement.md +19 -20
  279. package/playbooks/plan-to-prd.md +18 -3
  280. package/playbooks/qa-session-draft.md +136 -1
  281. package/playbooks/qa-session-execute.md +80 -2
  282. package/playbooks/qa-session-setup.md +17 -1
  283. package/playbooks/qa-validate.md +1 -1
  284. package/playbooks/setup.md +2 -0
  285. package/playbooks/shared-rules.md +25 -32
  286. package/playbooks/templates/followup-dispatch.md +4 -3
  287. package/playbooks/verify.md +1 -1
  288. package/prompts/cc-system.md +19 -27
  289. package/watch-plugins/README.md +92 -0
  290. package/watch-plugins/ado-author-prs.js +336 -0
  291. package/watch-plugins/gh-author-prs.js +375 -0
  292. package/watch-plugins/http.js +474 -0
  293. package/watch-plugins/teams-channel.js +869 -0
  294. package/docs/dev-composite-workflow.md +0 -101
  295. package/docs/pr-screenshots/pr-886/after-single-header.png +0 -0
  296. package/docs/pr-screenshots/pr-886/before-duplicate-header.png +0 -0
  297. package/docs/pr-screenshots/pr-895/01-cancellation-reason-detail.png +0 -0
  298. package/docs/pr-screenshots/pr-899/worker-pool-worktrees-AFTER.png +0 -0
  299. package/docs/pr-screenshots/pr-899/worker-pool-worktrees-BEFORE.png +0 -0
  300. package/docs/pr-screenshots/pr-901/projects-tab-default.png +0 -0
  301. package/docs/pr-screenshots/pr-901/projects-tab-fmf-selected.png +0 -0
  302. package/docs/pr-screenshots/pr-916/model-picker-AFTER-crop.png +0 -0
  303. package/docs/pr-screenshots/pr-916/model-picker-AFTER.png +0 -0
  304. package/docs/pr-screenshots/pr-916/model-picker-BEFORE-crop.png +0 -0
  305. package/docs/pr-screenshots/pr-916/model-picker-BEFORE.png +0 -0
  306. package/docs/pr-screenshots/pr-916/model-picker-dropdown-AFTER.png +0 -0
  307. package/docs/pr-screenshots/pr-979/auto-fix-pane-AFTER.png +0 -0
  308. package/docs/pr-screenshots/pr-979/auto-fix-pane-BEFORE.png +0 -0
  309. package/docs/pr-screenshots/pr-985/pr-column-em-dash-AFTER.png +0 -0
  310. package/docs/pr-screenshots/pr-985/pr-column-em-dash-BEFORE.png +0 -0
  311. package/docs/visual-evidence-ci.md +0 -103
  312. package/engine/bridge.js +0 -379
  313. package/engine/quarantine-refs.js +0 -103
  314. package/engine/state-operations.js +0 -178
  315. /package/engine/{steering-constraints.js → agents/steering-constraints.js} +0 -0
@@ -1,16 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * engine/ado-status.js — CLI shim for querying PR and build status.
3
+ * engine/ado/status.js — CLI implementation for querying PR and build status.
4
4
  *
5
5
  * Agents steered to "check on the builds" or "is CI green for PR #123" should
6
6
  * use this instead of raw curl + ad-hoc auth calls. All ADO auth and retry
7
7
  * logic is handled by ado.js internally.
8
8
  *
9
9
  * Usage:
10
- * node engine/ado-status.js <prNumber>
11
- * node engine/ado-status.js <prNumber> --live
12
- * node engine/ado-status.js <prNumber> --project MyProject
13
- * node engine/ado-status.js <prNumber> --live --project MyProject
10
+ * node engine/ado/status.js <prNumber>
11
+ * node engine/ado/status.js <prNumber> --live
14
12
  *
15
13
  * Output: JSON to stdout. Exit 0 on success, 1 on error/not-found.
16
14
  *
@@ -22,7 +20,7 @@
22
20
  'use strict';
23
21
 
24
22
  const path = require('path');
25
- const shared = require('./shared');
23
+ const shared = require('../core/shared');
26
24
  const { safeJson, readPullRequests, getProjects, MINIONS_DIR } = shared;
27
25
 
28
26
  // ── Arg parsing ──────────────────────────────────────────────────────────────
@@ -35,7 +33,7 @@ const projectName = projectIdx >= 0 ? args[projectIdx + 1] : null;
35
33
 
36
34
  if (!prNumberArg) {
37
35
  console.error([
38
- 'Usage: node engine/ado-status.js <prNumber> [--live] [--project <name>]',
36
+ 'Usage: node engine/ado/status.js <prNumber> [--live] [--project <name>]',
39
37
  '',
40
38
  ' <prNumber> PR number to look up (required)',
41
39
  ' --live Make a fresh ADO API call instead of reading cached state',
@@ -110,7 +108,7 @@ async function main() {
110
108
  }
111
109
 
112
110
  // Live path: query all projects in parallel, return first match
113
- const ado = require('./ado');
111
+ const ado = require('./index');
114
112
  const settled = await Promise.allSettled(
115
113
  projects.map(p => ado.fetchSinglePrBuildStatus(p, prNumber))
116
114
  );
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Shared Azure DevOps token acquisition.
2
+ * engine/ado/token.js — Shared Azure DevOps token acquisition.
3
3
  *
4
4
  * Prefer Azure CLI because it is the most common authenticated tool in agent
5
5
  * environments; keep azureauth as the non-interactive fallback for corp setups.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * engine/acp-transport.js — Shared ACP (Agent Client Protocol) transport layer
3
- * (P-4c6e8a72, extracted from engine/cc-worker-pool.js).
2
+ * engine/agents/acp-transport.js — Shared ACP (Agent Client Protocol) transport layer
3
+ * (P-4c6e8a72, extracted from engine/agents/cc-worker-pool.js).
4
4
  *
5
5
  * ACP-capable harnesses expose a long-lived JSON-RPC server over stdin/stdout.
6
6
  * This module owns protocol plumbing that is identical regardless of which
@@ -15,8 +15,8 @@
15
15
  * `mapAcpToolCallToToolUse`) and the `session/new` params builder
16
16
  * (`buildSessionNewParams`).
17
17
  *
18
- * Consumers (engine/cc-worker-pool.js — one persistent worker per CC/doc-chat
19
- * tab, permanent ownership; engine/agent-worker-pool.js — a fixed-size pool of
18
+ * Consumers (engine/agents/cc-worker-pool.js — one persistent worker per CC/doc-chat
19
+ * tab, permanent ownership; engine/agents/agent-worker-pool.js — a fixed-size pool of
20
20
  * workers leased/released per fleet agent dispatch) own their OWN pooling
21
21
  * policy (eviction rules, idle reaping, FIFO acquire queues, mcpServersHash
22
22
  * matching strategy) on top of this shared transport. Neither consumer
@@ -45,12 +45,13 @@
45
45
 
46
46
  const { spawn } = require('child_process');
47
47
  const crypto = require('crypto');
48
- const { normalizeExecutionModel } = require('./execution-model');
48
+ const processUtils = require('../processes/process-utils');
49
+ const { normalizeExecutionModel } = require('../core/execution-model');
49
50
  const {
50
51
  resolveRuntime,
51
52
  resolveRuntimeByCapability,
52
53
  buildWorkerArgs,
53
- } = require('./runtimes');
54
+ } = require('../runtimes');
54
55
 
55
56
  // W-mpmwxni2000c25c7-c — typed error codes the transport emits through every
56
57
  // failure exit so a consumer (CC streaming handler / doc-chat pool wrapper /
@@ -93,11 +94,47 @@ function typedError(message, code, retriable = true) {
93
94
  // consumers that pre-warm (like cc-worker-pool.js's warmTab) can share the
94
95
  // same knob instead of hardcoding their own copy.
95
96
  const WARM_MAX_CONCURRENT = 3;
96
- const ACP_HANDSHAKE_TIMEOUT_MS = 60000;
97
+ // Budget for the cold ACP handshake — `initialize` plus the follow-up
98
+ // `session/new` / `session/load`. Issue #1105 raised the default from 60s to
99
+ // 180s: a cold `copilot --acp` start that loads the user's MCP configuration
100
+ // routinely needs ~96s, and the old ceiling surfaced as "Command Center
101
+ // returned no output / handshake timed out after 60000ms". This is the
102
+ // module-level fallback only — consumers override it per Worker via
103
+ // `internals.handshakeTimeoutMs` (pushed in from
104
+ // `engine.acpHandshakeTimeoutMs` through each pool's setHandshakeTimeoutMs()).
105
+ const ACP_HANDSHAKE_TIMEOUT_MS = 180000;
97
106
  const SESSION_LOAD_RETRY_ATTEMPTS = 10;
98
107
  const SESSION_LOAD_RETRY_DELAY_MS = 100;
99
108
  const SESSION_ROTATION_CANCEL_WAIT_MS = 1000;
100
109
 
110
+ /**
111
+ * Issue #1105 — shared accessor pair for the cold-handshake budget a pool
112
+ * publishes on its own `_internals` seam. Both ACP pools (engine/cc-worker-pool
113
+ * and engine/agent-worker-pool) keep isolated `_internals` objects so their test
114
+ * stubs cannot collide, but the knob semantics are identical, so they share this
115
+ * factory rather than forking two copies.
116
+ *
117
+ * `_internals` is what `Worker` is constructed with, so every worker a pool owns
118
+ * — warm ones included — re-reads the current value on each handshake and a
119
+ * Settings change takes effect without recreating workers. Non-finite and
120
+ * non-positive values are ignored so a config typo can neither make the
121
+ * handshake un-cancellable nor fire before a cold start can finish.
122
+ */
123
+ function createHandshakeTimeoutControls(internals) {
124
+ internals.handshakeTimeoutMs = ACP_HANDSHAKE_TIMEOUT_MS;
125
+ return {
126
+ setHandshakeTimeoutMs(ms) {
127
+ const n = Number(ms);
128
+ if (!Number.isFinite(n) || n <= 0) return internals.handshakeTimeoutMs;
129
+ internals.handshakeTimeoutMs = n;
130
+ return internals.handshakeTimeoutMs;
131
+ },
132
+ getHandshakeTimeoutMs() {
133
+ return internals.handshakeTimeoutMs;
134
+ },
135
+ };
136
+ }
137
+
101
138
  function resolveWorkerRuntime(runtime) {
102
139
  const adapter = typeof runtime === 'string'
103
140
  ? resolveRuntime(runtime)
@@ -124,7 +161,7 @@ function spawnAcp({ runtime, cwd, env, workerOptions } = {}) {
124
161
  ...leadingArgs,
125
162
  ...buildWorkerArgs(adapter, { ...(workerOptions || {}), cwd, env: workerEnv }),
126
163
  ];
127
- // Mirror engine/spawn-agent.js: native binaries run directly; a non-native
164
+ // Mirror engine/agents/spawn-agent.js: native binaries run directly; a non-native
128
165
  // (JS entry / npm shim) runs under process.execPath as `node <bin> ...`.
129
166
  const execBin = native ? bin : process.execPath;
130
167
  const execArgs = native ? acpArgs : [bin, ...acpArgs];
@@ -140,18 +177,13 @@ function spawnAcp({ runtime, cwd, env, workerOptions } = {}) {
140
177
  }
141
178
 
142
179
  // Real kill implementation — lazy require so a caller that stubs its own
143
- // _internals for tests doesn't need engine/shared loaded.
180
+ // _internals for tests doesn't need engine/core/shared loaded.
144
181
  function killImmediate(proc) {
145
- try {
146
- const shared = require('./shared');
147
- shared.killImmediate(proc);
148
- } catch {
149
- try { proc.kill('SIGKILL'); } catch { /* already dead */ }
150
- }
182
+ return processUtils.terminateProcess('engine.acp-worker-close', proc);
151
183
  }
152
184
 
153
185
  function killRoot(proc) {
154
- try { proc.kill('SIGKILL'); } catch { /* already dead */ }
186
+ return processUtils.terminateProcess('engine.acp-worker-root-close', proc);
155
187
  }
156
188
 
157
189
  function hashMcpServers(mcpServers) {
@@ -337,6 +369,16 @@ class Worker {
337
369
  this.initPromise = null;
338
370
  }
339
371
 
372
+ // Resolve the configured handshake budget at call time (not construction
373
+ // time) so a Settings change pushed into the pool's `_internals` between
374
+ // acquisitions takes effect without recreating warm workers (issue #1105).
375
+ _handshakeTimeoutMs() {
376
+ const configured = Number(this._internals.handshakeTimeoutMs);
377
+ return Number.isFinite(configured) && configured > 0
378
+ ? configured
379
+ : ACP_HANDSHAKE_TIMEOUT_MS;
380
+ }
381
+
340
382
  // ── Spawn + initialize handshake ────────────────────────────────────────
341
383
  async _spawnAndInit() {
342
384
  let proc;
@@ -398,10 +440,7 @@ class Worker {
398
440
  };
399
441
  proc.on('error', errorHandler);
400
442
 
401
- const configuredHandshakeTimeout = Number(this._internals.handshakeTimeoutMs);
402
- const handshakeTimeoutMs = Number.isFinite(configuredHandshakeTimeout) && configuredHandshakeTimeout > 0
403
- ? configuredHandshakeTimeout
404
- : ACP_HANDSHAKE_TIMEOUT_MS;
443
+ const handshakeTimeoutMs = this._handshakeTimeoutMs();
405
444
  let handshakeTimer;
406
445
  const handshakeTimeoutPromise = new Promise((_, reject) => {
407
446
  handshakeTimer = setTimeout(() => {
@@ -600,7 +639,7 @@ class Worker {
600
639
  let lastError;
601
640
  for (let attempt = 0; attempt < SESSION_LOAD_RETRY_ATTEMPTS; attempt++) {
602
641
  try {
603
- return await this._call('session/load', params, ACP_HANDSHAKE_TIMEOUT_MS);
642
+ return await this._call('session/load', params, this._handshakeTimeoutMs());
604
643
  } catch (err) {
605
644
  lastError = err;
606
645
  if (!/already loaded/i.test(String(err && err.message))) throw err;
@@ -758,7 +797,7 @@ class Worker {
758
797
  });
759
798
  const result = method === 'session/load'
760
799
  ? await this._loadSession(params)
761
- : await this._call(method, params, ACP_HANDSHAKE_TIMEOUT_MS);
800
+ : await this._call(method, params, this._handshakeTimeoutMs());
762
801
  this.sessionId = (result && result.sessionId) || sessionId;
763
802
  if (!this.sessionId) {
764
803
  const hint = this.runtime.workerErrorHint || `${this.runtime.name} persistent worker failed`;
@@ -848,4 +887,5 @@ module.exports = {
848
887
  Worker,
849
888
  WARM_MAX_CONCURRENT,
850
889
  ACP_HANDSHAKE_TIMEOUT_MS,
890
+ createHandshakeTimeoutControls,
851
891
  };
@@ -1,14 +1,14 @@
1
1
  /**
2
- * engine/agent-worker-pool.js — Fixed-size ACP worker pool for fleet agent
2
+ * engine/agents/agent-worker-pool.js — Fixed-size ACP worker pool for fleet agent
3
3
  * dispatches (P-4c6e8a72, W-mre7fhxz001ka5fa / P-9b3d5f61 plan).
4
4
  *
5
- * Modeled on engine/cc-worker-pool.js but with a DIFFERENT ownership model:
5
+ * Modeled on engine/agents/cc-worker-pool.js but with a DIFFERENT ownership model:
6
6
  * cc-worker-pool.js gives each CC/doc-chat tab a permanently-owned worker
7
7
  * (tabId → Worker, kept warm for the tab's lifetime); this pool instead
8
8
  * leases a worker to exactly one active fleet dispatch at a time and
9
9
  * returns it to a shared free set on release — 1 worker : 1 ACTIVE dispatch,
10
10
  * not 1 worker : 1 dispatch for life. Both pools share the same underlying
11
- * spawn + JSON-RPC transport (engine/acp-transport.js) — no duplicated
11
+ * spawn + JSON-RPC transport (engine/agents/acp-transport.js) — no duplicated
12
12
  * framing code.
13
13
  *
14
14
  * Public API:
@@ -63,10 +63,10 @@
63
63
 
64
64
  const path = require('path');
65
65
  const transport = require('./acp-transport');
66
- const { buildWorkerArgs } = require('./runtimes');
66
+ const { buildWorkerArgs } = require('../runtimes');
67
67
  const { Worker, hashMcpServers, hashProcessContext } = transport;
68
68
 
69
- // Test seam — mirrors engine/cc-worker-pool.js's `_internals` pattern, but is
69
+ // Test seam — mirrors engine/agents/cc-worker-pool.js's `_internals` pattern, but is
70
70
  // its OWN object (constructor-injected into Worker per acquisition) so this
71
71
  // pool's test stubs never collide with cc-worker-pool.js's.
72
72
  const _internals = {
@@ -74,7 +74,7 @@ const _internals = {
74
74
  killImmediate: transport.killImmediate,
75
75
  killRoot: transport.killRoot,
76
76
  async getProcessStartedAt(pid) {
77
- const processes = await require('./shared').listAllProcessesAsync();
77
+ const processes = await require('../core/shared').listAllProcessesAsync();
78
78
  return Number(processes.find((entry) => entry.pid === pid)?.startedAt) || 0;
79
79
  },
80
80
  now() { return Date.now(); },
@@ -84,7 +84,7 @@ const _internals = {
84
84
  // chain (engine.agentAcpPoolSize > engine.maxConcurrent >
85
85
  // ENGINE_DEFAULTS.maxConcurrent) once the spawn-routing item (P-1d8f0b93)
86
86
  // wires `setPoolSize` in on config load. ENGINE_DEFAULTS.maxConcurrent is 5
87
- // (engine/shared.js) — mirrored here as the pre-wiring default so a caller
87
+ // (engine/core/shared.js) — mirrored here as the pre-wiring default so a caller
88
88
  // exercising this module directly (e.g. tests) gets a sane cap.
89
89
  const DEFAULT_POOL_SIZE = 5;
90
90
  let _poolSize = DEFAULT_POOL_SIZE;
@@ -103,6 +103,12 @@ function getPoolSize() {
103
103
  return _poolSize;
104
104
  }
105
105
 
106
+ // Issue #1105 — cold ACP handshake budget (`initialize` + `session/new` /
107
+ // `session/load`). Pushed in by engine.js#_syncAgentWorkerPoolConfig() from
108
+ // `engine.acpHandshakeTimeoutMs`; shares the transport factory with
109
+ // engine/cc-worker-pool.js and writes this pool's own `_internals` seam.
110
+ const { setHandshakeTimeoutMs, getHandshakeTimeoutMs } = transport.createHandshakeTimeoutControls(_internals);
111
+
106
112
  // AGENT_POOL_TRACE-gated structured trace logger — mirrors cc-worker-pool.js's
107
113
  // CC_POOL_TRACE convention but under its own env var so the two pools can be
108
114
  // traced independently. NO PII — dispatchId (caller-supplied), sessionIds
@@ -323,7 +329,7 @@ async function _spawnFreshWorker(req) {
323
329
 
324
330
  // Spawn + initialize + session/new a brand-new Worker for `req`. Attaches
325
331
  // the pool's own proc-exit eviction listener once the handshake succeeds —
326
- // Worker's own internal exit handler (engine/acp-transport.js) already marks
332
+ // Worker's own internal exit handler (engine/agents/acp-transport.js) already marks
327
333
  // `.killed` and fails any pending/inflight calls; this listener runs after
328
334
  // it (registered later on the same EventEmitter) and removes the worker from
329
335
  // whichever pool collection it's currently sitting in, then re-pumps so a
@@ -682,6 +688,9 @@ module.exports = {
682
688
  abandon,
683
689
  setPoolSize,
684
690
  getPoolSize,
691
+ // Issue #1105 — configurable cold ACP handshake budget.
692
+ setHandshakeTimeoutMs,
693
+ getHandshakeTimeoutMs,
685
694
  setEnabled,
686
695
  isEnabled,
687
696
  beginDrain,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * engine/cc-worker-pool.js — Persistent per-tab Copilot worker pool (W-mp3ioyh300056f36).
2
+ * engine/agents/cc-worker-pool.js — Persistent per-tab Copilot worker pool (W-mp3ioyh300056f36).
3
3
  *
4
4
  * Sub-task B of W-mp2w003600196c51 ("CC perf: persistent per-tab Copilot
5
5
  * worker"). Wraps `copilot --acp` (Agent Client Protocol — long-lived JSON-RPC
@@ -21,7 +21,7 @@
21
21
  *
22
22
  * Internal model (one process per tab):
23
23
  *
24
- * tabs: Map<tabId, Worker> — Worker (engine/acp-transport.js) owns the
24
+ * tabs: Map<tabId, Worker> — Worker (engine/agents/acp-transport.js) owns the
25
25
  * spawn + JSON-RPC framing; this module owns per-tab lifecycle policy:
26
26
  * eviction rules, idle reaping, and the warm-prewarm FIFO queue.
27
27
  *
@@ -73,9 +73,9 @@ const {
73
73
  // Test seam — every external side effect goes through `_internals` so
74
74
  // test/unit/cc-worker-pool.test.js can stub spawn/now/killImmediate. This
75
75
  // object is passed to each Worker constructed by this pool (constructor
76
- // injection, engine/acp-transport.js#Worker) rather than the transport
76
+ // injection, engine/agents/acp-transport.js#Worker) rather than the transport
77
77
  // reaching for a module-level singleton — that keeps this pool's test stubs
78
- // isolated from engine/agent-worker-pool.js's own `_internals`.
78
+ // isolated from engine/agents/agent-worker-pool.js's own `_internals`.
79
79
  const _internals = {
80
80
  spawnAcp: transport.spawnAcp,
81
81
  killImmediate: transport.killImmediate,
@@ -85,7 +85,7 @@ const _internals = {
85
85
 
86
86
  // 30 minutes default — matches ENGINE_DEFAULTS.ccWorkerIdleTimeoutMs. This is
87
87
  // now a runtime-configurable knob (W-mr0qs0vw): the pool stays dependency-free
88
- // at module load (no static `require('./shared')`), so the dashboard pushes the
88
+ // at module load (no static `require('../core/shared')`), so the dashboard pushes the
89
89
  // configured value in via `setIdleTimeoutMs()` on every reloadConfig(). Shorter
90
90
  // = less idle memory/process footprint; longer = more context durability across
91
91
  // gaps between messages.
@@ -130,6 +130,13 @@ function getIdleTimeoutMs() {
130
130
  return _idleReaperMs;
131
131
  }
132
132
 
133
+ // Issue #1105 — cold ACP handshake budget (`initialize` + `session/new` /
134
+ // `session/load`). Pushed in by dashboard.js#reloadConfig() from
135
+ // `engine.acpHandshakeTimeoutMs`; the accessors are shared with
136
+ // engine/agent-worker-pool.js via the transport factory and write this pool's
137
+ // own `_internals` seam, so warm workers pick the new budget up in place.
138
+ const { setHandshakeTimeoutMs, getHandshakeTimeoutMs } = transport.createHandshakeTimeoutControls(_internals);
139
+
133
140
  // Returns true (and clears the notice) if `tabId`'s warm worker was killed by
134
141
  // the idle reaper since the last consume. One-shot: the dashboard calls this
135
142
  // once per turn while resolving session-reset state.
@@ -401,6 +408,9 @@ module.exports = {
401
408
  setIdleTimeoutMs,
402
409
  getIdleTimeoutMs,
403
410
  consumeIdleReapNotice,
411
+ // Issue #1105 — configurable cold ACP handshake budget.
412
+ setHandshakeTimeoutMs,
413
+ getHandshakeTimeoutMs,
404
414
  // Exposed for unit tests; engine code MUST go through the public API.
405
415
  _internals,
406
416
  _tabs,
@@ -414,7 +424,7 @@ module.exports = {
414
424
  // dashboard pool wrappers (and their tests) reference the same string
415
425
  // constants and so the doc-chat timeout path can stamp the same
416
426
  // `{ message, code, retriable }` shape the pool itself emits. Re-exported
417
- // from engine/acp-transport.js (P-4c6e8a72) — this pool no longer defines
427
+ // from engine/agents/acp-transport.js (P-4c6e8a72) — this pool no longer defines
418
428
  // its own copy.
419
429
  ERROR_CODES,
420
430
  _typedError,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * engine/claude-md-context.js — CLAUDE.md propagation for non-Claude runtimes.
2
+ * engine/agents/claude-md-context.js — CLAUDE.md propagation for non-Claude runtimes.
3
3
  *
4
4
  * W-mrdon0pe000l045a. CLAUDE.md auto-discovery is a Claude-Code-CLI-only
5
5
  * convention (the claude binary reads CLAUDE.md itself at startup). Copilot and
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * This module discovers the *nearest applicable* CLAUDE.md files for a dispatch
11
11
  * (bounded walk-UP from path hints toward the project root — NOT a full monorepo
12
- * walk) and renders them into a prompt block. engine/playbook.js injects that
12
+ * walk) and renders them into a prompt block. engine/agents/playbook.js injects that
13
13
  * block as a "Project instructions (CLAUDE.md)" context layer, gated on the
14
14
  * runtime capability `claudeMdNativeDiscovery` (skip when true → Claude) and the
15
15
  * `propagateClaudeMdForNonClaudeRuntimes` config flag.
@@ -24,7 +24,7 @@
24
24
 
25
25
  const fs = require('fs');
26
26
  const path = require('path');
27
- const { truncateTextBytes, ENGINE_DEFAULTS } = require('./shared');
27
+ const { truncateTextBytes, ENGINE_DEFAULTS } = require('../core/shared');
28
28
 
29
29
  const CLAUDE_MD_FILENAME = 'CLAUDE.md';
30
30
  // Cap the number of CLAUDE.md files collected across all hints — defense against
@@ -130,7 +130,7 @@ function discoverClaudeMdFiles({ projectRoot, pathHints = [] } = {}) {
130
130
 
131
131
  /**
132
132
  * Build the CLAUDE.md propagation block (inner content, no outer header/fence —
133
- * engine/playbook.js owns those). Reads each discovered file, labels it by its
133
+ * engine/agents/playbook.js owns those). Reads each discovered file, labels it by its
134
134
  * repo-relative path, and truncates to stay within `maxBytes` total. Returns
135
135
  * `{ block, files }` where `block` is '' when nothing was found or all files
136
136
  * were empty.
@@ -176,7 +176,7 @@ function buildClaudeMdPropagationBlock({ projectRoot, pathHints = [], maxBytes =
176
176
  */
177
177
  function runtimeAutoDiscoversClaudeMd(cliName) {
178
178
  try {
179
- const { resolveRuntime } = require('./runtimes');
179
+ const { resolveRuntime } = require('../runtimes');
180
180
  const rt = resolveRuntime(cliName);
181
181
  return !!(rt && rt.capabilities && rt.capabilities.claudeMdNativeDiscovery);
182
182
  } catch {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * engine/harness-context.js — "Repo harnesses used" PR-body section.
2
+ * engine/agents/harness-context.js — "Repo harnesses used" PR-body section.
3
3
  *
4
4
  * W-mrtdmtwq000kf391. When Minions opens/updates a PR for a dispatch, we surface
5
5
  * the repo HARNESS assets that were actually USED by THAT dispatch's runtime +
@@ -11,12 +11,12 @@
11
11
  *
12
12
  * This module is pure REPORTING. It reuses the same read-only harness-diagnostics
13
13
  * source that backs `GET /api/harness/diagnostics` and `minions doctor --harness`
14
- * (engine/preflight.js `_runtimeHarnessRows`) plus the CLAUDE.md propagation
15
- * discovery (engine/claude-md-context.js). It never propagates, injects,
14
+ * (engine/agents/preflight.js `_runtimeHarnessRows`) plus the CLAUDE.md propagation
15
+ * discovery (engine/agents/claude-md-context.js). It never propagates, injects,
16
16
  * suppresses, or attests any repository harness asset — the runtime-adapter
17
17
  * harness methods are diagnostic-only (see docs/harness-propagation.md).
18
18
  *
19
- * engine/playbook.js renders the section into a dispatch prompt appendix that
19
+ * engine/agents/playbook.js renders the section into a dispatch prompt appendix that
20
20
  * instructs the agent to append the fenced block verbatim to its PR body. The
21
21
  * block is delimited by stable HTML-comment markers so a PR-description refresh
22
22
  * (the description audit) can replace it in place instead of duplicating it.
@@ -168,7 +168,7 @@ function computeDispatchHarnessInventory({
168
168
  let registry = null;
169
169
  try { claudeMdCtx = require('./claude-md-context'); } catch { /* optional */ }
170
170
  try { preflight = require('./preflight'); } catch { /* optional */ }
171
- try { registry = require('./runtimes'); } catch { /* optional */ }
171
+ try { registry = require('../runtimes'); } catch { /* optional */ }
172
172
 
173
173
  // CLAUDE.md discovery is a runtime CAPABILITY (Claude reads CLAUDE.md itself;
174
174
  // Copilot/Codex do not). Prefer the caller-resolved value; fall back to the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * engine/harness.js — Tri-agent harness mode for long-running missions.
2
+ * engine/agents/harness.js — Tri-agent harness mode for long-running missions.
3
3
  *
4
4
  * Inspired by Anthropic's Harness Design (April 2026), this module implements
5
5
  * the "tri_agent" mission mode: a schedule firing produces three coordinated
@@ -43,13 +43,13 @@
43
43
  * generatorType: 'ask', // remembered so iteration N+1 reuses it
44
44
  * }
45
45
  *
46
- * Zero dependencies beyond Node built-ins + engine/shared.
46
+ * Zero dependencies beyond Node built-ins + engine/core/shared.
47
47
  */
48
48
 
49
49
  'use strict';
50
50
 
51
51
  const path = require('path');
52
- const shared = require('./shared');
52
+ const shared = require('../core/shared');
53
53
  const { MINIONS_DIR, WI_STATUS, ts } = shared;
54
54
 
55
55
  const HARNESS_MODE = Object.freeze({
@@ -1,5 +1,5 @@
1
1
  /**
2
- * engine/llm.js — Shared LLM utilities for Minions engine + dashboard.
2
+ * engine/agents/llm.js — Shared LLM utilities for Minions engine + dashboard.
3
3
  *
4
4
  * Provides callLLM() / callLLMStreaming() (with optional session resume) and
5
5
  * trackEngineUsage(). As of P-5e1b7a3c the CC / doc-chat direct-spawn path
@@ -11,7 +11,7 @@
11
11
 
12
12
  const fs = require('fs');
13
13
  const path = require('path');
14
- const shared = require('./shared');
14
+ const shared = require('../core/shared');
15
15
  const {
16
16
  safeWrite, safeUnlink, uid, ts, runFile, cleanChildEnv,
17
17
  parseStreamJsonOutput, mutateJsonFileLocked, appendTextTail,
@@ -26,7 +26,7 @@ const {
26
26
  sanitizeInvocationOptions,
27
27
  resolveInvocationOptions,
28
28
  buildSpawnFlags,
29
- } = require('./runtimes');
29
+ } = require('../runtimes');
30
30
 
31
31
  const MINIONS_DIR = shared.MINIONS_DIR;
32
32
  const ENGINE_DIR = path.join(MINIONS_DIR, 'engine');
@@ -111,7 +111,7 @@ function flushMetricsBuffer() {
111
111
  _pendingMetrics = { engine: Object.create(null), daily: Object.create(null) };
112
112
 
113
113
  try {
114
- const { mutateMetrics } = require('./shared');
114
+ const { mutateMetrics } = require('../core/shared');
115
115
  mutateMetrics((metrics) => {
116
116
  if (!metrics._engine) metrics._engine = {};
117
117
  for (const [category, delta] of Object.entries(pending.engine)) {
@@ -361,7 +361,7 @@ function _buildSpawnAgentFlags(runtime, opts = {}) {
361
361
  * Direct path (`direct: true`): bypasses spawn-agent.js, spawns the runtime
362
362
  * binary directly. Fewer file syscalls. Used by CC and doc-chat.
363
363
  *
364
- * Indirect path: uses engine/spawn-agent.js — mostly a fallback when the
364
+ * Indirect path: uses engine/agents/spawn-agent.js — mostly a fallback when the
365
365
  * direct path can't resolve the binary cache. spawn-agent.js handles
366
366
  * adapter resolution itself; we hand it the runtime plus an opaque options
367
367
  * bag, so adding a harness flag does not require wrapper changes.
@@ -439,7 +439,7 @@ function _spawnProcess(promptText, sysPromptText, callOpts) {
439
439
  const pidPath = promptPath.replace(/prompt-/, 'pid-').replace(/\.md$/, '.pid');
440
440
  cleanupFiles.push(promptPath, sysPath, pidPath);
441
441
 
442
- const spawnScript = runtime.spawnScript || path.join(ENGINE_DIR, 'spawn-agent.js');
442
+ const spawnScript = runtime.spawnScript || path.join(ENGINE_DIR, 'agents', 'spawn-agent.js');
443
443
  const indirectAdapterOpts = { ...adapterOpts };
444
444
  if (Array.isArray(indirectAdapterOpts.images) && indirectAdapterOpts.images.length) {
445
445
  const imagesPath = path.join(llmTmpDir, `runtime-images-${id}.json`);
@@ -735,7 +735,7 @@ function callLLM(promptText, sysPromptText, opts = {}) {
735
735
  cli: cliOverride,
736
736
  engineConfig,
737
737
  // Cross-runtime + Copilot opts:
738
- maxBudget, bare, fallbackModel,
738
+ maxBudget, bare, fallbackModel, disableTools = false,
739
739
  stream, disableBuiltinMcps, reasoningSummaries,
740
740
  invocationScope,
741
741
  // P-7b2e4d01 — optional image attachments: [{ mimeType, dataBase64, filename? }]
@@ -751,7 +751,7 @@ function callLLM(promptText, sysPromptText, opts = {}) {
751
751
  if (imageGate.error) return _resolvedCallResult(_imageUnsupportedResult(runtime, imageGate.error));
752
752
  const runtimeOptions = resolveInvocationOptions(runtime, {
753
753
  model, maxTurns, allowedTools, effort, sessionId,
754
- maxBudget, bare, fallbackModel, images: imageGate.images,
754
+ maxBudget, bare, fallbackModel, disableTools, images: imageGate.images,
755
755
  stream, disableBuiltinMcps, reasoningSummaries,
756
756
  }, { engineConfig: engineConfig || {}, invocationScope });
757
757
 
@@ -779,12 +779,14 @@ function callLLM(promptText, sysPromptText, opts = {}) {
779
779
  onTerminalResult: () => scheduleExitFallback(exitCode != null ? exitCode : 0),
780
780
  });
781
781
 
782
- _abort = () => { shared.killImmediate(proc); };
782
+ _abort = () => { shared.terminateProcess('engine.llm.abort', proc); };
783
783
 
784
784
  proc.stdout.on('data', d => { acc.ingestStdout(d); });
785
785
  proc.stderr.on('data', d => { acc.ingestStderr(d); });
786
786
 
787
- const timer = setTimeout(() => { shared.killImmediate(proc); }, timeout);
787
+ const timer = setTimeout(() => {
788
+ shared.terminateProcess('engine.llm.timeout', proc);
789
+ }, timeout);
788
790
 
789
791
  const finalizeAndResolve = (code) => {
790
792
  if (resolved) return;
@@ -866,7 +868,7 @@ function callLLMStreaming(promptText, sysPromptText, opts = {}) {
866
868
  onProgress = null,
867
869
  effort = null, direct = false,
868
870
  model: modelOverride, cli: cliOverride, engineConfig,
869
- maxBudget, bare, fallbackModel,
871
+ maxBudget, bare, fallbackModel, disableTools = false,
870
872
  stream, disableBuiltinMcps, reasoningSummaries,
871
873
  invocationScope,
872
874
  // P-7b2e4d01 — optional image attachments: [{ mimeType, dataBase64, filename? }]
@@ -882,7 +884,7 @@ function callLLMStreaming(promptText, sysPromptText, opts = {}) {
882
884
  if (imageGate.error) return _resolvedCallResult(_imageUnsupportedResult(runtime, imageGate.error));
883
885
  const runtimeOptions = resolveInvocationOptions(runtime, {
884
886
  model, maxTurns, allowedTools, effort, sessionId,
885
- maxBudget, bare, fallbackModel, images: imageGate.images,
887
+ maxBudget, bare, fallbackModel, disableTools, images: imageGate.images,
886
888
  stream, disableBuiltinMcps, reasoningSummaries,
887
889
  }, { engineConfig: engineConfig || {}, invocationScope });
888
890
 
@@ -915,12 +917,14 @@ function callLLMStreaming(promptText, sysPromptText, opts = {}) {
915
917
  onProgress,
916
918
  });
917
919
 
918
- _abort = () => { shared.killImmediate(proc); };
920
+ _abort = () => { shared.terminateProcess('engine.llm.abort', proc); };
919
921
 
920
922
  proc.stdout.on('data', d => { acc.ingestStdout(d); });
921
923
  proc.stderr.on('data', d => { acc.ingestStderr(d); });
922
924
 
923
- const timer = setTimeout(() => { shared.killImmediate(proc); }, timeout);
925
+ const timer = setTimeout(() => {
926
+ shared.terminateProcess('engine.llm.timeout', proc);
927
+ }, timeout);
924
928
 
925
929
  const finalizeAndResolve = (code) => {
926
930
  if (resolved) return;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * engine/model-discovery.js — Per-runtime model catalog cache + REST helpers.
2
+ * engine/agents/model-discovery.js — Per-runtime model catalog cache + REST helpers.
3
3
  *
4
4
  * Backs the dashboard endpoints:
5
5
  * GET /api/runtimes → listAllRuntimes()
@@ -24,7 +24,7 @@
24
24
  */
25
25
 
26
26
  const fs = require('fs');
27
- const { resolveRuntime, listRuntimes } = require('./runtimes');
27
+ const { resolveRuntime, listRuntimes } = require('../runtimes');
28
28
 
29
29
  // 1 hour — matches the spec ("< 1hr TTL"). Keep separate from ENGINE_DEFAULTS
30
30
  // so the test suite can override per-call without polluting the global config.