@moretea-labs/forge 1.8.0 → 1.8.1

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 (528) hide show
  1. package/AGENTS.md +70 -7
  2. package/CHANGELOG.md +14 -0
  3. package/CLAUDE.md +17 -2
  4. package/CONTRIBUTING.md +3 -2
  5. package/THIRD_PARTY_NOTICES.md +1 -1
  6. package/adapters/chatgpt/browser-delivery-host.ts +7 -1
  7. package/adapters/chatgpt/browser-delivery-runtime.ts +529 -56
  8. package/adapters/chatgpt/controller-binding-store.ts +101 -22
  9. package/adapters/chatgpt/controller-round-host.ts +15 -25
  10. package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
  11. package/adapters/chatgpt/provider-delivery.ts +228 -1
  12. package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
  13. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  14. package/adapters/computer/chatgpt-target-router.ts +103 -0
  15. package/adapters/computer/chrome-extension/background.js +385 -0
  16. package/adapters/computer/chrome-extension/content.js +378 -0
  17. package/adapters/computer/chrome-extension/core.js +24 -0
  18. package/adapters/computer/chrome-extension/manifest.json +30 -0
  19. package/adapters/computer/desktop-operator-discovery.ts +11 -31
  20. package/adapters/computer/interaction-target-authority.ts +142 -18
  21. package/adapters/mcp/auth.ts +0 -1
  22. package/adapters/mcp/instructions.ts +5 -4
  23. package/adapters/mcp/multi-repository.ts +3 -19
  24. package/adapters/mcp/oauth.ts +73 -0
  25. package/adapters/mcp/paths.ts +4 -1
  26. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  27. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  28. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  29. package/adapters/mcp/runtime-gateway/context-adapter.ts +411 -73
  30. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  31. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
  32. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  33. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
  34. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  35. package/adapters/mcp/runtime-gateway/execution-tools.ts +8 -42
  36. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
  37. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
  38. package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
  39. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
  40. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
  41. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
  42. package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
  43. package/adapters/mcp/runtime-gateway/router.ts +18 -504
  44. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  45. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
  46. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  47. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
  48. package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
  49. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
  50. package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
  51. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
  52. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  53. package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
  54. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  55. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  56. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  57. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  58. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  59. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  60. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  61. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  62. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  63. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  64. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  65. package/adapters/mcp/server.ts +67 -23
  66. package/adapters/mcp/setup.ts +1 -3
  67. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
  68. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
  69. package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
  70. package/adapters/mcp/toolset-names.ts +5 -0
  71. package/adapters/mcp/toolset.ts +6 -5
  72. package/adapters/mcp/transports/http-observation.ts +365 -0
  73. package/adapters/mcp/transports/http.ts +154 -677
  74. package/adapters/mcp/transports/oauth-http.ts +322 -0
  75. package/adapters/mcp/transports/session-registry.ts +6 -0
  76. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
  77. package/assets/plugin-registry.v1.json +6 -4
  78. package/assets/reference-configs/agentic-development-flow.md +25 -0
  79. package/assets/reference-configs/global-working-rules.md +19 -0
  80. package/assets/skill-version.json +2 -2
  81. package/docs/architecture/CURRENT.md +111 -41
  82. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  83. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  84. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
  85. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
  86. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  87. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  88. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  89. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  90. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  91. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  92. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  93. package/docs/architecture/domains/verification.md +1 -0
  94. package/docs/architecture/domains/workflow-engine.md +6 -0
  95. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  96. package/docs/forge-plugin-management.md +2 -2
  97. package/docs/operations/controller-performance-and-502.md +17 -0
  98. package/docs/operations/controller-reliability-runbook.md +2 -2
  99. package/docs/operations/features.md +1 -1
  100. package/docs/operations/features.zh-CN.md +1 -1
  101. package/docs/operations/homebrew.md +2 -2
  102. package/docs/operations/mcp-tool-exposure.md +2 -0
  103. package/docs/operations/releasing.md +2 -0
  104. package/docs/operations/standalone-disaster-recovery.md +14 -6
  105. package/docs/wiki/Implementation.md +1 -1
  106. package/package.json +25 -14
  107. package/packages/kernel/cognition/api/index.ts +6 -0
  108. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  109. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  110. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  111. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  112. package/packages/kernel/cognition/domain/learning.ts +106 -0
  113. package/packages/kernel/cognition/domain/memory.ts +254 -0
  114. package/packages/kernel/controller/api/index.ts +1 -0
  115. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  116. package/packages/kernel/controller/application/controller-round-service.ts +12 -0
  117. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
  118. package/packages/kernel/controller/domain/controller-round.ts +4 -1
  119. package/packages/kernel/controller/domain/execution-quality.ts +3 -1
  120. package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
  121. package/packages/kernel/controller/infrastructure/controller-session-store.ts +297 -71
  122. package/packages/kernel/controller/ports/controller-host.ts +2 -0
  123. package/packages/kernel/identity/api/index.ts +10 -0
  124. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  125. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  126. package/packages/kernel/identity/domain/grant.ts +72 -0
  127. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  128. package/packages/kernel/identity/domain/user-request.ts +93 -0
  129. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  130. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  131. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  132. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  133. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  134. package/packages/kernel/scheduler/api/index.ts +0 -2
  135. package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
  136. package/packages/kernel/scheduler/application/settlement.ts +0 -15
  137. package/packages/kernel/scheduler/domain/schedule.ts +87 -0
  138. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +153 -133
  139. package/packages/kernel/work/api/index.ts +3 -2
  140. package/packages/kernel/work/application/work-service.ts +17 -42
  141. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  142. package/packages/kernel/work/domain/engineering-design.ts +10 -5
  143. package/packages/kernel/work/domain/engineering-profile.ts +8 -12
  144. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  145. package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
  146. package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
  147. package/packages/kernel/work/domain/implementation-review.ts +14 -331
  148. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  149. package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
  150. package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
  151. package/packages/kernel/work/domain/state-machine.ts +25 -63
  152. package/packages/kernel/work/domain/types.ts +57 -51
  153. package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
  154. package/packages/kernel/work/ports/work-contract-store.ts +5 -2
  155. package/packages/plugin-runtime/browser/session-authority.ts +2 -1
  156. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  157. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  158. package/packages/plugin-runtime/computer/index.ts +2 -0
  159. package/packages/plugin-runtime/computer/target-authority.ts +26 -1
  160. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
  161. package/packages/protocols/computer/contract.ts +27 -1
  162. package/scripts/activate-source-baseline.ts +7 -9
  163. package/scripts/canary-controller-semantic-wait.ts +12 -24
  164. package/scripts/check-mcp-compatibility.ts +48 -136
  165. package/scripts/check-runtime-architecture.mjs +622 -217
  166. package/scripts/forge-local-recovery-helper.mjs +93 -15
  167. package/scripts/lib/project-init-lib.sh +3 -0
  168. package/scripts/open-source-audit-allowlist.txt +1 -2
  169. package/scripts/run-bounded-command.mjs +5 -0
  170. package/scripts/run-governed-gate.ts +0 -1
  171. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  172. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  173. package/scripts/smoke-mcp-http-runtime.ts +5 -0
  174. package/scripts/smoke-runtime-recovery.ts +12 -43
  175. package/scripts/smoke-schedule-engine.ts +23 -15
  176. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  177. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  178. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  179. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  180. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  181. package/scripts/smoke-workflow-supervisor.ts +103 -0
  182. package/scripts/verify-forge-runtime.sh +2 -1
  183. package/src/cli/agent-jobs/executor-health.ts +11 -34
  184. package/src/cli/agent-jobs/integration.ts +18 -49
  185. package/src/cli/agent-jobs/job-manager.ts +7 -3
  186. package/src/cli/commands/brain-assistant.ts +27 -13
  187. package/src/cli/commands/brain.ts +13 -15
  188. package/src/cli/commands/chatgpt.ts +1 -163
  189. package/src/cli/commands/recovery.ts +135 -121
  190. package/src/cli/commands/runtime.ts +3 -3
  191. package/src/cli/commands/setup-profile.ts +8 -0
  192. package/src/cli/controller/check-runner.ts +13 -2
  193. package/src/cli/controller/completion-backlog.ts +3 -3
  194. package/src/cli/controller/completion-orchestrator.ts +4 -43
  195. package/src/cli/controller/completion-target.ts +3 -72
  196. package/src/cli/controller/context/source-materializer.ts +81 -100
  197. package/src/cli/controller/context-pack.ts +10 -8
  198. package/src/cli/controller/execution-completion.ts +4 -7
  199. package/src/cli/controller/execution-policy.ts +36 -153
  200. package/src/cli/controller/governance.ts +2 -3
  201. package/src/cli/controller/issue-store.ts +4 -99
  202. package/src/cli/controller/launch-agents.ts +59 -18
  203. package/src/cli/controller/operational-plan.ts +24 -51
  204. package/src/cli/controller/runtime-config.ts +5 -1
  205. package/src/cli/controller/stuck-state-migration.ts +2 -3
  206. package/src/cli/controller/systemd-user.ts +39 -1
  207. package/src/cli/editing/edit-session.ts +1 -7
  208. package/src/cli/local-bridge/console-automations.ts +18 -13
  209. package/src/cli/local-bridge/console-view-models.ts +3 -12
  210. package/src/cli/local-bridge/facade-api.ts +64 -191
  211. package/src/cli/local-bridge/server.ts +24 -147
  212. package/src/cli/local-bridge/types.ts +0 -1
  213. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  214. package/src/cli/repositories/command-executor.ts +29 -23
  215. package/src/cli/repositories/command-scope.ts +35 -16
  216. package/src/cli/repositories/controller-home.ts +48 -0
  217. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  218. package/src/cli/repositories/git-command-executor.ts +2 -2
  219. package/src/cli/repositories/registry.ts +77 -11
  220. package/src/cli/repositories/structured-git.ts +62 -2
  221. package/src/cli/repository/session-cache.ts +92 -6
  222. package/src/runtime/context/assistant-context.ts +20 -7
  223. package/src/runtime/context/assistant-work-context.ts +89 -27
  224. package/src/runtime/context/automatic-learning.ts +565 -0
  225. package/src/runtime/context/cognitive-attention.ts +173 -0
  226. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  227. package/src/runtime/context/context-closure.ts +46 -9
  228. package/src/runtime/context/context-pack-process.ts +103 -0
  229. package/src/runtime/context/context-plane.ts +1 -9
  230. package/src/runtime/context/direct-controller-learning.ts +298 -0
  231. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  232. package/src/runtime/context/semantic-navigation.ts +6 -34
  233. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  234. package/src/runtime/context/typescript-navigation.ts +89 -3
  235. package/src/runtime/control-plane/cleanup-artifact-retention.ts +212 -9
  236. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
  237. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
  238. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
  239. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  240. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  241. package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
  242. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  243. package/src/runtime/control-plane/execution/validation.ts +6 -8
  244. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
  245. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  246. package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
  247. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  248. package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
  249. package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
  250. package/src/runtime/control-plane/execution/work-handle-authority.ts +188 -109
  251. package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
  252. package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
  253. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
  254. package/src/runtime/control-plane/execution/work-operation-service.ts +43 -27
  255. package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
  256. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  257. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  258. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +173 -186
  259. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
  260. package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
  261. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
  262. package/src/runtime/control-plane/facade/capability-registry.ts +362 -37
  263. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  264. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  265. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  266. package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
  267. package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
  268. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
  269. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
  270. package/src/runtime/control-plane/facade/index.ts +0 -1
  271. package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
  272. package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
  273. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  274. package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
  275. package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
  276. package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
  277. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
  278. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  279. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
  280. package/src/runtime/control-plane/facade/types.ts +49 -108
  281. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  282. package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
  283. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  284. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
  285. package/src/runtime/control-plane/global-scheduler/maintenance.ts +239 -112
  286. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
  287. package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
  288. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  289. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  290. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  291. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
  292. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -300
  293. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  294. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
  295. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
  296. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  297. package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
  298. package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
  299. package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
  300. package/src/runtime/control-plane/release-retention.ts +135 -47
  301. package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
  302. package/src/runtime/control-plane/runtime-cleanup.ts +290 -21
  303. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  304. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
  305. package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
  306. package/src/runtime/diagnostics/incident-repair.ts +313 -146
  307. package/src/runtime/diagnostics/mcp-timing.ts +114 -0
  308. package/src/runtime/evidence/artifact-store.ts +158 -40
  309. package/src/runtime/evidence/evidence-store.ts +112 -8
  310. package/src/runtime/evidence/output-handle-index.ts +225 -0
  311. package/src/runtime/evidence/result-store.ts +158 -44
  312. package/src/runtime/execution/jobs/store.ts +3 -4
  313. package/src/runtime/execution/managed-workspace.ts +57 -0
  314. package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
  315. package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
  316. package/src/runtime/execution/process-runtime/check-result.ts +105 -1
  317. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
  318. package/src/runtime/execution/process-runtime/command-facade.ts +79 -27
  319. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  320. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  321. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  322. package/src/runtime/execution/process-runtime/index.ts +3 -0
  323. package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
  324. package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
  325. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  326. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  327. package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
  328. package/src/runtime/execution/process-runtime/runtime.ts +35 -2
  329. package/src/runtime/execution/process-runtime/store.ts +30 -2
  330. package/src/runtime/execution/process-runtime/types.ts +6 -1
  331. package/src/runtime/execution/workers/executor.ts +2 -6
  332. package/src/runtime/platform/service-inventory.ts +130 -0
  333. package/src/runtime/platform/service-manager.ts +8 -0
  334. package/src/runtime/plugins/action-application.ts +85 -28
  335. package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
  336. package/src/runtime/plugins/browser-adapter.ts +757 -34
  337. package/src/runtime/plugins/browser-automation-service.ts +23 -3
  338. package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
  339. package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
  340. package/src/runtime/plugins/browser-native-session-service.ts +63 -13
  341. package/src/runtime/plugins/browser-registration.ts +16 -0
  342. package/src/runtime/plugins/browser-runtime.ts +14 -1
  343. package/src/runtime/plugins/browser-session-authority.ts +2 -2
  344. package/src/runtime/plugins/browser-session-store.ts +46 -76
  345. package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
  346. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  347. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  348. package/src/runtime/plugins/computer-registration.ts +222 -11
  349. package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
  350. package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
  351. package/src/runtime/plugins/external-adapter.ts +42 -6
  352. package/src/runtime/plugins/external-registration.ts +21 -1
  353. package/src/runtime/plugins/gmail-adapter.ts +23 -2
  354. package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
  355. package/src/runtime/plugins/google-shared.ts +14 -7
  356. package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
  357. package/src/runtime/plugins/ios-adapter.ts +1 -1
  358. package/src/runtime/plugins/lightweight-action.ts +208 -2
  359. package/src/runtime/plugins/local-system-adapter.ts +12 -2
  360. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  361. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  362. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  363. package/src/runtime/plugins/store.ts +602 -428
  364. package/src/runtime/plugins/types.ts +20 -0
  365. package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
  366. package/src/runtime/projections/invalidation.ts +7 -3
  367. package/src/runtime/projections/materialized-view.ts +80 -36
  368. package/src/runtime/recovery/actions.ts +3 -3
  369. package/src/runtime/recovery/capability-action-application.ts +46 -45
  370. package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
  371. package/src/runtime/recovery/maintenance-executor.ts +374 -123
  372. package/src/runtime/recovery/store.ts +29 -11
  373. package/src/runtime/release/release-coordinator.ts +296 -0
  374. package/src/runtime/release/release-session.ts +716 -0
  375. package/src/runtime/release/release-state-migration.ts +25 -0
  376. package/src/runtime/resources/leases/store.ts +56 -25
  377. package/src/runtime/root/computer-composition.ts +191 -6
  378. package/src/runtime/root/controller-progression-composition.ts +192 -0
  379. package/src/runtime/root/controller-round-composition.ts +20 -1
  380. package/src/runtime/root/deployment-topology.ts +106 -0
  381. package/src/runtime/root/entry.ts +4 -3
  382. package/src/runtime/root/known-good-recovery.ts +184 -0
  383. package/src/runtime/root/local-bridge.ts +0 -1
  384. package/src/runtime/root/mcp-transport.ts +111 -18
  385. package/src/runtime/root/ownership.ts +261 -9
  386. package/src/runtime/root/package-connector-service.ts +105 -19
  387. package/src/runtime/root/package-runtime-release.ts +117 -18
  388. package/src/runtime/root/package-runtime-service.ts +17 -11
  389. package/src/runtime/root/release-execution-canary.ts +44 -12
  390. package/src/runtime/root/release-loader.ts +90 -8
  391. package/src/runtime/root/release-manifest.ts +80 -6
  392. package/src/runtime/root/release-materialize.ts +372 -28
  393. package/src/runtime/root/release-store.ts +395 -36
  394. package/src/runtime/root/runtime-lane.ts +191 -0
  395. package/src/runtime/root/runtime.ts +159 -27
  396. package/src/runtime/root/scheduled-controller-composition.ts +28 -3
  397. package/src/runtime/root/service-runner.ts +2 -2
  398. package/src/runtime/root/service.ts +36 -33
  399. package/src/runtime/root/status.ts +48 -0
  400. package/src/runtime/root/types.ts +32 -3
  401. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  402. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  403. package/src/runtime/root/write-fence.ts +50 -2
  404. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  405. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  406. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  407. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  408. package/src/runtime/shared/process-environment.ts +20 -9
  409. package/src/runtime/shared/response-budget.ts +1 -3
  410. package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
  411. package/src/runtime/standalone-recovery/core.ts +3702 -342
  412. package/src/runtime/standalone-recovery/entry.ts +469 -39
  413. package/src/runtime/standalone-recovery/installer.ts +262 -148
  414. package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
  415. package/src/runtime/standalone-recovery/operation-lock.ts +1 -1
  416. package/src/runtime/standalone-recovery/performance.ts +54 -16
  417. package/src/runtime/standalone-recovery/release.ts +53 -5
  418. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  419. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  420. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  421. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +10 -3
  422. package/src/runtime/workflow/schedules/engine.ts +138 -172
  423. package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
  424. package/src/runtime/workflows/runtime.ts +15 -19
  425. package/src/testing/test-governance.ts +5 -1
  426. package/supervisor/chatgpt-conversation.ts +23 -0
  427. package/supervisor/client.ts +201 -0
  428. package/supervisor/control-plane.ts +868 -0
  429. package/supervisor/entry.ts +15 -0
  430. package/supervisor/forge-validators.ts +80 -0
  431. package/supervisor/index.ts +5 -0
  432. package/supervisor/native-browser-adapter.ts +786 -0
  433. package/supervisor/native-messaging/host.ts +39 -0
  434. package/supervisor/native-messaging/manifest.ts +26 -0
  435. package/supervisor/native-messaging/protocol.ts +27 -0
  436. package/supervisor/paths.ts +18 -0
  437. package/supervisor/protocol.ts +202 -0
  438. package/supervisor/server.ts +404 -0
  439. package/supervisor/store.ts +1451 -0
  440. package/supervisor/tsconfig.json +8 -0
  441. package/supervisor/types.ts +255 -0
  442. package/adapters/chatgpt/controller-host.ts +0 -119
  443. package/adapters/mcp/controller-round-compatibility.ts +0 -184
  444. package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
  445. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
  446. package/packages/kernel/progression/api/index.ts +0 -2
  447. package/packages/kernel/progression/application/projector.ts +0 -211
  448. package/packages/kernel/progression/domain/types.ts +0 -116
  449. package/packages/kernel/progression/index.ts +0 -1
  450. package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
  451. package/packages/kernel/scheduler/domain/continuation.ts +0 -38
  452. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
  453. package/packages/kernel/work/domain/admission-policy.ts +0 -34
  454. package/scripts/benchmark-background-check-overlap.ts +0 -228
  455. package/scripts/benchmark-computer-hotpath.ts +0 -255
  456. package/scripts/benchmark-controller-hotpath.ts +0 -212
  457. package/scripts/benchmark-controller-round2.ts +0 -191
  458. package/scripts/benchmark-ios-agent-device.ts +0 -511
  459. package/scripts/benchmark-mcp-host.sh +0 -117
  460. package/scripts/benchmark-mcp-transport.ts +0 -169
  461. package/scripts/benchmark-operational-memory-activation.ts +0 -235
  462. package/scripts/benchmark-operational-shadow.ts +0 -28
  463. package/scripts/benchmark-quality-harness.ts +0 -146
  464. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  465. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  466. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  467. package/scripts/benchmark-thin-harness.ts +0 -251
  468. package/scripts/benchmark-typescript-navigation.ts +0 -186
  469. package/scripts/benchmark-work-efficiency.ts +0 -334
  470. package/scripts/build-controller-ui.ts +0 -28
  471. package/scripts/check-npm-release.sh +0 -32
  472. package/scripts/check-public-release-surface.sh +0 -19
  473. package/scripts/check-release-published.sh +0 -57
  474. package/scripts/check-release-readiness.sh +0 -37
  475. package/scripts/check-release-version.mjs +0 -74
  476. package/scripts/check-tarball-install-smoke.sh +0 -150
  477. package/scripts/package-source-archive.sh +0 -147
  478. package/scripts/public-release-files.txt +0 -39
  479. package/scripts/public-release.ts +0 -174
  480. package/scripts/publish-release-tarball.sh +0 -27
  481. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  482. package/scripts/stage-runtime-release.ts +0 -44
  483. package/src/cli/controller/progress.ts +0 -656
  484. package/src/cli/controller/work-mode.ts +0 -181
  485. package/src/cli/local-bridge/console-assets.ts +0 -17
  486. package/src/cli/local-bridge/dashboard.ts +0 -17
  487. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  488. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  489. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  490. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  491. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  492. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  493. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  494. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  495. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  496. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  497. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  498. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  499. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  500. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  501. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  502. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  503. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  504. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  505. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  506. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  507. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  508. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  509. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  510. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  511. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  512. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  513. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  514. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  515. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
  516. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
  517. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
  518. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
  519. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  520. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
  521. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
  522. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
  523. package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
  524. package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
  525. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  526. package/src/runtime/control-plane/routing/index.ts +0 -1
  527. package/src/runtime/control-plane/routing/route-policy.ts +0 -401
  528. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -19,8 +19,7 @@ import {
19
19
  } from '../repositories/controller-home';
