@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
package/docs/README.md CHANGED
@@ -31,7 +31,9 @@ Architecture, design proposals, and lifecycle references for people working on t
31
31
 
32
32
  - [api-errors.md](api-errors.md) — Dashboard API error contract: the stable `{error, code, field, …}` envelope, the 400/404/409/422/5xx status taxonomy, the safe (bounded + secret-redacted) rejected-value policy, alias/enum compatibility rules, and the self-correct-4xx / don't-blindly-retry-5xx behavior. Contracts are discoverable via `GET /api/routes` and the `engine/api-contracts` route-to-validation matrix.
33
33
  - [branch-derivation.md](branch-derivation.md) — Engine-side branch fallback (`work/<wi-id>`) vs. agent-authored long form, the structured-vs-loose PR-pointer extractors, and the canonical PR-fix duplication incident.
34
+ - [ci-runner-canary.md](ci-runner-canary.md) — The hourly hosted-runner canary: why a self-hosted outage produces stalled runs instead of failed ones (so failure-only health checks report "all green" while CI is dark), the properties that keep the canary out of that failure domain, and why the runner-inventory check is unavailable to `GITHUB_TOKEN`.
34
35
  - [claude-md-propagation.md](claude-md-propagation.md) — Propagating repo-authored `CLAUDE.md` instructions to runtimes that don't auto-load it (Copilot/Codex): the `claudeMdNativeDiscovery` capability flag, the bounded nearest-applicable walk-up discovery, the `propagateClaudeMdForNonClaudeRuntimes` config knob, and why it's orthogonal to each runtime's native `AGENTS.md` discovery.
36
+ - [cloud-agent-dispatch.md](cloud-agent-dispatch.md) — The `cloud` execution surface: handing a work item to a REMOTE coding agent (Agency / Copilot cloud) that authors its own PR. Covers why a cloud provider is not a runtime adapter, the `engine/cloud` provider contract, the PR-producing eligibility allowlist (and why `review`/`verify` are refused), and the fail-closed gating that refuses a cloud dispatch rather than silently running it locally.
35
37
  - [command-center.md](command-center.md) — Command Center (CC) chat panel: configured-runtime sessions, resume semantics, system-prompt invalidation, and per-tab session storage.
36
38
  - [specs/agent-rename.md](specs/agent-rename.md) — Design spec for **agent rename & name decoupling** — the prerequisite for the Role/Agent Library. Formalizes the stable opaque agent id, makes charters name-agnostic, and adds `POST /api/agents/rename` (display name + emoji). Feature-flagged (`agent-rename`) and fully backward-compatible.
37
39
  - [specs/agent-configurability.md](specs/agent-configurability.md) — Design spec for the user-configurable Role / Agent Library, feature-flagged behind `agent-library` and fully backward-compatible. Builds on `agent-rename.md`. Role = the reusable durable charter; agent = a thin instance (identity + variable expertise + role pointer). Phase 0 renames `skills`→`expertise`; Phase 1 exposes/edits role charters + per-agent expertise; Phase 2 adds role/agent CRUD with builtin delete-protection.
@@ -43,38 +45,41 @@ Architecture, design proposals, and lifecycle references for people working on t
43
45
  - [copilot-cli-schema.md](copilot-cli-schema.md) — Behavior and schema reference for the GitHub Copilot CLI adapter (capability flags, stdin vs `-p`, model discovery, effort levels).
44
46
  - [cross-repo-plans.md](cross-repo-plans.md) — Cross-repo plans: a single plan whose work items ship into two or more configured projects — per-item `project` field, per-project work-item fan-out, and one verify work item per touched repo.
45
47
  - [dead-code-audit-retractions.md](dead-code-audit-retractions.md) — Retracted dead-code-audit findings (false positives) that future audits MUST read before re-citing.
48
+ - [default-branch-ci.md](default-branch-ci.md) — The post-merge default-branch gate: why a `pull_request` gate cannot catch merge-order defects (two green PRs that break only in combination), why the post-merge workflow *calls* the PR gate rather than copying it or inverting the direction (the ruleset requires the `Unit Tests` context by exact string), the cost controls, and the evaluated-but-rejected merge-queue alternative.
46
49
  - [deprecated-process.md](deprecated-process.md) — Schema for `docs/deprecated.json` and the weekly `cleanup-deprecated` audit walk that retires entries past their removal signal.
47
50
  - [design-inbox-entries-schema.md](design-inbox-entries-schema.md) — Implemented SQL schema and store contract for the future operator/agent inbox queue, including current indexes, mutators, event emission, and integration status.
51
+ - [design-language.md](design-language.md) — Code-derived Minions design-language specification: color tokens, typography, spacing, component primitives (buttons/badges/tables/modals/Command Center), status→class→color maps, Classic vs Slim shared-vs-different foundations, a migration playbook, and an objective audit rubric — all traceable to `dashboard/` CSS/JS with file+line citations.
48
52
  - [design-state-storage.md](design-state-storage.md) — Design proposal evaluating five database options for replacing Minions' file-based JSON state; recommends `node:sqlite` (accepted; implementation tracked in CHANGELOG.md Phases 0–10).
49
- - [dev-composite-workflow.md](dev-composite-workflow.md) — The recurring "rebuild the composite branch from all my open PRs and relaunch the dev dashboard" workflow, and the `rebuild-composite` skill + `scripts/rebuild-composite.ps1` that automate it.
50
53
  - [harness-mode.md](harness-mode.md) — Tri-Agent Harness Mode (`harness_mode: "tri_agent"` on scheduled tasks): Planner → Generator → Evaluator loop that iterates a shared on-disk artifact until a rubric passes or the iteration cap fires.
51
54
  - [harness-propagation.md](harness-propagation.md) — The native runtime
52
55
  contract for repository instructions, skills, commands, and MCPs.
