@moretea-labs/forge 1.7.2 → 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 (900) hide show
  1. package/AGENTS.md +121 -62
  2. package/CHANGELOG.md +40 -0
  3. package/CLAUDE.md +57 -62
  4. package/CONTRIBUTING.md +3 -2
  5. package/README.md +2 -2
  6. package/SKILL.md +0 -1
  7. package/THIRD_PARTY_NOTICES.md +5 -2
  8. package/adapters/browser/index.ts +2 -0
  9. package/adapters/chatgpt/browser-delivery-host.ts +77 -0
  10. package/adapters/chatgpt/browser-delivery-runtime.ts +1256 -0
  11. package/adapters/chatgpt/controller-binding-store.ts +134 -0
  12. package/adapters/chatgpt/controller-round-host.ts +68 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +99 -0
  14. package/adapters/chatgpt/provider-delivery.ts +340 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +218 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  18. package/adapters/computer/chatgpt-target-router.ts +103 -0
  19. package/adapters/computer/chrome-extension/background.js +385 -0
  20. package/adapters/computer/chrome-extension/content.js +378 -0
  21. package/adapters/computer/chrome-extension/core.js +24 -0
  22. package/adapters/computer/chrome-extension/manifest.json +30 -0
  23. package/adapters/computer/desktop-operator-contract.ts +7 -0
  24. package/adapters/computer/desktop-operator-discovery.ts +181 -0
  25. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  26. package/adapters/computer/desktop-operator-provider.ts +312 -0
  27. package/adapters/computer/index.ts +1 -0
  28. package/adapters/computer/interaction-target-authority.ts +1068 -0
  29. package/adapters/controller-process/binding-store.ts +34 -0
  30. package/adapters/controller-process/controller-host.ts +26 -0
  31. package/adapters/mcp/access-mode.ts +132 -0
  32. package/adapters/mcp/audit.ts +32 -0
  33. package/adapters/mcp/auth.ts +406 -0
  34. package/adapters/mcp/instructions.ts +37 -0
  35. package/adapters/mcp/legacy-context.ts +18 -0
  36. package/adapters/mcp/multi-repository.ts +421 -0
  37. package/adapters/mcp/oauth.ts +464 -0
  38. package/adapters/mcp/paths.ts +143 -0
  39. package/adapters/mcp/policy.ts +232 -0
  40. package/adapters/mcp/proxy-env.ts +62 -0
  41. package/adapters/mcp/readiness-projection.ts +24 -0
  42. package/adapters/mcp/redaction.ts +21 -0
  43. package/adapters/mcp/repo.ts +24 -0
  44. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  45. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  46. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  47. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  48. package/adapters/mcp/runtime-gateway/context-adapter.ts +1167 -0
  49. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  50. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +206 -0
  51. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  52. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +130 -0
  53. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  54. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  55. package/adapters/mcp/runtime-gateway/execution-tools.ts +173 -0
  56. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  57. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +412 -0
  58. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  59. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  60. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  61. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  62. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +380 -0
  63. package/adapters/mcp/runtime-gateway/process-tools.ts +457 -0
  64. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +88 -0
  65. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +285 -0
  66. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  67. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  68. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +79 -0
  69. package/adapters/mcp/runtime-gateway/result-adapter.ts +114 -0
  70. package/adapters/mcp/runtime-gateway/router.ts +242 -0
  71. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  72. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1200 -0
  73. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  74. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +574 -0
  75. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  76. package/adapters/mcp/runtime-gateway/runtime-tools.ts +78 -0
  77. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +187 -0
  78. package/adapters/mcp/runtime-gateway/shared-adapter.ts +45 -0
  79. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +962 -0
  80. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  81. package/adapters/mcp/runtime-gateway/work-adapter.ts +325 -0
  82. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  83. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  84. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  85. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  86. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  87. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  88. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  89. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  90. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  91. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  92. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  93. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  94. package/adapters/mcp/server.ts +1092 -0
  95. package/adapters/mcp/setup.ts +789 -0
  96. package/adapters/mcp/tool-capability-cache.ts +87 -0
  97. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  98. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5139 -0
  99. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +145 -0
  100. package/adapters/mcp/tool-mapping/repository-tools.ts +1682 -0
  101. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  102. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  103. package/adapters/mcp/toolset-names.ts +79 -0
  104. package/adapters/mcp/toolset-selection.ts +41 -0
  105. package/adapters/mcp/toolset.ts +337 -0
  106. package/adapters/mcp/transports/http-observation.ts +365 -0
  107. package/adapters/mcp/transports/http.ts +933 -0
  108. package/adapters/mcp/transports/oauth-http.ts +322 -0
  109. package/adapters/mcp/transports/session-registry.ts +519 -0
  110. package/adapters/mcp/transports/stdio.ts +8 -0
  111. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +223 -0
  112. package/adapters/mcp/types.ts +41 -0
  113. package/assets/AGENTS.md +2 -16
  114. package/assets/CLAUDE.md +2 -16
  115. package/assets/hooks/AGENTS.md +3 -14
  116. package/assets/hooks/CLAUDE.md +3 -14
  117. package/assets/hooks/hook-input.sh +9 -2
  118. package/assets/hooks/lib/workflow-state.sh +28 -10
  119. package/assets/hooks/prompt-guard.sh +63 -37
  120. package/assets/hooks/security-sentinel.sh +2 -1
  121. package/assets/hooks/session-start-context.sh +7 -5
  122. package/assets/hooks/stop-orchestrator.sh +13 -3
  123. package/assets/initializer-question-pack.v4.json +11 -7
  124. package/assets/partials/05-workflow.partial.md +18 -73
  125. package/assets/partials/07-footer.partial.md +1 -1
  126. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  127. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  128. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  129. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  130. package/assets/plan-map.json +11 -11
  131. package/assets/plugin-registry.v1.json +11 -3
  132. package/assets/plugin-trust-policy.v1.json +6 -0
  133. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  134. package/assets/recovery/forge-wsl-rescue +271 -0
  135. package/assets/reference-configs/agentic-development-flow.md +25 -0
  136. package/assets/reference-configs/development-protocol.md +11 -15
  137. package/assets/reference-configs/document-generation.md +1 -1
  138. package/assets/reference-configs/global-working-rules.md +28 -1
  139. package/assets/reference-configs/harness-overview.md +22 -112
  140. package/assets/reference-configs/hook-operations.md +1 -1
  141. package/assets/reference-configs/sprint-contracts.md +2 -2
  142. package/assets/skill-version.json +2 -2
  143. package/assets/templates/helpers/architecture-event.ts +3 -34
  144. package/assets/templates/helpers/architecture-queue.sh +61 -10
  145. package/assets/templates/helpers/archive-workflow.sh +90 -180
  146. package/assets/templates/helpers/capability-config.ts +8 -11
  147. package/assets/templates/helpers/capability-resolver.ts +37 -19
  148. package/assets/templates/helpers/capture-plan.sh +2 -2
  149. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  150. package/assets/templates/helpers/check-task-sync.sh +82 -11
  151. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  152. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  153. package/assets/templates/helpers/contract-worktree.sh +26 -24
  154. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  155. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  156. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  157. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  158. package/assets/templates/helpers/new-plan.sh +2 -2
  159. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  160. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  161. package/assets/templates/helpers/switch-plan.sh +1 -1
  162. package/assets/templates/helpers/workflow-contract.ts +1 -0
  163. package/assets/workflow-contract.v1.json +63 -171
  164. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  165. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  166. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  167. package/docs/architecture/CURRENT.md +233 -28
  168. package/docs/architecture/EVOLUTION.md +13 -0
  169. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  170. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  171. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  172. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  173. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  174. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  175. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +37 -0
  176. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +311 -0
  177. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  178. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  179. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  180. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  181. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  182. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  183. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  184. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  185. package/docs/architecture/domains/verification.md +8 -0
  186. package/docs/architecture/domains/workflow-engine.md +7 -1
  187. package/docs/architecture/index.md +3 -3
  188. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  189. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  190. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  191. package/docs/forge-plugin-management.md +20 -4
  192. package/docs/forge-runtime-self-healing-loop.md +2 -0
  193. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  194. package/docs/operations/controller-browser-plugin.md +3 -1
  195. package/docs/operations/controller-performance-and-502.md +17 -0
  196. package/docs/operations/controller-reliability-runbook.md +2 -2
  197. package/docs/operations/features.md +1 -1
  198. package/docs/operations/features.zh-CN.md +1 -1
  199. package/docs/operations/homebrew.md +2 -2
  200. package/docs/operations/mcp-tool-exposure.md +2 -0
  201. package/docs/operations/platform-support.md +16 -8
  202. package/docs/operations/platform-support.zh-CN.md +2 -2
  203. package/docs/operations/releasing.md +2 -0
  204. package/docs/operations/standalone-disaster-recovery.md +38 -5
  205. package/docs/operations/uu-remote-rescue.md +41 -0
  206. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  207. package/docs/public-usage-guide.md +1 -1
  208. package/docs/public-usage-guide.zh-CN.md +1 -1
  209. package/docs/tutorials/01-install-and-start.md +1 -1
  210. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  211. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  212. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  213. package/docs/wiki/Implementation.md +1 -1
  214. package/package.json +46 -26
  215. package/packages/kernel/cognition/api/index.ts +6 -0
  216. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  217. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  218. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  219. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  220. package/packages/kernel/cognition/domain/learning.ts +106 -0
  221. package/packages/kernel/cognition/domain/memory.ts +254 -0
  222. package/packages/kernel/controller/api/index.ts +3 -0
  223. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  224. package/packages/kernel/controller/application/controller-round-service.ts +41 -0
  225. package/packages/kernel/controller/application/controller-service.ts +30 -0
  226. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +529 -0
  227. package/packages/kernel/controller/domain/controller-round.ts +110 -0
  228. package/packages/kernel/controller/domain/execution-quality.ts +135 -0
  229. package/packages/kernel/controller/domain/types.ts +56 -0
  230. package/packages/kernel/controller/index.ts +1 -0
  231. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  232. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1970 -0
  233. package/packages/kernel/controller/infrastructure/controller-session-store.ts +804 -0
  234. package/packages/kernel/controller/ports/controller-host.ts +18 -0
  235. package/packages/kernel/goal/api/index.ts +1 -0
  236. package/packages/kernel/goal/domain/types.ts +40 -0
  237. package/packages/kernel/goal/index.ts +1 -0
  238. package/packages/kernel/identity/api/index.ts +15 -0
  239. package/packages/kernel/identity/application/identity-service.ts +67 -0
  240. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  241. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  242. package/packages/kernel/identity/domain/grant.ts +72 -0
  243. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  244. package/packages/kernel/identity/domain/scope.ts +63 -0
  245. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  246. package/packages/kernel/identity/domain/types.ts +44 -0
  247. package/packages/kernel/identity/domain/user-request.ts +93 -0
  248. package/packages/kernel/identity/domain/workspace.ts +56 -0
  249. package/packages/kernel/identity/index.ts +1 -0
  250. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  251. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  252. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  253. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  254. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  255. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  256. package/packages/kernel/memory/api/index.ts +5 -0
  257. package/packages/kernel/memory/application/experience-service.ts +118 -0
  258. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  259. package/packages/kernel/memory/domain/experience.ts +103 -0
  260. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  261. package/packages/kernel/memory/index.ts +1 -0
  262. package/packages/kernel/scheduler/api/index.ts +4 -0
  263. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  264. package/packages/kernel/scheduler/application/schedule-service.ts +27 -0
  265. package/packages/kernel/scheduler/application/settlement.ts +182 -0
  266. package/packages/kernel/scheduler/domain/schedule.ts +236 -0
  267. package/packages/kernel/scheduler/index.ts +1 -0
  268. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +805 -0
  269. package/packages/kernel/work/api/index.ts +16 -0
  270. package/packages/kernel/work/application/work-service.ts +123 -0
  271. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  272. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  273. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  274. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  275. package/packages/kernel/work/domain/engineering-design.ts +286 -0
  276. package/packages/kernel/work/domain/engineering-profile.ts +238 -0
  277. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  278. package/packages/kernel/work/domain/execution-concurrency.ts +247 -0
  279. package/packages/kernel/work/domain/execution-snapshot.ts +2 -0
  280. package/packages/kernel/work/domain/implementation-review.ts +193 -0
  281. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  282. package/packages/kernel/work/domain/project-engineering-contract.ts +224 -0
  283. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  284. package/{src/runtime/control-plane/facade/work-state-machine.ts → packages/kernel/work/domain/state-machine.ts} +37 -66
  285. package/packages/kernel/work/domain/types.ts +534 -0
  286. package/packages/kernel/work/index.ts +1 -0
  287. package/packages/kernel/work/infrastructure/work-contract-store.ts +1967 -0
  288. package/packages/kernel/work/ports/work-contract-store.ts +21 -0
  289. package/packages/plugin-runtime/browser/index.ts +3 -0
  290. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  291. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  292. package/packages/plugin-runtime/browser/session-authority.ts +62 -0
  293. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  294. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  295. package/packages/plugin-runtime/computer/index.ts +8 -0
  296. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  297. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  298. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  299. package/packages/plugin-runtime/computer/provider.ts +19 -0
  300. package/packages/plugin-runtime/computer/target-authority.ts +215 -0
  301. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  302. package/packages/plugin-runtime/external/index.ts +1 -0
  303. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +581 -0
  304. package/packages/plugin-runtime/index.ts +3 -0
  305. package/packages/protocols/browser/index.ts +1 -0
  306. package/packages/protocols/browser/session.ts +98 -0
  307. package/packages/protocols/computer/contract.ts +225 -0
  308. package/packages/protocols/computer/index.ts +1 -0
  309. package/packages/protocols/failure/contract.ts +158 -0
  310. package/packages/protocols/failure/index.ts +1 -0
  311. package/packages/protocols/handoff/index.ts +1 -0
  312. package/packages/protocols/handoff/status.ts +22 -0
  313. package/packages/protocols/mcp/execution-context.ts +11 -0
  314. package/packages/protocols/mcp/index.ts +2 -0
  315. package/packages/protocols/mcp/tool-contract.ts +42 -0
  316. package/packages/workflow-runtime/api/index.ts +2 -0
  317. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  318. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  319. package/packages/workflow-runtime/index.ts +1 -0
  320. package/scripts/activate-source-baseline.ts +7 -9
  321. package/scripts/assemble-template.ts +1 -1
  322. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  323. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  324. package/scripts/canary-controller-semantic-wait.ts +183 -0
  325. package/scripts/canary-global-hook.sh +2 -2
  326. package/scripts/check-mcp-compatibility.ts +85 -7
  327. package/scripts/check-platform-support.mjs +28 -2
  328. package/scripts/check-public-docs.sh +1 -1
  329. package/scripts/check-repository-hygiene.mjs +92 -0
  330. package/scripts/check-runtime-architecture.mjs +1643 -127
  331. package/scripts/check-source-duplication.mjs +9 -1
  332. package/scripts/controller-ngrok-rotation.sh +5 -4
  333. package/scripts/create-project-dirs.sh +10 -74
  334. package/scripts/forge-local-recovery-helper.mjs +282 -0
  335. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  336. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  337. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  338. package/scripts/hook-shim.sh +2 -2
  339. package/scripts/init-project.sh +12 -70
  340. package/scripts/install-desktop-operator-registration.ts +4 -2
  341. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  342. package/scripts/install-standalone-recovery.ts +122 -10
  343. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  344. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  345. package/scripts/lib/controller-home-env.sh +6 -3
  346. package/scripts/lib/project-init-lib.sh +42 -582
  347. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  348. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  349. package/scripts/open-source-audit-allowlist.txt +11 -1
  350. package/scripts/portability-bindings.mjs +70 -0
  351. package/scripts/run-bounded-command.mjs +60 -0
  352. package/scripts/run-bun-test-file.ts +22 -6
  353. package/scripts/run-governed-gate.ts +4 -2
  354. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  355. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  356. package/scripts/smoke-mcp-http-runtime.ts +6 -1
  357. package/scripts/smoke-runtime-recovery.ts +13 -11
  358. package/scripts/smoke-schedule-engine.ts +24 -16
  359. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  360. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  361. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  362. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  363. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  364. package/scripts/smoke-workflow-supervisor.ts +103 -0
  365. package/scripts/test-governance.ts +51 -2
  366. package/scripts/verify-forge-runtime.sh +2 -1
  367. package/src/cli/agent-jobs/executor-health.ts +11 -34
  368. package/src/cli/agent-jobs/integration.ts +18 -49
  369. package/src/cli/agent-jobs/job-manager.ts +17 -4
  370. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  371. package/src/cli/chatgpt-browser/binding.ts +20 -10
  372. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  373. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  374. package/src/cli/chatgpt-browser/engine.ts +10 -11
  375. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  376. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  377. package/src/cli/chatgpt-browser/types.ts +1 -0
  378. package/src/cli/commands/bootstrap-control.ts +334 -0
  379. package/src/cli/commands/brain-assistant.ts +52 -0
  380. package/src/cli/commands/brain.ts +191 -40
  381. package/src/cli/commands/chatgpt.ts +32 -67
  382. package/src/cli/commands/computer.ts +437 -0
  383. package/src/cli/commands/doctor.ts +18 -1
  384. package/src/cli/commands/init-hook.ts +71 -61
  385. package/src/cli/commands/init.ts +3 -1
  386. package/src/cli/commands/mcp.ts +16 -10
  387. package/src/cli/commands/plugin.ts +38 -12
  388. package/src/cli/commands/recovery.ts +507 -80
  389. package/src/cli/commands/runtime.ts +12 -7
  390. package/src/cli/commands/setup-profile.ts +97 -39
  391. package/src/cli/commands/status.ts +2 -1
  392. package/src/cli/controller/check-runner.ts +500 -100
  393. package/src/cli/controller/completion-backlog.ts +3 -3
  394. package/src/cli/controller/completion-orchestrator.ts +4 -43
  395. package/src/cli/controller/completion-target.ts +3 -72
  396. package/src/cli/controller/context/source-materializer.ts +81 -100
  397. package/src/cli/controller/context/types.ts +7 -1
  398. package/src/cli/controller/context-pack.ts +28 -6
  399. package/src/cli/controller/execution-completion.ts +4 -7
  400. package/src/cli/controller/execution-policy.ts +36 -153
  401. package/src/cli/controller/governance.ts +2 -3
  402. package/src/cli/controller/issue-store.ts +4 -99
  403. package/src/cli/controller/launch-agents.ts +59 -18
  404. package/src/cli/controller/operational-plan.ts +24 -51
  405. package/src/cli/controller/runtime-config.ts +5 -1
  406. package/src/cli/controller/stuck-state-migration.ts +2 -3
  407. package/src/cli/controller/systemd-user.ts +148 -0
  408. package/src/cli/controller/types.ts +10 -70
  409. package/src/cli/controller/worklog.ts +67 -13
  410. package/src/cli/editing/edit-operation-contract.ts +92 -0
  411. package/src/cli/editing/edit-session.ts +290 -20
  412. package/src/cli/github/plugin.ts +17 -12
  413. package/src/cli/hook/route-registry.ts +3 -5
  414. package/src/cli/hook/runtime.ts +49 -3
  415. package/src/cli/index.ts +3 -0
  416. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  417. package/src/cli/local-bridge/console-automations.ts +20 -15
  418. package/src/cli/local-bridge/console-view-models.ts +3 -12
  419. package/src/cli/local-bridge/facade-api.ts +105 -205
  420. package/src/cli/local-bridge/job-store.ts +1 -1
  421. package/src/cli/local-bridge/server.ts +48 -174
  422. package/src/cli/local-bridge/types.ts +0 -1
  423. package/src/cli/mcp/access-mode.ts +2 -132
  424. package/src/cli/mcp/access-tools.ts +2 -387
  425. package/src/cli/mcp/audit.ts +2 -32
  426. package/src/cli/mcp/auth.ts +2 -404
  427. package/src/cli/mcp/instructions.ts +2 -34
  428. package/src/cli/mcp/legacy-context.ts +2 -16
  429. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  430. package/src/cli/mcp/multi-repository.ts +2 -436
  431. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  432. package/src/cli/mcp/oauth.ts +2 -375
  433. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  434. package/src/cli/mcp/paths.ts +2 -140
  435. package/src/cli/mcp/policy.ts +2 -232
  436. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  437. package/src/cli/mcp/proxy-env.ts +2 -62
  438. package/src/cli/mcp/readiness-projection.ts +2 -24
  439. package/src/cli/mcp/redaction.ts +2 -21
  440. package/src/cli/mcp/repo.ts +2 -24
  441. package/src/cli/mcp/repository-tools.ts +2 -1613
  442. package/src/cli/mcp/server.ts +2 -951
  443. package/src/cli/mcp/setup.ts +2 -737
  444. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  445. package/src/cli/mcp/tool-contract.ts +2 -14
  446. package/src/cli/mcp/tools.ts +2 -9
  447. package/src/cli/mcp/toolset-names.ts +2 -70
  448. package/src/cli/mcp/toolset-selection.ts +2 -41
  449. package/src/cli/mcp/toolset.ts +2 -336
  450. package/src/cli/mcp/transports/AGENTS.md +1 -10
  451. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  452. package/src/cli/mcp/transports/http.ts +2 -1414
  453. package/src/cli/mcp/transports/session-registry.ts +2 -490
  454. package/src/cli/mcp/transports/stdio.ts +2 -8
  455. package/src/cli/mcp/types.ts +2 -41
  456. package/src/cli/mcp/umbrella-tools.ts +2 -117
  457. package/src/cli/repositories/command-executor.ts +91 -39
  458. package/src/cli/repositories/command-scope.ts +139 -4
  459. package/src/cli/repositories/controller-home.ts +167 -1
  460. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  461. package/src/cli/repositories/git-command-executor.ts +2 -2
  462. package/src/cli/repositories/identity.ts +13 -0
  463. package/src/cli/repositories/registry.ts +145 -60
  464. package/src/cli/repositories/repository-snapshot.ts +53 -7
  465. package/src/cli/repositories/runtime-storage.ts +27 -2
  466. package/src/cli/repositories/safe-patch.ts +34 -38
  467. package/src/cli/repositories/selected-path-actions.ts +22 -2
  468. package/src/cli/repositories/structured-git.ts +167 -27
  469. package/src/cli/repository/session-cache.ts +92 -6
  470. package/src/cli/runtime/helper-runner.ts +7 -0
  471. package/src/cli/runtime-invocation.ts +8 -1
  472. package/src/cli/tools/codegraph.ts +44 -25
  473. package/src/core/adoption/manifest-templates.ts +1 -1
  474. package/src/core/adoption/plan.ts +3 -26
  475. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  476. package/src/effects/process-runner.ts +8 -14
  477. package/src/runtime/context/assistant-context.ts +167 -0
  478. package/src/runtime/context/assistant-work-context.ts +209 -0
  479. package/src/runtime/context/automatic-learning.ts +565 -0
  480. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  481. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  482. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  483. package/src/runtime/context/cognitive-attention.ts +173 -0
  484. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  485. package/src/runtime/context/context-closure.ts +305 -0
  486. package/src/runtime/context/context-pack-process.ts +103 -0
  487. package/src/runtime/context/context-plane.ts +203 -0
  488. package/src/runtime/context/direct-controller-learning.ts +298 -0
  489. package/src/runtime/context/project-engineering-contract.ts +60 -0
  490. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  491. package/src/runtime/context/semantic-navigation.ts +6 -34
  492. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  493. package/src/runtime/context/typescript-navigation.ts +89 -3
  494. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  495. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  496. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  497. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  498. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  499. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  500. package/src/runtime/control-plane/cleanup-artifact-retention.ts +531 -0
  501. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  502. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +282 -0
  503. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +380 -0
  504. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +113 -16
  505. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  506. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  507. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  508. package/src/runtime/control-plane/execution/retained-work-resume.ts +439 -102
  509. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  510. package/src/runtime/control-plane/execution/validation.ts +34 -11
  511. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +87 -0
  512. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  513. package/src/runtime/control-plane/execution/work-completion-authority.ts +31 -44
  514. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  515. package/src/runtime/control-plane/execution/work-evidence-policy.ts +46 -53
  516. package/src/runtime/control-plane/execution/work-execution-support.ts +85 -164
  517. package/src/runtime/control-plane/execution/work-handle-authority.ts +349 -73
  518. package/src/runtime/control-plane/execution/work-handle-store.ts +55 -2
  519. package/src/runtime/control-plane/execution/work-head-settlement.ts +108 -0
  520. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +173 -28
  521. package/src/runtime/control-plane/execution/work-operation-service.ts +92 -40
  522. package/src/runtime/control-plane/execution/work-preparation-service.ts +145 -269
  523. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  524. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  525. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +543 -225
  526. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +59 -45
  527. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  528. package/src/runtime/control-plane/execution/work-verification-service.ts +662 -52
  529. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +205 -16
  530. package/src/runtime/control-plane/facade/capability-registry.ts +380 -44
  531. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  532. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  533. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  534. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  535. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -22
  536. package/src/runtime/control-plane/facade/goal-workloop.ts +565 -1202
  537. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +145 -0
  538. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +266 -52
  539. package/src/runtime/control-plane/facade/index.ts +4 -3
  540. package/src/runtime/control-plane/facade/operation-digest.ts +34 -73
  541. package/src/runtime/control-plane/facade/plan-contract-store.ts +671 -245
  542. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  543. package/src/runtime/control-plane/facade/repository-work-admission.ts +31 -23
  544. package/src/runtime/control-plane/facade/requirement-authority.ts +121 -0
  545. package/src/runtime/control-plane/facade/requirement-board.ts +9 -4
  546. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +85 -0
  547. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  548. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  549. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -15
  550. package/src/runtime/control-plane/facade/types.ts +218 -620
  551. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  552. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  553. package/src/runtime/control-plane/generated-cache-retention.ts +336 -19
  554. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  555. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +13 -2
  556. package/src/runtime/control-plane/global-scheduler/maintenance.ts +274 -84
  557. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  558. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  559. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -2
  560. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  561. package/src/runtime/control-plane/global-scheduler/scheduler.ts +227 -109
  562. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  563. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  564. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  565. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  566. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +160 -0
  567. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  568. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +139 -670
  569. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  570. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +25 -6
  571. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -194
  572. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  573. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  574. package/src/runtime/control-plane/persistence/experience-store.ts +302 -0
  575. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  576. package/src/runtime/control-plane/persistence/requirement-store.ts +230 -80
  577. package/src/runtime/control-plane/persistence/sqlite-store.ts +654 -78
  578. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  579. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  580. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  581. package/src/runtime/control-plane/release-retention.ts +154 -26
  582. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  583. package/src/runtime/control-plane/runtime-cleanup.ts +844 -38
  584. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  585. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  586. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +479 -0
  587. package/src/runtime/control-plane/workspace/workspace-store.ts +249 -0
  588. package/src/runtime/diagnostics/incident-repair.ts +573 -0
  589. package/src/runtime/diagnostics/mcp-timing.ts +239 -6
  590. package/src/runtime/diagnostics/performance.ts +6 -14
  591. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  592. package/src/runtime/evidence/artifact-store.ts +216 -35
  593. package/src/runtime/evidence/evidence-store.ts +112 -8
  594. package/src/runtime/evidence/operational-shadow.ts +38 -0
  595. package/src/runtime/evidence/output-handle-index.ts +225 -0
  596. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  597. package/src/runtime/evidence/result-store.ts +158 -44
  598. package/src/runtime/evidence/sensitive-output.ts +4 -4
  599. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  600. package/src/runtime/execution/jobs/store.ts +124 -6
  601. package/src/runtime/execution/managed-workspace.ts +112 -5
  602. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  603. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  604. package/src/runtime/execution/process-runtime/check-facade.ts +24 -10
  605. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  606. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  607. package/src/runtime/execution/process-runtime/check-result.ts +177 -2
  608. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +58 -9
  609. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  610. package/src/runtime/execution/process-runtime/command-facade.ts +117 -114
  611. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  612. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  613. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  614. package/src/runtime/execution/process-runtime/index.ts +4 -0
  615. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  616. package/src/runtime/execution/process-runtime/lightweight-managed.ts +283 -73
  617. package/src/runtime/execution/process-runtime/persisted-check.ts +130 -23
  618. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  619. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  620. package/src/runtime/execution/process-runtime/resource-claims.ts +125 -64
  621. package/src/runtime/execution/process-runtime/runtime.ts +167 -17
  622. package/src/runtime/execution/process-runtime/store.ts +30 -2
  623. package/src/runtime/execution/process-runtime/types.ts +27 -0
  624. package/src/runtime/execution/workers/executor.ts +18 -19
  625. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  626. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  627. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  628. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  629. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  630. package/src/runtime/gateway/mcp/router.ts +2 -1125
  631. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  632. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  633. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  634. package/src/runtime/maintenance/cleanup.ts +38 -24
  635. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  636. package/src/runtime/platform/computer-platform.ts +14 -0
  637. package/src/runtime/platform/executable-discovery.ts +54 -0
  638. package/src/runtime/platform/fetch-http-server.ts +90 -0
  639. package/src/runtime/platform/service-inventory.ts +130 -0
  640. package/src/runtime/platform/service-manager.ts +146 -0
  641. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  642. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  643. package/src/runtime/plugins/action-application.ts +192 -0
  644. package/src/runtime/plugins/app-store-connect-adapter.ts +47 -35
  645. package/src/runtime/plugins/browser-adapter.ts +898 -135
  646. package/src/runtime/plugins/browser-automation-service.ts +33 -34
  647. package/src/runtime/plugins/browser-macos-bridge.ts +386 -46
  648. package/src/runtime/plugins/browser-manifest-surface.ts +75 -17
  649. package/src/runtime/plugins/browser-native-session-service.ts +64 -14
  650. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  651. package/src/runtime/plugins/browser-registration.ts +32 -0
  652. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  653. package/src/runtime/plugins/browser-runtime.ts +55 -10
  654. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  655. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  656. package/src/runtime/plugins/browser-session-store.ts +243 -80
  657. package/src/runtime/plugins/browser-session-types.ts +2 -98
  658. package/src/runtime/plugins/capability-authorization-grants.ts +272 -59
  659. package/src/runtime/plugins/catalog-trust.ts +82 -0
  660. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  661. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  662. package/src/runtime/plugins/computer-registration.ts +1050 -0
  663. package/src/runtime/plugins/config-store.ts +119 -0
  664. package/src/runtime/plugins/desktop-operator-external-policy.ts +964 -0
  665. package/src/runtime/plugins/desktop-operator-registration.ts +123 -12
  666. package/src/runtime/plugins/errors.ts +8 -1
  667. package/src/runtime/plugins/external-adapter.ts +82 -323
  668. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  669. package/src/runtime/plugins/external-registration.ts +30 -2
  670. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  671. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  672. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  673. package/src/runtime/plugins/first-party-registry.ts +3 -1
  674. package/src/runtime/plugins/github-adapter.ts +1 -2
  675. package/src/runtime/plugins/gmail-adapter.ts +29 -8
  676. package/src/runtime/plugins/google-calendar-adapter.ts +8 -8
  677. package/src/runtime/plugins/google-shared.ts +45 -53
  678. package/src/runtime/plugins/google-tasks-adapter.ts +8 -8
  679. package/src/runtime/plugins/ios-adapter.ts +2 -3
  680. package/src/runtime/plugins/lightweight-action.ts +208 -2
  681. package/src/runtime/plugins/local-system-adapter.ts +192 -2
  682. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  683. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  684. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  685. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  686. package/src/runtime/plugins/resend-adapter.ts +15 -24
  687. package/src/runtime/plugins/store.ts +1003 -387
  688. package/src/runtime/plugins/types.ts +28 -1
  689. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  690. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  691. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  692. package/src/runtime/plugins/xiaohongshu-publish.ts +102 -430
  693. package/src/runtime/projections/controller-context.ts +12 -6
  694. package/src/runtime/projections/git-status-sampler.ts +73 -22
  695. package/src/runtime/projections/invalidation.ts +7 -3
  696. package/src/runtime/projections/materialized-view.ts +93 -43
  697. package/src/runtime/recovery/actions.ts +3 -3
  698. package/src/runtime/recovery/capability-action-application.ts +229 -0
  699. package/src/runtime/recovery/index.ts +3 -0
  700. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  701. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  702. package/src/runtime/recovery/maintenance-executor.ts +701 -168
  703. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  704. package/src/runtime/recovery/store.ts +29 -11
  705. package/src/runtime/release/identity.ts +6 -0
  706. package/src/runtime/release/release-coordinator.ts +296 -0
  707. package/src/runtime/release/release-session.ts +716 -0
  708. package/src/runtime/release/release-state-migration.ts +25 -0
  709. package/src/runtime/resources/leases/store.ts +56 -25
  710. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  711. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  712. package/src/runtime/root/browser-session-composition.ts +59 -0
  713. package/src/runtime/root/computer-composition.ts +376 -0
  714. package/src/runtime/root/computer-target-composition.ts +16 -0
  715. package/src/runtime/root/computer-target-persistence.ts +39 -0
  716. package/src/runtime/root/controller-progression-composition.ts +192 -0
  717. package/src/runtime/root/controller-round-composition.ts +126 -0
  718. package/src/runtime/root/controller-services.ts +2 -0
  719. package/src/runtime/root/deployment-topology.ts +106 -0
  720. package/src/runtime/root/entry.ts +8 -6
  721. package/src/runtime/root/gateway-adapter.ts +3 -3
  722. package/src/runtime/root/known-good-recovery.ts +184 -0
  723. package/src/runtime/root/local-bridge.ts +5 -3
  724. package/src/runtime/root/mcp-transport.ts +116 -23
  725. package/src/runtime/root/ownership.ts +261 -9
  726. package/src/runtime/root/package-connector-service.ts +212 -74
  727. package/src/runtime/root/package-runtime-release.ts +199 -33
  728. package/src/runtime/root/package-runtime-service.ts +77 -108
  729. package/src/runtime/root/release-execution-canary.ts +103 -0
  730. package/src/runtime/root/release-loader.ts +150 -0
  731. package/src/runtime/root/release-manifest.ts +185 -7
  732. package/src/runtime/root/release-materialize.ts +474 -31
  733. package/src/runtime/root/release-store.ts +425 -37
  734. package/src/runtime/root/runtime-lane.ts +191 -0
  735. package/src/runtime/root/runtime.ts +379 -32
  736. package/src/runtime/root/scheduled-controller-composition.ts +76 -0
  737. package/src/runtime/root/scheduler.ts +12 -4
  738. package/src/runtime/root/service-runner.ts +3 -3
  739. package/src/runtime/root/service.ts +73 -45
  740. package/src/runtime/root/status.ts +49 -0
  741. package/src/runtime/root/types.ts +55 -3
  742. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  743. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  744. package/src/runtime/root/write-fence.ts +50 -2
  745. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  746. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  747. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  748. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  749. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  750. package/src/runtime/shared/process-environment.ts +36 -10
  751. package/src/runtime/shared/response-budget.ts +1 -3
  752. package/src/runtime/shared/storage-capacity.ts +68 -0
  753. package/src/runtime/standalone-recovery/controller-home-migration.ts +1108 -0
  754. package/src/runtime/standalone-recovery/core.ts +4609 -495
  755. package/src/runtime/standalone-recovery/entry.ts +642 -81
  756. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  757. package/src/runtime/standalone-recovery/installer.ts +399 -177
  758. package/src/runtime/standalone-recovery/mcp-server.ts +79 -0
  759. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  760. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  761. package/src/runtime/standalone-recovery/performance.ts +173 -0
  762. package/src/runtime/standalone-recovery/release.ts +58 -5
  763. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  764. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  765. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  766. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  767. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -4
  768. package/src/runtime/workflow/schedules/engine.ts +298 -484
  769. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  770. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  771. package/src/runtime/workflow/schedules/store.ts +2 -607
  772. package/src/runtime/workflow/schedules/types.ts +2 -127
  773. package/src/runtime/workflow/schedules/work-continuation.ts +220 -16
  774. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  775. package/src/runtime/workflows/runtime.ts +482 -0
  776. package/src/testing/test-governance.ts +95 -30
  777. package/supervisor/chatgpt-conversation.ts +23 -0
  778. package/supervisor/client.ts +201 -0
  779. package/supervisor/control-plane.ts +868 -0
  780. package/supervisor/entry.ts +15 -0
  781. package/supervisor/forge-validators.ts +80 -0
  782. package/supervisor/index.ts +5 -0
  783. package/supervisor/native-browser-adapter.ts +786 -0
  784. package/supervisor/native-messaging/host.ts +39 -0
  785. package/supervisor/native-messaging/manifest.ts +26 -0
  786. package/supervisor/native-messaging/protocol.ts +27 -0
  787. package/supervisor/paths.ts +18 -0
  788. package/supervisor/protocol.ts +202 -0
  789. package/supervisor/server.ts +404 -0
  790. package/supervisor/store.ts +1451 -0
  791. package/supervisor/tsconfig.json +8 -0
  792. package/supervisor/types.ts +255 -0
  793. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  794. package/docs/architecture/history/README.md +0 -7
  795. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  796. package/docs/architecture/history/global-hook-runtime.md +0 -166
  797. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  798. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  799. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  800. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  801. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  802. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  803. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  804. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  805. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  806. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  807. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  808. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  809. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  810. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  811. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  812. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  813. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  814. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  815. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  816. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  817. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  818. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  819. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  820. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  821. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  822. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  823. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  824. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  825. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  826. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  827. package/docs/architecture/requests/archive/2026/root.md +0 -68
  828. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  829. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  830. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  831. package/scripts/archive-architecture-request.sh +0 -4
  832. package/scripts/benchmark-background-check-overlap.ts +0 -228
  833. package/scripts/benchmark-controller-hotpath.ts +0 -212
  834. package/scripts/benchmark-controller-round2.ts +0 -139
  835. package/scripts/benchmark-ios-agent-device.ts +0 -514
  836. package/scripts/benchmark-mcp-host.sh +0 -117
  837. package/scripts/benchmark-mcp-transport.ts +0 -170
  838. package/scripts/benchmark-quality-harness.ts +0 -146
  839. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  840. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  841. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  842. package/scripts/benchmark-thin-harness.ts +0 -251
  843. package/scripts/benchmark-typescript-navigation.ts +0 -186
  844. package/scripts/benchmark-work-efficiency.ts +0 -334
  845. package/scripts/build-controller-ui.ts +0 -28
  846. package/scripts/check-npm-release.sh +0 -32
  847. package/scripts/check-public-release-surface.sh +0 -19
  848. package/scripts/check-release-published.sh +0 -57
  849. package/scripts/check-release-readiness.sh +0 -37
  850. package/scripts/check-release-version.mjs +0 -74
  851. package/scripts/check-tarball-install-smoke.sh +0 -67
  852. package/scripts/package-source-archive.sh +0 -147
  853. package/scripts/public-release-files.txt +0 -39
  854. package/scripts/public-release.ts +0 -174
  855. package/scripts/publish-release-tarball.sh +0 -27
  856. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  857. package/scripts/run-skill-evals.ts +0 -1022
  858. package/scripts/stage-runtime-release.ts +0 -39
  859. package/src/cli/controller/progress.ts +0 -656
  860. package/src/cli/controller/work-mode.ts +0 -181
  861. package/src/cli/local-bridge/console-assets.ts +0 -17
  862. package/src/cli/local-bridge/dashboard.ts +0 -17
  863. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  864. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  865. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  866. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  867. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  868. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  869. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  870. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  871. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  872. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  873. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  874. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  875. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  876. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  877. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  878. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  879. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  880. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  881. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  882. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  883. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  884. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  885. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  886. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  887. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  888. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  889. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  890. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  891. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -385
  892. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -1913
  893. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  894. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -449
  895. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -1118
  896. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -93
  897. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  898. package/src/runtime/control-plane/routing/index.ts +0 -1
  899. package/src/runtime/control-plane/routing/route-policy.ts +0 -382
  900. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -0,0 +1,716 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from 'fs';
