@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
@@ -10,6 +10,7 @@ import { assertRuntimeReleaseExecutionSurface } from './release-manifest';
10
10
  import { assertRuntimeReleaseExecutionCanaries } from './release-execution-canary';
11
11
  import type { RuntimeReleaseManifest } from './types';
12
12
  import { assertStorageHeadroom } from '../shared/storage-capacity';
13
+ import { PROCESS_RUNTIME_RELEASE_CANARY_ARG } from '../execution/process-runtime/canary';
13
14
 
14
15
  export interface PackageRuntimeFileRecord {
15
16
  path: string;
@@ -35,10 +36,33 @@ export interface PackageRuntimeRelease {
35
36
  // TypeScript entrypoints import both `src/` and the top-level modular-monolith
36
37
  // roots at runtime, so retaining only `src/` creates a release that passes
37
38
  // staging but cannot start after the installed package moves or disappears.
38
- const PACKAGE_RUNTIME_ROOTS = ['src', 'adapters', 'packages', 'bin', 'assets', 'scripts', 'node_modules'] as const;
39
+ const PACKAGE_RUNTIME_ROOTS = ['src', 'adapters', 'packages', 'supervisor', 'bin', 'assets', 'scripts', 'node_modules'] as const;
39
40
  const PACKAGE_RUNTIME_FILES = ['package.json'] as const;
41
+ // Compiled releases execute only compiled/bundled artifacts. Keep a tiny package
42
+ // projection for browser-extension installation plus two legacy Recovery
43
+ // recognition sentinels; neither sentinel is executed when the compiled
44
+ // Connector sidecar is present.
45
+ const COMPILED_RUNTIME_PACKAGE_ROOTS = ['adapters/computer/chrome-extension'] as const;
46
+ const COMPILED_RUNTIME_PACKAGE_FILES = [
47
+ 'package.json',
48
+ 'src/cli/index.ts',
49
+ 'src/runtime/shared/node-ts-loader.mjs',
50
+ ] as const;
40
51
  const PACKAGE_RUNTIME_STAGING_RESERVE_BYTES = 256 * 1024 * 1024;
41
52
 
53
+ function isNonRuntimePackageHelper(path: string): boolean {
54
+ if (path.startsWith('scripts/benchmark-')) return true;
55
+ if (path.startsWith('scripts/check-release-')) return true;
56
+ if (path.startsWith('scripts/public-release')) return true;
57
+ return path === 'scripts/route-nl-vs-ts-eval.ts'
58
+ || path === 'scripts/check-npm-release.sh'
59
+ || path === 'scripts/check-public-release-surface.sh'
60
+ || path === 'scripts/check-tarball-install-smoke.sh'
61
+ || path === 'scripts/publish-release-tarball.sh'
62
+ || path === 'scripts/stage-runtime-release.ts'
63
+ || path === 'scripts/package-source-archive.sh';
64
+ }
65
+
42
66
  function sha256(value: Buffer | string): string {
43
67
  return createHash('sha256').update(value).digest('hex');
44
68
  }
@@ -50,7 +74,7 @@ function atomicWrite(path: string, content: string, mode = 0o600): void {
50
74
  renameSync(temporary, path);
51
75
  }
52
76
 
53
- function walkRegularFiles(root: string, current: string, output: string[]): void {
77
+ function walkRegularFiles(root: string, current: string, output: string[], prefix = ''): void {
54
78
  if (!existsSync(current)) return;
55
79
  const stat = lstatSync(current);
56
80
  // Package managers such as Bun can materialize dependency files as
@@ -59,38 +83,89 @@ function walkRegularFiles(root: string, current: string, output: string[]): void
59
83
  // regular files beneath its own immutable package root.
60
84
  if (stat.isSymbolicLink()) {
61
85
  const target = statSync(current);
62
- if (target.isFile()) output.push(relative(root, current).split('\\').join('/'));
86
+ if (target.isFile()) {
87
+ const relativePath = relative(root, current).split('\\').join('/');
88
+ output.push(prefix ? `${prefix}/${relativePath}` : relativePath);
89
+ }
63
90
  return;
64
91
  }
65
92
  if (stat.isFile()) {
66
- output.push(relative(root, current).split('\\').join('/'));
93
+ const relativePath = relative(root, current).split('\\').join('/');
94
+ output.push(prefix ? `${prefix}/${relativePath}` : relativePath);
67
95
  return;
68
96
  }
69
97
  if (!stat.isDirectory()) return;
70
- for (const entry of readdirSync(current).sort()) walkRegularFiles(root, join(current, entry), output);
98
+ for (const entry of readdirSync(current).sort()) walkRegularFiles(root, join(current, entry), output, prefix);
71
99
  }
72
100
 
73
- export function packageRuntimeFileIndex(packageRoot = packageRuntimeSourceRoot()): PackageRuntimeFileRecord[] {
101
+ function packageSourcePath(packageRoot: string, path: string, dependencyRoot = packageRoot): string {
102
+ return path === 'node_modules' || path.startsWith('node_modules/')
103
+ ? join(resolve(dependencyRoot), path)
104
+ : join(resolve(packageRoot), path);
105
+ }
106
+
107
+ function packageFileIndex(
108
+ packageRoot: string,
109
+ roots: readonly string[],
110
+ files: readonly string[],
111
+ dependencyRoot = packageRoot,
112
+ ): PackageRuntimeFileRecord[] {
74
113
  const root = resolve(packageRoot);
114
+ const dependencies = resolve(dependencyRoot);
75
115
  const paths: string[] = [];
76
- for (const directory of PACKAGE_RUNTIME_ROOTS) walkRegularFiles(root, join(root, directory), paths);
77
- for (const file of PACKAGE_RUNTIME_FILES) walkRegularFiles(root, join(root, file), paths);
78
- const unique = [...new Set(paths)].sort();
79
- if (!unique.includes('package.json') || !unique.some((path) => path === 'bin/forge-runtime.mjs')) {
80
- throw new Error(`PACKAGE_RUNTIME_SURFACE_INCOMPLETE: ${root}`);
116
+ for (const directory of roots) {
117
+ if (directory === 'node_modules' && dependencies !== root) {
118
+ const dependencyNodeModules = join(dependencies, 'node_modules');
119
+ walkRegularFiles(dependencyNodeModules, dependencyNodeModules, paths, 'node_modules');
120
+ } else {
121
+ walkRegularFiles(root, join(root, directory), paths);
122
+ }
81
123
  }
82
- return unique.map((path) => {
83
- const bytes = readFileSync(join(root, path));
124
+ for (const file of files) walkRegularFiles(root, join(root, file), paths);
125
+ return [...new Set(paths)].sort().map((path) => {
126
+ const bytes = readFileSync(packageSourcePath(root, path, dependencies));
84
127
  return { path, sha256: sha256(bytes), bytes: bytes.length };
85
128
  });
86
129
  }
87
130
 
131
+ export function packageRuntimeFileIndex(packageRoot = packageRuntimeSourceRoot(), dependencyRoot = packageRoot): PackageRuntimeFileRecord[] {
132
+ const root = resolve(packageRoot);
133
+ const records = packageFileIndex(root, PACKAGE_RUNTIME_ROOTS, PACKAGE_RUNTIME_FILES, dependencyRoot)
134
+ .filter((record) => !isNonRuntimePackageHelper(record.path));
135
+ const paths = new Set(records.map((record) => record.path));
136
+ if (!paths.has('package.json') || !paths.has('bin/forge-runtime.mjs')) {
137
+ throw new Error(`PACKAGE_RUNTIME_SURFACE_INCOMPLETE: ${root}`);
138
+ }
139
+ return records;
140
+ }
141
+
142
+ export function compiledRuntimePackageFileIndex(packageRoot = packageRuntimeSourceRoot()): PackageRuntimeFileRecord[] {
143
+ const root = resolve(packageRoot);
144
+ const records = packageFileIndex(root, COMPILED_RUNTIME_PACKAGE_ROOTS, COMPILED_RUNTIME_PACKAGE_FILES);
145
+ const paths = new Set(records.map((record) => record.path));
146
+ for (const required of COMPILED_RUNTIME_PACKAGE_FILES) {
147
+ if (!paths.has(required)) throw new Error(`COMPILED_RUNTIME_PACKAGE_SURFACE_INCOMPLETE: ${required}`);
148
+ }
149
+ if (![...paths].some((path) => path.startsWith('adapters/computer/chrome-extension/'))) {
150
+ throw new Error('COMPILED_RUNTIME_PACKAGE_SURFACE_INCOMPLETE: adapters/computer/chrome-extension');
151
+ }
152
+ return records;
153
+ }
154
+
88
155
  export function packageRuntimeFingerprint(records: PackageRuntimeFileRecord[]): string {
89
156
  const hash = createHash('sha256');
90
157
  for (const record of records) hash.update(record.path).update('\0').update(record.sha256).update('\0').update(String(record.bytes)).update('\n');
91
158
  return hash.digest('hex');
92
159
  }
93
160
 
161
+ function packageRuntimeArtifactIdentity(root: string, records: PackageRuntimeFileRecord[]): string {
162
+ const hash = createHash('sha256');
163
+ for (const record of records) {
164
+ hash.update(record.path).update('\0').update(readFileSync(join(root, record.path))).update('\0');
165
+ }
166
+ return `sha256:${hash.digest('hex')}`;
167
+ }
168
+
94
169
  function assertPackageRuntimeSnapshot(snapshotRoot: string, records: PackageRuntimeFileRecord[]): void {
95
170
  if (!existsSync(snapshotRoot)) throw new Error('PACKAGE_RUNTIME_RELEASE_IMMUTABILITY_VIOLATION: package snapshot is missing');
96
171
  const rootStat = lstatSync(snapshotRoot);
@@ -111,10 +186,15 @@ function assertPackageRuntimeSnapshot(snapshotRoot: string, records: PackageRunt
111
186
  }
112
187
  }
113
188
 
114
- export function stagePackageRuntimeSnapshot(sourceRoot: string, snapshotRoot: string, records: PackageRuntimeFileRecord[]): void {
189
+ export function stagePackageRuntimeSnapshot(
190
+ sourceRoot: string,
191
+ snapshotRoot: string,
192
+ records: PackageRuntimeFileRecord[],
193
+ dependencyRoot = sourceRoot,
194
+ ): void {
115
195
  mkdirSync(snapshotRoot, { recursive: false, mode: 0o700 });
116
196
  for (const record of records) {
117
- const source = join(sourceRoot, record.path);
197
+ const source = packageSourcePath(sourceRoot, record.path, dependencyRoot);
118
198
  const link = lstatSync(source);
119
199
  const stat = link.isSymbolicLink() ? statSync(source) : link;
120
200
  if (!stat.isFile()) throw new Error(`PACKAGE_RUNTIME_SOURCE_CHANGED_DURING_STAGE: ${record.path}`);
@@ -146,6 +226,7 @@ function launcherSource(input: {
146
226
  indexSha256: string;
147
227
  entryRelativePath?: string;
148
228
  managerSignalsProcessGroup?: boolean;
229
+ ownsProcessRuntimeCanary?: boolean;
149
230
  }): string {
150
231
  const entryRelativePath = input.entryRelativePath ?? 'src/runtime/root/entry.ts';
151
232
  return `#!${process.execPath}\n`
@@ -154,7 +235,12 @@ function launcherSource(input: {
154
235
  + `import { dirname, join } from 'node:path';\n`
155
236
  + `import { fileURLToPath } from 'node:url';\n`
156
237
  + `import { spawn } from 'node:child_process';\n`
157
- + `const releaseRoot=dirname(fileURLToPath(import.meta.url));\n`
238
+ // macOS runs a byte-for-byte mirror of this launcher from its fixed,
239
+ // TCC-stable service path. The mirrored file is not its immutable release
240
+ // directory, so use the launch contract's attested release binding when it
241
+ // is present. Direct execution from the immutable release still derives
242
+ // the same root from the entrypoint location.
243
+ + `const releaseRoot=process.env.FORGE_RELEASE_PATH?.trim()||dirname(fileURLToPath(import.meta.url));\n`
158
244
  + `const packageRoot=join(releaseRoot,'package');\n`
159
245
  + `const indexPath=join(releaseRoot,'package-files.json');\n`
160
246
  + `const expectedIndex=${JSON.stringify(input.indexSha256)};\n`
@@ -163,6 +249,8 @@ function launcherSource(input: {
163
249
  + `if(digest(raw)!==expectedIndex){console.error('FORGE_PACKAGE_RUNTIME_INDEX_CHANGED');process.exit(78);}\n`
164
250
  + `let records; try { records=JSON.parse(raw.toString('utf8')).files; } catch { console.error('FORGE_PACKAGE_RUNTIME_INDEX_INVALID'); process.exit(78); }\n`
165
251
  + `for(const record of records){const path=join(packageRoot,record.path);if(!existsSync(path)||digest(readFileSync(path))!==record.sha256){console.error('FORGE_PACKAGE_RUNTIME_SOURCE_CHANGED: '+record.path);process.exit(78);}}\n`
252
+ + `const ownsProcessRuntimeCanary=${input.ownsProcessRuntimeCanary === true ? 'true' : 'false'};\n`
253
+ + `if(ownsProcessRuntimeCanary&&process.argv.length===3&&process.argv[2]===${JSON.stringify(PROCESS_RUNTIME_RELEASE_CANARY_ARG)})process.exit(0);\n`
166
254
  + `const entry=join(packageRoot,...${JSON.stringify(entryRelativePath.split('/'))});\n`
167
255
  + `const loader=join(packageRoot,'src','runtime','shared','node-ts-loader.mjs');\n`
168
256
  + `const args=process.versions?.bun?[entry,...process.argv.slice(2)]:['--loader',loader,entry,...process.argv.slice(2)];\n`
@@ -224,7 +312,12 @@ function assertImmutablePackageRuntimeRelease(input: {
224
312
  && manifest.checkRunnerArtifactIdentity === expected.checkRunnerArtifactIdentity
225
313
  && JSON.stringify(manifest.arguments ?? []) === JSON.stringify(expected.arguments ?? [])
226
314
  && manifest.configurationSchemaVersion === expected.configurationSchemaVersion
227
- && resolve(manifest.controllerHome) === resolve(expected.controllerHome)
315
+ && manifest.deploymentScope === expected.deploymentScope
316
+ && (manifest.deploymentScope === 'portable'
317
+ ? expected.deploymentScope === 'portable'
318
+ : typeof manifest.controllerHome === 'string'
319
+ && typeof expected.controllerHome === 'string'
320
+ && resolve(manifest.controllerHome) === resolve(expected.controllerHome))
228
321
  && JSON.stringify(manifest.databaseSchemaCompatibility) === JSON.stringify(expected.databaseSchemaCompatibility)
229
322
  && manifest.workerProtocolVersion === expected.workerProtocolVersion
230
323
  && manifest.releaseRevision === expected.releaseRevision
@@ -232,6 +325,7 @@ function assertImmutablePackageRuntimeRelease(input: {
232
325
  && typeof manifest.createdAt === 'string'
233
326
  && Number.isFinite(Date.parse(manifest.createdAt));
234
327
  if (!compatible) throw new Error('PACKAGE_RUNTIME_RELEASE_IMMUTABILITY_VIOLATION: manifest identity changed');
328
+ if (!expected.controllerHome) throw new Error('PACKAGE_RUNTIME_RELEASE_IMMUTABILITY_VIOLATION: package release must remain ControllerHome-bound');
235
329
  assertRuntimeReleaseExecutionSurface(input.manifestPath, expected.controllerHome);
236
330
  }
237
331
 
@@ -245,8 +339,9 @@ export function materializePackageRuntimeRelease(input: {
245
339
  const version = packageVersion(sourcePackageRoot);
246
340
  const records = packageRuntimeFileIndex(sourcePackageRoot);
247
341
  const fingerprint = packageRuntimeFingerprint(records);
342
+ const packageArtifactIdentity = packageRuntimeArtifactIdentity(sourcePackageRoot, records);
248
343
  const safeVersion = version.replace(/[^A-Za-z0-9._-]+/g, '-');
249
- const launcherBinding = sha256(`${resolve(process.execPath)}\0package-launcher-v5`);
344
+ const launcherBinding = sha256(`${resolve(process.execPath)}\0package-launcher-v9`);
250
345
  const releaseId = `package-${safeVersion}-${fingerprint.slice(0, 16)}-${launcherBinding.slice(0, 12)}`;
251
346
  const releasesRoot = join(controllerHome, 'runtime', 'releases');
252
347
  const releaseRoot = join(releasesRoot, releaseId);
@@ -262,6 +357,7 @@ export function materializePackageRuntimeRelease(input: {
262
357
  const processRunnerLauncher = launcherSource({
263
358
  indexSha256,
264
359
  entryRelativePath: 'src/runtime/execution/process-runtime/process-runner-entry.ts',
360
+ ownsProcessRuntimeCanary: true,
265
361
  });
266
362
  const processRunnerArtifactIdentity = `sha256:${sha256(Buffer.from(processRunnerLauncher))}`;
267
363
  const checkRunnerEntrypoint = 'forge-check-runner' as const;
@@ -269,6 +365,7 @@ export function materializePackageRuntimeRelease(input: {
269
365
  const checkRunnerLauncher = launcherSource({
270
366
  indexSha256,
271
367
  entryRelativePath: 'src/runtime/execution/process-runtime/check-runner-sidecar.ts',
368
+ ownsProcessRuntimeCanary: true,
272
369
  });
273
370
  const checkRunnerArtifactIdentity = `sha256:${sha256(Buffer.from(checkRunnerLauncher))}`;
274
371
  const expectedManifest: Omit<RuntimeReleaseManifest, 'createdAt'> = {
@@ -280,6 +377,8 @@ export function materializePackageRuntimeRelease(input: {
280
377
  processRunnerArtifactIdentity,
281
378
  checkRunnerEntrypoint,
282
379
  checkRunnerArtifactIdentity,
380
+ packageRoot: 'package',
381
+ packageArtifactIdentity,
283
382
  arguments: [],
284
383
  configurationSchemaVersion: 1,
285
384
  controllerHome,
@@ -4,7 +4,8 @@ import { setTimeout as sleep } from 'timers/promises';
4
4
  import { dirname, join, resolve } from 'path';
5
5
  import { resolveControllerHome } from '../../cli/repositories/controller-home';
6
6
  import { createPlatformServiceManagerHost, probeSystemdUserAvailable, type PlatformServiceManagerHost, type PlatformServiceManagerKind, type SystemdUserUnitInput } from '../platform/service-manager';
7
- import { RUNTIME_WRITE_CLAIM_ENV } from './write-fence';
7
+ import { reconcileRetiredForgePersistentServices, type ForgeRetiredServiceReconciliation } from '../platform/service-inventory';
8
+ import { runtimeAuthorityFreeEnvironment } from '../shared/process-environment';
8
9
  import {
9
10
  activeRuntimeEntrypoint,
10
11
  activeRuntimeLaunchSpec,
@@ -19,6 +20,7 @@ import { materializePackageRuntimeRelease, type PackageRuntimeRelease } from './
19
20
  import { readRuntimeReleaseAuthority, revertInitialRuntimeReleasePublication, rollbackRuntimeRelease } from './release-store';
20
21
  import { loadMcpServiceLocalConfig } from '../../../adapters/mcp/auth';
21
22
  import { ensurePackageConnectorService, type PackageConnectorServiceResult } from './package-connector-service';
23
+ import { normalizeRuntimeDeploymentTopology, type RuntimeDeploymentTopology } from './deployment-topology';
22
24
 
23
25
  export type PackageRuntimeServiceMode = PlatformServiceManagerKind;
24
26
 
@@ -74,6 +76,7 @@ export interface PackageRuntimeServiceInstallResult {
74
76
  pid?: number;
75
77
  warnings: string[];
76
78
  connector?: PackageConnectorServiceResult;
79
+ retiredServices?: ForgeRetiredServiceReconciliation[];
77
80
  activation?: {
78
81
  operationId: string;
79
82
  status: 'activation_scheduled';
@@ -89,11 +92,11 @@ export interface PackageRuntimeServiceOptions {
89
92
  host?: string;
90
93
  port?: number;
91
94
  authTokenFile: string;
92
- exclusiveWorkId?: string;
93
95
  platform?: NodeJS.Platform;
94
96
  env?: NodeJS.ProcessEnv;
95
97
  forcePortable?: boolean;
96
98
  refreshConnector?: boolean;
99
+ topology?: RuntimeDeploymentTopology;
97
100
  }
98
101
 
99
102
  export interface PackageRuntimeServiceDependencies {
@@ -101,6 +104,7 @@ export interface PackageRuntimeServiceDependencies {
101
104
  ensureConnectorService?: typeof ensurePackageConnectorService;
102
105
  scheduleDarwinActivation?: (request: PackageRuntimeActivationRequest) => Promise<{ label: string; servicePath: string }>;
103
106
  activationMode?: 'detached' | 'inline';
107
+ reconcileRetiredServices?: typeof reconcileRetiredForgePersistentServices;
104
108
  }
105
109
 
106
110
  export interface PackageRuntimeActivationDependencies {
@@ -131,14 +135,10 @@ export function systemdUserAvailable(env: NodeJS.ProcessEnv = process.env): bool
131
135
  }
132
136
 
133
137
  function cleanRuntimeInstallerEnvironment(env: NodeJS.ProcessEnv, releaseEnvironment: Record<string, string>): NodeJS.ProcessEnv {
134
- const next = { ...env };
135
- for (const key of Object.values(RUNTIME_WRITE_CLAIM_ENV)) delete next[key];
136
- delete next.FORGE_CONTROLLER_LIFECYCLE_OWNER;
137
- delete next.FORGE_RELEASE_PATH;
138
- delete next.FORGE_RELEASE_REVISION;
139
- delete next.FORGE_RELEASE_SOURCE_COMMIT;
140
- delete next.FORGE_RELEASE_CLEAN_WORKSPACE;
141
- return { ...next, ...releaseEnvironment };
138
+ // The selected immutable release is the only authority reintroduced below.
139
+ // Do not carry an installer, host Runtime or Supervisor writer claim across
140
+ // this service boundary.
141
+ return { ...runtimeAuthorityFreeEnvironment(env), ...releaseEnvironment };
142
142
  }
143
143
 
144
144
  export function systemdRuntimeInstallCommands(unitName: string): string[][] {
@@ -471,7 +471,7 @@ export async function installPackageRuntimeService(
471
471
  host: options.host ?? '127.0.0.1',
472
472
  port: options.port ?? 8765,
473
473
  authTokenFile: options.authTokenFile,
474
- ...(options.exclusiveWorkId?.trim() ? { exclusiveWorkId: options.exclusiveWorkId.trim() } : {}),
474
+ topology: normalizeRuntimeDeploymentTopology(options.topology),
475
475
  };
476
476
  writeForgeRuntimeServiceConfig(config);
477
477
  syncForgeRuntimeActiveEntrypoint(controllerHome);
@@ -479,6 +479,11 @@ export async function installPackageRuntimeService(
479
479
  const env = options.env ?? process.env;
480
480
  const serviceHost = createPlatformServiceManagerHost({ platform, env, forcePortable: options.forcePortable });
481
481
  const serviceManager = serviceHost.selection;
482
+ const retiredServices = await (dependencies.reconcileRetiredServices ?? reconcileRetiredForgePersistentServices)({
483
+ host: serviceHost,
484
+ env,
485
+ accountHome: env.HOME,
486
+ });
482
487
  const installDarwinService = dependencies.installDarwinService ?? installForgeRuntimeService;
483
488
  const explicitInjectedInline = Boolean(dependencies.installDarwinService && !dependencies.scheduleDarwinActivation && !dependencies.activationMode);
484
489
  const activationMode = dependencies.activationMode ?? (explicitInjectedInline ? 'inline' : 'detached');
@@ -592,6 +597,7 @@ export async function installPackageRuntimeService(
592
597
  }
593
598
  }
594
599
 
600
+ base = { ...base, retiredServices };
595
601
  if (!connectorEndpoint || base.status === 'activation_scheduled') return base;
596
602
  const ensureConnectorService = dependencies.ensureConnectorService ?? ensurePackageConnectorService;
597
603
  const connector = await ensureConnectorService({
@@ -1,12 +1,14 @@
1
+ import { join } from 'path';
1
2
  import { runProcess } from '../../effects/process-runner';
2
3
  import { PROCESS_RUNTIME_RELEASE_CANARY_ARG } from '../execution/process-runtime/canary';
4
+ import { resolveBunExecutable } from '../shared/process-environment';
3
5
  import {
4
6
  assertRuntimeReleaseExecutionSurface,
5
7
  type RuntimeReleaseExecutionSurface,
6
8
  } from './release-manifest';
7
9
 
8
10
  export interface RuntimeReleaseExecutionCanaryCommand {
9
- name: RuntimeReleaseExecutionSurface['entries'][number]['name'];
11
+ name: RuntimeReleaseExecutionSurface['entries'][number]['name'] | 'connector_cli';
10
12
  executable: string;
11
13
  args: string[];
12
14
  }
@@ -22,8 +24,10 @@ export interface RuntimeReleaseExecutionCanaryDependencies {
22
24
 
23
25
  /**
24
26
  * Release execution canaries deliberately do not inherit developer-tool PATH
25
- * entries. A manifest-owned executable that only works because Homebrew, Bun,
26
- * nvm, etc. happens to be present is not an immutable Runtime artifact.
27
+ * entries. Standalone-binary artifacts must execute without Homebrew, Bun, nvm,
28
+ * or similar PATH dependencies. Legacy script releases predate the embedded
29
+ * Runtime interpreter and are probed through the same explicitly resolved Bun
30
+ * executable that their Process Runtime uses in production.
27
31
  */
28
32
  export function runtimeReleaseCanaryEnvironment(
29
33
  env: NodeJS.ProcessEnv = process.env,
@@ -39,7 +43,12 @@ export function runtimeReleaseCanaryEnvironment(
39
43
  return { ...env, PATH: '/usr/bin:/bin:/usr/sbin:/sbin' };
40
44
  }
41
45
 
42
- /** Execute the exact manifest-owned Process/Check Runner artifacts in bounded no-op mode. */
46
+ /**
47
+ * Execute the minimum immutable Runtime execution surface plus the package
48
+ * Connector CLI import graph. The latter is intentionally a help-only command:
49
+ * it loads the exact CLI dependency closure used by the persistent Connector
50
+ * without opening a listener or mutating Runtime authority.
51
+ */
43
52
  export function assertRuntimeReleaseExecutionCanaries(
44
53
  manifestPath: string,
45
54
  controllerHome: string,
@@ -52,20 +61,43 @@ export function assertRuntimeReleaseExecutionCanaries(
52
61
  {
53
62
  cwd: surface.releaseRoot,
54
63
  env: runtimeReleaseCanaryEnvironment(),
55
- timeoutMs: 10_000,
64
+ timeoutMs: 30_000,
56
65
  maxOutputBytes: 64 * 1024,
57
66
  },
58
67
  ));
59
- for (const entry of surface.entries) {
60
- const canary: RuntimeReleaseExecutionCanaryCommand = {
61
- name: entry.name,
62
- executable: entry.path,
63
- args: [PROCESS_RUNTIME_RELEASE_CANARY_ARG],
64
- };
68
+ const assertCanary = (canary: RuntimeReleaseExecutionCanaryCommand): void => {
65
69
  const result = runExecutionEntryCanary(canary);
66
70
  if (!result.ok) {
67
- throw new Error(`RUNTIME_RELEASE_EXECUTION_CANARY_FAILED: ${canary.name}: ${result.stderr || result.stdout || result.error || 'unknown failure'}`.slice(0, 2_000));
71
+ const detail = result.stderr || result.stdout || result.error || 'unknown failure';
72
+ const legacyCheckRunnerUsageProbe = surface.manifest.executionMode !== 'standalone-binary'
73
+ && canary.name === 'check_runner'
74
+ && detail.trim() === 'PERSISTED_CHECK_USAGE: missing --repo';
75
+ if (legacyCheckRunnerUsageProbe) return;
76
+ throw new Error(`RUNTIME_RELEASE_EXECUTION_CANARY_FAILED: ${canary.name}: ${detail}`.slice(0, 2_000));
68
77
  }
78
+ };
79
+
80
+ for (const entry of surface.entries) {
81
+ const args = entry.canary === 'runtime_interpreter' ? ['--version'] : [PROCESS_RUNTIME_RELEASE_CANARY_ARG];
82
+ const legacyScript = surface.manifest.executionMode !== 'standalone-binary'
83
+ && /\.(?:[cm]?js|tsx?)$/i.test(entry.path);
84
+ assertCanary({
85
+ name: entry.name,
86
+ executable: legacyScript ? resolveBunExecutable(process.execPath, process.env) : entry.path,
87
+ args: legacyScript ? [entry.path, ...args] : args,
88
+ });
69
89
  }
90
+
91
+ // Package launcher releases execute source-backed CLI code from their own
92
+ // immutable snapshot. Compiled standalone releases have a different closed
93
+ // artifact surface and therefore do not use this source CLI probe.
94
+ if (surface.manifest.executionMode !== 'standalone-binary' && surface.manifest.packageRoot) {
95
+ assertCanary({
96
+ name: 'connector_cli',
97
+ executable: resolveBunExecutable(process.execPath, process.env),
98
+ args: [join(surface.releaseRoot, 'package', 'src', 'cli', 'index.ts'), 'mcp', 'serve', '--help'],
99
+ });
100
+ }
101
+
70
102
  return surface;
71
103
  }
@@ -1,13 +1,18 @@
1
+ import { spawn } from 'child_process';
1
2
  import { createHash } from 'crypto';
2
- import { readFileSync } from 'fs';
3
+ import { lstatSync, readFileSync } from 'fs';
3
4
  import { dirname, join, resolve } from 'path';
4
- import { pathToFileURL } from 'url';
5
5
 
6
6
  export const RUNTIME_BUNDLE_ENTRYPOINT = 'forge-runtime-bundle.js' as const;
7
+ export const RUNTIME_INTERPRETER_ENTRYPOINT = process.platform === 'win32'
8
+ ? 'forge-runtime-bun.exe' as const
9
+ : 'forge-runtime-bun' as const;
7
10
 
8
11
  interface RuntimeBundleManifestRecord {
9
12
  runtimeBundleEntrypoint?: unknown;
10
13
  runtimeBundleArtifactIdentity?: unknown;
14
+ runtimeInterpreterEntrypoint?: unknown;
15
+ runtimeInterpreterArtifactIdentity?: unknown;
11
16
  }
12
17
 
13
18
  function releaseManifestPath(argv: readonly string[]): string {
@@ -21,6 +26,8 @@ export function resolveCompiledRuntimeBundle(argv: readonly string[] = process.a
21
26
  manifestPath: string;
22
27
  bundlePath: string;
23
28
  artifactIdentity: string;
29
+ interpreterPath: string;
30
+ interpreterArtifactIdentity: string;
24
31
  } {
25
32
  const manifestPath = releaseManifestPath(argv);
26
33
  let manifest: RuntimeBundleManifestRecord;
@@ -38,9 +45,14 @@ export function resolveCompiledRuntimeBundle(argv: readonly string[] = process.a
38
45
  if (!/^sha256:[a-f0-9]{64}$/.test(artifactIdentity)) {
39
46
  throw new Error('RUNTIME_RELEASE_BUNDLE_IDENTITY_INVALID');
40
47
  }
41
- const bundlePath = join(dirname(manifestPath), RUNTIME_BUNDLE_ENTRYPOINT);
48
+ const releaseRoot = dirname(manifestPath);
49
+ const bundlePath = join(releaseRoot, RUNTIME_BUNDLE_ENTRYPOINT);
42
50
  let actualIdentity: string;
43
51
  try {
52
+ const status = lstatSync(bundlePath);
53
+ if (status.isSymbolicLink() || !status.isFile()) {
54
+ throw new Error('bundle must be a regular file');
55
+ }
44
56
  actualIdentity = `sha256:${createHash('sha256').update(readFileSync(bundlePath)).digest('hex')}`;
45
57
  } catch (error) {
46
58
  throw new Error(`RUNTIME_RELEASE_BUNDLE_READ_FAILED: ${error instanceof Error ? error.message : String(error)}`);
@@ -48,16 +60,86 @@ export function resolveCompiledRuntimeBundle(argv: readonly string[] = process.a
48
60
  if (actualIdentity !== artifactIdentity) {
49
61
  throw new Error('RUNTIME_RELEASE_BUNDLE_ARTIFACT_IDENTITY_MISMATCH');
50
62
  }
51
- return { manifestPath, bundlePath, artifactIdentity };
63
+ if (manifest.runtimeInterpreterEntrypoint !== RUNTIME_INTERPRETER_ENTRYPOINT) {
64
+ throw new Error(`RUNTIME_RELEASE_INTERPRETER_ENTRYPOINT_INVALID: expected ${RUNTIME_INTERPRETER_ENTRYPOINT}`);
65
+ }
66
+ const interpreterArtifactIdentity = typeof manifest.runtimeInterpreterArtifactIdentity === 'string'
67
+ ? manifest.runtimeInterpreterArtifactIdentity.trim().toLowerCase()
68
+ : '';
69
+ if (!/^sha256:[a-f0-9]{64}$/.test(interpreterArtifactIdentity)) {
70
+ throw new Error('RUNTIME_RELEASE_INTERPRETER_IDENTITY_INVALID');
71
+ }
72
+ const interpreterPath = join(releaseRoot, RUNTIME_INTERPRETER_ENTRYPOINT);
73
+ let actualInterpreterIdentity: string;
74
+ try {
75
+ const status = lstatSync(interpreterPath);
76
+ if (status.isSymbolicLink() || !status.isFile() || (status.mode & 0o111) === 0) {
77
+ throw new Error('interpreter must be a regular executable file');
78
+ }
79
+ actualInterpreterIdentity = `sha256:${createHash('sha256').update(readFileSync(interpreterPath)).digest('hex')}`;
80
+ } catch (error) {
81
+ throw new Error(`RUNTIME_RELEASE_INTERPRETER_READ_FAILED: ${error instanceof Error ? error.message : String(error)}`);
82
+ }
83
+ if (actualInterpreterIdentity !== interpreterArtifactIdentity) {
84
+ throw new Error('RUNTIME_RELEASE_INTERPRETER_ARTIFACT_IDENTITY_MISMATCH');
85
+ }
86
+ return { manifestPath, bundlePath, artifactIdentity, interpreterPath, interpreterArtifactIdentity };
87
+ }
88
+
89
+ function runtimeChildArgs(argv: readonly string[]): string[] {
90
+ const firstRuntimeArgument = argv.findIndex((argument) => argument.startsWith('--'));
91
+ if (firstRuntimeArgument < 0 || !argv.includes('--controller-home')) {
92
+ throw new Error('RUNTIME_CONTROLLER_HOME_ARGUMENT_REQUIRED');
93
+ }
94
+ return argv.slice(firstRuntimeArgument);
52
95
  }
53
96
 
54
97
  export async function runCompiledRuntimeLoader(argv: string[] = process.argv): Promise<void> {
55
98
  const bundle = resolveCompiledRuntimeBundle(argv);
56
- const loaded = await import(pathToFileURL(bundle.bundlePath).href) as { runCanonicalRuntimeCli?: (argv?: string[]) => Promise<void> };
57
- if (typeof loaded.runCanonicalRuntimeCli !== 'function') {
58
- throw new Error('RUNTIME_RELEASE_BUNDLE_ENTRY_EXPORT_MISSING');
99
+ const child = spawn(bundle.interpreterPath, [bundle.bundlePath, ...runtimeChildArgs(argv)], {
100
+ cwd: dirname(bundle.manifestPath),
101
+ stdio: 'inherit',
102
+ env: process.env,
103
+ });
104
+ let childExited = false;
105
+ const forwardSignal = (signal: NodeJS.Signals): void => {
106
+ if (childExited) return;
107
+ try { child.kill(signal); } catch { /* child lifecycle reconciliation owns terminal state */ }
108
+ };
109
+ const terminateChildOnLauncherExit = (): void => {
110
+ if (childExited) return;
111
+ try { child.kill('SIGTERM'); } catch { /* launcher is already exiting */ }
112
+ };
113
+ const forwardedSignals: NodeJS.Signals[] = process.platform === 'win32'
114
+ ? ['SIGINT', 'SIGTERM']
115
+ : ['SIGINT', 'SIGTERM', 'SIGUSR1', 'SIGUSR2'];
116
+ const signalHandlers = new Map<NodeJS.Signals, () => void>();
117
+ for (const signal of forwardedSignals) {
118
+ const handler = () => forwardSignal(signal);
119
+ signalHandlers.set(signal, handler);
120
+ process.on(signal, handler);
121
+ }
122
+ process.once('exit', terminateChildOnLauncherExit);
123
+ try {
124
+ const outcome = await new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolveChild, rejectChild) => {
125
+ child.once('error', rejectChild);
126
+ child.once('exit', (code, signal) => {
127
+ childExited = true;
128
+ resolveChild({ code, signal });
129
+ });
130
+ });
131
+ if (outcome.signal) {
132
+ for (const [signal, handler] of signalHandlers) process.off(signal, handler);
133
+ signalHandlers.clear();
134
+ process.off('exit', terminateChildOnLauncherExit);
135
+ process.kill(process.pid, outcome.signal);
136
+ return;
137
+ }
138
+ if (outcome.code !== 0) process.exitCode = outcome.code ?? 1;
139
+ } finally {
140
+ for (const [signal, handler] of signalHandlers) process.off(signal, handler);
141
+ process.off('exit', terminateChildOnLauncherExit);
59
142
  }
60
- await loaded.runCanonicalRuntimeCli(argv);
61
143
  }
62
144
 
63
145
  if (import.meta.main) {