53
56
  - [kb-dedup-duplicate-pair-investigation.md](kb-dedup-duplicate-pair-investigation.md) — Investigation-only pass diffing suspected duplicate KB filename groups (content-hash dedup for agent-authored reviews/build-reports) to confirm true full-body duplication before any fix is proposed.
54
57
  - [kb-pr3223-cascade-archiving.md](kb-pr3223-cascade-archiving.md) — Findings from PR #3223: cascade-archiving PRDs when their linked markdown plan is archived, including the per-concern try/catch pattern and `source_plan` basename-matching invariant in `handlePlansArchive` (`dashboard.js`).
55
- - [kb-pr696-merge-conflict-docs.md](kb-pr696-merge-conflict-docs.md) — Findings from PR #696: resolving a merge conflict in `docs/kb-sweep.md` with stale line-number citations to `engine/kb-sweep.js`.
56
- - [keep-processes.md](keep-processes.md) — `meta.keep_processes` sidecar contract: when to use it vs managed-spawn, sidecar schema, caps, and the [`engine/keep-process-sweep.js`](../engine/keep-process-sweep.js) lifecycle.
58
+ - [kb-pr696-merge-conflict-docs.md](kb-pr696-merge-conflict-docs.md) — Findings from PR #696: resolving a merge conflict in `docs/kb-sweep.md` with stale line-number citations to `engine/memory/kb-sweep.js`.
59
+ - [keep-processes.md](keep-processes.md) — `meta.keep_processes` sidecar contract: when to use it vs managed-spawn, sidecar schema, caps, and the [`engine/processes/keep-process-sweep.js`](../engine/processes/keep-process-sweep.js) lifecycle.
57
60
  - [live-checkout-mode.md](live-checkout-mode.md) — Per-project opt-in `checkoutMode: 'live'`: skips `git worktree add` and dispatches in-place inside `project.localPath` for `repo`-managed trees, submodule-heavy repos, deep Windows paths, and native build state. Includes the refuse-on-dirty contract and the per-project mutating-concurrency cap of 1.
58
61
  - [managed-spawn.md](managed-spawn.md) — Engine-owned long-running services (managed-spawn primitive): sidecar schema, healthcheck examples, lifecycle, dashboard API, and the WI 1 (build) → WI 2 (test) chained-validation pattern.
59
62
  - [named-agents.md](named-agents.md) — The named-agent roster (Ripley / Dallas / Lambert / Rebecca / Ralph): per-agent `config.json` shape, the per-agent → `engine.*` → runtime resolution chain, how `routing.md` (not the `role`/`skills` metadata) drives dispatch, descriptive vs runtime skills, and per-agent memory files.
60
63
  - [plan-lifecycle.md](plan-lifecycle.md) — Full plan pipeline from `/plan` through PRD materialization, dispatch with dependency gating, verify task, and human archive.
61
64
  - [pr-auto-fix-dispatch.md](pr-auto-fix-dispatch.md) — Short reference table mapping each PR auto-fix / review dispatch site in `engine.js#discoverFromPrs` to its gate flag, plus the `pollingPaused` / `autoFixPaused` master kill-switches and the per-provider polling gates.
65
+ - [pr-author-identity.md](pr-author-identity.md) — Separating a PR's real author identity (`pr.author`, provider-linked) from the Minions agent that owns the automated work (`pr.agent`): the structured author shape, the provider builders, centralized merge, migration 031, and the dashboard Author column.
62
66
  - [pr-comment-followup.md](pr-comment-followup.md) — PR-comment follow-up dispatch contract: fix/review agents may spin off a new WI via `POST /api/work-items` with `meta.pr_followup` instead of broadening the current PR or rebutting the comment.
63
67
  - [pr-review-fix-loop.md](pr-review-fix-loop.md) — How the engine moves a PR from creation through review, fix dispatch, and re-review, including stale-status guards.
68
+ - [process-termination.md](process-termination.md) — The `terminateProcess` gateway: `PROCESS_TERMINATION_SITES` is the authoritative site inventory (mode + ownership proof per entry), how to print it, what the gateway test enforces, and the signal-0 liveness exemption.
64
69
  - [proposals/repo-pool-for-live-checkout.md](proposals/repo-pool-for-live-checkout.md) — Review-only artifact reproducing the approved plan + PRD for a repo pool covering live-checkout projects (multi-enlistment dispatch), so the design has a git-tracked surface for human comment before the dependent implementation work items land as code PRs.
65
70
  - [qa-runbook-lifecycle.md](qa-runbook-lifecycle.md) — End-to-end QA runbook lifecycle (W-mpeiwz6k0005bf34): runbook + run-record storage, `POST /api/qa/runbooks/run` dispatch into the `qa-validate` playbook, artifact contract, and how the `/qa` page mirrors managed-spawn observability.
66
71
  - [qa-runbooks.md](qa-runbooks.md) — Per-project QA runbook schema, storage layout (`projects/<name>/runbooks/<id>.json`), CRUD endpoints, run-record lifecycle, and the `qa-validate` agent sidecar contract.
67
72
  - [rfc-completion-json.md](rfc-completion-json.md) — RFC for replacing stdout regex-scraping with a structured `completion.json` control-plane protocol.
68
73
  - [runtime-adapters.md](runtime-adapters.md) — Runtime adapter contract (`engine/runtimes/*`): how the engine talks to Claude Code, Copilot CLI, and future CLIs through a single capability-flagged interface.
69
74
  - [self-improvement.md](self-improvement.md) — The six self-improvement mechanisms (learnings inbox, per-agent history, review feedback, quality metrics, etc.) that form Minions' continuous feedback loop, including structured review learning (durable, always-on lessons from verified review findings).
