@moretea-labs/forge 1.8.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/AGENTS.md +70 -7
  2. package/CHANGELOG.md +14 -0
  3. package/CLAUDE.md +17 -2
  4. package/CONTRIBUTING.md +3 -2
  5. package/THIRD_PARTY_NOTICES.md +1 -1
  6. package/adapters/chatgpt/browser-delivery-host.ts +7 -1
  7. package/adapters/chatgpt/browser-delivery-runtime.ts +529 -56
  8. package/adapters/chatgpt/controller-binding-store.ts +101 -22
  9. package/adapters/chatgpt/controller-round-host.ts +15 -25
  10. package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
  11. package/adapters/chatgpt/provider-delivery.ts +228 -1
  12. package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
  13. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  14. package/adapters/computer/chatgpt-target-router.ts +103 -0
  15. package/adapters/computer/chrome-extension/background.js +385 -0
  16. package/adapters/computer/chrome-extension/content.js +378 -0
  17. package/adapters/computer/chrome-extension/core.js +24 -0
  18. package/adapters/computer/chrome-extension/manifest.json +30 -0
  19. package/adapters/computer/desktop-operator-discovery.ts +11 -31
  20. package/adapters/computer/interaction-target-authority.ts +142 -18
  21. package/adapters/mcp/auth.ts +0 -1
  22. package/adapters/mcp/instructions.ts +5 -4
  23. package/adapters/mcp/multi-repository.ts +3 -19
  24. package/adapters/mcp/oauth.ts +73 -0
  25. package/adapters/mcp/paths.ts +4 -1
  26. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  27. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  28. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  29. package/adapters/mcp/runtime-gateway/context-adapter.ts +411 -73
  30. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  31. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
  32. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  33. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
  34. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  35. package/adapters/mcp/runtime-gateway/execution-tools.ts +8 -42
  36. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
  37. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
  38. package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
  39. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
  40. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
  41. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
  42. package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
  43. package/adapters/mcp/runtime-gateway/router.ts +18 -504
  44. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  45. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
  46. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  47. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
  48. package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
  49. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
  50. package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
  51. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
  52. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  53. package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
  54. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  55. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  56. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  57. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  58. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  59. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  60. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  61. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  62. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  63. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  64. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  65. package/adapters/mcp/server.ts +67 -23
  66. package/adapters/mcp/setup.ts +1 -3
  67. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
  68. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
  69. package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
  70. package/adapters/mcp/toolset-names.ts +5 -0
  71. package/adapters/mcp/toolset.ts +6 -5
  72. package/adapters/mcp/transports/http-observation.ts +365 -0
  73. package/adapters/mcp/transports/http.ts +154 -677
  74. package/adapters/mcp/transports/oauth-http.ts +322 -0
  75. package/adapters/mcp/transports/session-registry.ts +6 -0
  76. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
  77. package/assets/plugin-registry.v1.json +6 -4
  78. package/assets/reference-configs/agentic-development-flow.md +25 -0
  79. package/assets/reference-configs/global-working-rules.md +19 -0
  80. package/assets/skill-version.json +2 -2
  81. package/docs/architecture/CURRENT.md +111 -41
  82. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  83. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  84. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
  85. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
  86. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  87. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  88. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  89. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  90. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  91. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  92. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  93. package/docs/architecture/domains/verification.md +1 -0
  94. package/docs/architecture/domains/workflow-engine.md +6 -0
  95. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  96. package/docs/forge-plugin-management.md +2 -2
  97. package/docs/operations/controller-performance-and-502.md +17 -0
  98. package/docs/operations/controller-reliability-runbook.md +2 -2
  99. package/docs/operations/features.md +1 -1
  100. package/docs/operations/features.zh-CN.md +1 -1
  101. package/docs/operations/homebrew.md +2 -2
  102. package/docs/operations/mcp-tool-exposure.md +2 -0
  103. package/docs/operations/releasing.md +2 -0
  104. package/docs/operations/standalone-disaster-recovery.md +14 -6
  105. package/docs/wiki/Implementation.md +1 -1
  106. package/package.json +25 -14
  107. package/packages/kernel/cognition/api/index.ts +6 -0
  108. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  109. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  110. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  111. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  112. package/packages/kernel/cognition/domain/learning.ts +106 -0
  113. package/packages/kernel/cognition/domain/memory.ts +254 -0
  114. package/packages/kernel/controller/api/index.ts +1 -0
  115. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  116. package/packages/kernel/controller/application/controller-round-service.ts +12 -0
  117. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
  118. package/packages/kernel/controller/domain/controller-round.ts +4 -1
  119. package/packages/kernel/controller/domain/execution-quality.ts +3 -1
  120. package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
  121. package/packages/kernel/controller/infrastructure/controller-session-store.ts +297 -71
  122. package/packages/kernel/controller/ports/controller-host.ts +2 -0
  123. package/packages/kernel/identity/api/index.ts +10 -0
  124. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  125. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  126. package/packages/kernel/identity/domain/grant.ts +72 -0
  127. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  128. package/packages/kernel/identity/domain/user-request.ts +93 -0
  129. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  130. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  131. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  132. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  133. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  134. package/packages/kernel/scheduler/api/index.ts +0 -2
  135. package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
  136. package/packages/kernel/scheduler/application/settlement.ts +0 -15
  137. package/packages/kernel/scheduler/domain/schedule.ts +87 -0
  138. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +153 -133
  139. package/packages/kernel/work/api/index.ts +3 -2
  140. package/packages/kernel/work/application/work-service.ts +17 -42
  141. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  142. package/packages/kernel/work/domain/engineering-design.ts +10 -5
  143. package/packages/kernel/work/domain/engineering-profile.ts +8 -12
  144. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  145. package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
  146. package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
  147. package/packages/kernel/work/domain/implementation-review.ts +14 -331
  148. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  149. package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
  150. package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
  151. package/packages/kernel/work/domain/state-machine.ts +25 -63
  152. package/packages/kernel/work/domain/types.ts +57 -51
  153. package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
  154. package/packages/kernel/work/ports/work-contract-store.ts +5 -2
  155. package/packages/plugin-runtime/browser/session-authority.ts +2 -1
  156. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  157. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  158. package/packages/plugin-runtime/computer/index.ts +2 -0
  159. package/packages/plugin-runtime/computer/target-authority.ts +26 -1
  160. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
  161. package/packages/protocols/computer/contract.ts +27 -1
  162. package/scripts/activate-source-baseline.ts +7 -9
  163. package/scripts/canary-controller-semantic-wait.ts +12 -24
  164. package/scripts/check-mcp-compatibility.ts +48 -136
  165. package/scripts/check-runtime-architecture.mjs +622 -217
  166. package/scripts/forge-local-recovery-helper.mjs +93 -15
  167. package/scripts/lib/project-init-lib.sh +3 -0
  168. package/scripts/open-source-audit-allowlist.txt +1 -2
  169. package/scripts/run-bounded-command.mjs +5 -0
  170. package/scripts/run-governed-gate.ts +0 -1
  171. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  172. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  173. package/scripts/smoke-mcp-http-runtime.ts +5 -0
  174. package/scripts/smoke-runtime-recovery.ts +12 -43
  175. package/scripts/smoke-schedule-engine.ts +23 -15
  176. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  177. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  178. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  179. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  180. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  181. package/scripts/smoke-workflow-supervisor.ts +103 -0
  182. package/scripts/verify-forge-runtime.sh +2 -1
  183. package/src/cli/agent-jobs/executor-health.ts +11 -34
  184. package/src/cli/agent-jobs/integration.ts +18 -49
  185. package/src/cli/agent-jobs/job-manager.ts +7 -3
  186. package/src/cli/commands/brain-assistant.ts +27 -13
  187. package/src/cli/commands/brain.ts +13 -15
  188. package/src/cli/commands/chatgpt.ts +1 -163
  189. package/src/cli/commands/recovery.ts +135 -121
  190. package/src/cli/commands/runtime.ts +3 -3
  191. package/src/cli/commands/setup-profile.ts +8 -0
  192. package/src/cli/controller/check-runner.ts +13 -2
  193. package/src/cli/controller/completion-backlog.ts +3 -3
  194. package/src/cli/controller/completion-orchestrator.ts +4 -43
  195. package/src/cli/controller/completion-target.ts +3 -72
  196. package/src/cli/controller/context/source-materializer.ts +81 -100
  197. package/src/cli/controller/context-pack.ts +10 -8
  198. package/src/cli/controller/execution-completion.ts +4 -7
  199. package/src/cli/controller/execution-policy.ts +36 -153
  200. package/src/cli/controller/governance.ts +2 -3
  201. package/src/cli/controller/issue-store.ts +4 -99
  202. package/src/cli/controller/launch-agents.ts +59 -18
  203. package/src/cli/controller/operational-plan.ts +24 -51
  204. package/src/cli/controller/runtime-config.ts +5 -1
  205. package/src/cli/controller/stuck-state-migration.ts +2 -3
  206. package/src/cli/controller/systemd-user.ts +39 -1
  207. package/src/cli/editing/edit-session.ts +1 -7
  208. package/src/cli/local-bridge/console-automations.ts +18 -13
  209. package/src/cli/local-bridge/console-view-models.ts +3 -12
  210. package/src/cli/local-bridge/facade-api.ts +64 -191
  211. package/src/cli/local-bridge/server.ts +24 -147
  212. package/src/cli/local-bridge/types.ts +0 -1
  213. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  214. package/src/cli/repositories/command-executor.ts +29 -23
  215. package/src/cli/repositories/command-scope.ts +35 -16
  216. package/src/cli/repositories/controller-home.ts +48 -0
  217. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  218. package/src/cli/repositories/git-command-executor.ts +2 -2
  219. package/src/cli/repositories/registry.ts +77 -11
  220. package/src/cli/repositories/structured-git.ts +62 -2
  221. package/src/cli/repository/session-cache.ts +92 -6
  222. package/src/runtime/context/assistant-context.ts +20 -7
  223. package/src/runtime/context/assistant-work-context.ts +89 -27
  224. package/src/runtime/context/automatic-learning.ts +565 -0
  225. package/src/runtime/context/cognitive-attention.ts +173 -0
  226. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  227. package/src/runtime/context/context-closure.ts +46 -9
  228. package/src/runtime/context/context-pack-process.ts +103 -0
  229. package/src/runtime/context/context-plane.ts +1 -9
  230. package/src/runtime/context/direct-controller-learning.ts +298 -0
  231. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  232. package/src/runtime/context/semantic-navigation.ts +6 -34
  233. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  234. package/src/runtime/context/typescript-navigation.ts +89 -3
  235. package/src/runtime/control-plane/cleanup-artifact-retention.ts +212 -9
  236. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
  237. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
  238. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
  239. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  240. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  241. package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
  242. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  243. package/src/runtime/control-plane/execution/validation.ts +6 -8
  244. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
  245. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  246. package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
  247. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  248. package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
  249. package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
  250. package/src/runtime/control-plane/execution/work-handle-authority.ts +188 -109
  251. package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
  252. package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
  253. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
  254. package/src/runtime/control-plane/execution/work-operation-service.ts +43 -27
  255. package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
  256. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  257. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  258. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +173 -186
  259. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
  260. package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
  261. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
  262. package/src/runtime/control-plane/facade/capability-registry.ts +362 -37
  263. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  264. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  265. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  266. package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
  267. package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
  268. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
  269. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
  270. package/src/runtime/control-plane/facade/index.ts +0 -1
  271. package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
  272. package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
  273. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  274. package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
  275. package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
  276. package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
  277. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
  278. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  279. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
  280. package/src/runtime/control-plane/facade/types.ts +49 -108
  281. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  282. package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
  283. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  284. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
  285. package/src/runtime/control-plane/global-scheduler/maintenance.ts +239 -112
  286. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
  287. package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
  288. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  289. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  290. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  291. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
  292. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -300
  293. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  294. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
  295. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
  296. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  297. package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
  298. package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
  299. package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
  300. package/src/runtime/control-plane/release-retention.ts +135 -47
  301. package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
  302. package/src/runtime/control-plane/runtime-cleanup.ts +290 -21
  303. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  304. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
  305. package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
  306. package/src/runtime/diagnostics/incident-repair.ts +313 -146
  307. package/src/runtime/diagnostics/mcp-timing.ts +114 -0
  308. package/src/runtime/evidence/artifact-store.ts +158 -40
  309. package/src/runtime/evidence/evidence-store.ts +112 -8
  310. package/src/runtime/evidence/output-handle-index.ts +225 -0
  311. package/src/runtime/evidence/result-store.ts +158 -44
  312. package/src/runtime/execution/jobs/store.ts +3 -4
  313. package/src/runtime/execution/managed-workspace.ts +57 -0
  314. package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
  315. package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
  316. package/src/runtime/execution/process-runtime/check-result.ts +105 -1
  317. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
  318. package/src/runtime/execution/process-runtime/command-facade.ts +79 -27
  319. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  320. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  321. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  322. package/src/runtime/execution/process-runtime/index.ts +3 -0
  323. package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
  324. package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
  325. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  326. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  327. package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
  328. package/src/runtime/execution/process-runtime/runtime.ts +35 -2
  329. package/src/runtime/execution/process-runtime/store.ts +30 -2
  330. package/src/runtime/execution/process-runtime/types.ts +6 -1
  331. package/src/runtime/execution/workers/executor.ts +2 -6
  332. package/src/runtime/platform/service-inventory.ts +130 -0
  333. package/src/runtime/platform/service-manager.ts +8 -0
  334. package/src/runtime/plugins/action-application.ts +85 -28
  335. package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
  336. package/src/runtime/plugins/browser-adapter.ts +757 -34
  337. package/src/runtime/plugins/browser-automation-service.ts +23 -3
  338. package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
  339. package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
  340. package/src/runtime/plugins/browser-native-session-service.ts +63 -13
  341. package/src/runtime/plugins/browser-registration.ts +16 -0
  342. package/src/runtime/plugins/browser-runtime.ts +14 -1
  343. package/src/runtime/plugins/browser-session-authority.ts +2 -2
  344. package/src/runtime/plugins/browser-session-store.ts +46 -76
  345. package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
  346. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  347. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  348. package/src/runtime/plugins/computer-registration.ts +222 -11
  349. package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
  350. package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
  351. package/src/runtime/plugins/external-adapter.ts +42 -6
  352. package/src/runtime/plugins/external-registration.ts +21 -1
  353. package/src/runtime/plugins/gmail-adapter.ts +23 -2
  354. package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
  355. package/src/runtime/plugins/google-shared.ts +14 -7
  356. package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
  357. package/src/runtime/plugins/ios-adapter.ts +1 -1
  358. package/src/runtime/plugins/lightweight-action.ts +208 -2
  359. package/src/runtime/plugins/local-system-adapter.ts +12 -2
  360. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  361. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  362. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  363. package/src/runtime/plugins/store.ts +602 -428
  364. package/src/runtime/plugins/types.ts +20 -0
  365. package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
  366. package/src/runtime/projections/invalidation.ts +7 -3
  367. package/src/runtime/projections/materialized-view.ts +80 -36
  368. package/src/runtime/recovery/actions.ts +3 -3
  369. package/src/runtime/recovery/capability-action-application.ts +46 -45
  370. package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
  371. package/src/runtime/recovery/maintenance-executor.ts +374 -123
  372. package/src/runtime/recovery/store.ts +29 -11
  373. package/src/runtime/release/release-coordinator.ts +296 -0
  374. package/src/runtime/release/release-session.ts +716 -0
  375. package/src/runtime/release/release-state-migration.ts +25 -0
  376. package/src/runtime/resources/leases/store.ts +56 -25
  377. package/src/runtime/root/computer-composition.ts +191 -6
  378. package/src/runtime/root/controller-progression-composition.ts +192 -0
  379. package/src/runtime/root/controller-round-composition.ts +20 -1
  380. package/src/runtime/root/deployment-topology.ts +106 -0
  381. package/src/runtime/root/entry.ts +4 -3
  382. package/src/runtime/root/known-good-recovery.ts +184 -0
  383. package/src/runtime/root/local-bridge.ts +0 -1
  384. package/src/runtime/root/mcp-transport.ts +111 -18
  385. package/src/runtime/root/ownership.ts +261 -9
  386. package/src/runtime/root/package-connector-service.ts +105 -19
  387. package/src/runtime/root/package-runtime-release.ts +117 -18
  388. package/src/runtime/root/package-runtime-service.ts +17 -11
  389. package/src/runtime/root/release-execution-canary.ts +44 -12
  390. package/src/runtime/root/release-loader.ts +90 -8
  391. package/src/runtime/root/release-manifest.ts +80 -6
  392. package/src/runtime/root/release-materialize.ts +372 -28
  393. package/src/runtime/root/release-store.ts +395 -36
  394. package/src/runtime/root/runtime-lane.ts +191 -0
  395. package/src/runtime/root/runtime.ts +159 -27
  396. package/src/runtime/root/scheduled-controller-composition.ts +28 -3
  397. package/src/runtime/root/service-runner.ts +2 -2
  398. package/src/runtime/root/service.ts +36 -33
  399. package/src/runtime/root/status.ts +48 -0
  400. package/src/runtime/root/types.ts +32 -3
  401. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  402. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  403. package/src/runtime/root/write-fence.ts +50 -2
  404. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  405. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  406. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  407. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  408. package/src/runtime/shared/process-environment.ts +20 -9
  409. package/src/runtime/shared/response-budget.ts +1 -3
  410. package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
  411. package/src/runtime/standalone-recovery/core.ts +3702 -342
  412. package/src/runtime/standalone-recovery/entry.ts +469 -39
  413. package/src/runtime/standalone-recovery/installer.ts +262 -148
  414. package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
  415. package/src/runtime/standalone-recovery/operation-lock.ts +1 -1
  416. package/src/runtime/standalone-recovery/performance.ts +54 -16
  417. package/src/runtime/standalone-recovery/release.ts +53 -5
  418. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  419. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  420. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  421. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +10 -3
  422. package/src/runtime/workflow/schedules/engine.ts +138 -172
  423. package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
  424. package/src/runtime/workflows/runtime.ts +15 -19
  425. package/src/testing/test-governance.ts +5 -1
  426. package/supervisor/chatgpt-conversation.ts +23 -0
  427. package/supervisor/client.ts +201 -0
  428. package/supervisor/control-plane.ts +868 -0
  429. package/supervisor/entry.ts +15 -0
  430. package/supervisor/forge-validators.ts +80 -0
  431. package/supervisor/index.ts +5 -0
  432. package/supervisor/native-browser-adapter.ts +786 -0
  433. package/supervisor/native-messaging/host.ts +39 -0
  434. package/supervisor/native-messaging/manifest.ts +26 -0
  435. package/supervisor/native-messaging/protocol.ts +27 -0
  436. package/supervisor/paths.ts +18 -0
  437. package/supervisor/protocol.ts +202 -0
  438. package/supervisor/server.ts +404 -0
  439. package/supervisor/store.ts +1451 -0
  440. package/supervisor/tsconfig.json +8 -0
  441. package/supervisor/types.ts +255 -0
  442. package/adapters/chatgpt/controller-host.ts +0 -119
  443. package/adapters/mcp/controller-round-compatibility.ts +0 -184
  444. package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
  445. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
  446. package/packages/kernel/progression/api/index.ts +0 -2
  447. package/packages/kernel/progression/application/projector.ts +0 -211
  448. package/packages/kernel/progression/domain/types.ts +0 -116
  449. package/packages/kernel/progression/index.ts +0 -1
  450. package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
  451. package/packages/kernel/scheduler/domain/continuation.ts +0 -38
  452. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
  453. package/packages/kernel/work/domain/admission-policy.ts +0 -34
  454. package/scripts/benchmark-background-check-overlap.ts +0 -228
  455. package/scripts/benchmark-computer-hotpath.ts +0 -255
  456. package/scripts/benchmark-controller-hotpath.ts +0 -212
  457. package/scripts/benchmark-controller-round2.ts +0 -191
  458. package/scripts/benchmark-ios-agent-device.ts +0 -511
  459. package/scripts/benchmark-mcp-host.sh +0 -117
  460. package/scripts/benchmark-mcp-transport.ts +0 -169
  461. package/scripts/benchmark-operational-memory-activation.ts +0 -235
  462. package/scripts/benchmark-operational-shadow.ts +0 -28
  463. package/scripts/benchmark-quality-harness.ts +0 -146
  464. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  465. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  466. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  467. package/scripts/benchmark-thin-harness.ts +0 -251
  468. package/scripts/benchmark-typescript-navigation.ts +0 -186
  469. package/scripts/benchmark-work-efficiency.ts +0 -334
  470. package/scripts/build-controller-ui.ts +0 -28
  471. package/scripts/check-npm-release.sh +0 -32
  472. package/scripts/check-public-release-surface.sh +0 -19
  473. package/scripts/check-release-published.sh +0 -57
  474. package/scripts/check-release-readiness.sh +0 -37
  475. package/scripts/check-release-version.mjs +0 -74
  476. package/scripts/check-tarball-install-smoke.sh +0 -150
  477. package/scripts/package-source-archive.sh +0 -147
  478. package/scripts/public-release-files.txt +0 -39
  479. package/scripts/public-release.ts +0 -174
  480. package/scripts/publish-release-tarball.sh +0 -27
  481. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  482. package/scripts/stage-runtime-release.ts +0 -44
  483. package/src/cli/controller/progress.ts +0 -656
  484. package/src/cli/controller/work-mode.ts +0 -181
  485. package/src/cli/local-bridge/console-assets.ts +0 -17
  486. package/src/cli/local-bridge/dashboard.ts +0 -17
  487. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  488. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  489. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  490. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  491. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  492. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  493. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  494. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  495. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  496. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  497. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  498. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  499. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  500. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  501. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  502. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  503. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  504. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  505. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  506. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  507. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  508. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  509. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  510. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  511. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  512. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  513. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  514. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  515. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
  516. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
  517. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
  518. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
  519. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  520. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
  521. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
  522. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
  523. package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
  524. package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
  525. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  526. package/src/runtime/control-plane/routing/index.ts +0 -1
  527. package/src/runtime/control-plane/routing/route-policy.ts +0 -401
  528. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -5,7 +5,10 @@ import { ensureControllerHome } from '../../cli/repositories/controller-home';
