@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
@@ -4,15 +4,46 @@ import { existsSync, readFileSync } from 'fs';
4
4
  import { isAbsolute, join, resolve } from 'path';
5
5
  import { pathToFileURL } from 'url';
6
6
  import { resolveControllerHome } from '../src/cli/repositories/controller-home.ts';
7
- import { findRegisteredRepositoryByCheckoutRoot } from '../src/cli/repositories/registry.ts';
7
+ import { findRegisteredRepositoryByCheckoutRoot, getRepository } from '../src/cli/repositories/registry.ts';
8
8
  import { createRecoveryConfig, gatewayToken, loadRecoveryConfig } from '../src/runtime/standalone-recovery/core.ts';
9
9
 
10
10
  export const PLUGIN_ID = 'local_recovery';
11
11
  export const PLUGIN_VERSION = '0.1.0';
12
12
  export const PROTOCOL_VERSION = 1;
13
13
  export const CAPABILITIES = ['forge.local_recovery.transport.v1'];
14
- export const ACTIONS = ['runtime_status', 'list_releases', 'stage_and_activate_runtime_release'];
15
- const MUTATING_ACTIONS = new Set(['stage_and_activate_runtime_release']);
14
+ export const ACTIONS = [
15
+ 'runtime_status',
16
+ 'list_releases',
17
+ 'verify_stable_runtime',
18
+ 'stage_and_activate_runtime_release',
19
+ 'release_session_status',
20
+ 'advance_runtime_release_session',
21
+ 'verify_runtime_release_session_static',
22
+ 'verify_runtime_release_session_candidate',
23
+ 'cutover_runtime_release_session',
24
+ 'cancel_runtime_release_session',
25
+ 'rollback_runtime_release_session',
26
+ 'promote_runtime_release_session_known_good',
27
+ ];
28
+ const RELEASE_SESSION_ACTIONS = new Set([
29
+ 'release_session_status',
30
+ 'verify_runtime_release_session_static',
31
+ 'verify_runtime_release_session_candidate',
32
+ 'cutover_runtime_release_session',
33
+ 'cancel_runtime_release_session',
34
+ 'rollback_runtime_release_session',
35
+ 'promote_runtime_release_session_known_good',
36
+ ]);
37
+ const MUTATING_ACTIONS = new Set([
38
+ 'stage_and_activate_runtime_release',
39
+ 'advance_runtime_release_session',
40
+ 'verify_runtime_release_session_static',
41
+ 'verify_runtime_release_session_candidate',
42
+ 'cutover_runtime_release_session',
43
+ 'cancel_runtime_release_session',
44
+ 'rollback_runtime_release_session',
45
+ 'promote_runtime_release_session_known_good',
46
+ ]);
16
47
  const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);
17
48
 
18
49
  function providerError(code, message, retryable = false, details) {
@@ -91,8 +122,7 @@ export async function callRecoveryTool(controllerHome, toolName, args = {}, inje
91
122
  protocolVersion: '2025-06-18', capabilities: {}, clientInfo: { name: 'forge-local-recovery-provider', version: PLUGIN_VERSION },
92
123
  },
93
124
  });