70
- - [shared-lifecycle-module-map.md](shared-lifecycle-module-map.md) — Documentation-only module-boundary audit of `engine/shared.js` / `engine/lifecycle.js`: function inventory, cross-file call graph, and a proposed split map (no code moved).
75
+ - [shared-lifecycle-module-map.md](shared-lifecycle-module-map.md) — Documentation-only module-boundary audit of `engine/core/shared.js` / `engine/orchestration/lifecycle.js`: function inventory, cross-file call graph, and a proposed split map (no code moved).
71
76
  - [skills.md](skills.md) — Skill block format: how agents emit reusable `\`\`\`skill` blocks and how the engine extracts them into native personal-skill directories.
72
77
  - [slim-ux/concepts.md](slim-ux/concepts.md) — Slim-UX design notes: simplified surface concepts driving the project picker, inline project link, and decoupled folder picker.
73
78
  - [slim-ux/architecture-suggestions.md](slim-ux/architecture-suggestions.md) — Slim-UX follow-up architecture suggestions paired with `concepts.md`.
74
79
  - [team-memory.md](team-memory.md) — End-to-end hybrid memory system: file-backed inputs and consolidation, SQL/FTS5 records, retrieval and fallback, prompt bounds, episodic capture, the review-learning lifecycle (capture/recall/promotion/contradiction/diagnostics) and its rollout history + acceptance measurement, security, APIs, and operations.
75
80
  - [timeouts-and-liveness.md](timeouts-and-liveness.md) — What kills (or doesn't kill) a live tracked agent: the wall-clock vs steering kill invariants, spawn-phase watchdog gates, steering safety nets, and stale-orphan detection ladder.
76
81
  - [visual-evidence-ci.md](visual-evidence-ci.md) — GitHub Actions before/after dashboard capture: path and label triggers, deterministic base/head fixtures, artifact/comment lifecycle, trust boundary, and local reproduction.
77
- - [watches.md](watches.md) — Persistent monitoring jobs: target-type registry, conditions, follow-up actions, and the `watches.d/` plugin folder.
82
+ - [watches.md](watches.md) — Persistent monitoring jobs: target-type registry, conditions, follow-up actions, and the `watch-plugins/` extension folder.
78
83
  - [workspace-manifests.md](workspace-manifests.md) — Declarative per-agent permission scoping: `allowed_tools` / `allowed_repos` / `allowed_external_urls` / `memory_scope`, dispatch-time repo gate, and runtime `--allowedTools` narrowing.
79
84
  - [worktree-lifecycle.md](worktree-lifecycle.md) — Worktree pool recycling, the live-dispatch guard that prevents wiping an agent's unpushed work, the dirty/divergent quarantine path, and the Windows EPERM/EBUSY file-lock retry footgun.
80
85
 
@@ -87,7 +92,7 @@ Operational runbooks for engine operators and fleet maintainers.
87
92
  - [diagnostics-crash-reports.md](diagnostics-crash-reports.md) — Proactive Node crash-diagnostics reports (`--report-on-fatalerror --report-on-signal --diagnostic-dir=...`) for the engine.js process on Windows: where reports land, config/opt-out, and retention.
88
93
  - [engine-restart.md](engine-restart.md) — How agents survive an engine restart: state persistence, the 20-minute startup grace period, and orphan reattachment via PID files and `live-output.log`.
89
94
  - [human-vs-automated.md](human-vs-automated.md) — Quick reference table of which features humans start, run, decide, and recover, and the two human approval gates.
90
- - [kb-sweep.md](kb-sweep.md) — Knowledge-base sweep runbook: how `engine/kb-sweep.js` consolidates `notes/inbox/` into `knowledge/` and survives `minions restart`.
95
+ - [kb-sweep.md](kb-sweep.md) — Knowledge-base sweep runbook: how `engine/memory/kb-sweep.js` consolidates `notes/inbox/` into `knowledge/` and survives `minions restart`.
91
96
  - [preflight.md](preflight.md) — `minions doctor` and the internal initialization/startup preflight: what each non-self-explanatory row (permission bypass, runtime detection, drive-root, etc.) is asserting.
92
97
  - [security.md](security.md) — Threat model: single-user/loopback deployment assumptions, dashboard Origin gate, data-flow trust boundaries, secret handling, and known residual risks (CSRF sweep, prompt injection, log-redactor audit).
93
98
 
@@ -38,7 +38,7 @@ immediately in the plan verification guide.
38
38
  ## Stable error envelope
39
39
 
40
40
  Every rejected request returns a JSON body with a stable shape (built by
41
- `engine/api-validation.js#toApiErrorResponse` / `exposedEnvelope`):
41
+ `engine/api/api-validation.js#toApiErrorResponse` / `exposedEnvelope`):
42
42
 
