@yemi33/minions 0.1.2447 → 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 +66 -7
  7. package/dashboard/js/detail-panel.js +36 -0
  8. package/dashboard/js/memory-panel.js +59 -12
  9. package/dashboard/js/qa.js +186 -45
  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 +52 -6
  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,8 +1,8 @@
1
1
  /**
2
- * engine/managed-spawn.js — Item 1 of plan P-7a3b1c92.
2
+ * engine/processes/managed-spawn.js — Item 1 of plan P-7a3b1c92.
3
3
  *
4
4
  * Schema, validator, sidecar reader, acceptance helper, and playbook hint for
5
- * the managed-spawn primitive. Mirrors engine/keep-process-sweep.js
5
+ * the managed-spawn primitive. Mirrors engine/processes/keep-process-sweep.js
6
6
  * beat-for-beat: an agent writes agents/<id>/managed-spawn.json describing
7
7
  * long-running services it wants the engine to spawn + healthcheck on its
8
8
  * behalf; this module validates the file, returns a structured acceptance
@@ -13,7 +13,7 @@
13
13
  * plan items (P-7a3b1c93+). This module is pure: no spawns, no network, no
14
14
  * mutation of shared state.
15
15
  *
16
- * Design template: engine/keep-process-sweep.js. Divergences are justified
16
+ * Design template: engine/processes/keep-process-sweep.js. Divergences are justified
17
17
  * inline; symmetry with keep-pids is the convention.
18
18
  */
19
19
 
@@ -22,8 +22,8 @@ const path = require('path');
22
22
  const http = require('http');
23
23
  const https = require('https');
24
24
  const { spawn, exec } = require('child_process');
25
- const shared = require('./shared');
26
- const queries = require('./queries');
25
+ const shared = require('../core/shared');
26
+ const queries = require('../core/queries');
27
27
  const processUtils = require('./process-utils');
28
28
 
29
29
  const { log, ENGINE_DEFAULTS } = shared;