3
+ import { dirname, join, resolve } from 'path';
4
+ import { assertStorageHeadroom } from '../shared/storage-capacity';
5
+ import type { CandidateExecutionLane, StableExecutionLane } from '../root/runtime-lane';
6
+ import type { RuntimePublishedRelease, RuntimeReleaseAuthority } from '../root/release-store';
7
+
8
+ export const RELEASE_SESSION_PHASES = [
9
+ 'source_frozen',
10
+ 'built',
11
+ 'static_verified',
12
+ 'candidate_booted',
13
+ 'candidate_verified',
14
+ 'cutover_eligible',
15
+ 'cutover_attempting',
16
+ 'cutover_committed',
17
+ 'soaking',
18
+ 'known_good',
19
+ 'rolled_back',
20
+ 'failed',
21
+ ] as const;
22
+
23
+ export type ReleaseSessionPhase = (typeof RELEASE_SESSION_PHASES)[number];
24
+
25
+ export interface ReleaseSessionStableRelease {
26
+ authorityRevision: number;
27
+ releaseId: string;
28
+ artifactIdentity: string;
29
+ manifestSha256: string;
30
+ workerProtocolVersion: number;
31
+ releaseFencingTokenSha256: string;
32
+ }
33
+
34
+ export interface ReleaseSessionCandidateRelease {
35
+ releaseId: string;
36
+ manifestPath: string;
37
+ artifactIdentity: string;
38
+ manifestSha256: string;
39
+ treeSha256: string;
40
+ sourceCommit: string;
41
+ sourceRepositoryId?: string;
42
+ }
43
+
44
+ export interface ReleaseSessionReceipt {
45
+ id: string;
46
+ kind: 'source' | 'build' | 'static_gate' | 'candidate_canary' | 'cutover' | 'soak' | 'known_good' | 'rollback';
47
+ recordedAt: string;
48
+ summary: string;
49
+ }
50
+
51
+ /**
52
+ * Durable semantic rollback authority for one ReleaseSession after physical
53
+ * cutover has published Candidate B. RuntimeReleaseAuthority stores only
54
+ * physical active/previous release identity and backing artifacts; rollback
55
+ * eligibility and transaction semantics live only in this ReleaseSession.
56
+ */
57
+ export interface ReleaseSessionTransaction {
58
+ schemaVersion: 1;
59
+ operationId: string;
60
+ candidateReleaseId: string;
61
+ cutoverAuthorityRevision: number;
62
+ rollbackRelease: RuntimePublishedRelease;
63
+ startedAt: string;
64
+ }
65
+
66
+ /**
67
+ * Runtime startup migration may persist the exact cutover transaction between
68
+ * activation and Recovery's post-start receipt. Operation ids and timestamps
69
+ * are writer-local evidence, so the semantic transaction identity excludes
70
+ * those fields while retaining every release/authority identity that fences a
71
+ * different cutover.
72
+ */
73
+ function sameReleaseSessionTransactionIdentity(
74
+ left: ReleaseSessionTransaction,
75
+ right: ReleaseSessionTransaction,
76
+ ): boolean {
77
+ return left.schemaVersion === right.schemaVersion
78
+ && left.candidateReleaseId === right.candidateReleaseId
79
+ && left.cutoverAuthorityRevision === right.cutoverAuthorityRevision
80
+ && left.rollbackRelease.releaseId === right.rollbackRelease.releaseId
81
+ && left.rollbackRelease.artifactIdentity === right.rollbackRelease.artifactIdentity
82
+ && left.rollbackRelease.manifestPath === right.rollbackRelease.manifestPath
83
+ && left.rollbackRelease.manifestSha256 === right.rollbackRelease.manifestSha256
84
+ && left.rollbackRelease.workerProtocolVersion === right.rollbackRelease.workerProtocolVersion
85
+ && left.rollbackRelease.publishedAt === right.rollbackRelease.publishedAt
86
+ && left.rollbackRelease.databaseBackup?.path === right.rollbackRelease.databaseBackup?.path
87
+ && left.rollbackRelease.databaseBackup?.schemaVersion === right.rollbackRelease.databaseBackup?.schemaVersion
88
+ && left.rollbackRelease.databaseBackup?.createdAt === right.rollbackRelease.databaseBackup?.createdAt
89
+ && left.rollbackRelease.databaseBackup?.auditEventCount === right.rollbackRelease.databaseBackup?.auditEventCount
90
+ && left.rollbackRelease.databaseBackup?.recordCount === right.rollbackRelease.databaseBackup?.recordCount;
91
+ }
92
+
93
+ export interface ReleaseSession {
94
+ /** Wire/storage schema remains readable by the previous Recovery release. */
95
+ schemaVersion: 1;
96
+ /** Current semantic model. Legacy records omit this field (or carry epoch 1). */
97
+ semanticEpoch: 2;
98
+ sessionId: string;
99
+ stable: StableExecutionLane;
100
+ stableRelease: ReleaseSessionStableRelease;
101
+ candidate: CandidateExecutionLane;
102
+ candidateRelease?: ReleaseSessionCandidateRelease;
103
+ transaction?: ReleaseSessionTransaction;
104
+ sourceRevision: string;
105
+ phase: ReleaseSessionPhase;
106
+ revision: number;
107
+ receipts: ReleaseSessionReceipt[];
108
+ createdAt: string;
109
+ updatedAt: string;
110
+ }
111
+
112
+ const REQUIRED_STATIC_GATES = new Set(['type', 'runtime_architecture', 'architecture_sync', 'bootstrap']);
113
+ const REQUIRED_CANDIDATE_CANARIES = new Set(['recovery', 'mcp', 'scheduler', 'supervisor', 'controller']);
114
+ const REQUIRED_KNOWN_GOOD_SOAK_GATES = new Set(['supervisor_continuation_proof']);
115
+
116
+ function sessionPath(controllerHome: string, sessionId: string): string {
117
+ return join(resolve(controllerHome), 'recovery', 'state', 'release-sessions', `${sessionId}.json`);
118
+ }
119
+
120
+ function validSessionId(value: string): string {
121
+ const sessionId = value.trim();
122
+ if (!/^[A-Za-z0-9][A-Za-z0-9_-]{7,119}$/.test(sessionId)) throw new Error('RELEASE_SESSION_ID_INVALID');
123
+ return sessionId;
124
+ }
125
+
126
+ function writeSession(path: string, session: ReleaseSession): void {
127
+ const content = `${JSON.stringify(session, null, 2)}\n`;
128
+ assertStorageHeadroom(path, { operation: 'release_session_write', requiredBytes: Buffer.byteLength(content), reserveBytes: 16 * 1024 * 1024 });
129
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
130
+ const temporary = `${path}.${process.pid}.${randomUUID().slice(0, 8)}.tmp`;
131
+ writeFileSync(temporary, content, { encoding: 'utf8', mode: 0o600 });
132
+ renameSync(temporary, path);
133
+ invalidateCompleteReleaseSessionInventory(dirname(path));
134
+ }
135
+
136
+ function sameStableRelease(session: Pick<ReleaseSession, 'stableRelease'>, release: RuntimePublishedRelease): boolean {
137
+ return release.releaseId === session.stableRelease.releaseId
138
+ && release.artifactIdentity === session.stableRelease.artifactIdentity
139
+ && release.manifestSha256 === session.stableRelease.manifestSha256
140
+ && release.workerProtocolVersion === session.stableRelease.workerProtocolVersion;
141
+ }
142
+
143
+ function validTransaction(session: ReleaseSession): boolean {
144
+ const transaction = session.transaction;
145
+ if (!transaction) return !['cutover_committed', 'soaking'].includes(session.phase);
146
+ const rollback = transaction.rollbackRelease;
147
+ return transaction.schemaVersion === 1
148
+ && Boolean(transaction.operationId?.trim())
149
+ && Boolean(session.candidateRelease)
150
+ && transaction.candidateReleaseId === session.candidateRelease!.releaseId
151
+ && Number.isInteger(transaction.cutoverAuthorityRevision)
152
+ && transaction.cutoverAuthorityRevision > session.stableRelease.authorityRevision
153
+ && Number.isFinite(Date.parse(transaction.startedAt))
154
+ && sameStableRelease(session, rollback)
155
+ && Boolean(rollback.manifestPath?.trim())
156
+ && Number.isFinite(Date.parse(rollback.publishedAt))
157
+ && Boolean(rollback.databaseBackup)
158
+ && resolve(rollback.databaseBackup!.path) === rollback.databaseBackup!.path
159
+ && Number.isInteger(rollback.databaseBackup!.schemaVersion)
160
+ && rollback.databaseBackup!.schemaVersion > 0
161
+ && Number.isFinite(Date.parse(rollback.databaseBackup!.createdAt));
162
+ }
163
+
164
+ function assertCurrentSession(value: ReleaseSession, sessionId: string): ReleaseSession {
165
+ if (
166
+ value.schemaVersion !== 1
167
+ || value.semanticEpoch !== 2
168
+ || value.sessionId !== sessionId
169
+ || !RELEASE_SESSION_PHASES.includes(value.phase)
170
+ || !Number.isInteger(value.revision)
171
+ || value.revision < 1
172
+ || !validTransaction(value)
173
+ ) throw new Error('RELEASE_SESSION_INVALID');
174
+ return value;
175
+ }
176
+
177
+ export interface ReleaseSessionStateMigration {
178
+ migratedSessionIds: string[];
179
+ currentSessionIds: string[];
180
+ inspected: number;
181
+ }
182
+
183
+ type LegacyReleaseSessionV1 = Omit<ReleaseSession, 'semanticEpoch' | 'transaction'> & {
184
+ schemaVersion: 1;
185
+ semanticEpoch?: 1;
186
+ };
187
+
188
+ type TransitionalReleaseSessionV2 = Omit<ReleaseSession, 'schemaVersion' | 'semanticEpoch'> & {
189
+ schemaVersion: 2;
190
+ semanticEpoch?: never;
191
+ };
192
+
193
+ type MigratableReleaseSession = ReleaseSession | LegacyReleaseSessionV1 | TransitionalReleaseSessionV2;
194
+
195
+ function releaseIdentityKey(release: {
196
+ releaseId?: string;
197
+ artifactIdentity?: string;
198
+ manifestSha256?: string;
199
+ } | undefined): string | undefined {
200
+ const releaseId = release?.releaseId?.trim() || '';
201
+ const artifactIdentity = release?.artifactIdentity?.trim() || '';
202
+ const manifestSha256 = release?.manifestSha256?.trim() || '';
203
+ if (!releaseId || !artifactIdentity || !manifestSha256) return undefined;
204
+ return `${releaseId}\u0000${artifactIdentity}\u0000${manifestSha256}`;
205
+ }
206
+
207
+ function basicMigratableSessionShape(raw: MigratableReleaseSession, id: string): boolean {
208
+ const schemaSupported = (raw.schemaVersion === 1 && (raw.semanticEpoch === undefined || raw.semanticEpoch === 1 || raw.semanticEpoch === 2))
209
+ || (raw.schemaVersion === 2 && raw.semanticEpoch === undefined);
210
+ return schemaSupported
211
+ && raw.sessionId === id
212
+ && RELEASE_SESSION_PHASES.includes(raw.phase)
213
+ && Number.isFinite(Date.parse(raw.createdAt))
214
+ && Number.isFinite(Date.parse(raw.updatedAt));
215
+ }
216
+
217
+ function historicalAcceptanceReceipt(
218
+ sessionId: string,
219
+ recordedAt: string,
220
+ proof: string,
221
+ ): ReleaseSessionReceipt {
222
+ return {
223
+ id: `migration:historical-known-good:${sessionId}`,
224
+ kind: 'known_good',
225
+ recordedAt,
226
+ summary: `Legacy soaking state reconciled as known-good from exact durable release lineage: ${proof}.`,
227
+ };
228
+ }
229
+
230
+ export function migrateReleaseSessionState(
231
+ controllerHome: string,
232
+ dependencies: { readAuthority?: () => RuntimeReleaseAuthority | undefined } = {},
233
+ ): ReleaseSessionStateMigration {
234
+ const root = dirname(sessionPath(controllerHome, 'release-session-migration'));
235
+ if (!existsSync(root)) return { migratedSessionIds: [], currentSessionIds: [], inspected: 0 };
236
+ const authority = dependencies.readAuthority?.();
237
+ const migratedSessionIds: string[] = [];
238
+ const currentSessionIds: string[] = [];
239
+ const names = readdirSync(root).filter((name) => name.endsWith('.json')).sort();
240
+ const parsed = names.map((name) => {
241
+ const id = name.slice(0, -'.json'.length);
242
+ const path = sessionPath(controllerHome, validSessionId(id));
243
+ try {
244
+ return { id, path, raw: JSON.parse(readFileSync(path, 'utf8')) as MigratableReleaseSession };
245
+ } catch {
246
+ throw new Error(`RELEASE_SESSION_MIGRATION_INVALID_JSON: ${id}`);
247
+ }
248
+ });
249
+ const stableSuccessors = new Map<string, Array<{ sessionId: string; createdAt: string }>>();
250
+ for (const entry of parsed) {
251
+ if (!basicMigratableSessionShape(entry.raw, entry.id)) continue;
252
+ const stableKey = releaseIdentityKey(entry.raw.stableRelease);
253
+ if (!stableKey) continue;
254
+ const existing = stableSuccessors.get(stableKey) ?? [];
255
+ existing.push({ sessionId: entry.id, createdAt: entry.raw.createdAt });
256
+ stableSuccessors.set(stableKey, existing);
257
+ }
258
+ const activeKey = releaseIdentityKey(authority?.active);
259
+ const previousKey = releaseIdentityKey(authority?.previous);
260
+
261
+ for (const { id, path, raw } of parsed) {
262
+ if (raw.schemaVersion === 1 && raw.semanticEpoch === 2) {
263
+ let current = raw as ReleaseSession;
264
+ if (
265
+ !current.transaction
266
+ && current.phase === 'cutover_attempting'
267
+ && current.candidateRelease
268
+ && authority?.active.releaseId === current.candidateRelease.releaseId
269
+ && authority.active.artifactIdentity === current.candidateRelease.artifactIdentity
270
+ && authority.previous?.databaseBackup
271
+ && authority.previous.releaseId === current.stableRelease.releaseId
272
+ && authority.previous.artifactIdentity === current.stableRelease.artifactIdentity
273
+ && authority.previous.manifestSha256 === current.stableRelease.manifestSha256
274
+ ) {
275
+ current = {
276
+ ...current,
277
+ transaction: {
278
+ schemaVersion: 1,
279
+ operationId: `reconcile:${id}:${authority.revision}`,
280
+ candidateReleaseId: current.candidateRelease.releaseId,
281
+ cutoverAuthorityRevision: authority.revision,
282
+ rollbackRelease: authority.previous,
283
+ startedAt: authority.committedAt,
284
+ },
285
+ revision: current.revision + 1,
286
+ updatedAt: new Date().toISOString(),
287
+ };
288
+ assertCurrentSession(current, id);
289
+ writeSession(path, current);
290
+ migratedSessionIds.push(id);
291
+ } else {
292
+ assertCurrentSession(current, id);
293
+ currentSessionIds.push(id);
294
+ }
295
+ continue;
296
+ }
297
+ const legacyV1 = raw.schemaVersion === 1
298
+ && (raw.semanticEpoch === undefined || raw.semanticEpoch === 1);
299
+ const transitionalV2 = raw.schemaVersion === 2
300
+ && raw.semanticEpoch === undefined;
301
+ if ((!legacyV1 && !transitionalV2) || !basicMigratableSessionShape(raw, id)) {
302
+ throw new Error(`RELEASE_SESSION_MIGRATION_UNSUPPORTED_SCHEMA: ${id}`);
303
+ }
304
+
305
+ let transaction: ReleaseSessionTransaction | undefined = 'transaction' in raw
306
+ ? raw.transaction
307
+ : undefined;
308
+ let migratedPhase = raw.phase;
309
+ let migratedReceipts = raw.receipts;
310
+ const candidateKey = releaseIdentityKey(raw.candidateRelease);
311
+ const candidateIsActive = Boolean(candidateKey && activeKey && candidateKey === activeKey);
312
+ if (!transaction && ['cutover_attempting', 'cutover_committed', 'soaking', 'known_good'].includes(raw.phase)) {
313
+ const candidate = raw.candidateRelease;
314
+ const previous = authority?.previous;
315
+ if (
316
+ candidateIsActive
317
+ && candidate
318
+ && authority
319
+ && previous?.databaseBackup
320
+ && previous.releaseId === raw.stableRelease.releaseId
321
+ && previous.artifactIdentity === raw.stableRelease.artifactIdentity
322
+ && previous.manifestSha256 === raw.stableRelease.manifestSha256
323
+ ) {
324
+ transaction = {
325
+ schemaVersion: 1,
326
+ operationId: `migration:${id}:${authority.revision}`,
327
+ candidateReleaseId: candidate.releaseId,
328
+ cutoverAuthorityRevision: authority.revision,
329
+ rollbackRelease: previous,
330
+ startedAt: raw.updatedAt,
331
+ };
332
+ } else if (raw.phase === 'known_good') {
333
+ // Historical terminal acceptance needs no live rollback authority. Keep
334
+ // exact transaction evidence when it is reconstructable above, but do
335
+ // not invent obsolete rollback state for already-terminal sessions.
336
+ } else if (raw.phase === 'soaking' && candidateKey && !candidateIsActive) {
337
+ const updatedAtMs = Date.parse(raw.updatedAt);
338
+ const successors = (stableSuccessors.get(candidateKey) ?? [])
339
+ .filter((entry) => entry.sessionId !== id && Date.parse(entry.createdAt) >= updatedAtMs);
340
+ const previousAuthorityProof = Boolean(previousKey && candidateKey === previousKey);
341
+ if (successors.length === 0 && !previousAuthorityProof) {
342
+ throw new Error(`RELEASE_SESSION_MIGRATION_HISTORICAL_ACCEPTANCE_UNPROVEN: ${id}`);
343
+ }
344
+ migratedPhase = 'known_good';
345
+ const proof = successors.length > 0
346
+ ? `${successors.length} later ReleaseSession attempt(s) use exact Candidate B as Stable A; first=${successors[0]!.sessionId}`
347
+ : 'current RuntimeReleaseAuthority.previous references Candidate B';
348
+ const receiptId = `migration:historical-known-good:${id}`;
349
+ migratedReceipts = raw.receipts.some((receipt) => receipt.id === receiptId)
350
+ ? raw.receipts
351
+ : [...raw.receipts, historicalAcceptanceReceipt(id, raw.updatedAt, proof)];
352
+ } else {
353
+ throw new Error(`RELEASE_SESSION_MIGRATION_AUTHORITY_MISMATCH: ${id}`);
354
+ }
355
+ }
356
+ const migrated = assertCurrentSession({
357
+ ...raw,
358
+ schemaVersion: 1,
359
+ semanticEpoch: 2,
360
+ phase: migratedPhase,
361
+ receipts: migratedReceipts,
362
+ ...(transaction ? { transaction } : {}),
363
+ } as ReleaseSession, id);
364
+ writeSession(path, migrated);
365
+ migratedSessionIds.push(id);
366
+ }
367
+ return { migratedSessionIds, currentSessionIds, inspected: names.length };
368
+ }
369
+
370
+ export function readReleaseSession(controllerHome: string, sessionId: string): ReleaseSession | undefined {
371
+ const path = sessionPath(controllerHome, validSessionId(sessionId));
372
+ if (!existsSync(path)) return undefined;
373
+ try {
374
+ const value = JSON.parse(readFileSync(path, 'utf8')) as ReleaseSession;
375
+ return assertCurrentSession(value, sessionId);
376
+ } catch (error) {
377
+ if (error instanceof Error && error.message === 'RELEASE_SESSION_INVALID') throw error;
378
+ throw new Error('RELEASE_SESSION_INVALID');
379
+ }
380
+ }
381
+
382
+ export interface ReleaseSessionInventory {
383
+ sessions: ReleaseSession[];
384
+ invalidSessionFiles: string[];
385
+ inspected: number;
386
+ truncated: boolean;
387
+ }
388
+
389
+ interface CompleteReleaseSessionInventoryCacheEntry {
390
+ revision: string;
391
+ inventory: ReleaseSessionInventory;
392
+ }
393
+
394
+ const completeReleaseSessionInventoryCache = new Map<string, CompleteReleaseSessionInventoryCacheEntry>();
395
+
396
+ function releaseSessionInventoryRoot(controllerHome: string): string {
397
+ return dirname(sessionPath(controllerHome, 'release-session-inventory'));
398
+ }
399
+
400
+ function invalidateCompleteReleaseSessionInventory(root: string): void {
401
+ completeReleaseSessionInventoryCache.delete(resolve(root));
402
+ }
403
+
404
+ function copyReleaseSessionInventory(inventory: ReleaseSessionInventory): ReleaseSessionInventory {
405
+ return {
406
+ sessions: [...inventory.sessions],
407
+ invalidSessionFiles: [...inventory.invalidSessionFiles],
408
+ inspected: inventory.inspected,
409
+ truncated: inventory.truncated,
410
+ };
411
+ }
412
+
413
+ /**
414
+ * Complete ReleaseSession authority inventory. The JSON files remain the single
415
+ * durable authority; this cache is process-local and is invalidated by every
416
+ * atomic session write. Directory metadata also invalidates cache entries when
417
+ * another Recovery process replaces a session file.
418
+ */
419
+ export function listCompleteReleaseSessions(controllerHome: string): ReleaseSessionInventory {
420
+ const root = releaseSessionInventoryRoot(controllerHome);
421
+ if (!existsSync(root)) {
422
+ invalidateCompleteReleaseSessionInventory(root);
423
+ return { sessions: [], invalidSessionFiles: [], inspected: 0, truncated: false };
424
+ }
425
+ const names = readdirSync(root)
426
+ .filter((name) => name.endsWith('.json'))
427
+ .sort();
428
+ const directory = statSync(root);
429
+ const revision = [directory.mtimeMs, directory.ctimeMs, names.length, names[0] ?? '', names[names.length - 1] ?? ''].join(':');
430
+ const cacheKey = resolve(root);
431
+ const cached = completeReleaseSessionInventoryCache.get(cacheKey);
432
+ if (cached?.revision === revision) return copyReleaseSessionInventory(cached.inventory);
433
+
434
+ const sessions: ReleaseSession[] = [];
435
+ const invalidSessionFiles: string[] = [];
436
+ for (const name of names) {
437
+ const sessionId = name.slice(0, -'.json'.length);
438
+ try {
439
+ const session = readReleaseSession(controllerHome, sessionId);
440
+ if (session) sessions.push(session);
441
+ else invalidSessionFiles.push(name);
442
+ } catch {
443
+ invalidSessionFiles.push(name);
444
+ }
445
+ }
446
+ const inventory: ReleaseSessionInventory = {
447
+ sessions,
448
+ invalidSessionFiles,
449
+ inspected: names.length,
450
+ truncated: false,
451
+ };
452
+ completeReleaseSessionInventoryCache.set(cacheKey, { revision, inventory });
453
+ return copyReleaseSessionInventory(inventory);
454
+ }
455
+
456
+ /**
457
+ * Bounded read-only inventory for diagnostic/projection consumers.
458
+ * The release domain owns phase progression. Recovery may execute fenced
459
+ * Runtime mutations, but it is not the semantic owner of normal release intent.
460
+ */
461
+ export function listReleaseSessions(
462
+ controllerHome: string,
463
+ options: { maxEntries?: number } = {},
464
+ ): ReleaseSessionInventory {
465
+ const root = releaseSessionInventoryRoot(controllerHome);
466
+ if (!existsSync(root)) return { sessions: [], invalidSessionFiles: [], inspected: 0, truncated: false };
467
+ const maxEntries = Math.max(1, Math.floor(options.maxEntries ?? 512));
468
+ const names = readdirSync(root)
469
+ .filter((name) => name.endsWith('.json'))
470
+ .sort();
471
+ const selected = names.slice(0, maxEntries);
472
+ const sessions: ReleaseSession[] = [];
473
+ const invalidSessionFiles: string[] = [];
474
+ for (const name of selected) {
475
+ const sessionId = name.slice(0, -'.json'.length);
476
+ try {
477
+ const session = readReleaseSession(controllerHome, sessionId);
478
+ if (session) sessions.push(session);
479
+ else invalidSessionFiles.push(name);
480
+ } catch {
481
+ invalidSessionFiles.push(name);
482
+ }
483
+ }
484
+ return {
485
+ sessions,
486
+ invalidSessionFiles,
487
+ inspected: selected.length,
488
+ truncated: names.length > selected.length,
489
+ };
490
+ }
491
+
492
+ const RELEASE_SESSION_TERMINAL_PHASES = new Set<ReleaseSessionPhase>([
493
+ 'known_good',
494
+ 'rolled_back',
495
+ 'failed',
496
+ ]);
497
+
498
+ const RELEASE_SESSION_CANDIDATE_RETIRED_PHASES = new Set<ReleaseSessionPhase>([
499
+ 'soaking',
500
+ ...RELEASE_SESSION_TERMINAL_PHASES,
501
+ ]);
502
+
503
+ export function releaseSessionIsTerminal(session: ReleaseSession): boolean {
504
+ return RELEASE_SESSION_TERMINAL_PHASES.has(session.phase);
505
+ }
506
+
507
+ /**
508
+ * A soaking ReleaseSession may temporarily remain non-terminal while a repair
509
+ * successor is prepared. This relation is deliberately stricter than generic
510
+ * release equality: the predecessor must have durably cut over the exact
511
+ * release/authority revision that the successor freezes as Stable A. It
512
+ * therefore preserves the predecessor's rollback authority until the successor
513
+ * itself has committed a replacement cutover without permitting arbitrary
514
+ * multiple active ReleaseSessions.
515
+ */
516
+ export function releaseSessionIsSoakingPredecessorOfStable(
517
+ session: ReleaseSession,
518
+ stableRelease: ReleaseSessionStableRelease,
519
+ ): boolean {
520
+ const candidate = session.candidateRelease;
521
+ const transaction = session.transaction;
522
+ return session.phase === 'soaking'
523
+ && Boolean(candidate)
524
+ && Boolean(transaction)
525
+ && transaction!.candidateReleaseId === candidate!.releaseId
526
+ && transaction!.cutoverAuthorityRevision === stableRelease.authorityRevision
527
+ && candidate!.releaseId === stableRelease.releaseId
528
+ && candidate!.artifactIdentity === stableRelease.artifactIdentity
529
+ && candidate!.manifestSha256 === stableRelease.manifestSha256;
530
+ }
531
+
532
+ /**
533
+ * Emergency Recovery may publish a later whole-Runtime authority outside the
534
+ * original soaking ReleaseSession. The old session is superseded only when the
535
+ * active authority revision has strictly advanced beyond its cutover and the
536
+ * active stable identity is no longer that exact candidate. Equal/older or
537
+ * partially-matching identities remain ambiguous and must stay fail-closed.
538
+ */
539
+ export function releaseSessionIsSoakingSupersededByStableAuthority(
540
+ session: ReleaseSession,
541
+ stableRelease: ReleaseSessionStableRelease,
542
+ ): boolean {
543
+ const candidate = session.candidateRelease;
544
+ const transaction = session.transaction;
545
+ if (
546
+ session.phase !== 'soaking'
547
+ || !candidate
548
+ || !transaction
549
+ || transaction.candidateReleaseId !== candidate.releaseId
550
+ || stableRelease.authorityRevision <= transaction.cutoverAuthorityRevision
551
+ ) return false;
552
+ return candidate.releaseId !== stableRelease.releaseId
553
+ || candidate.artifactIdentity !== stableRelease.artifactIdentity
554
+ || candidate.manifestSha256 !== stableRelease.manifestSha256;
555
+ }
556
+
557
+ /**
558
+ * Durable semantic proof that Candidate B is no longer required as a mutable
559
+ * Controller Home. This does not itself authorize deletion: cleanup must still
560
+ * prove the exact fenced path and absence of a live Runtime owner.
561
+ */
562
+ export function releaseSessionCandidateIsRetired(session: ReleaseSession): boolean {
563
+ return RELEASE_SESSION_CANDIDATE_RETIRED_PHASES.has(session.phase);
564
+ }
565
+
566
+ export function createReleaseSession(input: {
567
+ controllerHome: string;
568
+ sessionId: string;
569
+ stable: StableExecutionLane;
570
+ stableRelease: ReleaseSessionStableRelease;
571
+ candidate: CandidateExecutionLane;
572
+ sourceRevision: string;
573
+ }): ReleaseSession {
574
+ const sessionId = validSessionId(input.sessionId);
575
+ const path = sessionPath(input.controllerHome, sessionId);
576
+ if (existsSync(path)) throw new Error('RELEASE_SESSION_ALREADY_EXISTS');
577
+ const inventory = listCompleteReleaseSessions(input.controllerHome);
578
+ if (inventory.invalidSessionFiles.length > 0) {
579
+ throw new Error(`RELEASE_SESSION_INVENTORY_INCOMPLETE: invalid=${inventory.invalidSessionFiles.join(',')}`);
580
+ }
581
+ const active = inventory.sessions.filter((session) => !releaseSessionIsTerminal(session));
582
+ const sourceRevision = input.sourceRevision.trim();
583
+ const allowedRepairPredecessor = active.length === 1
584
+ && active[0] !== undefined
585
+ && releaseSessionIsSoakingPredecessorOfStable(active[0], input.stableRelease)
586
+ && active[0].sourceRevision !== sourceRevision;
587
+ if (active.length > 0 && !allowedRepairPredecessor) {
588
+ throw new Error(`RELEASE_SESSION_ACTIVE_EXISTS: ${active.map((session) => `${session.sessionId}:${session.phase}`).join(',')}`);
589
+ }
590
+ if (resolve(input.stable.controllerHome) === resolve(input.candidate.controllerHome)) throw new Error('RELEASE_SESSION_LANE_COLLISION');
591
+ const timestamp = new Date().toISOString();
592
+ const session: ReleaseSession = {
593
+ schemaVersion: 1,
594
+ semanticEpoch: 2,
595
+ sessionId,
596
+ stable: input.stable,
597
+ stableRelease: input.stableRelease,
598
+ candidate: input.candidate,
599
+ sourceRevision,
600
+ phase: 'source_frozen',
601
+ revision: 1,
602
+ receipts: [{ id: `source:${sessionId}`, kind: 'source', recordedAt: timestamp, summary: `source frozen at ${input.sourceRevision.trim()}` }],
603
+ createdAt: timestamp,
604
+ updatedAt: timestamp,
605
+ };
606
+ if (!session.sourceRevision) throw new Error('RELEASE_SESSION_SOURCE_REVISION_REQUIRED');
607
+ if (
608
+ !Number.isInteger(session.stableRelease.authorityRevision)
609
+ || session.stableRelease.authorityRevision < 1
610
+ || !session.stableRelease.releaseId
611
+ || !session.stableRelease.artifactIdentity
612
+ || !session.stableRelease.manifestSha256
613
+ || !Number.isInteger(session.stableRelease.workerProtocolVersion)
614
+ || session.stableRelease.workerProtocolVersion < 1
615
+ || !session.stableRelease.releaseFencingTokenSha256
616
+ ) throw new Error('RELEASE_SESSION_STABLE_RELEASE_IDENTITY_INVALID');
617
+ writeSession(path, session);
618
+ return session;
619
+ }
620
+
621
+ function receiptIds(session: ReleaseSession, kind: ReleaseSessionReceipt['kind']): Set<string> {
622
+ return new Set(session.receipts.filter((receipt) => receipt.kind === kind).map((receipt) => receipt.id));
623
+ }
624
+
625
+ function assertTransition(session: ReleaseSession, phase: ReleaseSessionPhase): void {
626
+ const order: ReleaseSessionPhase[] = ['source_frozen', 'built', 'static_verified', 'candidate_booted', 'candidate_verified', 'cutover_eligible', 'cutover_attempting', 'cutover_committed', 'soaking', 'known_good'];
627
+ if (session.phase === 'failed' || session.phase === 'rolled_back' || session.phase === 'known_good') {
628
+ throw new Error('RELEASE_SESSION_TERMINAL');
629
+ }
630
+ if (phase === 'failed') return;
631
+ if (phase === 'rolled_back') {
632
+ if (order.indexOf(session.phase) < order.indexOf('cutover_attempting')) {
633
+ throw new Error('RELEASE_SESSION_ROLLBACK_BEFORE_CUTOVER_ATTEMPT');
634
+ }
635
+ return;
636
+ }
637
+ if (order.indexOf(phase) !== order.indexOf(session.phase) + 1) throw new Error('RELEASE_SESSION_TRANSITION_INVALID');
638
+ if ((phase === 'built' || phase === 'static_verified') && !session.candidateRelease) {
639
+ throw new Error('RELEASE_SESSION_CANDIDATE_RELEASE_REQUIRED');
640
+ }
641
+ if (phase === 'static_verified' && [...REQUIRED_STATIC_GATES].some((id) => !receiptIds(session, 'static_gate').has(id))) {
642
+ throw new Error('RELEASE_SESSION_STATIC_GATES_INCOMPLETE');
643
+ }
644
+ if (phase === 'candidate_verified' && [...REQUIRED_CANDIDATE_CANARIES].some((id) => !receiptIds(session, 'candidate_canary').has(id))) {
645
+ throw new Error('RELEASE_SESSION_CANDIDATE_CANARIES_INCOMPLETE');
646
+ }
647
+ if (phase === 'known_good' && [...REQUIRED_KNOWN_GOOD_SOAK_GATES].some((id) => !receiptIds(session, 'soak').has(id))) {
648
+ throw new Error('RELEASE_SESSION_SOAK_GATES_INCOMPLETE');
649
+ }
650
+ if (phase === 'cutover_eligible' && (session.stable.controllerHome === session.candidate.controllerHome || session.stable.port === session.candidate.port)) {
651
+ throw new Error('RELEASE_SESSION_LANE_COLLISION');
652
+ }
653
+ }
654
+
655
+ /**
656
+ * The release coordinator calls this while the executing provider holds the
657
+ * appropriate mutation lock. expectedRevision is a CAS fence, so a stale
658
+ * observer cannot advance a newer session.
659
+ */
660
+ export function recordReleaseSessionTransaction(input: {
661
+ controllerHome: string;
662
+ sessionId: string;
663
+ expectedRevision: number;
664
+ transaction: ReleaseSessionTransaction;
665
+ }): ReleaseSession {
666
+ const current = readReleaseSession(input.controllerHome, input.sessionId);
667
+ if (!current) throw new Error('RELEASE_SESSION_MISSING');
668
+ if (current.phase !== 'cutover_attempting') throw new Error(`RELEASE_SESSION_TRANSACTION_REQUIRES_CUTOVER_ATTEMPTING: ${current.phase}`);
669
+ // Runtime startup migration and the Recovery activation writer are two
670
+ // legitimate physical writers for this one bounded transaction. If the
671
+ // migration already persisted the exact transaction, accept its durable
672
+ // result instead of treating the activation's stale local revision as a
673
+ // competing semantic update. Any different transaction remains fenced.
674
+ if (current.transaction && sameReleaseSessionTransactionIdentity(current.transaction, input.transaction)) {
675
+ return current;
676
+ }
677
+ if (current.revision !== input.expectedRevision) throw new Error('RELEASE_SESSION_REVISION_FENCED');
678
+ const next = {
679
+ ...current,
680
+ transaction: input.transaction,
681
+ revision: current.revision + 1,
682
+ updatedAt: new Date().toISOString(),
683
+ } satisfies ReleaseSession;
684
+ if (!validTransaction(next)) throw new Error('RELEASE_SESSION_TRANSACTION_INVALID');
685
+ writeSession(sessionPath(input.controllerHome, current.sessionId), next);
686
+ return next;
687
+ }
688
+
689
+ export function advanceReleaseSession(input: {
690
+ controllerHome: string;
691
+ sessionId: string;
692
+ expectedRevision: number;
693
+ phase: ReleaseSessionPhase;
694
+ candidateRelease?: ReleaseSessionCandidateRelease;
695
+ receipts?: Array<Omit<ReleaseSessionReceipt, 'recordedAt'>>;
696
+ }): ReleaseSession {
697
+ const current = readReleaseSession(input.controllerHome, input.sessionId);
698
+ if (!current) throw new Error('RELEASE_SESSION_MISSING');
699
+ if (current.revision !== input.expectedRevision) throw new Error('RELEASE_SESSION_REVISION_FENCED');
700
+ const recordedAt = new Date().toISOString();
701
+ const receipts = [...current.receipts, ...(input.receipts ?? []).map((receipt) => ({ ...receipt, recordedAt }))].slice(-64);
702
+ const candidateRelease = input.candidateRelease ?? current.candidateRelease;
703
+ if (candidateRelease && (
704
+ !candidateRelease.releaseId
705
+ || !candidateRelease.manifestPath
706
+ || !candidateRelease.artifactIdentity
707
+ || !candidateRelease.manifestSha256
708
+ || !/^[a-f0-9]{64}$/i.test(candidateRelease.treeSha256)
709
+ || candidateRelease.sourceCommit !== current.sourceRevision
710
+ )) throw new Error('RELEASE_SESSION_CANDIDATE_RELEASE_IDENTITY_INVALID');
711
+ const proposed: ReleaseSession = { ...current, ...(candidateRelease ? { candidateRelease } : {}), receipts };
712
+ assertTransition(proposed, input.phase);
713
+ const next: ReleaseSession = { ...proposed, phase: input.phase, revision: current.revision + 1, updatedAt: recordedAt };
714
+ writeSession(sessionPath(input.controllerHome, current.sessionId), next);
715
+ return next;
716
+ }