43
43
  ```json
44
44
  {
@@ -83,7 +83,7 @@ reach the client.
83
83
  ## Safe rejected-value policy
84
84
 
85
85
  Echoing back the value that was rejected is convenient for debugging but is a
86
- data-exfiltration and log-poisoning risk. `engine/api-validation.js` enforces a
86
+ data-exfiltration and log-poisoning risk. `engine/api/api-validation.js` enforces a
87
87
  uniform **safe rejected-value policy**:
88
88
 
89
89
  - **Strings** are bounded (default cap) before being echoed.
@@ -81,7 +81,7 @@ These require separate focused changes rather than expanding this PR:
81
81
  frequently while the runtime is alive.
82
82
  6. **Supervisor stale PID reuse (medium).** Startup trusts any live PID in
83
83
  `supervisor.pid`. Validate the command line against this checkout's
84
- `engine/supervisor.js` before suppressing startup.
84
+ `engine/recovery/supervisor.js` before suppressing startup.
85
85
 
86
86
  ## Healthy areas
87
87
 
@@ -1268,11 +1268,11 @@
1268
1268
  "versionNonce": 1339287385,
1269
1269
  "fontSize": 13,
1270
1270
  "fontFamily": 3,
1271
- "text": "PR integrations\n\nengine/github.js \u00b7 engine/ado.js\ngh-token.js \u00b7 ado-token.js\n\n\u2022 status + comment polling\n\u2022 reconciliation\n\u2022 verdict-flip reset",
1271
+ "text": "PR integrations\n\nengine/providers/github.js \u00b7 engine/ado/index.js\nproviders/gh-token.js \u00b7 ado/token.js\n\n\u2022 status + comment polling\n\u2022 reconciliation\n\u2022 verdict-flip reset",
1272
1272
  "textAlign": "center",
1273
1273
  "verticalAlign": "middle",
1274
1274
  "containerId": "P5ocuAQmXTFm8tYonVs7",
1275
- "originalText": "PR integrations\n\nengine/github.js \u00b7 engine/ado.js\ngh-token.js \u00b7 ado-token.js\n\n\u2022 status + comment polling\n\u2022 reconciliation\n\u2022 verdict-flip reset",
1275
+ "originalText": "PR integrations\n\nengine/providers/github.js \u00b7 engine/ado/index.js\nproviders/gh-token.js \u00b7 ado/token.js\n\n\u2022 status + comment polling\n\u2022 reconciliation\n\u2022 verdict-flip reset",
1276
1276
  "lineHeight": 1.25,
1277
1277
  "autoResize": false
1278
1278
  },
@@ -1,6 +1,6 @@
1
1
  # Auto-Discovery & Execution Pipeline
2
2
 
3
- > Last verified: 2026-07-21 against `engine.js` `tickInner()`, `engine/shared.js`, and `routing.md`.
3
+ > Last verified: 2026-07-21 against `engine.js` `tickInner()`, `engine/core/shared.js`, and `routing.md`.
4
4
 
5
5
  How the minions engine finds work and dispatches agents automatically.
6
6
 
@@ -72,11 +72,11 @@ Skips PRs where `status !== "active"`.
72
72
 
73
73
  Inside `discoverFromPrs()`, ADO and GitHub projects first resolve their own provider poll gate (`adoPollEnabled` or `ghPollEnabled`). PR-derived automation is inert when that provider's polling is off, so cached build, vote, conflict, and comment state cannot trigger new dispatches. The shared dispatch toggles (`autoReviewPrs`, `autoReReviewPrs`, `autoFixReviewFeedback`, `autoFixHumanComments`, `autoFixBuilds`, and `autoFixConflicts`) apply to both providers. `evalLoop` gates the minion review loop: initial minion reviews, minion re-reviews, and minion review-feedback fixes. Human-feedback fixes are evaluated outside `evalLoop`. Conflict fixes are additionally gated by `!fixDispatched`, so an earlier successful human/review/build fix dispatch in the same PR discovery pass suppresses the conflict fix until a later pass.
74
74
 
75
- **`autoReReviewPrs` gates both re-review paths (`P-e8b1c4d2`).** Re-reviews fire from two places: (1) the open-loop **discovery** path in `engine.js:discoverFromPrs` (PR shows `reviewStatus=waiting` after a fix push), and (2) the **closure-loop** in `engine/lifecycle.js:dispatchReReviewForFix` (a fix WI completes whose meta carries `addresses_review_wi`, queuing the next review against the same PR). The `engine.autoReReviewPrs` toggle is read at BOTH sites so flipping it OFF mutes the entire re-review cycle — not just the discovery sweep. Default ON; flip via Dashboard → Settings → Auto-fix & Review Loop, or `engine.autoReReviewPrs: false` in `config.json`.
75
+ **`autoReReviewPrs` gates both re-review paths (`P-e8b1c4d2`).** Re-reviews fire from two places: (1) the open-loop **discovery** path in `engine.js:discoverFromPrs` (PR shows `reviewStatus=waiting` after a fix push), and (2) the **closure-loop** in `engine/orchestration/lifecycle.js:dispatchReReviewForFix` (a fix WI completes whose meta carries `addresses_review_wi`, queuing the next review against the same PR). The `engine.autoReReviewPrs` toggle is read at BOTH sites so flipping it OFF mutes the entire re-review cycle — not just the discovery sweep. Default ON; flip via Dashboard → Settings → Plan & PR Workflow → Monitor, or `engine.autoReReviewPrs: false` in `config.json`.
76
76
 
77
77
  **Hard-stop kill-switch (`pollingPaused`).** `engine.pollingPaused: true` is a master override that wins over both `adoPollEnabled` and `ghPollEnabled`. When ON, section 2.6/2.7 of the tick cycle skips `pollPrStatus` and `pollPrHumanComments` for both providers, `discoverFromPrs` forces `pollEnabled=false` for every project so every per-PR auto-dispatch gate (`autoReviewPrs` / `autoFixBuilds` / `autoFixConflicts` / `autoFixReviewFeedback` / `autoFixHumanComments`) becomes inert, and — since W-ms5eljc60090f0d5 — the reconcile tail (`reconcilePrs`, `ghReconcilePrs`, `reconcileSharedBranchPrs`) is skipped too. Reconciliation was previously exempt as a "recovery sweep", but those sweeps walk every tracked PR and issue provider API calls, so the documented emergency pause did not actually stop provider network traffic. The per-provider `*PrReconcileEnabled` flags remain independent whenever the master switch is OFF. The engine logs `[engine] PR polling paused — …` once on the transition from unpaused → paused; routine PR poll log lines resume when cleared. Flip via Dashboard → Settings → Polling, `POST /api/engine/polling/pause`, or set `engine.pollingPaused: true` in `config.json`. Default OFF — fresh installs behave identically to before this knob existed.
78
78
 
79
- **Hard-stop kill-switch (`autoFixPaused`).** `engine.autoFixPaused: true` is a narrower master override that wins over every auto-fix dispatch gate. When ON, `discoverFromPrs` forces `autoFixBuilds` / `autoFixConflicts` / `autoFixReviewFeedback` / `autoFixHumanComments` to false for every project, so no fix agent is auto-dispatched against any PR. Review dispatch (`autoReviewPrs` / `autoReReviewPrs`), PR status / human-comment polling, and reconciliation are intentionally not gated — operators can pause a fix-storm during an incident while still seeing fresh review verdicts and build status. The engine logs `[engine] auto-fix paused — …` once on the transition from unpaused → paused; routine discovery resumes when cleared. Flip via Dashboard → Settings → Auto-fix & Review Loop, or set `engine.autoFixPaused: true` in `config.json`. Default OFF — fresh installs behave identically to before this knob existed.
79
+ **Hard-stop kill-switch (`autoFixPaused`).** `engine.autoFixPaused: true` is a narrower master override that wins over every auto-fix dispatch gate. When ON, `discoverFromPrs` forces `autoFixBuilds` / `autoFixConflicts` / `autoFixReviewFeedback` / `autoFixHumanComments` to false for every project, so no fix agent is auto-dispatched against any PR. Review dispatch (`autoReviewPrs` / `autoReReviewPrs`), PR status / human-comment polling, and reconciliation are intentionally not gated — operators can pause a fix-storm during an incident while still seeing fresh review verdicts and build status. The engine logs `[engine] auto-fix paused — …` once on the transition from unpaused → paused; routine discovery resumes when cleared. Flip via Dashboard → Settings → Plan & PR Workflow → Monitor, or set `engine.autoFixPaused: true` in `config.json`. Default OFF — fresh installs behave identically to before this knob existed.
80
80
 
81
81
  **Granular per-poller flags (`P-c4d8e1a3`).** The legacy `adoPollEnabled` / `ghPollEnabled` macros are bundle toggles that silence three axes at once (status, comments, reconcile) when set to `false`. To turn off only one axis, set the matching granular flag in `config.engine`:
82
82
 
@@ -167,10 +167,19 @@ This means a single work item like "Add telemetry to the document creation pipel
167
167
 
168
168
  **Reads:** `config.schedules[]` and persistent schedule-run state.
169
169
 
170
- Enabled schedules whose three-field cron expression matches the current minute produce work through `engine/scheduler.js`. Ordinary tasks and tri-agent harness missions are written to the central SQL work-item scope with `_scheduleId` metadata; meeting schedules create meeting records directly. The persisted `lastRun` value prevents a schedule from firing twice in the same calendar minute.
170
+ Enabled schedules whose three-field cron expression matches the current minute produce work through `engine/orchestration/scheduler.js`. Ordinary tasks and tri-agent harness missions are written to the central SQL work-item scope with `_scheduleId` metadata; meeting schedules create meeting records directly. The persisted `lastRun` value prevents a schedule from firing twice in the same calendar minute.
171
+
172
+ #### Scheduled-failure retention (`pruneSupersededFailedScheduledItems`)
173
+
174
+ Machine-generated scheduled runs fail routinely (an hourly review/fetch sweep with a transient auth or network error), so without a retention policy their **failed** work items accumulate a week of duplicates. `engine/orchestration/failed-scheduled-cleanup.js` runs a conservative daily sweep inside `runCleanup` (step 21) to age them out:
175
+
176
+ - **Targets only provable scheduled runs.** An item qualifies via structured provenance (`createdBy === 'scheduler'` **and** `_scheduleId`) or the canonical legacy `sched-<scheduleId>-<ts>` id prefix. Classification is **never** by title/description prose, so a human-authored item that merely mentions "scheduled" is untouched.
177
+ - **Groups failures by originating schedule.** The **newest** failure per schedule is retained long enough to diagnose the current failure; **superseded** (older) failures are pruned once past the diagnostic window (`DIAGNOSTIC_RETENTION_MS`, 24h). A later **successful** run lets the newest failure be pruned too, once that window has elapsed. An absolute threshold (`ABSOLUTE_RETENTION_MS`, 7d) prunes stale failures regardless.
178
+ - **Fails open.** Non-scheduled / human-authored failures, items with plan/PRD/decomposition/followup lineage (`parent_id`, `_prdItemId`), and any item referenced by a live (pending/active/review) dispatch are skipped, never deleted. This is destructive retention and is deliberately separate from the non-destructive navigation-badge age-out for user failures.
179
+ - **Cadence, concurrency, idempotency.** Although `runCleanup` fires every ~10 min, a persisted `lastFailedScheduledPruneAt` marker in the engine small-state store gates the sweep to at most once per `PRUNE_INTERVAL_MS` (daily); the marker is claimed inside a single small-state transaction so overlapping ticks or a restart race cannot double-run it. Deletions go through `mutateWorkItems` and re-validate status/provenance against the fresh SQL row, so a re-run prunes nothing further. Pruned counts are logged once per sweep with the per-schedule breakdown — no per-tick noise. The policy is a documented shared default (no `engine.*` knob), so there is no Settings toggle to configure.
171
180
 
172
181
  `engine.bootstrapDefaultSchedules` defaults to `true` and is configurable under
173
- Dashboard → Settings → Workflow Defaults. `engine/schedule-bootstrap.js`
182
+ Dashboard → Settings → Plan & PR Workflow → Monitor. `engine/orchestration/schedule-bootstrap.js`
174
183
  idempotently creates a read-only per-project git-fetch schedule (title-derived
175
184
  `keep-branch-fresh-git-fetch-origin-…` id, `0 */12 *`, `explore`) and one shared
176
185
  `harness-sweep-all-projects` schedule (`0 6 *`, `explore`, low priority).
@@ -202,7 +211,7 @@ Both write to the SQL work-item store and are picked up by Source 2 on the same
202
211
 
203
212
  ## PR Status Polling (`pollPrStatus`)
204
213
 
205
- **Runs:** On a wall-clock cadence derived from `prPollStatusEvery × engine.tickInterval` (default 72 × 10s, ≈ 12 minutes), independently of work discovery. ADO polling lives in `engine/ado.js`; GitHub polling lives in `engine/github.js` — both run in parallel each cycle (`Promise.allSettled`) and write the shared SQL PR schema. Replaces the retired agent-based `pr-sync`.
214
+ **Runs:** On a wall-clock cadence derived from `prPollStatusEvery × engine.tickInterval` (default 72 × 10s, ≈ 12 minutes), independently of work discovery. ADO polling lives in `engine/ado/index.js`; GitHub polling lives in `engine/providers/github.js` — both run in parallel each cycle (`Promise.allSettled`) and write the shared SQL PR schema. Replaces the retired agent-based `pr-sync`.
206
215
 
207
216
  The engine directly polls host REST APIs for **all** PR metadata: build/CI status, human review votes, and completion state. No agent dispatch is needed.
208
217
 
@@ -220,7 +229,7 @@ The engine directly polls host REST APIs for **all** PR metadata: build/CI statu
220
229
  | `buildStatus` | ADO builds or GitHub check-runs | `passing` / `failing` / `running` / `none` |
221
230
  | `buildFailReason` | Failed build/check name | Set on failure, cleared otherwise |
222
231
 
223
- **Auth:** Bearer token via shared `engine/ado-token.js`: prefer `az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv`, then fall back to `azureauth ado token --mode iwa --mode broker --output token --timeout 1` (cached 30 minutes). The `--timeout 1` flag is required — without it, azureauth can hang indefinitely in headless sessions. GitHub polling resolves a repo-scoped token through `engine/gh-token.js` and threads it as `GH_TOKEN` per call; it never switches global `gh` auth.
232
+ **Auth:** Bearer token via shared `engine/ado/token.js`: prefer `az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv`, then fall back to `azureauth ado token --mode iwa --mode broker --output token --timeout 1` (cached 30 minutes). The `--timeout 1` flag is required — without it, azureauth can hang indefinitely in headless sessions. GitHub polling resolves a repo-scoped token through `engine/providers/gh-token.js` and threads it as `GH_TOKEN` per call; it never switches global `gh` auth.
224
233
 
225
234
  This feeds `discoverFromPrs` — when `buildStatus` flips to `"failing"`, the next discovery tick dispatches a fix agent. When `status` becomes `"merged"`, the PR drops out of active polling.
226
235
 
@@ -342,8 +351,8 @@ memory are used. Human/LLM-authored appendices are wrapped as untrusted input.
342
351
  The engine resolves `resolveRuntime(resolveAgentCli(...))`; the selected adapter
343
352
  owns binary discovery, argv, prompt delivery, workspace preparation, and output
344
353
  parsing. Cold agent dispatches use the runtime-neutral
345
- `engine/spawn-agent.js`; opt-in Copilot fleet dispatch can use the ACP worker
346
- pool. CC/doc-chat use direct `engine/llm.js` calls.
354
+ `engine/agents/spawn-agent.js`; opt-in Copilot fleet dispatch can use the ACP worker
355
+ pool. CC/doc-chat use direct `engine/agents/llm.js` calls.
347
356
 
348
357
  - Process runs in the resolved worktree/live checkout (or `MINIONS_DIR` for
349
358
  project-less read-only work)
@@ -4,7 +4,7 @@ How the engine decides which branch a dispatch is going to push to.
4
4
  CLAUDE.md → Branch Naming holds the one-line summary; the structured
5
5
  vs. loose-extractor rules and the canonical PR-fix incident live here.
6
6
 
7
- > Source of truth: `engine/shared.js`
7
+ > Source of truth: `engine/core/shared.js`
8
8
  > (`deriveWorkItemBranchName`, `extractStructuredWorkItemPrRef`,
9
9
  > `extractWorkItemPrRef`, `copyWorkItemPrFields`),
10
10
  > `engine.js#getWorkItemPrRef` + `getStructuredWorkItemPrRef`,