@@ -801,7 +801,7 @@ function buildManagedSpawnHint(opts) {
801
801
  '}',
802
802
  '```',
803
803
  '',
804
- 'Known device-farm tooling to reach for instead of re-deriving a pattern from scratch: `adb` and `emulator` (both on the managed-spawn executable allowlist — device/emulator shell, install, logcat; `emulator -list-avds` discovers configured AVDs before you pick one for the spec), and `maestro` (declarative mobile UI-flow runner already wired in as a built-in QA runner adapter — see `engine/qa-runners.js` — for the DRAFT/EXECUTE phases, not for the managed-spawn `cmd`/healthcheck allowlist itself).',
804
+ 'Known device-farm tooling to reach for instead of re-deriving a pattern from scratch: `adb` and `emulator` (both on the managed-spawn executable allowlist — device/emulator shell, install, logcat; `emulator -list-avds` discovers configured AVDs before you pick one for the spec), and `maestro` (declarative mobile UI-flow runner already wired in as a built-in QA runner adapter — see `engine/qa-runners/index.js` — for the DRAFT/EXECUTE phases, not for the managed-spawn `cmd`/healthcheck allowlist itself).',
805
805
  '',
806
806
  '### Verify before exit',
807
807
  '',
@@ -1174,11 +1174,32 @@ function reapOrTrackManagedRuntime(spec, runtime, ctx, options = {}) {
1174
1174
  // back to a liveness re-check + sweep-retry tracking when the kill itself
1175
1175
  // FAILED (or there was no pid to kill).
1176
1176
  let killed = false;
1177
+ // A CONCLUSIVE identity mismatch — a real creation time that is later than
1178
+ // the child we recorded — proves the PID is not ours (recycled, or an
1179
+ // EPERM-guarded foreign/system process that isPidAlive reports as alive).
1180
+ // There is nothing of ours to reap, so do not signal it, and do not pin the
1181
+ // runtime into the sweep-retry loop forever (W-ms8d10y3003t0588).
1182
+ let foreignPid = false;
1177
1183
  if (Number.isInteger(pid) && pid > 0) {
1178
- try { killed = shared.killImmediate({ pid }) !== false; }
1179
- catch (_e) { killed = false; }
1184
+ const getIdentity = typeof options.getProcessIdentity === 'function'
1185
+ ? options.getProcessIdentity
1186
+ : processUtils.getProcessIdentity;
1187
+ let expectedIdentity = null;
1188
+ try { expectedIdentity = getIdentity(pid); } catch { /* fail closed below */ }
1189
+ foreignPid = processUtils.isProcessIdentityConclusiveMismatch(
1190
+ expectedIdentity,
1191
+ _managedStartedAtMs(runtime),
1192
+ );
1193
+ if (!foreignPid) {
1194
+ try {
1195
+ killed = shared.terminateProcess('engine.managed-spawn.reap-failed', { pid }, {
1196
+ expectedIdentity,
1197
+ }) !== false;
1198
+ }
1199
+ catch (_e) { killed = false; }
1200
+ }
1180
1201
  }
1181
- if (killed || !shared.isPidAlive(pid)) return { reaped: true, tracked: false };
1202
+ if (foreignPid || killed || !shared.isPidAlive(pid)) return { reaped: true, tracked: false };
1182
1203
 
1183
1204
  const record = _toStateRecord(spec, runtime, ctx);
1184
1205
  record.healthy = false;
@@ -1227,17 +1248,47 @@ function removeManagedSpec(name, opts = {}) {
1227
1248
  return { removed: false, reason: 'generation-changed' };
1228
1249
  }
1229
1250
  const killPid = Number.isInteger(candidate.pid) && candidate.pid > 0 ? candidate.pid : null;
1230
- const verifyIdentity = opts.verifyIdentity === true;
1251
+ const verifyIdentity = opts.verifyIdentity !== false;
1231
1252
  const getIdentity = typeof opts.getProcessIdentity === 'function'
1232
1253
  ? opts.getProcessIdentity
1233
1254
  : processUtils.getProcessIdentity;
1255
+ // Tri-state probe (W-ms6dmv99005o26f4), consulted ONLY to interpret a null
1256
+ // identity. `getIdentity` keeps priority so the injected/monkey-patched
1257
+ // getProcessIdentity seams used by callers and tests are unaffected.
1258
+ const inspectIdentity = typeof opts.inspectProcessIdentity === 'function'
1259
+ ? opts.inspectProcessIdentity
1260
+ : processUtils.inspectProcessIdentity;
1234
1261
  const wasAlive = killPid !== null && shared.isPidAlive(killPid);
1235
1262
  let identityBefore = null;
1236
1263
  if (verifyIdentity && wasAlive) {
1237
1264
  identityBefore = getIdentity(killPid);
1238
- if (!identityBefore) return { removed: false, reason: 'identity-unavailable' };
1239
- if (!processUtils.isProcessIdentityCompatible(identityBefore, _managedStartedAtMs(candidate))) {
1240
- return { removed: false, reason: 'identity-mismatch' };
1265
+ if (!identityBefore) {
1266
+ // A null identity is not one condition but two, and they demand opposite
1267
+ // handling. isPidAlive() reports EPERM as alive (the kernel found the
1268
+ // process and refused the signal), so a foreign/system process — or a
1269
+ // recycled PID number no longer ours — now reaches this branch.
1270
+ // CONCLUSIVE absence from the process table → the PID is demonstrably
1271
+ // not our managed child; there is nothing of ours to kill, so drop
1272
+ // the stale record instead of pinning it forever.
1273
+ // INCONCLUSIVE (enumeration failed, no start time) → we learned
1274
+ // nothing; preserve the spec so a later sweep can retry.
1275
+ let conclusive = false;
1276
+ try { conclusive = inspectIdentity(killPid).conclusive === true; }
1277
+ catch { conclusive = false; }
1278
+ if (!conclusive) return { removed: false, reason: 'identity-unavailable' };
1279
+ } else if (!processUtils.isProcessIdentityCompatible(identityBefore, _managedStartedAtMs(candidate))) {
1280
+ // Same split as the null branch above. A CONCLUSIVE mismatch (a real
1281
+ // creation time later than the child we recorded) is exactly as decisive
1282
+ // as a conclusive absence: the PID is demonstrably not our managed child,
1283
+ // so drop the stale record instead of pinning it forever behind
1284
+ // `identity-mismatch` — which leaked the spec through
1285
+ // removeManagedSpecsForProject and re-failed on every sweep retry
1286
+ // (W-ms8d10y3003t0588). Clearing identityBefore routes it into the same
1287
+ // never-signal path the conclusive-absence case uses.
1288
+ if (!processUtils.isProcessIdentityConclusiveMismatch(identityBefore, _managedStartedAtMs(candidate))) {
1289
+ return { removed: false, reason: 'identity-mismatch' };
1290
+ }
1291
+ identityBefore = null;
1241
1292
  }
1242
1293
  }
1243
1294
 
@@ -1268,15 +1319,21 @@ function removeManagedSpec(name, opts = {}) {
1268
1319
  // qemu-system-x86_64 child) whose descendants survive a single-PID kill and
1269
1320
  // leak indefinitely (opg-microsoft/minions#710).
1270
1321
  let killed = false;
1271
- if (killPid !== null && (!verifyIdentity || wasAlive)) {
1272
- if (verifyIdentity) {
1273
- const identityAfter = getIdentity(killPid);
1274
- if (!processUtils.isSameProcessIdentity(identityBefore, identityAfter)) {
1275
- _restoreManagedRecord(removedRecord);
1276
- return { removed: false, reason: 'identity-changed' };
1277
- }
1322
+ // `identityBefore` is required: reaching here with a null identity means the
1323
+ // PID was CONCLUSIVELY absent from the process table, or its live identity
1324
+ // CONCLUSIVELY proved it is not our child (see above). Either way there is no
1325
+ // verified target and we must not fire a kill at a foreign PID.
1326
+ if (killPid !== null && verifyIdentity && wasAlive && identityBefore) {
1327
+ const identityAfter = getIdentity(killPid);
1328
+ if (!processUtils.isSameProcessIdentity(identityBefore, identityAfter)) {
1329
+ _restoreManagedRecord(removedRecord);
1330
+ return { removed: false, reason: 'identity-changed' };
1331
+ }
1332
+ try {
1333
+ killed = shared.terminateProcess('engine.managed-spawn.remove', { pid: killPid }, {
1334
+ expectedIdentity: identityAfter,
1335
+ }) !== false;
1278
1336
  }
1279
- try { killed = shared.killImmediate({ pid: killPid }) !== false; }
1280
1337
  catch (e) {
1281
1338
  log('warn', 'managed-spawn removeManagedSpec: kill ' + killPid + ' failed: ' + e.message);
1282
1339
  }
@@ -1293,7 +1350,7 @@ function removeManagedSpec(name, opts = {}) {
1293
1350
 
1294
1351
  function listManagedSpecs(opts) {
1295
1352
  opts = opts || {};
1296
- const parsed = require('./small-state-store').readManagedProcesses();
1353
+ const parsed = require('../persistence/small-state-store').readManagedProcesses();
1297
1354
  const specs = (parsed && Array.isArray(parsed.specs)) ? parsed.specs : [];
1298
1355
  if (opts.project) return specs.filter(s => s && s.owner_project === opts.project);
1299
1356
  return specs.slice();
@@ -1547,7 +1604,7 @@ function tailManagedLog(name, lines) {
1547
1604
  // ─── Item 6 (P-1f9c3a45) ─────────────────────────────────────────────────────
1548
1605
  //
1549
1606
  // Playbook auto-inject of the live-managed-processes block. Called by
1550
- // engine/playbook.js renderPlaybook (project-scoped, computed once per render).
1607
+ // engine/agents/playbook.js renderPlaybook (project-scoped, computed once per render).
1551
1608
  // Filters listManagedSpecs() to specs where:
1552
1609
  // - owner_project === opts.project
1553
1610
  // - healthy === true
@@ -1899,7 +1956,7 @@ function restartManagedSpec(name, opts = {}) {
1899
1956
  // Kills + drops every spec whose
1900
1957
  // owner_project matches, unlinks the
1901
1958
  // log + log.1. Returns {killed,
1902
- // unlinked}. engine/projects.js
1959
+ // unlinked}. engine/planning/projects.js
1903
1960
  // removeProject calls this — no
1904
1961
  // managed-process awareness elsewhere.
1905
1962
  //
@@ -2096,28 +2153,22 @@ function removeManagedSpecsForProject(projectName) {
2096
2153
  if (typeof projectName !== 'string' || projectName.length === 0) {
2097
2154
  return { killed: 0, unlinked: 0, scanned: 0 };
2098
2155
  }
2099
- let toKill = [];
2100
- let logPaths = [];
2101
- shared.mutateManagedProcesses((data) => {
2102
- if (!data || typeof data !== 'object' || !Array.isArray(data.specs)) {
2103
- return _initialStateShape();
2104
- }
2105
- const keep = [];
2106
- for (const rec of data.specs) {
2107
- if (rec && rec.owner_project === projectName) {
2108
- if (Number.isInteger(rec.pid) && rec.pid > 0) toKill.push(rec.pid);
2109
- if (rec.log_path) logPaths.push(rec.log_path);
2110
- continue; // drop
2111
- }
2112
- keep.push(rec);
2113
- }
2114
- data.specs = keep;
2115
- return data;
2116
- }, { defaultValue: _initialStateShape() });
2156
+ const records = listManagedSpecs({ project: projectName });
2117
2157
  let killed = 0;
2118
- if (toKill.length > 0) {
2119
- try { killed = shared.killByPidTreesImmediate(toKill); }
2120
- catch (e) { log('warn', 'managed-spawn removeForProject: kill batch failed for ' + projectName + ': ' + e.message); }
2158
+ let removed = 0;
2159
+ const logPaths = [];
2160
+ for (const rec of records) {
2161
+ const result = removeManagedSpec(rec.name, {
2162
+ expected: rec,
2163
+ verifyIdentity: true,
2164
+ });
2165
+ if (!result.removed) {
2166
+ log('warn', 'managed-spawn removeForProject: preserved ' + rec.name + ' — ' + result.reason);
2167
+ continue;
2168
+ }
2169
+ removed++;
2170
+ if (result.killed) killed++;
2171
+ if (rec.log_path) logPaths.push(rec.log_path);
2121
2172
  }
2122
2173
  let unlinked = 0;
2123
2174
  for (const p of logPaths) {
@@ -2126,7 +2177,7 @@ function removeManagedSpecsForProject(projectName) {
2126
2177
  catch (e) { if (e && e.code !== 'ENOENT') log('warn', 'managed-spawn removeForProject: unlink ' + candidate + ' failed: ' + e.message); }
2127
2178
  }
2128
2179
  }
2129
- return { killed: killed, unlinked: unlinked, scanned: toKill.length };
2180
+ return { killed, unlinked, scanned: records.length, removed };
2130
2181
  }
2131
2182
 
2132
2183
  module.exports = {