94
- const sessionId = initialized.response.headers.get('mcp-session-id');
95
- if (!sessionId) throw providerError('LOCAL_RECOVERY_MCP_SESSION_MISSING', 'Recovery MCP initialize did not return a session id.');
125
+ const sessionId = initialized.response.headers.get('mcp-session-id') || undefined;
96
126
  try {
97
127
  await postRpc(fetchImpl, endpoint, token, { jsonrpc: '2.0', method: 'notifications/initialized' }, sessionId);
98
128
  const called = await postRpc(fetchImpl, endpoint, token, {
@@ -101,15 +131,21 @@ export async function callRecoveryTool(controllerHome, toolName, args = {}, inje
101
131
  if (called.payload?.error) throw providerError('LOCAL_RECOVERY_TOOL_FAILED', String(called.payload.error?.message ?? 'Recovery tool failed.'), false);
102
132
  const content = called.payload?.result?.content;
103
133
  const text = Array.isArray(content) ? content.find((entry) => entry?.type === 'text' && typeof entry.text === 'string')?.text : undefined;
134
+ if (called.payload?.result?.isError === true) {
135
+ const message = typeof text === 'string' && text.trim() ? text.trim().slice(0, 4000) : 'Recovery tool failed.';
136
+ throw providerError('LOCAL_RECOVERY_TOOL_FAILED', message, false);
137
+ }
104
138
  if (text) return parseJson(text, 'LOCAL_RECOVERY_TOOL_RESULT_INVALID');
105
139
  return called.payload?.result ?? {};
106
140
  } finally {
107
- try {
108
- await fetchImpl(endpoint, {
109
- method: 'DELETE',
110
- headers: { authorization: `Bearer ${token}`, accept: 'application/json, text/event-stream', 'mcp-session-id': sessionId },
111
- });
112
- } catch { /* Session cleanup is best effort; Recovery owns mutation transaction durability. */ }
141
+ if (sessionId) {
142
+ try {
143
+ await fetchImpl(endpoint, {
144
+ method: 'DELETE',
145
+ headers: { authorization: `Bearer ${token}`, accept: 'application/json, text/event-stream', 'mcp-session-id': sessionId },
146
+ });
147
+ } catch { /* Session cleanup is best effort; ReleaseSession durability is independent from this transport session. */ }
148
+ }
113
149
  }
114
150
  }
115
151
 
@@ -119,6 +155,17 @@ function assertEmptyInput(input) {
119
155
  }
120
156
  }
121
157
 
158
+ function releaseSessionInput(input) {
159
+ if (!input || typeof input !== 'object' || Array.isArray(input) || Object.keys(input).length !== 1 || typeof input.session_id !== 'string') {
160
+ throw providerError('LOCAL_RECOVERY_RELEASE_SESSION_ARGUMENTS_INVALID', 'ReleaseSession actions accept only session_id.');
161
+ }
162
+ const sessionId = input.session_id.trim();
163
+ if (sessionId.length < 8 || sessionId.length > 120) {
164
+ throw providerError('LOCAL_RECOVERY_RELEASE_SESSION_ID_INVALID', 'ReleaseSession session_id must be 8 to 120 characters.');
165
+ }
166
+ return { session_id: sessionId };
167
+ }
168
+
122
169
  function mutationRequestId(requestId) {
123
170
  return `local-recovery:${createHash('sha256').update(String(requestId)).digest('hex').slice(0, 32)}`;
124
171
  }
@@ -127,9 +174,36 @@ export function ensureSourceRepositoryProvenance(controllerHome, injected = {})
127
174
  const loadConfig = injected.loadRecoveryConfig ?? loadRecoveryConfig;
128
175
  const persistConfig = injected.createRecoveryConfig ?? createRecoveryConfig;
129
176
  const findRepository = injected.findRegisteredRepositoryByCheckoutRoot ?? findRegisteredRepositoryByCheckoutRoot;
177
+ const readRepository = injected.getRepository ?? getRepository;
130
178
  const recoveryConfig = loadConfig(controllerHome);
131
- if (typeof recoveryConfig.primaryRuntimeSourceRepositoryId === 'string' && recoveryConfig.primaryRuntimeSourceRepositoryId.trim()) return recoveryConfig;
179
+ const repositoryId = typeof recoveryConfig.primaryRuntimeSourceRepositoryId === 'string'
180
+ ? recoveryConfig.primaryRuntimeSourceRepositoryId.trim()
181
+ : '';
132
182
  const sourceRoot = typeof recoveryConfig.primaryRuntimeSourceRoot === 'string' ? recoveryConfig.primaryRuntimeSourceRoot.trim() : '';
183
+
184
+ if (repositoryId) {
185
+ let repository;
186
+ try {
187
+ repository = readRepository(repositoryId, controllerHome);
188
+ } catch {
189
+ throw providerError('LOCAL_RECOVERY_SOURCE_REPOSITORY_UNRESOLVED', 'Configured primary Runtime source repository id is not one enabled registered repository.');
190
+ }
191
+ if (!repository || repository.repoId !== repositoryId || repository.enabled === false || repository.removedAt) {
192
+ throw providerError('LOCAL_RECOVERY_SOURCE_REPOSITORY_UNRESOLVED', 'Configured primary Runtime source repository id is not one enabled registered repository.');
193
+ }
194
+ const canonicalRoot = typeof repository.canonicalRoot === 'string' && repository.canonicalRoot.trim()
195
+ ? resolve(repository.canonicalRoot.trim())
196
+ : '';
197
+ if (!canonicalRoot || !isAbsolute(canonicalRoot) || !existsSync(canonicalRoot)) {
198
+ throw providerError('LOCAL_RECOVERY_SOURCE_CANONICAL_ROOT_UNAVAILABLE', 'Configured primary Runtime source repository canonical root is unavailable.');
199
+ }
200
+ if (sourceRoot && resolve(sourceRoot) === canonicalRoot) return recoveryConfig;
201
+ return persistConfig(controllerHome, {
202
+ primaryRuntimeSourceRoot: canonicalRoot,
203
+ primaryRuntimeSourceRepositoryId: repositoryId,
204
+ });
205
+ }
206
+
133
207
  if (!sourceRoot) throw providerError('LOCAL_RECOVERY_SOURCE_ROOT_UNAVAILABLE', 'Installed Recovery config does not identify the primary Runtime source root.');
134
208
  const repository = findRepository(sourceRoot, controllerHome);
135
209
  if (!repository?.repoId) throw providerError('LOCAL_RECOVERY_SOURCE_REPOSITORY_UNRESOLVED', 'Configured primary Runtime source root is not owned by one registered repository.');
@@ -142,10 +216,14 @@ export function ensureSourceRepositoryProvenance(controllerHome, injected = {})
142
216
  export async function executeAction(actionId, input, providerConfig, injected = {}) {
143
217
  const config = validateProviderConfig(providerConfig);
144
218
  if (!ACTIONS.includes(actionId)) throw providerError('LOCAL_RECOVERY_ACTION_UNSUPPORTED', 'Unsupported Local Recovery action.');
145
- assertEmptyInput(input);
219
+ const sessionArgs = RELEASE_SESSION_ACTIONS.has(actionId) ? releaseSessionInput(input) : undefined;
220
+ if (!sessionArgs) assertEmptyInput(input);
146
221
  const callTool = injected.callRecoveryTool ?? callRecoveryTool;
147
- if (actionId === 'stage_and_activate_runtime_release') ensureSourceRepositoryProvenance(config.controllerHome, injected);
148
- const args = MUTATING_ACTIONS.has(actionId) ? { request_id: mutationRequestId(injected.requestId ?? actionId) } : {};
222
+ if (actionId === 'stage_and_activate_runtime_release' || actionId === 'advance_runtime_release_session') ensureSourceRepositoryProvenance(config.controllerHome, injected);
223
+ const args = {
224
+ ...(sessionArgs ?? {}),
225
+ ...(MUTATING_ACTIONS.has(actionId) ? { request_id: mutationRequestId(injected.requestId ?? actionId) } : {}),
226
+ };
149
227
  return await callTool(config.controllerHome, actionId, args, injected);
150
228
  }
151
229
 
@@ -1825,6 +1825,9 @@ This is the root routing contract for Claude Code and Codex.
1825
1825
  - Keep root context concise; route durable human-authored detail into product, architecture, research, or intentional project documents.
1826
1826
  - Treat `_ref/` as ignored external reference material and `_ops/` as ignored local operations residue.
1827
1827
  - Use Controller Home for mutable workflow state instead of recreating repo-local task/workstream/session projections.
1828
+ - For architecture migrations, use one bounded Delivery Transaction: batch discovery -> architecture/root-cause decision -> freeze scope -> coherent implementation -> whole-diff review -> focused validation wave -> canonical gates -> one delivery/cleanup.
1829
+ - Do not create sibling Work, per-file commits, repeated broad validation, or release/canary cycles for same-root-cause discoveries while the current candidate is still moving.
1830
+ - Treat release as a source-complete candidate boundary. Defer workflow/lifecycle machinery improvements to a post-release Plan when they are not required to converge the current version safely.
1828
1831
  EOF_ROOT_CONTEXT
1829
1832
  }