@@ -78,9 +78,9 @@ stamping:
78
78
  2. **Loose (description/title-scanned) refs on a fix WI** are confirmed via:
79
79
  - an already-tracked SQL PR record for the ref (cheap, no
80
80
  network), else
81
- - a host existence check — `engine/github.js#prExists` (`gh api
82
- repos/:owner/:repo/pulls/NNN`; 404 ⇒ issue) or `engine/ado.js#prExists`
83
- (`…/pullrequests/NNN`), routed via `engine/gh-token.js` per-account token.
81
+ - a host existence check — `engine/providers/github.js#prExists` (`gh api
82
+ repos/:owner/:repo/pulls/NNN`; 404 ⇒ issue) or `engine/ado/index.js#prExists`
83
+ (`…/pullrequests/NNN`), routed via `engine/providers/gh-token.js` per-account token.
84
84
  `shared.classifyPrRefForVerification(prRef, project)` does the pure host/slug
85
85
  /number routing; the result is TTL-cached.
86
86
  3. **Fail-safe:** when existence can't be confirmed (issue, 404, network/auth
@@ -3,13 +3,14 @@
3
3
  * Capture dashboard screenshots for GitHub Pages.
4
4
  * Seeds demo data, captures all pages, then cleans up.
5
5
  *
6
- * Run: node docs/capture-demos.js
7
- * Requires: dashboard running on :7331, playwright chromium installed
6
+ * Run: node docs/capture-demos.js --state-dir <isolated-state> --base-url <url>
7
+ * Requires: an isolated dashboard using the same state dir, and Playwright chromium
8
8
  */