5
5
  import {
6
6
  backupControlPlaneDatabase,
7
7
  controlPlaneDatabasePath,
8
+ openControlPlaneDatabaseChangeObserver,
8
9
  restoreControlPlaneDatabase,
10
+ sha256ControlPlaneDatabaseFile,
11
+ type ControlPlaneDatabaseChangeObserver,
9
12
  type ControlPlaneDatabaseInspection,
10
13
  } from '../control-plane/persistence/sqlite-store';
11
14
  import { loadRuntimeReleaseManifest } from './release-manifest';
@@ -21,6 +24,12 @@ export interface RuntimeDatabaseBackup {
21
24
  path: string;
22
25
  schemaVersion: number;
23
26
  createdAt: string;
27
+ /** Legacy partial mutation evidence retained for wire compatibility/audit. */
28
+ auditEventCount?: number;
29
+ /** Diagnostic cardinality captured with the same SQLite snapshot. */
30
+ recordCount?: number;
31
+ /** Whole SQLite snapshot identity; authoritative for rollback freshness. */
32
+ databaseSha256?: string;
24
33
  }
25
34
 
26
35
  export interface RuntimePublishedRelease {
@@ -34,7 +43,7 @@ export interface RuntimePublishedRelease {
34
43
  }
35
44
 
36
45
  export interface RuntimeReleaseAuthority {
37
- schemaVersion: 1;
46
+ schemaVersion: 2;
38
47
  status: 'committed';
39
48
  revision: number;
40
49
  fencingToken: string;
@@ -47,15 +56,51 @@ export interface RuntimeReleaseAuthority {
47
56
  export interface RuntimeReleaseStoreDependencies {
48
57
  backupDatabase(controllerHome: string, destinationPath: string): ControlPlaneDatabaseInspection;
49
58
  restoreDatabase(controllerHome: string, backupPath: string): ControlPlaneDatabaseInspection;
59
+ openDatabaseChangeObserver?(controllerHome: string): ControlPlaneDatabaseChangeObserver;
60
+ }
61
+
62
+ export interface PreparedRuntimeReleaseDatabaseBackup {
63
+ controllerHome: string;
64
+ activeReleaseId: string;
65
+ operationId: string;
66
+ path: string;
67
+ inspection: ControlPlaneDatabaseInspection;
68
+ databaseSha256: string;
69
+ takeIfCurrent(): { path: string; inspection: ControlPlaneDatabaseInspection; databaseSha256: string } | undefined;
70
+ release(): void;
71
+ discard(): void;
72
+ }
73
+
74
+ export type RuntimeDatabaseRollbackDisposition =
75
+ | 'restored_backup'
76
+ | 'preserved_newer_live_state'
77
+ | 'preserved_unversioned_backup';
78
+
79
+ export interface RuntimeReleaseRollbackResult {
80
+ authority: RuntimeReleaseAuthority;
81
+ databaseDisposition: RuntimeDatabaseRollbackDisposition;
82
+ liveAuditEventCount: number;
83
+ rollbackAuditEventCount?: number;
50
84
  }
51
85
 
52
86
  const DEFAULT_DEPENDENCIES: RuntimeReleaseStoreDependencies = {
53
87
  backupDatabase: backupControlPlaneDatabase,
54
88
  restoreDatabase: restoreControlPlaneDatabase,
89
+ openDatabaseChangeObserver: openControlPlaneDatabaseChangeObserver,
55
90
  };
56
91
 
57
92
  const RUNTIME_RELEASE_STATE_RESERVE_BYTES = 64 * 1024 * 1024;
58
93
 
94
+ interface RuntimeManifestIdentityCacheEntry {
95
+ size: number;
96
+ mtimeMs: number;
97
+ ctimeMs: number;
98
+ ino: number;
99
+ identity: Pick<RuntimePublishedRelease, 'releaseId' | 'artifactIdentity' | 'manifestPath' | 'manifestSha256' | 'workerProtocolVersion'>;
100
+ }
101
+
102
+ const runtimeManifestIdentityCache = new Map<string, RuntimeManifestIdentityCacheEntry>();
103
+
59
104
  function fileSize(path: string): number {
60
105
  try { return existsSync(path) ? statSync(path).size : 0; } catch { return 0; }
61
106
  }
@@ -79,6 +124,49 @@ function backupPath(controllerHome: string, releaseId: string, operationId: stri
79
124
  return join(ensureControllerHome(controllerHome), 'runtime', 'releases', 'backups', `${Date.now()}-${safe}.sqlite`);
80
125
  }
81
126
 
127
+ interface RuntimeReleasePublicationLease {
128
+ schemaVersion: 1;
129
+ pid: number;
130
+ operationId: string;
131
+ candidateReleasePath: string;
132
+ backupPath?: string;
133
+ }
134
+
135
+ function publicationLeaseDirectory(controllerHome: string): string {
136
+ return join(ensureControllerHome(controllerHome), 'runtime', 'releases', '.publication-leases');
137
+ }
138
+
139
+ function publicationLeasePath(controllerHome: string, operationId: string): string {
140
+ const safe = operationId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 120);
141
+ return join(publicationLeaseDirectory(controllerHome), `${safe}-${process.pid}.json`);
142
+ }
143
+
144
+ function writePublicationLease(
145
+ controllerHome: string,
146
+ operationId: string,
147
+ candidateManifestPath: string,
148
+ backupPathValue?: string,
149
+ ): () => void {
150
+ const path = publicationLeasePath(controllerHome, operationId);
151
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
152
+ const lease: RuntimeReleasePublicationLease = {
153
+ schemaVersion: 1,
154
+ pid: process.pid,
155
+ operationId,
156
+ candidateReleasePath: resolve(dirname(candidateManifestPath)),
157
+ ...(backupPathValue ? { backupPath: resolve(backupPathValue) } : {}),
158
+ };
159
+ const temporary = `${path}.${randomUUID().slice(0, 8)}.tmp`;
160
+ writeFileSync(temporary, `${JSON.stringify(lease)}\n`, { encoding: 'utf8', mode: 0o600 });
161
+ renameSync(temporary, path);
162
+ let released = false;
163
+ return () => {
164
+ if (released) return;
165
+ released = true;
166
+ rmSync(path, { force: true });
167
+ };
168
+ }
169
+
82
170
  function atomicWrite(path: string, value: unknown): void {
83
171
  const content = `${JSON.stringify(value, null, 2)}\n`;
84
172
  assertStorageHeadroom(path, {
@@ -94,14 +182,35 @@ function atomicWrite(path: string, value: unknown): void {
94
182
 
95
183
  function manifestRecord(controllerHome: string, manifestPath: string, publishedAt = new Date().toISOString()): RuntimePublishedRelease {
96
184
  const path = resolve(manifestPath);
97
- const manifest = loadRuntimeReleaseManifest(path, controllerHome);
98
- const bytes = readFileSync(path);
185
+ const file = statSync(path);
186
+ const cached = runtimeManifestIdentityCache.get(path);
187
+ const identity = cached
188
+ && cached.size === file.size
189
+ && cached.mtimeMs === file.mtimeMs
190
+ && cached.ctimeMs === file.ctimeMs
191
+ && cached.ino === file.ino
192
+ ? cached.identity
193
+ : (() => {
194
+ const manifest = loadRuntimeReleaseManifest(path, controllerHome);
195
+ const bytes = readFileSync(path);
196
+ const next: RuntimeManifestIdentityCacheEntry = {
197
+ size: file.size,
198
+ mtimeMs: file.mtimeMs,
199
+ ctimeMs: file.ctimeMs,
200
+ ino: Number(file.ino ?? 0),
201
+ identity: {
202
+ releaseId: manifest.releaseId,
203
+ artifactIdentity: manifest.artifactIdentity,
204
+ manifestPath: path,
205
+ manifestSha256: createHash('sha256').update(bytes).digest('hex'),
206
+ workerProtocolVersion: manifest.workerProtocolVersion,
207
+ },
208
+ };
209
+ runtimeManifestIdentityCache.set(path, next);
210
+ return next.identity;
211
+ })();
99
212
  return {
100
- releaseId: manifest.releaseId,
101
- artifactIdentity: manifest.artifactIdentity,
102
- manifestPath: path,
103
- manifestSha256: createHash('sha256').update(bytes).digest('hex'),
104
- workerProtocolVersion: manifest.workerProtocolVersion,
213
+ ...identity,
105
214
  publishedAt,
106
215
  };
107
216
  }
@@ -119,12 +228,77 @@ function validRelease(controllerHome: string, release: RuntimePublishedRelease |
119
228
  resolve(release.databaseBackup.path) === release.databaseBackup.path
120
229
  && Number.isInteger(release.databaseBackup.schemaVersion)
121
230
  && Number.isFinite(Date.parse(release.databaseBackup.createdAt))
231
+ && (release.databaseBackup.auditEventCount === undefined
232
+ || (Number.isSafeInteger(release.databaseBackup.auditEventCount) && release.databaseBackup.auditEventCount >= 0))
233
+ && (release.databaseBackup.recordCount === undefined
234
+ || (Number.isSafeInteger(release.databaseBackup.recordCount) && release.databaseBackup.recordCount >= 0))
235
+ && (release.databaseBackup.databaseSha256 === undefined
236
+ || /^[a-f0-9]{64}$/i.test(release.databaseBackup.databaseSha256))
122
237
  ));
123
238
  } catch {
124
239
  return false;
125
240
  }
126
241
  }
127
242
 
243
+ interface LegacyRuntimeReleaseActivationTransaction {
244
+ schemaVersion: 1;
245
+ operationId: string;
246
+ releaseSessionId?: string;
247
+ candidateReleaseId: string;
248
+ preActivationRevision: number;
249
+ preActivationActive: RuntimePublishedRelease;
250
+ preActivationPrevious?: RuntimePublishedRelease;
251
+ startedAt: string;
252
+ }
253
+
254
+ type LegacyRuntimeReleaseAuthorityV1 = Omit<RuntimeReleaseAuthority, 'schemaVersion'> & {
255
+ schemaVersion: 1;
256
+ activation?: LegacyRuntimeReleaseActivationTransaction;
257
+ };
258
+
259
+ function validRuntimeReleaseAuthority(controllerHome: string, value: RuntimeReleaseAuthority): boolean {
260
+ return value.schemaVersion === 2
261
+ && value.status === 'committed'
262
+ && Number.isInteger(value.revision)
263
+ && value.revision >= 1
264
+ && Boolean(value.fencingToken)
265
+ && Boolean(value.operationId)
266
+ && Number.isFinite(Date.parse(value.committedAt))
267
+ && validRelease(controllerHome, value.active)
268
+ && (value.previous === undefined || validRelease(controllerHome, value.previous));
269
+ }
270
+
271
+ export function migrateRuntimeReleaseAuthorityState(controllerHome: string): RuntimeReleaseAuthority | undefined {
272
+ const path = runtimeReleaseAuthorityPath(controllerHome);
273
+ if (!existsSync(path)) return undefined;
274
+ let raw: RuntimeReleaseAuthority | LegacyRuntimeReleaseAuthorityV1;
275
+ try {
276
+ raw = JSON.parse(readFileSync(path, 'utf8')) as RuntimeReleaseAuthority | LegacyRuntimeReleaseAuthorityV1;
277
+ } catch {
278
+ throw new Error('RUNTIME_RELEASE_AUTHORITY_MIGRATION_INVALID_JSON');
279
+ }
280
+ if (raw.schemaVersion === 2) {
281
+ if (!validRuntimeReleaseAuthority(controllerHome, raw as RuntimeReleaseAuthority)) {
282
+ throw new Error('RUNTIME_RELEASE_AUTHORITY_MIGRATION_INVALID_CURRENT');
283
+ }
284
+ return raw as RuntimeReleaseAuthority;
285
+ }
286
+ if (raw.schemaVersion !== 1) {
287
+ throw new Error(`RUNTIME_RELEASE_AUTHORITY_MIGRATION_UNSUPPORTED_SCHEMA: ${String((raw as { schemaVersion?: unknown }).schemaVersion)}`);
288
+ }
289
+ const legacy = raw as LegacyRuntimeReleaseAuthorityV1;
290
+ const { activation: _legacyActivation, ...physical } = legacy;
291
+ const migrated = {
292
+ ...physical,
293
+ schemaVersion: 2,
294
+ } satisfies RuntimeReleaseAuthority;
295
+ if (!validRuntimeReleaseAuthority(controllerHome, migrated)) {
296
+ throw new Error('RUNTIME_RELEASE_AUTHORITY_MIGRATION_INVALID_LEGACY_STATE');
297
+ }
298
+ atomicWrite(path, migrated);
299
+ return migrated;
300
+ }
301
+
128
302
  type RuntimeReleaseAuthorityRead =
129
303
  | { state: 'missing' }
130
304
  | { state: 'valid'; authority: RuntimeReleaseAuthority }
@@ -135,17 +309,9 @@ function inspectRuntimeReleaseAuthority(controllerHome: string): RuntimeReleaseA
135
309
  if (!existsSync(path)) return { state: 'missing' };
136
310
  try {
137
311
  const value = JSON.parse(readFileSync(path, 'utf8')) as RuntimeReleaseAuthority;
138
- if (
139
- value.schemaVersion !== 1
140
- || value.status !== 'committed'
141
- || !Number.isInteger(value.revision)
142
- || value.revision < 1
143
- || !value.fencingToken
144
- || !value.operationId
145
- || !Number.isFinite(Date.parse(value.committedAt))
146
- || !validRelease(controllerHome, value.active)
147
- || (value.previous !== undefined && !validRelease(controllerHome, value.previous))
148
- ) return { state: 'invalid', reason: 'authority fields or referenced release evidence are invalid' };
312
+ if (!validRuntimeReleaseAuthority(controllerHome, value)) {
313
+ return { state: 'invalid', reason: 'authority fields or referenced release evidence are invalid' };
314
+ }
149
315
  return { state: 'valid', authority: value };
150
316
  } catch (error) {
151
317
  return { state: 'invalid', reason: error instanceof Error ? error.message : String(error) };
@@ -166,7 +332,8 @@ export function readRuntimeReleaseAuthority(controllerHome: string): RuntimeRele
166
332
  }
167
333
 
168
334
  function writeRuntimeReleaseAuthority(controllerHome: string, authority: RuntimeReleaseAuthority): RuntimeReleaseAuthority {
169
- if (!validRelease(controllerHome, authority.active) || (authority.previous && !validRelease(controllerHome, authority.previous))) {
335
+ if (!validRelease(controllerHome, authority.active)
336
+ || (authority.previous && !validRelease(controllerHome, authority.previous))) {
170
337
  throw new Error('RUNTIME_RELEASE_AUTHORITY_INVALID');
171
338
  }
172
339
  atomicWrite(runtimeReleaseAuthorityPath(controllerHome), authority);
@@ -192,7 +359,7 @@ export function ensureActiveRuntimeRelease(
192
359
  return current;
193
360
  }
194
361
  return writeRuntimeReleaseAuthority(controllerHome, {
195
- schemaVersion: 1,
362
+ schemaVersion: 2,
196
363
  status: 'committed',
197
364
  revision: 1,
198
365
  fencingToken: randomUUID(),
@@ -202,18 +369,88 @@ export function ensureActiveRuntimeRelease(
202
369
  });
203
370
  }
204
371
 
372
+ export function prepareRuntimeReleaseDatabaseBackup(
373
+ controllerHome: string,
374
+ operationId: string,
375
+ dependencies: RuntimeReleaseStoreDependencies = DEFAULT_DEPENDENCIES,
376
+ ): PreparedRuntimeReleaseDatabaseBackup | undefined {
377
+ if (!operationId.trim()) throw new Error('RUNTIME_RELEASE_OPERATION_ID_REQUIRED');
378
+ const current = mutableRuntimeReleaseAuthority(controllerHome);
379
+ if (!current) return undefined;
380
+ assertDatabaseBackupHeadroom(controllerHome, 'prepare_runtime_release_database_backup');
381
+ const observer = (dependencies.openDatabaseChangeObserver ?? openControlPlaneDatabaseChangeObserver)(controllerHome);
382
+ const initialDataVersion = observer.dataVersion();
383
+ const path = backupPath(controllerHome, current.active.releaseId, operationId);
384
+ const releaseLease = writePublicationLease(controllerHome, operationId, current.active.manifestPath, path);
385
+ let settled = false;
386
+ try {
387
+ const inspection = dependencies.backupDatabase(controllerHome, path);
388
+ const databaseSha256 = sha256ControlPlaneDatabaseFile(path);
389
+ const capturedDataVersion = observer.dataVersion();
390
+ if (capturedDataVersion !== initialDataVersion) {
391
+ observer.close();
392
+ rmSync(path, { force: true });
393
+ releaseLease();
394
+ return undefined;
395
+ }
396
+ const discard = () => {
397
+ if (settled) return;
398
+ settled = true;
399
+ observer.close();
400
+ rmSync(path, { force: true });
401
+ releaseLease();
402
+ };
403
+ return {
404
+ controllerHome: resolve(controllerHome),
405
+ activeReleaseId: current.active.releaseId,
406
+ operationId,
407
+ path: resolve(path),
408
+ inspection,
409
+ databaseSha256,
410
+ takeIfCurrent() {
411
+ if (settled) return undefined;
412
+ settled = true;
413
+ try {
414
+ const currentDataVersion = observer.dataVersion();
415
+ if (currentDataVersion !== capturedDataVersion) {
416
+ rmSync(path, { force: true });
417
+ releaseLease();
418
+ return undefined;
419
+ }
420
+ return { path: resolve(path), inspection, databaseSha256 };
421
+ } catch (error) {
422
+ rmSync(path, { force: true });
423
+ releaseLease();
424
+ throw error;
425
+ } finally {
426
+ observer.close();
427
+ }
428
+ },
429
+ release: releaseLease,
430
+ discard,
431
+ };
432
+ } catch (error) {
433
+ observer.close();
434
+ rmSync(path, { force: true });
435
+ releaseLease();
436
+ throw error;
437
+ }
438
+ }
439
+
205
440
  export function publishRuntimeRelease(
206
441
  controllerHome: string,
207
442
  manifestPath: string,
208
443
  operationId: string,
209
444
  dependencies: RuntimeReleaseStoreDependencies = DEFAULT_DEPENDENCIES,
445
+ preparedDatabaseBackup?: PreparedRuntimeReleaseDatabaseBackup,
210
446
  ): RuntimeReleaseAuthority {
211
447
  if (!operationId.trim()) throw new Error('RUNTIME_RELEASE_OPERATION_ID_REQUIRED');
212
448
  const candidate = manifestRecord(controllerHome, manifestPath);
213
449
  const current = mutableRuntimeReleaseAuthority(controllerHome);
214
450
  if (!current) {
451
+ preparedDatabaseBackup?.discard();
215
452
  return writeRuntimeReleaseAuthority(controllerHome, {
216
- schemaVersion: 1,
453
+ schemaVersion: 2,
217
454
  status: 'committed',
218
455
  revision: 1,
219
456
  fencingToken: randomUUID(),
@@ -222,24 +459,73 @@ export function publishRuntimeRelease(
222
459
  committedAt: new Date().toISOString(),
223
460
  });
224
461
  }
225
- if (sameRelease(current.active, candidate)) return current;
226
- assertDatabaseBackupHeadroom(controllerHome, 'publish_runtime_release_database_backup');
227
- const backup = backupPath(controllerHome, current.active.releaseId, operationId);
228
- const inspection = dependencies.backupDatabase(controllerHome, backup);
462
+ if (sameRelease(current.active, candidate)) {
463
+ preparedDatabaseBackup?.discard();
464
+ return current;
465
+ }
466
+ const preparedMatches = Boolean(
467
+ preparedDatabaseBackup
468
+ && preparedDatabaseBackup.controllerHome === resolve(controllerHome)
469
+ && preparedDatabaseBackup.activeReleaseId === current.active.releaseId
470
+ && preparedDatabaseBackup.operationId === operationId,
471
+ );
472
+ const pendingBackupPath = preparedMatches && preparedDatabaseBackup
473
+ ? preparedDatabaseBackup.path
474
+ : backupPath(controllerHome, current.active.releaseId, operationId);
475
+ let releaseLease = () => {};
476
+ try {
477
+ let prepared: { path: string; inspection: ControlPlaneDatabaseInspection; databaseSha256: string } | undefined;
478
+ if (preparedMatches && preparedDatabaseBackup) {
479
+ prepared = preparedDatabaseBackup.takeIfCurrent();
480
+ } else {
481
+ preparedDatabaseBackup?.discard();
482
+ releaseLease = writePublicationLease(controllerHome, operationId, candidate.manifestPath, pendingBackupPath);
483
+ }
484
+ // A prepared backup lease initially protects Stable A. Refresh the same
485
+ // lease with Candidate B before publication so cleanup protects both sides
486
+ // of the complete authority transition.
487
+ if (prepared || preparedMatches) {
488
+ releaseLease = writePublicationLease(controllerHome, operationId, candidate.manifestPath, pendingBackupPath);
489
+ }
490
+ let backup: string;
491
+ let inspection: ControlPlaneDatabaseInspection;
492
+ let databaseSha256: string;
493
+ if (prepared) {
494
+ backup = prepared.path;
495
+ inspection = prepared.inspection;
496
+ databaseSha256 = prepared.databaseSha256;
497
+ } else {
498
+ assertDatabaseBackupHeadroom(controllerHome, 'publish_runtime_release_database_backup');
499
+ backup = pendingBackupPath;
500
+ inspection = dependencies.backupDatabase(controllerHome, backup);
501
+ databaseSha256 = sha256ControlPlaneDatabaseFile(backup);
502
+ }
229
503
  const committedAt = new Date().toISOString();
230
- return writeRuntimeReleaseAuthority(controllerHome, {
231
- schemaVersion: 1,
504
+ const authority = writeRuntimeReleaseAuthority(controllerHome, {
505
+ schemaVersion: 2,
232
506
  status: 'committed',
233
507
  revision: current.revision + 1,
234
508
  fencingToken: randomUUID(),
235
509
  active: { ...candidate, publishedAt: committedAt },
236
510
  previous: {
237
511
  ...current.active,
238
- databaseBackup: { path: resolve(backup), schemaVersion: inspection.schemaVersion, createdAt: committedAt },
512
+ databaseBackup: {
513
+ path: resolve(backup),
514
+ schemaVersion: inspection.schemaVersion,
515
+ createdAt: committedAt,
516
+ auditEventCount: inspection.auditEventCount,
517
+ recordCount: inspection.recordCount,
518
+ databaseSha256,
519
+ },
239
520
  },
240
521
  operationId,
241
522
  committedAt,
242
523
  });
524
+ return authority;
525
+ } finally {
526
+ releaseLease();
527
+ preparedDatabaseBackup?.release();
528
+ }
243
529
  }
244
530
 
245
531
  export function revertInitialRuntimeReleasePublication(controllerHome: string, operationId: string): void {
@@ -251,11 +537,11 @@ export function revertInitialRuntimeReleasePublication(controllerHome: string, o
251
537
  rmSync(runtimeReleaseAuthorityPath(controllerHome), { force: true });
252
538
  }
253
539
 
254
- export function rollbackRuntimeRelease(
540
+ export function rollbackRuntimeReleaseWithResult(
255
541
  controllerHome: string,
256
542
  operationId: string,
257
543
  dependencies: RuntimeReleaseStoreDependencies = DEFAULT_DEPENDENCIES,
258
- ): RuntimeReleaseAuthority {
544
+ ): RuntimeReleaseRollbackResult {
259
545
  if (!operationId.trim()) throw new Error('RUNTIME_RELEASE_OPERATION_ID_REQUIRED');
260
546
  const current = mutableRuntimeReleaseAuthority(controllerHome);
261
547
  const target = current?.previous;
@@ -267,11 +553,28 @@ export function rollbackRuntimeRelease(
267
553
  );
268
554
  const currentBackup = backupPath(controllerHome, current.active.releaseId, operationId);
269
555
  const currentInspection = dependencies.backupDatabase(controllerHome, currentBackup);
270
- dependencies.restoreDatabase(controllerHome, target.databaseBackup.path);
556
+ const currentDatabaseSha256 = sha256ControlPlaneDatabaseFile(currentBackup);
557
+ const rollbackDatabaseSha256 = target.databaseBackup.databaseSha256;
558
+ const rollbackAuditEventCount = target.databaseBackup.auditEventCount;
559
+ if (rollbackAuditEventCount !== undefined && currentInspection.auditEventCount < rollbackAuditEventCount) {
560
+ rmSync(currentBackup, { force: true });
561
+ throw new Error(`RUNTIME_RELEASE_DATABASE_GENERATION_REGRESSED: rollback=${rollbackAuditEventCount}; live=${currentInspection.auditEventCount}`);
562
+ }
563
+ // auditEventCount covers only record-store mutations and is retained as
564
+ // diagnostic/legacy evidence. Whole-snapshot identity is the only proof that
565
+ // no SQLite domain state changed after cutover.
566
+ const databaseDisposition: RuntimeDatabaseRollbackDisposition = rollbackDatabaseSha256 === undefined
567
+ ? 'preserved_unversioned_backup'
568
+ : currentDatabaseSha256 === rollbackDatabaseSha256
569
+ ? 'restored_backup'
570
+ : 'preserved_newer_live_state';
571
+ if (databaseDisposition === 'restored_backup') {
572
+ dependencies.restoreDatabase(controllerHome, target.databaseBackup.path);
573
+ }
271
574
  const committedAt = new Date().toISOString();
272
575
  try {
273
- return writeRuntimeReleaseAuthority(controllerHome, {
274
- schemaVersion: 1,
576
+ const authority = writeRuntimeReleaseAuthority(controllerHome, {
577
+ schemaVersion: 2,
275
578
  status: 'committed',
276
579
  revision: current.revision + 1,
277
580
  fencingToken: randomUUID(),
@@ -285,17 +588,73 @@ export function rollbackRuntimeRelease(
285
588
  },
286
589
  previous: {
287
590
  ...current.active,
288
- databaseBackup: { path: resolve(currentBackup), schemaVersion: currentInspection.schemaVersion, createdAt: committedAt },
591
+ databaseBackup: {
592
+ path: resolve(currentBackup),
593
+ schemaVersion: currentInspection.schemaVersion,
594
+ createdAt: committedAt,
595
+ auditEventCount: currentInspection.auditEventCount,
596
+ recordCount: currentInspection.recordCount,
597
+ databaseSha256: currentDatabaseSha256,
598
+ },
289
599
  },
290
600
  operationId,
291
601
  committedAt,
292
602
  });
603
+ return {
604
+ authority,
605
+ databaseDisposition,
606
+ liveAuditEventCount: currentInspection.auditEventCount,
607
+ ...(rollbackAuditEventCount === undefined ? {} : { rollbackAuditEventCount }),
608
+ };
293
609
  } catch (error) {
294
- dependencies.restoreDatabase(controllerHome, currentBackup);
610
+ if (databaseDisposition === 'restored_backup') {
611
+ dependencies.restoreDatabase(controllerHome, currentBackup);
612
+ }
295
613
  throw error;
296
614
  }
297
615
  }
298
616
 
617
+ export function rollbackRuntimeRelease(
618
+ controllerHome: string,
619
+ operationId: string,
620
+ dependencies: RuntimeReleaseStoreDependencies = DEFAULT_DEPENDENCIES,
621
+ ): RuntimeReleaseAuthority {
622
+ return rollbackRuntimeReleaseWithResult(controllerHome, operationId, dependencies).authority;
623
+ }
624
+
625
+ /**
626
+ * Failed activation is transaction compensation, not a user-requested reverse
627
+ * release transition. Once the physical rollback has restored the old active
628
+ * release, restore the exact pre-activation active/previous topology while
629
+ * keeping authority revision monotonic and rotating the fence.
630
+ */
631
+ export function reconcileFailedRuntimeReleaseActivationAuthority(
632
+ controllerHome: string,
633
+ before: RuntimeReleaseAuthority,
634
+ failedReleaseId: string,
635
+ operationId: string,
636
+ ): RuntimeReleaseAuthority {
637
+ if (!operationId.trim()) throw new Error('RUNTIME_RELEASE_OPERATION_ID_REQUIRED');
638
+ const current = mutableRuntimeReleaseAuthority(controllerHome);
639
+ if (!current) throw new Error('RUNTIME_RELEASE_FAILED_ACTIVATION_AUTHORITY_MISSING');
640
+ if (!sameRelease(current.active, before.active)) {
641
+ throw new Error('RUNTIME_RELEASE_FAILED_ACTIVATION_ACTIVE_MISMATCH');
642
+ }
643
+ if (current.previous?.releaseId !== failedReleaseId) {
644
+ throw new Error('RUNTIME_RELEASE_FAILED_ACTIVATION_CANDIDATE_MISMATCH');
645
+ }
646
+ return writeRuntimeReleaseAuthority(controllerHome, {
647
+ schemaVersion: 2,
648
+ status: 'committed',
649
+ revision: current.revision + 1,
650
+ fencingToken: randomUUID(),
651
+ active: before.active,
652
+ ...(before.previous ? { previous: before.previous } : {}),
653
+ operationId,
654
+ committedAt: new Date().toISOString(),
655
+ });
656
+ }
657
+
299
658
  export function activeRuntimeReleaseManifest(controllerHome: string): RuntimeReleaseManifest | undefined {
300
659
  const authority = readRuntimeReleaseAuthority(controllerHome);
301
660
  return authority ? loadRuntimeReleaseManifest(authority.active.manifestPath, controllerHome) : undefined;