1830
1833
 
@@ -45,8 +45,6 @@ tests/runtime/target-architecture.test.ts
45
45
  # and installation locations to prove discovery and identity fencing.
46
46
  scripts/portability-bindings.mjs
47
47
  tests/runtime/browser-product-discovery.test.ts
48
- tests/runtime/chatgpt-work-continuation.test.ts
49
- tests/runtime/frozen-tool-contract-abi.test.ts
50
48
  tests/runtime/windows-host-discovery.test.ts
51
49
  tests/runtime/standalone-recovery.test.ts
52
50
  # Secret-marker rejection tests use non-secret synthetic values by design.
@@ -55,3 +53,4 @@ tests/runtime/context-plane.test.ts
55
53
  # Supervisor service unit tests use synthetic homeDir placeholders for PATH assembly.
56
54
  # Local monitor bridge defaults may reference a development repository id.
57
55
  scripts/run-mobile-monitor-bridge.ts
56
+ tests/runtime/browser-session-authority.test.ts # Intentional placeholder user profile used to prove foreign Chrome profiles are never reclaimed.
@@ -49,6 +49,11 @@ if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || commandArgs.length === 0) {
49
49
  });
50
50
  child.once('close', (code) => {
51
51
  clearTimeout(timeout);
52
+ // The direct child can exit on SIGTERM while a stubborn descendant remains
53
+ // alive in its detached process group. Before dropping the escalation timer,
54
+ // synchronously send SIGKILL to that process group once more so timeout
55
+ // completion cannot orphan compiler/test descendants.
56
+ if (timedOut && process.platform !== 'win32') stop('SIGKILL');
52
57
  if (escalation) clearTimeout(escalation);
53
58
  process.exitCode = launchFailed ? 1 : (timedOut ? 124 : code ?? 1);
54
59
  });