9
9
  const { chromium } = require('@playwright/test');
10
10
  const { execFileSync } = require('child_process');
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
+ const { canonicalPath, pathsOverlap } = require('../.github/scripts/owned-directory');
13
14
 
14
15
  const DEMO_DIR = path.join(__dirname, 'demo');
15
16
  const DEFAULT_BASE_URL = 'http://localhost:7331';
@@ -32,6 +33,7 @@ function parseArgs(argv = process.argv.slice(2)) {
32
33
  baseUrl: DEFAULT_BASE_URL,
33
34
  outputDir: DEMO_DIR,
34
35
  stateDir: null,
36
+ expectedStateDir: null,
35
37
  skipSeed: false,
36
38
  fixedTime: null,
37
39
  };
@@ -55,6 +57,10 @@ function parseArgs(argv = process.argv.slice(2)) {
55
57
  options.stateDir = path.resolve(valueFor(argv[i], i));
56
58
  i++;
57
59
  break;
60
+ case '--expected-state-dir':
61
+ options.expectedStateDir = valueFor(argv[i], i);
62
+ i++;
63
+ break;
58
64
  case '--fixed-time':
59
65
  options.fixedTime = valueFor(argv[i], i);
60
66
  if (!Number.isFinite(Date.parse(options.fixedTime))) {
@@ -69,9 +75,33 @@ function parseArgs(argv = process.argv.slice(2)) {
69
75
  throw new Error(`Unknown argument: ${argv[i]}`);
70
76
  }
71
77
  }
78
+ if (!options.stateDir) {
79
+ throw new Error('--state-dir is required so capture cannot target live Minions state');
80
+ }
81
+ if (!options.expectedStateDir) options.expectedStateDir = options.stateDir;
72
82
  return options;
73
83
  }