20
20
  import { FORGE_VERSION } from '../../version';
21
21
  import {
22
- RECOVERY_GATEWAY_LABEL,
23
- RECOVERY_WATCHDOG_LABEL,
22
+ RECOVERY_DAEMON_LABEL,
24
23
  inspectRecoveryTunnelLaunchdContract,
25
24
  installStandaloneRecovery,
26
25
  recoveryLaunchdPid,
@@ -37,6 +36,7 @@ import {
37
36
  activateRuntimeRelease,
38
37
  defaultPrimaryRuntimeServiceConfig,
39
38
  loadRecoveryConfig,
39
+ normalizeRecoveryInstallProfile,
40
40
  recoverPrimaryRuntime,
41
41
  recoveryMachineIdentity,
42
42
  restartPrimaryConnector,
@@ -149,12 +149,57 @@ export type { RecoveryControllerHomeMigrationPreflight };
149
149
  export interface RecoveryConnectorDependencies {
150
150
  platform?: NodeJS.Platform;
151
151
  pathExists?: (path: string) => boolean;
152
- launchdPid?: (role: 'gateway' | 'watchdog') => number | undefined;
153
- systemdPid?: (role: 'gateway' | 'watchdog') => number | undefined;
152
+ launchdPid?: (role: 'daemon') => number | undefined;
153
+ systemdPid?: (role: 'daemon') => number | undefined;
154
154
  tunnelLaunchdPid?: (label: string) => number | undefined;
155
155
  tunnelSystemdPid?: (unitName: string) => number | undefined;
156
156
  openAiTunnelStatus?: (service: OpenAiSecureTunnelServiceConfig) => OpenAiSecureTunnelRuntimeObservation;
157
157
  processAlive?: (pid: number) => boolean;
158
+ processParentPid?: (pid: number) => number | undefined;
159
+ }
160
+
161
+ function recoveryProcessParentPid(pid: number): number | undefined {
162
+ if (process.platform === 'win32' || !Number.isInteger(pid) || pid <= 1) return undefined;
163
+ const result = spawnSync('ps', ['-o', 'ppid=', '-p', String(pid)], {
164
+ encoding: 'utf8',
165
+ timeout: 2_000,
166
+ maxBuffer: 8 * 1024,
167
+ });
168
+ if (result.status !== 0) return undefined;
169
+ const parent = Number.parseInt((result.stdout ?? '').trim(), 10);
170
+ return Number.isInteger(parent) && parent > 0 ? parent : undefined;
171
+ }
172
+
173
+ /**
174
+ * launchd may own a tiny wrapper (/usr/bin/env) while Recovery records the
175
+ * compiled child PID in its runtime identity. Treat only that bounded process
176
+ * lineage as the same managed service; unrelated live PIDs still fail closed.
177
+ */
178
+ export function recoveryManagedServiceOwnsRuntimeProcess(
179
+ managedPid: number | undefined,
180
+ runtimePid: number | undefined,
181
+ dependencies: {
182
+ processAlive?: (pid: number) => boolean;
183
+ processParentPid?: (pid: number) => number | undefined;
184
+ maxDepth?: number;
185
+ } = {},
186
+ ): boolean {
187
+ if (!managedPid || !runtimePid || managedPid <= 0 || runtimePid <= 0) return false;
188
+ const processAlive = dependencies.processAlive ?? isProcessAlive;
189
+ if (!processAlive(managedPid) || !processAlive(runtimePid)) return false;
190
+ if (managedPid === runtimePid) return true;
191
+ const parentPid = dependencies.processParentPid ?? recoveryProcessParentPid;
192
+ const maxDepth = Math.max(1, Math.min(Math.trunc(dependencies.maxDepth ?? 8), 32));
193
+ const visited = new Set<number>([runtimePid]);
194
+ let current = runtimePid;
195
+ for (let depth = 0; depth < maxDepth; depth += 1) {
196
+ const parent = parentPid(current);
197
+ if (!parent || parent <= 0 || visited.has(parent)) return false;
198
+ if (parent === managedPid) return true;
199
+ visited.add(parent);
200
+ current = parent;
201
+ }
202
+ return false;
158
203
  }
159
204
 
160
205
  export interface RecoveryConnectorDescriptor {
@@ -174,8 +219,7 @@ export interface RecoveryConnectorDescriptor {
174
219
  };
175
220
  healthUrl: string;
176
221
  services: {
177
- gateway: { label: string; platform: 'launchd' | 'systemd-user'; serviceInstalled: boolean; plistInstalled: boolean; running: boolean; pid?: number };
178
- watchdog: { label: string; platform: 'launchd' | 'systemd-user'; serviceInstalled: boolean; plistInstalled: boolean; running: boolean; pid?: number };
222
+ recovery: { label: string; platform: 'launchd' | 'systemd-user'; serviceInstalled: boolean; plistInstalled: boolean; running: boolean; pid?: number };
179
223
  tunnel: {
180
224
  configured: boolean;
181
225
  platform?: 'launchd' | 'systemd-user' | 'openai-secure-tunnel';
@@ -208,15 +252,19 @@ export function recoveryConnectorDescriptor(
208
252
  const url = configuredUrl ?? `${localOrigin}/recovery/mcp`;
209
253
  const origin = new URL(url).origin;
210
254
  const passphraseConfigured = Boolean(readMcpServiceOAuthPassphrase(home));
211
- const gatewayIdentity = readRecoveryRuntimeIdentity(home, 'gateway');
212
- const watchdogIdentity = readRecoveryRuntimeIdentity(home, 'watchdog');
255
+ const recoveryIdentity = readRecoveryRuntimeIdentity(home, 'daemon');
213
256
  const platform = dependencies.platform ?? process.platform;
214
257
  const servicePlatform: 'launchd' | 'systemd-user' = platform === 'linux' ? 'systemd-user' : 'launchd';
215
258
  const pathExists = dependencies.pathExists ?? existsSync;
216
259
  const launchdPid = dependencies.launchdPid ?? recoveryLaunchdPid;
217
- const systemdPid = dependencies.systemdPid ?? ((role: 'gateway' | 'watchdog') => systemdUserServicePid(role === 'gateway' ? RECOVERY_GATEWAY_LABEL : RECOVERY_WATCHDOG_LABEL));
218
- const managedPid = (role: 'gateway' | 'watchdog') => servicePlatform === 'systemd-user' ? systemdPid(role) : launchdPid(role);
260
+ const systemdPid = dependencies.systemdPid ?? ((_role: 'daemon') => systemdUserServicePid(RECOVERY_DAEMON_LABEL));
261
+ const managedPid = () => servicePlatform === 'systemd-user' ? systemdPid('daemon') : launchdPid('daemon');
219
262
  const processAlive = dependencies.processAlive ?? isProcessAlive;
263
+ const serviceOwnsRuntimeProcess = (managedPid: number | undefined, runtimePid: number | undefined) =>
264
+ recoveryManagedServiceOwnsRuntimeProcess(managedPid, runtimePid, {
265
+ processAlive,
266
+ processParentPid: dependencies.processParentPid,
267
+ });
220
268
  const configuredTunnel = config.recoveryTunnelService;
221
269
  const tunnelService = configuredTunnel?.platform === 'launchd' ? configuredTunnel : undefined;
222
270
  const systemdTunnelService = configuredTunnel?.platform === 'systemd-user' ? configuredTunnel : undefined;
@@ -256,40 +304,24 @@ export function recoveryConnectorDescriptor(
256
304
  : Boolean(tunnelLaunchdPid && processAlive(tunnelLaunchdPid));
257
305
  const tunnelHealthy = openAiTunnelService ? openAiTunnelStatus?.healthy === true : tunnelRunning;
258
306
  const tunnelReady = openAiTunnelService ? openAiTunnelStatus?.ok === true : tunnelRestartSafe && tunnelRunning;
259
- const gatewayPlistInstalled = pathExists(authority.gatewayLaunchAgent);
260
- const watchdogPlistInstalled = pathExists(authority.watchdogLaunchAgent);
261
- const gatewayServiceInstalled = servicePlatform === 'systemd-user'
262
- ? pathExists(systemdUserUnitPath(RECOVERY_GATEWAY_LABEL))
263
- : gatewayPlistInstalled;
264
- const watchdogServiceInstalled = servicePlatform === 'systemd-user'
265
- ? pathExists(systemdUserUnitPath(RECOVERY_WATCHDOG_LABEL))
266
- : watchdogPlistInstalled;
267
- const gatewayManagedPid = managedPid('gateway');
268
- const watchdogManagedPid = managedPid('watchdog');
269
- const gatewayRunning = Boolean(
270
- gatewayIdentity
271
- && gatewayManagedPid
272
- && gatewayIdentity.pid === gatewayManagedPid
273
- && processAlive(gatewayIdentity.pid)
307
+ const recoveryPlistInstalled = pathExists(authority.daemonLaunchAgent);
308
+ const recoveryServiceInstalled = servicePlatform === 'systemd-user'
309
+ ? pathExists(systemdUserUnitPath(RECOVERY_DAEMON_LABEL))
310
+ : recoveryPlistInstalled;
311
+ const recoveryManagedPid = managedPid();
312
+ const recoveryRunning = Boolean(
313
+ recoveryIdentity
314
+ && serviceOwnsRuntimeProcess(recoveryManagedPid, recoveryIdentity.pid)
274
315
  && authority.current
275
- && gatewayIdentity.releaseRevision === authority.current.releaseRevision
276
- && gatewayIdentity.manifestSha256 === authority.current.manifestSha256,
316
+ && recoveryIdentity.releaseRevision === authority.current.releaseRevision
317
+ && recoveryIdentity.manifestSha256 === authority.current.manifestSha256,
277
318
  );
278
- const watchdogRunning = Boolean(
279
- watchdogIdentity
280
- && watchdogManagedPid
281
- && watchdogIdentity.pid === watchdogManagedPid
282
- && processAlive(watchdogIdentity.pid)
283
- && authority.current
284
- && watchdogIdentity.releaseRevision === authority.current.releaseRevision
285
- && watchdogIdentity.manifestSha256 === authority.current.manifestSha256,
286
- );
287
- const installed = Boolean(authority.current && gatewayServiceInstalled && watchdogServiceInstalled);
319
+ const installed = Boolean(authority.current && recoveryServiceInstalled);
288
320
  const publicEndpoint = Boolean(configuredUrl?.startsWith('https://'));
289
321
  const warnings: string[] = [];
290
322
  if (!authority.current) warnings.push('No current immutable Forge Recovery release is installed. Run forge recovery install.');
291
- if (!gatewayServiceInstalled || !watchdogServiceInstalled) warnings.push(`Forge Recovery ${servicePlatform} services are not fully installed. Run forge recovery install.`);
292
- if (!gatewayRunning || !watchdogRunning) warnings.push('Forge Recovery Gateway or Watchdog is not running on the current Recovery release.');
323
+ if (!recoveryServiceInstalled) warnings.push(`Forge Recovery ${servicePlatform} service is not installed. Run forge recovery install.`);
324
+ if (!recoveryRunning) warnings.push('Forge Recovery service is not running on the current Recovery release.');
293
325
  if (!configuredTunnel) warnings.push('Recovery is loopback-only. Configure a dedicated OpenAI Secure MCP Tunnel or an HTTPS tunnel service before adding it to ChatGPT.');
294
326
  else if (openAiTunnelService) {
295
327
  if (!tunnelRestartSafe) warnings.push('The dedicated OpenAI Recovery tunnel must use a valid alias, tunnel id, loopback MCP endpoint, and env:/file: runtime API key reference.');
@@ -310,7 +342,7 @@ export function recoveryConnectorDescriptor(
310
342
  transport: 'streamable_http',
311
343
  url,
312
344
  public: publicEndpoint,
313
- readyForChatGPT: installed && gatewayRunning && watchdogRunning && tunnelReady && (openAiTunnelService ? true : publicEndpoint) && passphraseConfigured,
345
+ readyForChatGPT: installed && recoveryRunning && tunnelReady && (openAiTunnelService ? true : publicEndpoint) && passphraseConfigured,
314
346
  installed,
315
347
  currentRelease: authority.current?.releaseRevision,
316
348
  previousRelease: authority.previous?.releaseRevision,
@@ -321,21 +353,13 @@ export function recoveryConnectorDescriptor(
321
353
  },
322
354
  healthUrl: `${origin}/recovery/health`,
323
355
  services: {
324
- gateway: {
325
- label: RECOVERY_GATEWAY_LABEL,
326
- platform: servicePlatform,
327
- serviceInstalled: gatewayServiceInstalled,
328
- plistInstalled: gatewayPlistInstalled,
329
- running: gatewayRunning,
330
- ...(gatewayIdentity ? { pid: gatewayIdentity.pid } : {}),
331
- },
332
- watchdog: {
333
- label: RECOVERY_WATCHDOG_LABEL,
356
+ recovery: {
357
+ label: RECOVERY_DAEMON_LABEL,
334
358
  platform: servicePlatform,
335
- serviceInstalled: watchdogServiceInstalled,
336
- plistInstalled: watchdogPlistInstalled,
337
- running: watchdogRunning,
338
- ...(watchdogIdentity ? { pid: watchdogIdentity.pid } : {}),
359
+ serviceInstalled: recoveryServiceInstalled,
360
+ plistInstalled: recoveryPlistInstalled,
361
+ running: recoveryRunning,
362
+ ...(recoveryIdentity ? { pid: recoveryIdentity.pid } : {}),
339
363
  },
340
364
  tunnel: {
341
365
  configured: Boolean(configuredTunnel),
@@ -603,7 +627,6 @@ export async function verifyRecoveryConnector(
603
627
  credentialRetirement: 'shared_recovery_token_not_individually_revocable',
604
628
  };
605
629
 
606
- let mcpSessionId: string | undefined;
607
630
  const rpc = async (id: number | undefined, method: string, params?: Record<string, unknown>) => {
608
631
  const response = await request(connector.url, {
609
632
  method: 'POST',
@@ -612,10 +635,12 @@ export async function verifyRecoveryConnector(
612
635
  accept: 'application/json, text/event-stream',
613
636
  'content-type': 'application/json',
614
637
  'mcp-protocol-version': '2025-06-18',
615
- ...(mcpSessionId ? { 'mcp-session-id': mcpSessionId } : {}),
616
638
  },
617
639
  body: JSON.stringify({ jsonrpc: '2.0', ...(id === undefined ? {} : { id }), method, ...(params ? { params } : {}) }),
618
640
  });
641
+ if (response.headers.get('mcp-session-id')?.trim()) {
642
+ throw new Error(`${method} unexpectedly established transport session state`);
643
+ }
619
644
  if (method === 'notifications/initialized') {
620
645
  if (response.status !== 202) throw new Error(`${method} HTTP ${response.status}`);
621
646
  return { response, result: {} as Record<string, unknown> };
@@ -625,71 +650,44 @@ export async function verifyRecoveryConnector(
625
650
  if (response.status !== 200 || Object.keys(rpcError).length > 0) {
626
651
  throw new Error(`${method} HTTP ${response.status}${typeof rpcError.message === 'string' ? `: ${rpcError.message}` : ''}`);
627
652
  }
628
- if (method === 'initialize') {
629
- const returnedSessionId = response.headers.get('mcp-session-id')?.trim();
630
- if (!returnedSessionId) throw new Error('initialize HTTP 200: Mcp-Session-Id missing');
631
- mcpSessionId = returnedSessionId;
632
- }
633
653
  return { response, result: jsonObject(body.result) };
634
654
  };
635
- const closeMcpSession = async (): Promise<void> => {
636
- const sessionId = mcpSessionId;
637
- if (!sessionId) return;
638
- mcpSessionId = undefined;
639
- try {
640
- await request(connector.url, {
641
- method: 'DELETE',
642
- headers: {
643
- authorization: `Bearer ${accessToken}`,
644
- accept: 'application/json, text/event-stream',
645
- 'mcp-protocol-version': '2025-06-18',
646
- 'mcp-session-id': sessionId,
647
- },
648
- });
649
- } catch {
650
- // Session cleanup is best-effort and must not hide the verifier result.
651
- }
652
- };
653
655
 
654
- try {
655
- const initialized = await rpc(11, 'initialize', {
656
- protocolVersion: '2025-06-18',
657
- capabilities: {},
658
- clientInfo: { name: 'forge-recovery-verifier', version: FORGE_VERSION },
659
- });
660
- const initializedNotification = await rpc(undefined, 'notifications/initialized');
661
- const listed = await rpc(12, 'tools/list');
662
- const tools = Array.isArray(listed.result.tools)
663
- ? listed.result.tools.map((tool) => jsonObject(tool).name).filter((name): name is string => typeof name === 'string')
664
- : [];
665
- const expectedTools = RECOVERY_TOOLS.map((tool) => tool.name);
666
- const runtimeStatusCall = await rpc(13, 'tools/call', { name: 'runtime_status', arguments: {} });
667
- const listReleasesCall = await rpc(14, 'tools/call', { name: 'list_releases', arguments: {} });
668
- const initializedResult = initialized.result;
669
- const serverInfo = jsonObject(initializedResult.serverInfo);
670
- const mcpOk = initialized.response.status === 200
671
- && initializedNotification.response.status === 202
672
- && initializedResult.protocolVersion === '2025-06-18'
673
- && serverInfo.name === 'forge-standalone-recovery'
674
- && serverInfo.version === FORGE_VERSION
675
- && JSON.stringify(tools) === JSON.stringify(expectedTools)
676
- && runtimeStatusCall.response.status === 200
677
- && listReleasesCall.response.status === 200;
678
- probes.mcp = {
679
- ok: mcpOk,
680
- initializeStatus: initialized.response.status,
681
- initializedNotificationStatus: initializedNotification.response.status,
682
- protocolVersion: typeof initializedResult.protocolVersion === 'string' ? initializedResult.protocolVersion : undefined,
683
- serverName: typeof serverInfo.name === 'string' ? serverInfo.name : undefined,
684
- serverVersion: typeof serverInfo.version === 'string' ? serverInfo.version : undefined,
685
- tools,
686
- runtimeStatusCall: runtimeStatusCall.response.status === 200,
687
- listReleasesCall: listReleasesCall.response.status === 200,
688
- };
689
- if (!mcpOk) failures.push('mcp: initialize, Forge version, tool surface, or read-only calls did not match the Recovery contract.');
690
- } finally {
691
- await closeMcpSession();
692
- }
656
+ const initialized = await rpc(11, 'initialize', {
657
+ protocolVersion: '2025-06-18',
658
+ capabilities: {},
659
+ clientInfo: { name: 'forge-recovery-verifier', version: FORGE_VERSION },
660
+ });
661
+ const initializedNotification = await rpc(undefined, 'notifications/initialized');
662
+ const listed = await rpc(12, 'tools/list');
663
+ const tools = Array.isArray(listed.result.tools)
664
+ ? listed.result.tools.map((tool) => jsonObject(tool).name).filter((name): name is string => typeof name === 'string')
665
+ : [];
666
+ const expectedTools = RECOVERY_TOOLS.map((tool) => tool.name);
667
+ const runtimeStatusCall = await rpc(13, 'tools/call', { name: 'runtime_status', arguments: {} });
668
+ const listReleasesCall = await rpc(14, 'tools/call', { name: 'list_releases', arguments: {} });
669
+ const initializedResult = initialized.result;
670
+ const serverInfo = jsonObject(initializedResult.serverInfo);
671
+ const mcpOk = initialized.response.status === 200
672
+ && initializedNotification.response.status === 202
673
+ && initializedResult.protocolVersion === '2025-06-18'
674
+ && serverInfo.name === 'forge-standalone-recovery'
675
+ && serverInfo.version === FORGE_VERSION
676
+ && JSON.stringify(tools) === JSON.stringify(expectedTools)
677
+ && runtimeStatusCall.response.status === 200
678
+ && listReleasesCall.response.status === 200;
679
+ probes.mcp = {
680
+ ok: mcpOk,
681
+ initializeStatus: initialized.response.status,
682
+ initializedNotificationStatus: initializedNotification.response.status,
683
+ protocolVersion: typeof initializedResult.protocolVersion === 'string' ? initializedResult.protocolVersion : undefined,
684
+ serverName: typeof serverInfo.name === 'string' ? serverInfo.name : undefined,
685
+ serverVersion: typeof serverInfo.version === 'string' ? serverInfo.version : undefined,
686
+ tools,
687
+ runtimeStatusCall: runtimeStatusCall.response.status === 200,
688
+ listReleasesCall: listReleasesCall.response.status === 200,
689
+ };
690
+ if (!mcpOk) failures.push('mcp: stateless initialize, Forge version, tool surface, or read-only calls did not match the Recovery contract.');
693
691
  } catch (error) {
694
692
  failures.push(`oauthPkce/mcp: ${error instanceof Error ? error.message : String(error)}`);
695
693
  }
@@ -761,6 +759,10 @@ export function buildRecoveryCommand(): Command {
761
759
  }) => {
762
760
  const home = resolveControllerHome(opts.controllerHome);
763
761
  const repoRoot = resolve(opts.repo);
762
+ const primaryRuntimeSourceRepository = findRegisteredRepositoryByCheckoutRoot(repoRoot, home);
763
+ if (!primaryRuntimeSourceRepository) {
764
+ throw new Error(`RECOVERY_PRIMARY_RUNTIME_SOURCE_REPOSITORY_NOT_REGISTERED: ${repoRoot}`);
765
+ }
764
766
  const current = loadRecoveryConfig(home);
765
767
  const primaryConnectorBase = launchdService(
766
768
  opts.primaryConnectorServiceLabel,
@@ -774,6 +776,7 @@ export function buildRecoveryCommand(): Command {
774
776
  const installed = await installStandaloneRecovery({
775
777
  controllerHome: home,
776
778
  repoRoot,
779
+ primaryRuntimeSourceRepositoryId: primaryRuntimeSourceRepository.repoId,
777
780
  port: current.gateway?.port ?? 8787,
778
781
  publicMcpUrl: current.publicMcpUrl,
779
782
  recoveryPublicUrl: current.recoveryPublicUrl,
@@ -781,6 +784,7 @@ export function buildRecoveryCommand(): Command {
781
784
  primaryPublicTunnelService: current.primaryPublicTunnelService,
782
785
  primaryRuntimeService: current.primaryRuntimeService ?? defaultPrimaryRuntimeServiceConfig(),
783
786
  primaryConnectorService,
787
+ profile: 'self-healing',
784
788
  });
785
789
  const refreshed = loadRecoveryConfig(home);
786
790
  const runtime = await stageAndActivateConfiguredRuntimeRelease(refreshed);
@@ -952,8 +956,9 @@ export function buildRecoveryCommand(): Command {
952
956
  });
953
957
 
954
958
  command.command('install')
955
- .description('Build and activate the independent Forge Recovery Gateway and Watchdog release')
959
+ .description('Build Forge Recovery artifacts and activate only the explicitly selected persistent Recovery profile')
956
960
  .requiredOption('--controller-home <path>', 'Explicit Controller Home')
961
+ .option('--profile <profile>', 'Recovery install profile: manual, gateway, or self-healing', 'manual')
957
962
  .option('--port <port>', 'Loopback Recovery Gateway port', '8787')
958
963
  .option('--public-mcp-url <url>', 'Primary Forge MCP public URL')
959
964
  .option('--recovery-public-url <url>', 'Dedicated Forge Recovery MCP public URL')
@@ -978,7 +983,7 @@ export function buildRecoveryCommand(): Command {
978
983
  .option('--primary-openai-profile-dir <path>', 'Optional absolute tunnel-client profile directory for primary Forge')
979
984
  .option('--primary-openai-admin-profile <profile>', 'Optional tunnel-client admin profile used for primary runtime connect')
980
985
  .option('--primary-runtime-source-root <path>', 'Stable canonical/package source used by Recovery for future Runtime staging')
981
- .option('--stage-only', 'Build and canary the Recovery release without activating services')
986
+ .option('--stage-only', 'Compatibility alias: build/canary only and do not mutate installed Recovery config or services')
982
987
  .action(async (opts: {
983
988
  controllerHome: string;
984
989
  port: string;
@@ -1005,9 +1010,12 @@ export function buildRecoveryCommand(): Command {
1005
1010
  primaryOpenaiProfileDir?: string;
1006
1011
  primaryOpenaiAdminProfile?: string;
1007
1012
  primaryRuntimeSourceRoot?: string;
1013
+ profile: string;
1008
1014
  stageOnly?: boolean;
1009
1015
  }) => {
1010
1016
  const home = resolveControllerHome(opts.controllerHome);
1017
+ const profile = normalizeRecoveryInstallProfile(opts.stageOnly ? 'manual' : opts.profile, 'manual');
1018
+ if (opts.stageOnly && opts.profile !== 'manual') throw new Error('RECOVERY_STAGE_ONLY_PROFILE_CONFLICT');
1011
1019
  const port = Number(opts.port);
1012
1020
  if (!Number.isInteger(port) || port < 1024 || port > 65535) throw new Error('RECOVERY_PORT_INVALID');
1013
1021
  const recoveryLaunchdTunnel = launchdService(opts.recoveryTunnelServiceLabel, opts.recoveryTunnelServicePlist, 'RECOVERY_TUNNEL') as PublicTunnelServiceConfig | undefined;
@@ -1063,6 +1071,7 @@ export function buildRecoveryCommand(): Command {
1063
1071
  assertDistinctRecoveryOpenAiTunnelIdentity(recoveryTunnelService, primaryPublicTunnelService);
1064
1072
 
1065
1073
  const recoveryPublicUrl = endpoint(opts.recoveryPublicUrl, 'RECOVERY_PUBLIC_URL');
1074
+ if (profile === 'manual' && (recoveryTunnelService || recoveryPublicUrl)) throw new Error('RECOVERY_PROFILE_GATEWAY_REQUIRED');
1066
1075
  if (recoveryOpenAiTunnel && recoveryPublicUrl) throw new Error('RECOVERY_OPENAI_TUNNEL_PUBLIC_URL_CONFLICT');
1067
1076
  if ((recoveryLaunchdTunnel || recoverySystemdTunnel) && !recoveryPublicUrl) throw new Error('RECOVERY_PUBLIC_URL_AND_TUNNEL_SERVICE_MUST_BE_CONFIGURED_TOGETHER');
1068
1077
  if (!recoveryTunnelService && recoveryPublicUrl) throw new Error('RECOVERY_PUBLIC_URL_AND_TUNNEL_SERVICE_MUST_BE_CONFIGURED_TOGETHER');
@@ -1080,8 +1089,12 @@ export function buildRecoveryCommand(): Command {
1080
1089
  controllerHome: home,
1081
1090
  repoRoot: primaryRuntimeSourceRoot,
1082
1091
  ...(primaryRuntimeSourceRepository ? { primaryRuntimeSourceRepositoryId: primaryRuntimeSourceRepository.repoId } : {}),
1083
- sourceRoot: packageRoot,
1092
+ // The package root is only the CLI's location. A package installation
1093
+ // is not a Git checkout, while the explicitly registered primary
1094
+ // Runtime source is the immutable Recovery release's provenance.
1095
+ sourceRoot: primaryRuntimeSourceRoot,
1084
1096
  port,
1097
+ profile,
1085
1098
  stageOnly: opts.stageOnly === true,
1086
1099
  primaryRuntimeService: defaultPrimaryRuntimeServiceConfig(),
1087
1100
  publicMcpUrl: endpoint(opts.publicMcpUrl, 'PUBLIC_MCP_URL'),
@@ -1092,6 +1105,7 @@ export function buildRecoveryCommand(): Command {
1092
1105
  });
1093
1106
  output({
1094
1107
  status: opts.stageOnly ? 'staged' : 'installed',
1108
+ profile: result.profile,
1095
1109
  staged: result.staged.release,
1096
1110
  activation: result.activated,
1097
1111
  connector: recoveryConnectorDescriptor(home),
@@ -12,6 +12,7 @@ import { listOccurrences, listSchedules } from '../../../packages/kernel/schedul
12
12
  import { observeRuntimeStatus } from '../../runtime/root/status';
13
13
  import { readMcpServiceBearerToken } from '../../../adapters/mcp/auth';
14
14
  import { createSetupBootstrapControlApi } from './bootstrap-control';
15
+ import { readSetupProfile, runtimeDeploymentTopologyForSetupProfile } from './setup-profile';
15
16
  import { publishRuntimeRelease } from '../../runtime/root/release-store';
16
17
  import { installForgeRuntimeService } from '../../runtime/root/service';
17
18
  import { activateScheduledPackageRuntimeServiceFromPath, installPackageRuntimeService, readPackageRuntimeActivationReceipt } from '../../runtime/root/package-runtime-service';
@@ -73,12 +74,14 @@ export function buildRuntimeCommand(): Command {
73
74
  writeFileSync(tokenPath, `${token}\n`, { mode: 0o600 });
74
75
  }
75
76
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
77
+ const setupProfile = readSetupProfile();
76
78
  const result = await installPackageRuntimeService({
77
79
  controllerHome: home,
78
80
  packageRoot,
79
81
  host: opts.host,
80
82
  port,
81
83
  authTokenFile: tokenPath,
84
+ ...(setupProfile ? { topology: runtimeDeploymentTopologyForSetupProfile(setupProfile) } : {}),
82
85
  forcePortable: opts.portable === true,
83
86
  refreshConnector: opts.refreshConnector === true,
84
87
  });
@@ -116,7 +119,6 @@ export function buildRuntimeCommand(): Command {
116
119
  .option('--port <port>', 'MCP listener port', '8765')
117
120
  .option('--stage-only', 'Build and validate the immutable Runtime release without publishing or activating it')
118
121
  .option('--auth-token-file <path>', 'Raw bearer token file (defaults to controllerHome/mcp/runtime-token, created from the MCP bearer token when missing)')
119
- .option('--exclusive-work-id <id>', 'Persistently admit only this P0 Work while migration is active')
120
122
  .option('--node-executable <path>', 'Executable launchd uses to run the Forge Runtime service runner', process.execPath)
121
123
  .option('--runner-path <path>', 'Forge Runtime service runner entry', join(resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..'), 'bin', 'forge-runtime-service.mjs'))
122
124
  .action(async (opts: {
@@ -125,7 +127,6 @@ export function buildRuntimeCommand(): Command {
125
127
  host: string;
126
128
  port: string;
127
129
  authTokenFile?: string;
128
- exclusiveWorkId?: string;
129
130
  nodeExecutable: string;
130
131
  runnerPath: string;
131
132
  stageOnly?: boolean;
@@ -171,7 +172,6 @@ export function buildRuntimeCommand(): Command {
171
172
  host: opts.host,
172
173
  port,
173
174
  authTokenFile: tokenPath,
174
- ...(opts.exclusiveWorkId?.trim() ? { exclusiveWorkId: opts.exclusiveWorkId.trim() } : {}),
175
175
  },
176
176
  runnerPath: resolve(opts.runnerPath),
177
177
  nodeExecutable: resolve(opts.nodeExecutable),
@@ -8,6 +8,7 @@ import { dirname, join, resolve } from 'path';
8
8
  import { openAiSecureTunnelStatusArgs, parseOpenAiSecureTunnelRuntimeStatus, tunnelRuntimeProfileTargetsEndpoint } from '../../../adapters/mcp/tunnels/openai-secure-tunnel';
9
9
  import { discoverExecutable, type ExecutableDiscoveryResult } from '../../runtime/platform/executable-discovery';
10
10
  import { resolvePlatformServiceManager, type PlatformServiceManagerKind } from '../../runtime/platform/service-manager';
11
+ import { deriveRuntimeDeploymentTopology, type RuntimeDeploymentTopology } from '../../runtime/root/deployment-topology';
11
12
 
12
13
  export type SetupControllerKind = 'chatgpt' | 'codex' | 'claude' | 'mcp';
13
14
  export type SetupTunnelProvider = 'auto' | 'openai' | 'cloudflare' | 'tailscale' | 'existing' | 'none';
@@ -187,6 +188,13 @@ export function setupNeedsRemoteAccess(profile: SetupProfile | undefined): boole
187
188
  return Boolean(profile?.controllers.some((entry) => entry === 'chatgpt' || entry === 'mcp'));
188
189
  }
189
190
 
191
+ export function runtimeDeploymentTopologyForSetupProfile(profile: SetupProfile): RuntimeDeploymentTopology {
192
+ return deriveRuntimeDeploymentTopology({
193
+ controllers: profile.controllers,
194
+ capabilityIntents: profile.capabilityIntents,
195
+ });
196
+ }
197
+
190
198
  export type SetupConnectorAuthMode = 'oauth' | 'none';
191
199
 
192
200
  export function setupConnectorAuthMode(profile: SetupProfile | undefined): SetupConnectorAuthMode {
@@ -280,8 +280,19 @@ function inferredPackageCheckEffects(name: string): ControllerCheckEffects | und
280
280
  // and persist only content-bound receipts/caches outside repository source.
281
281
  return { reads: ['.'], cache: 'write', temp: 'isolated', git: 'read' };
282
282
  }
283
- const staticAnalysis = /(?:^|:)(?:type|typecheck|lint|format:check|runtime-architecture|mcp-compatibility|forge-runtime)$/.test(normalized);
284
- if (staticAnalysis) return { reads: ['.'], cache: 'write' };
283
+ if (normalized === 'check:type' || normalized === 'check:runtime-architecture') {
284
+ // These canonical gates are source readers: TypeScript runs with --noEmit,
285
+ // while runtime-architecture only inspects source/AST structure. Neither
286
+ // owns the shared repository build cache.
287
+ return { reads: ['.'] };
288
+ }
289
+ if (normalized === 'check:architecture-sync') {
290
+ // Architecture sync runs the queue in --check mode and inspects Git state.
291
+ // Its scratch space is check-local; it never mutates repository source.
292
+ return { reads: ['.'], temp: 'isolated', git: 'read' };
293
+ }
294
+ const cachedStaticAnalysis = /(?:^|:)(?:typecheck|lint|format:check|mcp-compatibility|forge-runtime)$/.test(normalized);
295
+ if (cachedStaticAnalysis) return { reads: ['.'], cache: 'write' };
285
296
  const isolatedReadOnlyCheck = /(?:^|:)(?:quality-harness|evaluation-framework|background-check-overlap|typescript-navigation|check-scheduling|bootstrap-files)$/.test(normalized);
286
297
  if (isolatedReadOnlyCheck) return { reads: ['.'], temp: 'isolated', git: 'read' };
287
298
  const browserLive = /(?:^|:)browser-live$/.test(normalized);
@@ -145,11 +145,11 @@ function classifyTask(repoRoot: string, issue: ControllerIssue, task: Controller
145
145
  }
146
146
 
147
147
  if (run && FINISHABLE_RUN_STATUSES.has(run.status)) {
148
- if (policy.requiresHumanAcceptance) {
148
+ if (task.acceptanceCriteria.length > 0) {
149
149
  return {
150
150
  ...base,
151
151
  action: 'needs_human_review',
152
- reason: `${policy.executionClass} requires explicit review before finishing ${run.runId}.`,
152
+ reason: `Task declares acceptance criteria that require an explicit acceptance decision before finishing ${run.runId}.`,
153
153
  canAutoFinish: false,
154
154
  suggestedDecision: 'approve_and_finish',
155
155
  };
@@ -157,7 +157,7 @@ function classifyTask(repoRoot: string, issue: ControllerIssue, task: Controller
157
157
  return {
158
158
  ...base,
159
159
  action: 'auto_finish',
160
- reason: `Run ${run.runId} is ${run.status} and policy allows automatic finish.`,
160
+ reason: `Run ${run.runId} is ${run.status} and the Task declares no semantic acceptance criteria, so automatic finish may proceed.`,
161
161
  canAutoFinish: true,
162
162
  suggestedDecision: 'auto',
163
163
  };
@@ -11,7 +11,7 @@ import { resolveRepoPreferredControllerHome } from '../repositories/controller-h
11
11
  import { withControllerLock } from '../repositories/locks';
12
12
  import { listActiveLeases } from '../../runtime/resources/leases/store';
13
13
  import { acceptVerifiedTask, getIssue, projectIssueEffectiveView, recordTaskVerification, updateTask } from './issue-store';
14
- import { cleanupEvidenceResourceBlockers, completionEvidenceComplete, taskExecutionPolicy } from './execution-policy';
14
+ import { cleanupEvidenceResourceBlockers, completionEvidenceComplete } from './execution-policy';
15
15
  import { currentCompletionTarget, resolveCompletionTargetBranch } from './completion-target';
16
16
  import { runControllerCheck } from './check-runner';
17
17
  import type { CleanupEvidence, ControllerIssue, ControllerTask, IntegrationEvidence, TaskCommandEvidence, TaskVerification } from './types';
@@ -183,7 +183,6 @@ function verificationForRun(
183
183
  reviewer: string,
184
184
  evidence: { integrationEvidence?: IntegrationEvidence; cleanupEvidence?: CleanupEvidence; completionReceipt?: CompletionReceipt; acceptanceConfirmed?: boolean } = {},
185
185
  ): TaskVerification {
186
- const policy = taskExecutionPolicy(task);
187
186
  const acceptanceResults = task.acceptanceCriteria.map((criterion) => evidence.acceptanceConfirmed
188
187
  ? {
189
188
  criterion,
@@ -204,8 +203,7 @@ function verificationForRun(
204
203
  integratedRevision: evidence.integrationEvidence?.targetRevision,
205
204
  reviewedDiffHash: hashArtifact(repoRoot, run.diffArtifactPath),
206
205
  reviewer,
207
- checkResults: policy.autoRunDeclaredChecks
208
- ? task.checks.map((checkId) => {
206
+ checkResults: task.checks.map((checkId) => {
209
207
  try {
210
208
  const result = runControllerCheck(repoRoot, checkId);
211
209
  return {
@@ -218,8 +216,7 @@ function verificationForRun(
218
216
  } catch (error) {
219
217
  return { checkId, ok: false, summary: error instanceof Error ? error.message : String(error) };
220
218
  }
221
- })
222
- : [],
219
+ }),
223
220
  commandEvidence: commandEvidenceForRun(run),
224
221
  acceptanceResults,
225
222
  verifiedAt: nowIso(),
@@ -233,8 +230,7 @@ function result(repoRoot: string, input: Omit<FinishTaskRunResult, 'issue'>): Fi
233
230
  }
234
231
 
235
232
  function canAutoFinish(task: ControllerTask): boolean {
236
- const policy = taskExecutionPolicy(task);
237
- return policy.autoCompleteAfterSuccessfulRun && !policy.requiresHumanAcceptance;
233
+ return task.acceptanceCriteria.length === 0;
238
234
  }
239
235
 
240
236
  function verifyAndMaybeAccept(input: {
@@ -247,16 +243,7 @@ function verifyAndMaybeAccept(input: {
247
243
  allowCompletion?: boolean;
248
244
  }): { issue: ControllerIssue; taskStatus: string } {
249
245
  const { repoRoot, run, task, decision, reviewer } = input;
250
- const policy = taskExecutionPolicy(task);
251
246
  const allowHumanAcceptance = decision === 'approve_and_finish';
252
- if (policy.requiresHumanAcceptance && !allowHumanAcceptance) {
253
- updateTask(repoRoot, run.issueId, run.taskId, {
254
- status: task.status === 'verified' ? 'verified' : task.status,
255
- note: input.note ?? `Run ${run.runId} is ready but ${policy.executionClass} requires an explicit review decision.`,
256
- });
257
- const waiting = getIssue(repoRoot, run.issueId);
258
- return { issue: waiting, taskStatus: taskForRun(waiting, run.taskId).status };
259
- }
260
247
 
261
248
  const current = getIssue(repoRoot, run.issueId);
262
249
  const currentTask = taskForRun(current, run.taskId);
@@ -438,19 +425,6 @@ function finishEditSessionUnlocked(repoRoot: string, options: FinishEditSessionO
438
425
  });
439
426
  }
440
427
 
441
- const policy = taskExecutionPolicy(task);
442
- if (policy.requiresHumanAcceptance && decision !== 'approve_and_finish') {
443
- return editResult(repoRoot, {
444
- action: 'needs_decision',
445
- sessionId: initialSession.sessionId,
446
- issueId: issue.id,
447
- taskId: task.id,
448
- decision,
449
- taskStatus: task.status,
450
- reason: `${policy.executionClass} requires approve_and_finish, request_changes, or discard.`,
451
- });
452
- }
453
-
454
428
  const completionTarget = currentCompletionTarget(repoRoot);
455
429
  if (!completionTarget.onTargetBranch) {
456
430
  return editResult(repoRoot, {
@@ -1165,19 +1139,6 @@ function finishTaskRunUnlocked(repoRoot: string, options: FinishTaskRunOptions):
1165
1139
  });
1166
1140
  }
1167
1141
 
1168
- const policy = taskExecutionPolicy(task);
1169
- if (policy.requiresHumanAcceptance && decision !== 'approve_and_finish') {
1170
- return result(repoRoot, {
1171
- action: 'needs_decision',
1172
- runId: run.runId,
1173
- issueId: issue.id,
1174
- taskId: task.id,
1175
- decision,
1176
- taskStatus: task.status,
1177
- reason: `${policy.executionClass} requires approve_and_finish, request_changes, or discard.`,
1178
- });
1179
- }
1180
-
1181
1142
  const ownedAutoFinalization = run.status === 'running'
1182
1143
  && run.autoIntegrate === true
1183
1144
  && run.executionMode === 'worktree'