@@ -22,7 +22,6 @@ export function stepsFor(gate: Gate): Step[] {
22
22
  { label: 'repository hygiene', command: 'node', args: ['scripts/check-repository-hygiene.mjs'], timeoutMs: 2 * 60_000 },
23
23
  { label: 'generated authority', command: 'node', args: ['scripts/sync-generated-authority.mjs', '--check'], timeoutMs: 2 * 60_000 },
24
24
  { label: 'source duplication', command: 'node', args: ['scripts/check-source-duplication.mjs'], timeoutMs: 2 * 60_000 },
25
- { label: 'controller UI bundle', command: 'bun', args: ['run', 'check:controller-ui'], timeoutMs: 5 * 60_000 },
26
25
  { label: 'test manifest', command: 'bun', args: ['run', 'check:test-governance'], timeoutMs: 5 * 60_000 },
27
26
  { label: 'affected tests', command: 'bun', args: ['run', 'test'], timeoutMs: 30 * 60_000 },
28
27
  ];
@@ -49,7 +49,6 @@ const handle = await startLocalBridgeServer({
49
49
  defaultRepoId,
50
50
  host,
51
51
  port,
52
- openBrowser: false,
53
52
  allowLanMobileIntents: true,
54
53
  mode: 'standalone',
55
54
  });