74
84
 
85
+ function assertOwnedStateDir(stateDir) {
86
+ if (pathsOverlap(stateDir, ROOT)) {
87
+ throw new Error(`Demo state directory must not overlap the source checkout: ${stateDir}`);
88
+ }
89
+ const marker = path.join(stateDir, '.minions-test-fixture');
90
+ if (!fs.existsSync(marker) || !fs.statSync(marker).isFile() || fs.readFileSync(marker, 'utf8') !== '') {
91
+ throw new Error(`Demo state directory is not marker-owned: ${stateDir}`);
92
+ }
93
+ }
94
+
95
+ async function assertDashboardUsesStateDir(baseUrl, expectedStateDir, fetchImpl = globalThis.fetch) {
96
+ const response = await fetchImpl(`${baseUrl.replace(/\/+$/, '')}/api/health`);
97
+ if (!response.ok) throw new Error(`Dashboard health check failed: HTTP ${response.status}`);
98
+ const health = await response.json();
99
+ if (!health.minionsDir) throw new Error('Dashboard health response did not identify its Minions state directory');
100
+ if (canonicalPath(health.minionsDir) !== canonicalPath(expectedStateDir)) {
101
+ throw new Error(`Refusing capture: dashboard uses ${health.minionsDir}, not isolated state ${expectedStateDir}`);
102
+ }
103
+ }
104
+
75
105
  function runSeed({ clean = false, stateDir = null } = {}) {
76
106
  const args = [path.join(ROOT, 'test', 'seed-demo-data.js')];
77
107
  if (clean) args.push('--clean');
@@ -84,9 +114,14 @@ async function capture(options = {}) {
84
114
  baseUrl = DEFAULT_BASE_URL,
85
115
  outputDir = DEMO_DIR,
86
116
  stateDir = null,
117
+ expectedStateDir = stateDir,
87
118
  skipSeed = false,
88
119
  fixedTime = null,
120
+ fetchImpl = globalThis.fetch,
89
121
  } = options;
122
+ if (!stateDir) throw new Error('stateDir is required so capture cannot target live Minions state');
123
+ assertOwnedStateDir(stateDir);
124
+ await assertDashboardUsesStateDir(baseUrl, expectedStateDir, fetchImpl);
90
125
  fs.mkdirSync(outputDir, { recursive: true });
91
126
 
92
127
  let browser;
@@ -287,4 +322,6 @@ module.exports = {
287
322
  SCREENSHOT_FILES,
288
323
  parseArgs,
289
324
  capture,
325
+ assertOwnedStateDir,
326
+ assertDashboardUsesStateDir,
290
327
  };
@@ -0,0 +1,123 @@
1
+ # CI runner canary
2
+
3
+ `.github/workflows/ci-runner-canary.yml` answers one question every hour: **is
4
+ this repository's CI actually able to run anything?**
5
+
6
+ ## The failure it exists for
7
+
8
+ On 2026-07-30 both self-hosted Windows runners on `yemi33/minions` went
9
+ offline. Every automated workflow on that fork ultimately targets that one host
10
+ label, so the effects cascaded:
11
+
12
+ - `Publish to npm` could never allocate a runner for its `validate` job. Its
13
+ run-level concurrency group (`cancel-in-progress: false`) therefore never
14
+ released, and ~59 runs piled up at `status=pending` with **zero jobs
15
+ created**. Bringing the runners back online did **not** drain them — they are
16
+ blocked at RUN level, before a job exists.
17
+ - `PR Tests` sat `queued` for days.
18
+ - The `Rerun stale PR CI` watchdog is itself self-hosted, so the watchdog was
19
+ dark too.
20
+
21
+ The critical property: **none of that ever becomes a failure.** A run with no
22
+ job never reaches a `failure` or `startup_failure` conclusion, and GitHub's 24h
23
+ queue timeout cannot fire on a run that never created a job to time out. The
24
+ hourly CI-health check lists only `--status failure` and `--status
25
+ startup_failure`, so it reported "all green" for ~2.5 days while CI was
26
+ completely dark and npm releases were blocked.
27
+
28
+ A canary that shares any part of that failure domain reports nothing. This one
29
+ is built not to.
30
+
31
+ ## What makes it survivable
32
+
33
+ | Property | Why |
34
+ | --- | --- |
35
+ | `runs-on: windows-latest` | A GitHub-**hosted** runner, so a self-hosted outage cannot stall it. Not `ubuntu-latest`: the yemi33 account cannot provision Linux hosted runners (dual-CI topology). `windows-latest` is proven on both forks — `publish.yml`'s `publish` job already uses it. |
36
+ | No `needs:` | Waiting on another job re-imports that job's ability to stall. |
37
+ | Its own concurrency group, `cancel-in-progress: true` | Sharing `npm-publish-*` or `windows-test-heavy-*` would make the canary queue behind the stall it reports. Cancelling in progress means a canary can never itself become the stalled run. |
38
+ | Nothing hardcoded to one fork | `.github/workflows/` is excluded from the backport, so the two forks sync this file by hand; every fork-specific literal is a drift surface. The default branch is read from the API (`master` on yemi33, `main` on opg) and the self-hosted label sets are derived from the workflows actually checked in. |
39
+
40
+ `test/unit/ci-runner-canary.test.js` pins each of these, because every one of
41
+ them is a way the canary could be quietly neutered back into silence.
42
+
43
+ ### Editing the `run:` script
44
+
45
+ GitHub substitutes `${{ … }}` expressions **anywhere** in a workflow file, a
46
+ `run:` block scalar included, before the script is handed to the shell. This
47
+ workflow parses other workflows' `runs-on:` values, so it has to *talk about*
48
+ that syntax — and therefore must never spell the opening delimiter out. It
49
+ assembles it at runtime instead (`$exprOpen = '$' + '{{'`).
50
+
51
+ Getting this wrong is silent in both directions:
52
+
53
+ - A **malformed** expression is rejected at parse time. The run reports
54
+ `conclusion=failure` with **zero jobs and no check run**, so `gh pr checks`
55
+ shows all-green and nothing observes that the workflow never ran. That is not
56
+ hypothetical — it is how [run 30754622581][rejected] shipped through review.
57
+ - A **well-formed** one is substituted, silently rewriting the script.
58
+
59
+ The unit test covers both: it parses every expression in every workflow the way
60
+ GitHub does, and it fails if the canary's `run:` block contains the literal
61
+ delimiter at all.
62
+
63
+ [rejected]: https://github.com/opg-microsoft/minions/actions/runs/30754622581
64
+
65
+ ## What it checks
66
+
67
+ **(a) Self-hosted fleet health.** Applicability is derived from the workflows
68
+ on disk, not from which runners happen to be registered. Registration is the
69
+ wrong source: if the fleet de-registers itself during a host rebuild, the repo
70
+ has zero runners carrying the label, and "no runners registered" would read as
71
+ "not applicable" at the exact moment every self-hosted job hangs forever. For
72
+ each `runs-on` label set containing `self-hosted`, the canary fails when no
73
+ registered runner carrying that whole set is `online`. Label matching is
74
+ case-insensitive, because workflows ask for `windows` while runners register
75
+ `Windows`.
76
+
77
+ **(b) Stalled runs on the default branch.** Any run `pending` or `queued`
78
+ longer than the threshold fails the canary. This is the load-bearing check: a
79
+ dark fleet always surfaces here, and it needs only `actions: read`.
80
+
81
+ Both emit an actionable job summary — which runners are offline, and the oldest
82
+ stalled run's id, workflow name, age, and URL.
83
+
84
+ ## Condition (a) is off by default
85
+
86
+ `GITHUB_TOKEN` **cannot** list self-hosted runners. That endpoint needs
87
+ `administration:read`, and `administration` is not a grantable key in a
88
+ workflow `permissions:` block; the request comes back `404`, which is how
89
+ GitHub masks an unauthorized read here.
90
+
91
+ So condition (a) reports itself as **UNAVAILABLE** — in the log, as a
92
+ `::warning` annotation, in the job summary, and in the closing verdict. It is
93
+ never treated as a pass. To enable it, add a repository secret
94
+ `RUNNER_STATUS_TOKEN` holding a PAT with repo `administration:read`; the
95
+ workflow prefers it over `GITHUB_TOKEN` automatically.
96
+
97
+ Until then, condition (b) still catches the outage, because a fleet that cannot
98
+ allocate runners always produces runs stuck pending or queued.
99
+
100
+ ## Tuning and operating
101
+
102
+ - Threshold: `stall_hours` (`workflow_dispatch` input), default **2**.
103
+ - Cadence: hourly, at `:23`.
104
+ - Manual run: `gh workflow run "CI runner canary" --repo <owner>/<repo>`, or
105
+ with an override, `-f stall_hours=6`.
106
+
107
+ ### When it goes red
108
+
109
+ 1. **Fleet offline** — the failing repo's runners need an operator on the host;
110
+ no code change can bring them back. Restart the Actions runner service.
111
+ 2. **Stalled runs** — check whether a run-level `concurrency` group is holding
112
+ the queue. Runs blocked at RUN level do **not** drain on their own once
113
+ runners return; cancel the backlog explicitly:
114
+
115
+ ```bash
116
+ gh run list --repo <owner>/<repo> --branch <default> --status pending \
117
+ --limit 100 --json databaseId --jq '.[].databaseId' |
118
+ xargs -n1 gh run cancel --repo <owner>/<repo>
119
+ ```
120
+
121
+ Related: [default-branch-ci.md](default-branch-ci.md) covers the post-merge
122
+ gate, which answers "is the merged tree green?" — a different question from
123
+ "can CI run at all?".
@@ -3,7 +3,7 @@
3
3
  **Work item:** W-mrdon0pe000l045a
4
4
  **Config flag:** `engine.propagateClaudeMdForNonClaudeRuntimes` (default `true`)
5
5
  **Per-project override:** `project.propagateClaudeMdForNonClaudeRuntimes`
6
- **Module:** `engine/claude-md-context.js` · **Injection:** `engine/playbook.js`
6
+ **Module:** `engine/agents/claude-md-context.js` · **Injection:** `engine/agents/playbook.js`
7
7
 
8
8
  ## Problem
9
9
 
@@ -84,7 +84,7 @@ does not meaningfully slow dispatch even in a monorepo.
84
84
 
85
85
  ## Injection & byte cap
86
86
 
87
- `engine/playbook.js#renderPlaybook` adds `CLAUDE.md` propagation as a context
87
+ `engine/agents/playbook.js#renderPlaybook` adds `CLAUDE.md` propagation as a context
88
88
  layer alongside the existing `pinned.md` → `notes.md` →
89
89
  `knowledge/agents/<agentId>.md` layers:
90
90