@@ -0,0 +1,94 @@
1
+ import { strict as assert } from 'node:assert';
2
+ import { mkdtempSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import {
6
+ FORGE_RECOVERY_DAEMON_LABEL,
7
+ FORGE_RECOVERY_GATEWAY_LABEL,
8
+ forgeConnectorPersistentServiceLabel,
9
+ forgeRuntimePersistentServiceLabel,
10
+ } from '../src/runtime/platform/service-inventory';
11
+ import {
12
+ classifyRecoveryMcpRequest,
13
+ recoveryRuntimeRoleFromExecutable,
14
+ } from '../src/runtime/standalone-recovery/entry';
15
+ import { recentMcpTransportEvidence } from '../adapters/mcp/transports/http-observation';
16
+ import { recordMcpTransportEvent, readRecentMcpTransportEvents } from '../src/runtime/diagnostics/mcp-timing';
17
+
18
+ const controllerHome = mkdtempSync(join(tmpdir(), 'forge-control-plane-failure-domain-'));
19
+ try {
20
+ // Main Runtime/MCP and Recovery must have distinct service identities. A
21
+ // restart or crash fence for one must not name the other lifecycle owner.
22
+ const runtimeLabel = forgeRuntimePersistentServiceLabel(controllerHome);
23
+ const connectorLabel = forgeConnectorPersistentServiceLabel(controllerHome);
24
+ assert.notEqual(runtimeLabel, FORGE_RECOVERY_DAEMON_LABEL);
25
+ assert.notEqual(runtimeLabel, FORGE_RECOVERY_GATEWAY_LABEL);
26
+ assert.notEqual(connectorLabel, FORGE_RECOVERY_DAEMON_LABEL);
27
+ assert.notEqual(connectorLabel, FORGE_RECOVERY_GATEWAY_LABEL);
28
+ assert.notEqual(FORGE_RECOVERY_DAEMON_LABEL, FORGE_RECOVERY_GATEWAY_LABEL);
29
+ assert.equal(recoveryRuntimeRoleFromExecutable('/tmp/forge-recovery-gateway'), 'gateway');
30
+ assert.equal(recoveryRuntimeRoleFromExecutable('/tmp/forge-recovery-watchdog'), 'watchdog');
31
+
32
+ // Recovery owns its own MCP route. Main MCP being unavailable must not turn a
33
+ // valid Recovery request into a route-level 404; authorization is evaluated
34
+ // by the Recovery gateway itself.
35
+ assert.equal(classifyRecoveryMcpRequest({
36
+ method: 'POST',
37
+ url: '/recovery/mcp',
38
+ headers: { authorization: 'Bearer recovery-token' },
39
+ } as any, 'recovery-token'), 'mcp');
40
+ assert.equal(classifyRecoveryMcpRequest({
41
+ method: 'POST',
42
+ url: '/recovery/mcp',
43
+ headers: {},
44
+ } as any, 'recovery-token'), 'auth_required');
45
+ assert.equal(classifyRecoveryMcpRequest({
46
+ method: 'POST',
47
+ url: '/main/mcp',
48
+ headers: { authorization: 'Bearer recovery-token' },
49
+ } as any, 'recovery-token'), 'not_mcp');
50
+
51
+ // Current health and recent incident evidence are separate dimensions. A
52
+ // successful reconnect does not erase the interruption that immediately
53
+ // preceded it, and a later health probe may still truthfully be green.
54
+ const interruptedAt = '2026-09-22T12:00:00.000Z';
55
+ const recoveredAt = '2026-09-22T12:00:05.000Z';
56
+ recordMcpTransportEvent(controllerHome, {
57
+ kind: 'interruption',
58
+ sessionId: 'mcp-before-outage',
59
+ connectionId: 'connection-before-outage',
60
+ route: '/mcp',
61
+ principalId: 'chatgpt-controller',
62
+ reason: 'transport_close',
63
+ at: interruptedAt,
64
+ });
65
+ recordMcpTransportEvent(controllerHome, {
66
+ kind: 'session_initialized',
67
+ sessionId: 'mcp-after-outage',
68
+ connectionId: 'connection-after-outage',
69
+ route: '/mcp',
70
+ principalId: 'chatgpt-controller',
71
+ at: recoveredAt,
72
+ });
73
+ const evidence = recentMcpTransportEvidence(
74
+ readRecentMcpTransportEvents(controllerHome),
75
+ '2026-09-22T11:00:00.000Z',
76
+ Date.parse('2026-09-22T12:01:00.000Z'),
77
+ );
78
+ assert.equal(evidence.current, 'healthy');
79
+ assert.equal(evidence.recentStatus, 'recovered');
80
+ assert.equal(evidence.lastInterruption?.at, interruptedAt);
81
+ assert.equal(evidence.lastRecoveryAt, recoveredAt);
82
+
83
+ console.log(JSON.stringify({
84
+ status: 'ok',
85
+ mainRuntimeLabel: runtimeLabel,
86
+ mainConnectorLabel: connectorLabel,
87
+ recoveryDaemonLabel: FORGE_RECOVERY_DAEMON_LABEL,
88
+ recoveryGatewayLabel: FORGE_RECOVERY_GATEWAY_LABEL,
89
+ recoveryRouteIndependent: true,
90
+ health: evidence,
91
+ }, null, 2));
92
+ } finally {
93
+ rmSync(controllerHome, { recursive: true, force: true });
94
+ }
@@ -148,6 +148,11 @@ try {
148
148
  throw new Error(`GATEWAY_START_FAILED: ${error instanceof Error ? error.message : String(error)} ${stderr}`);
149
149
  }
150
150
  if (health.status !== 200 || health.body.status !== 'ok') throw new Error(`HEALTH_FAILED: ${JSON.stringify(health)} ${stderr}`);
151
+ const initialTransportEvidence = health.body.transportEvidence as Record<string, unknown> | undefined;
152
+ if (initialTransportEvidence?.current !== 'healthy') throw new Error(`TRANSPORT_CURRENT_HEALTH_MISSING: ${JSON.stringify(initialTransportEvidence)}`);
153
+ if (!['stable', 'recovering', 'recovered'].includes(String(initialTransportEvidence?.recentStatus))) {
154
+ throw new Error(`TRANSPORT_RECENT_STATUS_INVALID: ${JSON.stringify(initialTransportEvidence)}`);
155
+ }
151
156
  const expectedPolicy = runtimePolicy(repoRoot, {
152
157
  repo: repoRoot,
153
158
  controllerHome,
@@ -9,11 +9,8 @@ import {
9
9
  getWorkContract,
10
10
  getWorkContractByRequestId,
11
11
  recordWorkCompletionReceipt,
12
- recordWorkImplementationReview,
13
- requestWorkImplementationReview,
14
- transitionWorkContractPhase,
15
12
  } from '../src/runtime/control-plane/facade/work-contract-store';
16
- import { implementationReviewChangedPathDigest } from '../src/runtime/control-plane/facade/work-implementation-review';
13
+ import { reviseWorkSemanticContext } from '../packages/kernel/work/api/index';
17
14
  import {
18
15
  claimControllerSession,
19
16
  getControllerSession,
@@ -70,6 +67,7 @@ try {
70
67
  semanticKey: operation.semanticKey,
71
68
  operation,
72
69
  objective: 'Verify WorkContract and Process Runtime recovery without ExecutionJobs',
70
+ workKind: 'completed_no_change' as const,
73
71
  checks: [],
74
72
  };
75
73
  const accepted = acceptSubmittedWorkContract(controllerHome, request);
@@ -89,13 +87,6 @@ try {
89
87
  sessionId: 'session-recovery-a',
90
88
  leaseMs: 60_000,
91
89
  });
92
- // Recovery smoke follows the same Work-only phase API enforced in production.
93
- transitionWorkContractPhase({ controllerHome, repoId: repository.repoId }, accepted.contract.workId, {
94
- phase: 'implementation',
95
- status: 'running',
96
- state: 'active',
97
- summary: 'Process Runtime recovery smoke started implementation.',
98
- });
99
90
  const handle = await spawnManagedProcess({
100
91
  controllerHome,
101
92
  repoId: repository.repoId,
@@ -135,42 +126,13 @@ try {
135
126
  assert(getControllerSession({ controllerHome, repoId: repository.repoId }, accepted.contract.workId)?.sessionId === 'session-recovery-b', 'replacement Controller session missing');
136
127
  const completionRecordedAt = new Date().toISOString();
137
128
  const completionRevision = String(spawnSync('git', ['-C', repoRoot, 'rev-parse', 'HEAD'], { encoding: 'utf8' }).stdout).trim();
138
- transitionWorkContractPhase({ controllerHome, repoId: repository.repoId }, accepted.contract.workId, {
139
- phase: 'verification',
140
- status: 'running',
141
- state: 'satisfied',
142
- summary: 'Recovered Process completed successfully for the exact no-change candidate.',
143
- });
144
- requestWorkImplementationReview(
145
- { controllerHome, repoId: repository.repoId },
146
- accepted.contract.workId,
147
- 'Recovery smoke verification completed; implementation review is required before completion.',
148
- );
149
- recordWorkImplementationReview({ controllerHome, repoId: repository.repoId }, accepted.contract.workId, {
150
- schemaVersion: 1,
151
- reviewId: `REV-smoke-${accepted.contract.workId}`,
152
- workId: accepted.contract.workId,
153
- reviewerPrincipalId: replacement.principalId ?? replacement.controllerId,
154
- reviewerControllerSessionId: replacement.sessionId,
155
- decision: 'approved',
156
- rationale: 'Recovery smoke reviewed the exact recovered no-change candidate before terminal completion.',
157
- findings: [],
158
- sourceRevision: completionRevision,
159
- workspaceFingerprint: 'runtime-recovery-smoke-no-change-content',
160
- verificationWorkspaceFingerprint: 'runtime-recovery-smoke-no-change-verification',
161
- changedPaths: [],
162
- changedPathDigest: implementationReviewChangedPathDigest([]),
163
- acceptanceCriteriaSummary: 'Managed Process recovery, Controller reclaim, and no-change Work completion remain coherent.',
164
- verificationEvidence: [],
165
- architectureEvidence: [],
166
- recordedAt: completionRecordedAt,
167
- });
129
+ const completionReceiptId = `REC-smoke-${accepted.contract.workId}`;
168
130
  recordWorkCompletionReceipt(
169
131
  { controllerHome, repoId: repository.repoId },
170
132
  accepted.contract.workId,
171
133
  {
172
134
  schemaVersion: 1,
173
- receiptId: `REC-smoke-${accepted.contract.workId}`,
135
+ receiptId: completionReceiptId,
174
136
  source: 'direct_edit',
175
137
  issueId: 'ISS-runtime-recovery-smoke',
176
138
  taskId: 'T1',
@@ -186,7 +148,14 @@ try {
186
148
  'completed_no_change',
187
149
  'completed_no_change',
188
150
  );
189
- assert(getWorkContract({ controllerHome, repoId: repository.repoId }, accepted.contract.workId)?.status === 'completed', 'completed WorkContract was not persisted');
151
+ const delivered = getWorkContract({ controllerHome, repoId: repository.repoId }, accepted.contract.workId);
152
+ assert(delivered?.semanticState !== 'completed', 'delivery receipt must not implicitly complete semantic Work');
153
+ reviseWorkSemanticContext(
154
+ { controllerHome, repoId: repository.repoId },
155
+ accepted.contract.workId,
156
+ { expectedRevision: Number(delivered?.semanticRevision ?? 1), state: 'completed', resultRefs: [`receipt:${completionReceiptId}`] },
157
+ );
158
+ assert(getWorkContract({ controllerHome, repoId: repository.repoId }, accepted.contract.workId)?.semanticState === 'completed', 'explicit semantic Work completion was not persisted');
190
159
  assert(listExecutionJobs(controllerHome, repository.repoId, 20).length === 0, 'runtime recovery created an ExecutionJob');
191
160
 
192
161
  const scheduleInput = {
@@ -71,8 +71,8 @@ try {
71
71
  manualOccurrence?.status === 'skipped'
72
72
  && manualOccurrence.decision === 'operation_blocked'
73
73
  && manualOccurrence.decisionId
74
- && manualOccurrence.handoffId,
75
- 'manual semantic Schedule did not create an external-controller handoff',
74
+ && !manualOccurrence.handoffId,
75
+ 'manual semantic Schedule manufactured a human blocker instead of recording a trigger',
76
76
  );
77
77
  assert(
78
78
  getScheduleDecision(controllerHome, repository.repoId, manualOccurrence.decisionId)?.decision === 'operation_blocked',
@@ -105,7 +105,7 @@ try {
105
105
  { source: 'repository-event', eventName: 'git.push', eventId: 'evt-1' },
106
106
  );
107
107
  assert(eventA?.occurrenceId === eventB?.occurrenceId, 'repository event was not idempotent');
108
- assert(eventA?.handoffId === eventB?.handoffId, 'repository event created duplicate handoffs');
108
+ assert(eventA?.decisionId === eventB?.decisionId, 'repository event created a duplicate occurrence decision');
109
109
 
110
110
  const missingDependency = createSchedule(controllerHome, {
111
111
  ...semanticBase,
@@ -132,8 +132,8 @@ try {
132
132
  assert(
133
133
  conditionOccurrence?.status === 'skipped'
134
134
  && conditionOccurrence.decision === 'operation_blocked'
135
- && conditionOccurrence.handoffId,
136
- 'condition Schedule did not create an external-controller handoff',
135
+ && !conditionOccurrence.handoffId,
136
+ 'condition Schedule manufactured a human blocker instead of recording a trigger',
137
137
  );
138
138
 
139
139
  const cron = createSchedule(controllerHome, {
@@ -143,7 +143,7 @@ try {
143
143
  trigger: { type: 'cron', cronExpression: '* * * * *' },
144
144
  });
145
145
  const cronOccurrence = await evaluateSchedule(controllerHome, cron);
146
- assert(cronOccurrence?.decision === 'operation_blocked' && cronOccurrence.handoffId, 'cron Schedule did not hand off');
146
+ assert(cronOccurrence?.decision === 'operation_blocked' && !cronOccurrence.handoffId, 'cron Schedule did not record a bounded trigger');
147
147
 
148
148
  const calendar = createSchedule(controllerHome, {
149
149
  ...semanticBase,
@@ -153,8 +153,8 @@ try {
153
153
  });
154
154
  const calendarOccurrence = await evaluateSchedule(controllerHome, calendar);
155
155
  assert(
156
- calendarOccurrence?.decision === 'operation_blocked' && calendarOccurrence.handoffId,
157
- 'calendar Schedule did not hand off',
156
+ calendarOccurrence?.decision === 'operation_blocked' && !calendarOccurrence.handoffId,
157
+ 'calendar Schedule did not record a bounded trigger',
158
158
  );
159
159
 
160
160
  const staleJobPath = writeLocalJob('JOB-stale', {
@@ -231,9 +231,9 @@ try {
231
231
  assert(
232
232
  blockedOccurrence?.status === 'skipped'
233
233
  && blockedOccurrence.decision === 'maintenance_not_ready'
234
- && blockedOccurrence.handoffId
234
+ && !blockedOccurrence.handoffId
235
235
  && !blockedOccurrence.jobId,
236
- 'unsafe maintenance candidate did not create a bounded handoff',
236
+ 'retryable maintenance blocker was incorrectly promoted to a human handoff',
237
237
  );
238
238
  assert(readFileSync(brokenJobPath, 'utf8') === brokenBefore, 'blocked maintenance modified an unreadable candidate');
239
239
  const backedOff = getSchedule(controllerHome, repository.repoId, blockedMaintenance.scheduleId);
@@ -243,17 +243,25 @@ try {
243
243
  );
244
244
 
245
245
  const handoffs = listHandoffItems({ controllerHome, repoId: repository.repoId, status: 'all' });
246
- assert(handoffs.length >= 6, 'expected external-controller and maintenance handoffs were not persisted');
246
+ // Semantic Schedule triggers are continuation input, not human blockers. Only
247
+ // a real authorization/judgement boundary may persist a Handoff projection.
248
+ assert(
249
+ !manualOccurrence.handoffId && !conditionOccurrence.handoffId && !cronOccurrence.handoffId && !calendarOccurrence.handoffId,
250
+ 'semantic Schedule triggers manufactured human blockers',
251
+ );
252
+ assert(
253
+ !blockedOccurrence.handoffId && handoffs.length === 0,
254
+ 'retryable mechanical maintenance failure manufactured a human blocker',
255
+ );
247
256
  assert(listExecutionJobs(controllerHome, repository.repoId, 100).length === 0, 'Schedule smoke created an ExecutionJob');
248
257
 
249
258
  console.log(JSON.stringify({
250
259
  status: 'ok',
251
- manualHandoff: manualOccurrence.handoffId,
260
+ manualTriggerRecorded: manualOccurrence.decisionId,
252
261
  repositoryEventIdempotent: eventA?.occurrenceId === eventB?.occurrenceId,
253
262
  missingDependencySuppressed: true,
254
- conditionHandoff: conditionOccurrence.handoffId,
255
- cronHandoff: cronOccurrence.handoffId,
256
- calendarHandoff: calendarOccurrence.handoffId,
263
+ semanticScheduleHandoffs: 0,
264
+ maintenanceMechanicalBlockerHasHandoff: Boolean(blockedOccurrence.handoffId),
257
265
  maintenance: maintenanceOccurrence.status,
258
266
  maintenanceBackoffUntil: backedOff.nextEligibleAt,
259
267
  handoffCount: handoffs.length,