@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
@@ -8,10 +8,11 @@ import { listRepositories, repositoryCheckoutLifecycle, selectRepositoryCheckout
8
8
  import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
9
9
  import { ensureManagedWorkspace } from '../../execution/managed-workspace';
10
10
  import { getControllerSession } from '../../../../packages/kernel/controller/api/index';
11
- import { getWorkContract, recordWorkEvidenceState, resumeRetainedCancelledWorkContract, transitionWorkContractPhase, updateWorkContract } from '../../../../packages/kernel/work/api/index';
11
+ import { getWorkContract, recordWorkEvidenceState, transitionWorkContractPhase, updateWorkContract } from '../../../../packages/kernel/work/api/index';
12
12
  import { gitCommitAtRef, gitWorktreeSnapshot } from './work-lifecycle-audit';
13
- import { findWorkPathScopeViolation } from './work-path-scope';
14
13
  import { readWorkHandle, writeWorkHandle, type WorkHandleState } from './work-handle-store';
14
+ import { rearmFailedPreservedWorkHandle } from './work-handle-authority';
15
+ import { hasSettledWorkDeliveryReceipt } from './work-completion-authority';
15
16
 
16
17
  export interface RetainedWorkResumeIdentity {
17
18
  principalId: string;
@@ -19,16 +20,6 @@ export interface RetainedWorkResumeIdentity {
19
20
  controllerInstanceId: string;
20
21
  }
21
22
 
22
- export interface ReauthorizeRetainedCancelledWorkInput {
23
- controllerHome: string;
24
- repository: RepositoryRecord;
25
- workId: string;
26
- identity: RetainedWorkResumeIdentity;
27
- requestedBy?: string;
28
- approvalConfirmed?: boolean;
29
- prepareDependencies?: boolean;
30
- }
31
-
32
23
  export interface EnsureRunningRepositoryWorkCheckoutInput {
33
24
  controllerHome: string;
34
25
  repository: RepositoryRecord;
@@ -72,7 +63,7 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
72
63
  const { controllerHome, repository, work, handle, identity } = input;
73
64
  const receipt = handle.cleanupReceipt;
74
65
  if (handle.state !== 'cleaned' || receipt?.terminalOutcome !== 'blocked_terminal') return undefined;
75
- if (work.completionReceipt || work.completionOutcome || work.status !== 'blocked' || work.phase !== 'delivery') {
66
+ if (work.completionReceipt || work.completionOutcome || work.dispatchState !== 'blocked' || work.phase !== 'delivery') {
76
67
  throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_LIFECYCLE_CONFLICT: ${work.workId}`);
77
68
  }
78
69
  if (!['none', 'partial', 'valid', 'stale'].includes(work.evidenceState)) {
@@ -150,10 +141,6 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
150
141
  if (!changed.ok) throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_DIFF_UNAVAILABLE: ${work.workId}`);
151
142
  const changedPaths = normalizedPaths(changed.stdout.split(/\r?\n/));
152
143
  if (changedPaths.length === 0) throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_ZERO_DELTA: ${work.workId}`);
153
- const scopeViolation = findWorkPathScopeViolation(work, changedPaths);
154
- if (scopeViolation) {
155
- throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_SCOPE_VIOLATION: ${scopeViolation.kind}:${scopeViolation.path}`);
156
- }
157
144
  const recordedChangedPaths = normalizedPaths(work.scopeEvidence?.actualChangedPaths ?? []);
158
145
  if (recordedChangedPaths.length > 0 && JSON.stringify(recordedChangedPaths) !== JSON.stringify(changedPaths)) {
159
146
  throw new Error(`WORK_CONTINUE_ARCHIVED_DELIVERY_PATH_IDENTITY_MISMATCH: ${work.workId}`);
@@ -167,6 +154,7 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
167
154
  const workspace = ensureManagedWorkspace(controllerHome, repository, {
168
155
  requestId: `${work.workId}:archived-delivery-recovery:${candidateRevision}`,
169
156
  title: `${work.objective} archived delivery recovery`,
157
+ associatedWorkId: work.workId,
170
158
  branchName,
171
159
  baseRef: candidateRevision,
172
160
  prepareDependencies: input.prepareDependencies === true,
@@ -193,7 +181,6 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
193
181
  });
194
182
  transitionWorkContractPhase(store, work.workId, {
195
183
  phase: 'verification',
196
- status: 'running',
197
184
  state: 'active',
198
185
  dispatchState: 'running',
199
186
  summary: `Archived candidate ${candidateRevision} was rehydrated from verified blocked-terminal preservation; fresh verification is required before delivery.`,
@@ -225,114 +212,145 @@ function restoreArchivedBlockedDeliveryCheckout(input: {
225
212
  }
226
213
 
227
214
  /**
228
- * Re-establish the checkout binding for a still-running isolated Work only
229
- * when durable and Git evidence prove that the missing checkout carried no
230
- * repository delta. Any dirty, divergent, committed, or cleaned evidence
231
- * fails closed so recovery never becomes permission to discard source.
215
+ * Rehydrate a committed candidate whose validation process disappeared before
216
+ * delivery/cleanup. The candidate is safe to revisit only when the durable
217
+ * WorkHandle, Git object database, and recorded changed-path identity all agree.
218
+ * A missing cleanup receipt is intentional here: this is a pre-delivery
219
+ * recovery, not a second delivery authority.
232
220
  */
233
- export function ensureRunningRepositoryWorkCheckout(
234
- input: EnsureRunningRepositoryWorkCheckoutInput,
235
- ): { reconstructedCheckout: boolean } {
236
- const { controllerHome, repository, workId, identity } = input;
237
- const store = { controllerHome, repoId: repository.repoId };
238
- const work = getWorkContract(store, workId);
239
- if (!work || ['cancelled', 'completed', 'failed'].includes(work.status)) return { reconstructedCheckout: false };
240
- if (work.workKind !== 'repository_change' || work.worktreePolicy.required !== true) return { reconstructedCheckout: false };
241
-
242
- const recordedCheckoutId = work.checkoutId?.trim();
243
- const recordedWorktree = work.worktreeRef?.trim();
244
- if (!recordedCheckoutId || !recordedWorktree) return { reconstructedCheckout: false };
245
-
246
- const registryRepository = listRepositories(controllerHome, { includeRemoved: true })
247
- .find((candidate) => candidate.repoId === repository.repoId);
248
- if (!registryRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
249
- const checkoutRecord = registryRepository.checkouts.find((candidate) => candidate.checkoutId === recordedCheckoutId);
250
- const checkoutActive = checkoutRecord ? repositoryCheckoutLifecycle(checkoutRecord) === 'active' : false;
251
- const worktreePresent = existsSync(recordedWorktree);
252
- if (checkoutActive && worktreePresent) return { reconstructedCheckout: false };
253
- if (checkoutActive) throw new Error(`WORK_CONTINUE_CHECKOUT_PRESERVATION_AMBIGUOUS: ${workId}`);
221
+ function restoreArchivedPendingCandidateCheckout(input: {
222
+ controllerHome: string;
223
+ repository: RepositoryRecord;
224
+ work: NonNullable<ReturnType<typeof getWorkContract>>;
225
+ handle: WorkHandleState;
226
+ identity: RetainedWorkResumeIdentity;
227
+ }): { reconstructedCheckout: boolean } | undefined {
228
+ const { controllerHome, repository, work, handle, identity } = input;
229
+ if (work.semanticState !== 'open') return undefined;
230
+ if (work.phase !== 'verification' || work.workKind !== 'repository_change') return undefined;
231
+ if (handle.state !== 'failed'
232
+ || handle.finalization.validation !== 'failed'
233
+ || handle.finalization.commit !== 'done'
234
+ || handle.finalization.merge !== 'pending'
235
+ || handle.finalization.branchCleanup !== 'pending'
236
+ || handle.finalization.worktreeCleanup !== 'pending'
237
+ || handle.cleanupReceipt
238
+ || work.completionReceipt
239
+ || work.completionOutcome) return undefined;
254
240
 
255
- const handle = readWorkHandle(controllerHome, repository.repoId, workId);
256
- if (!handle) throw new Error(`WORK_CONTINUE_HANDLE_REQUIRED: ${workId}`);
257
- if (handle.repositoryId !== repository.repoId || (handle.workContractId && handle.workContractId !== workId)) {
258
- throw new Error(`WORK_CONTINUE_HANDLE_IDENTITY_MISMATCH: ${workId}`);
241
+ const candidateRevision = handle.expectedHead?.trim();
242
+ const baseRevisionRaw = work.baseRevision?.trim() || handle.baseCommit?.trim();
243
+ const recordedChangedPaths = normalizedPaths(work.scopeEvidence?.actualChangedPaths ?? []);
244
+ if (!candidateRevision || !baseRevisionRaw || recordedChangedPaths.length === 0) {
245
+ return undefined;
259
246
  }
260
- if (handle.principalId !== identity.principalId) throw new Error(`WORK_CONTINUE_HANDLE_PRINCIPAL_MISMATCH: ${workId}`);
261
- if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
262
- throw new Error(`WORK_CONTINUE_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
247
+
248
+ const candidateCommit = gitCommitAtRef(repository.canonicalRoot, candidateRevision);
249
+ if (candidateCommit !== candidateRevision) {
250
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_MISSING: ${work.workId}`);
263
251
  }
264
- const archivedDelivery = restoreArchivedBlockedDeliveryCheckout({
265
- controllerHome, repository, work, handle, identity, prepareDependencies: input.prepareDependencies,
266
- });
267
- if (archivedDelivery) return archivedDelivery;
268
- if (['committed', 'merged', 'cleaned', 'failed_terminal_cleanup'].includes(handle.state)
269
- || handle.finalization.commit === 'done'
270
- || handle.finalization.merge === 'done'
271
- || handle.cleanupReceipt?.complete === true) {
272
- throw new Error(`WORK_CONTINUE_DELIVERY_OR_CLEANUP_CONFLICT: ${workId}`);
252
+ const baseRevision = gitCommitAtRef(repository.canonicalRoot, baseRevisionRaw);
253
+ if (!baseRevision) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_BASE_MISSING: ${work.workId}`);
254
+ if (!git(repository.canonicalRoot, ['merge-base', '--is-ancestor', baseRevision, candidateRevision]).ok) {
255
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_REVISION_AMBIGUOUS: ${work.workId}`);
273
256
  }
274
257
 
275
- const actualChangedPaths = work.scopeEvidence?.actualChangedPaths;
276
- if (!actualChangedPaths || actualChangedPaths.length !== 0
277
- || work.checks.length !== 0
278
- || work.checkRefs.length !== 0
279
- || work.evidenceState !== 'none') {
280
- throw new Error(`WORK_CONTINUE_ZERO_DELTA_PROOF_REQUIRED: ${workId}`);
281
- }
282
- const recordedBase = work.baseRevision?.trim();
283
- if (!recordedBase) throw new Error(`WORK_CONTINUE_BASE_REVISION_REQUIRED: ${workId}`);
284
- const baseRevision = gitCommitAtRef(repository.canonicalRoot, recordedBase);
285
- if (!baseRevision) throw new Error(`WORK_CONTINUE_BASE_REVISION_MISSING: ${workId}`);
286
- const handleBase = handle.baseCommit ? gitCommitAtRef(repository.canonicalRoot, handle.baseCommit) : undefined;
287
- const handleHead = handle.expectedHead ? gitCommitAtRef(repository.canonicalRoot, handle.expectedHead) : undefined;
288
- if ((handle.baseCommit && handleBase !== baseRevision) || (handle.expectedHead && handleHead !== baseRevision)) {
289
- throw new Error(`WORK_CONTINUE_REVISION_AMBIGUOUS: ${workId}`);
258
+ const targetBranch = handle.deliveryTargetBranch?.trim() || repository.defaultBranch?.trim();
259
+ if (!targetBranch) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_TARGET_REQUIRED: ${work.workId}`);
260
+ if (git(repository.canonicalRoot, ['merge-base', '--is-ancestor', candidateRevision, targetBranch]).ok) {
261
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_ALREADY_INTEGRATED: ${work.workId}`);
290
262
  }
291
- if (handle.branch) {
292
- const historicalBranchHead = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${handle.branch}`);
293
- if (historicalBranchHead && historicalBranchHead !== baseRevision) {
294
- throw new Error(`WORK_CONTINUE_UNIQUE_COMMIT_CONFLICT: ${workId}`);
263
+ const changed = git(repository.canonicalRoot, ['diff', '--name-only', `${baseRevision}..${candidateRevision}`]);
264
+ if (!changed.ok) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_DIFF_UNAVAILABLE: ${work.workId}`);
265
+ const candidateChangedPaths = normalizedPaths(changed.stdout.split(/\r?\n/));
266
+ if (candidateChangedPaths.length === 0) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_ZERO_DELTA: ${work.workId}`);
267
+
268
+ // A delivery candidate can contain a canonical target advancement as a
269
+ // merge parent. Only the unique parent already reachable from the current
270
+ // target branch may be treated as target history; the Work-owned delta is
271
+ // then measured from that parent to the candidate. This keeps unrelated
272
+ // target changes out of Work scope evidence while still requiring the exact
273
+ // candidate tree and recorded path identity to agree.
274
+ let workOwnedChangedPaths = candidateChangedPaths;
275
+ let deliveryBaseCommit = baseRevision;
276
+ const parents = git(repository.canonicalRoot, ['rev-list', '--parents', '-n', '1', candidateRevision]);
277
+ if (parents.ok) {
278
+ const parentRevisions = parents.stdout.split(/\s+/).slice(1).filter(Boolean);
279
+ const targetParents = parentRevisions.filter((parent) =>
280
+ git(repository.canonicalRoot, ['merge-base', '--is-ancestor', parent, targetBranch]).ok,
281
+ );
282
+ if (parentRevisions.length === 2 && targetParents.length === 1 && targetParents[0] !== baseRevision) {
283
+ const targetParent = targetParents[0];
284
+ const targetRelative = git(repository.canonicalRoot, ['diff', '--name-only', `${targetParent}..${candidateRevision}`]);
285
+ if (!targetRelative.ok) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_TARGET_RELATIVE_DIFF_UNAVAILABLE: ${work.workId}`);
286
+ workOwnedChangedPaths = normalizedPaths(targetRelative.stdout.split(/\r?\n/));
287
+ if (workOwnedChangedPaths.length === 0) throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_ZERO_WORK_DELTA: ${work.workId}`);
288
+ deliveryBaseCommit = targetParent;
289
+ const expectedRecordedPaths = normalizedPaths([...workOwnedChangedPaths, ...normalizedPaths(
290
+ git(repository.canonicalRoot, ['diff', '--name-only', `${baseRevision}..${targetParent}`]).stdout.split(/\r?\n/),
291
+ )]);
292
+ if (JSON.stringify(recordedChangedPaths) !== JSON.stringify(candidateChangedPaths)
293
+ && JSON.stringify(recordedChangedPaths) !== JSON.stringify(workOwnedChangedPaths)
294
+ && JSON.stringify(recordedChangedPaths) !== JSON.stringify(expectedRecordedPaths)) {
295
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_PATH_IDENTITY_MISMATCH: ${work.workId}`);
296
+ }
295
297
  }
296
298
  }
297
- if (worktreePresent) {
298
- const retainedSnapshot = gitWorktreeSnapshot(recordedWorktree);
299
- if (!retainedSnapshot || !retainedSnapshot.clean || retainedSnapshot.head !== baseRevision || (handle.branch && retainedSnapshot.branch !== handle.branch)) {
300
- throw new Error(`WORK_CONTINUE_ZERO_DELTA_PHYSICAL_CONFLICT: ${workId}`);
301
- }
299
+ if (deliveryBaseCommit === baseRevision && JSON.stringify(recordedChangedPaths) !== JSON.stringify(candidateChangedPaths)) {
300
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_PATH_IDENTITY_MISMATCH: ${work.workId}`);
302
301
  }
303
302
 
304
- const branchName = `work/resume-${workId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 42)}-${baseRevision.slice(0, 12)}`;
303
+ const branchName = `work/resume-pending-candidate-${work.workId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 34)}-${candidateRevision.slice(0, 12)}`;
305
304
  const existingResumeBranch = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${branchName}`);
306
- if (existingResumeBranch && existingResumeBranch !== baseRevision) {
307
- throw new Error(`WORK_CONTINUE_RECONSTRUCTION_BRANCH_CONFLICT: ${workId}`);
305
+ if (existingResumeBranch && existingResumeBranch !== candidateRevision) {
306
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_BRANCH_CONFLICT: ${work.workId}`);
308
307
  }
309
308
  const workspace = ensureManagedWorkspace(controllerHome, repository, {
310
- requestId: `${workId}:active-checkout-recovery:${baseRevision}`,
311
- title: `${work.objective} checkout recovery`,
309
+ requestId: `${work.workId}:pending-candidate-recovery:${candidateRevision}`,
310
+ title: `${work.objective} pending candidate recovery`,
311
+ associatedWorkId: work.workId,
312
312
  branchName,
313
- baseRef: baseRevision,
314
- prepareDependencies: input.prepareDependencies === true,
313
+ baseRef: candidateRevision,
315
314
  });
316
315
  if (!workspace.managed || !workspace.checkoutId || !workspace.root || !workspace.branch) {
317
- throw new Error(`WORK_CONTINUE_RECONSTRUCTION_FAILED: ${workId}`);
316
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_RECONSTRUCTION_FAILED: ${work.workId}`);
318
317
  }
319
318
  const refreshedRepository = listRepositories(controllerHome, { includeRemoved: true })
320
319
  .find((candidate) => candidate.repoId === repository.repoId);
321
- if (!refreshedRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
320
+ if (!refreshedRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${work.workId}`);
322
321
  const reconstructed = selectRepositoryCheckout(refreshedRepository, workspace.checkoutId);
323
322
  const reconstructedStatus = repositoryGitStatus(reconstructed);
324
- if (!reconstructedStatus.clean || reconstructedStatus.head !== baseRevision || reconstructedStatus.branch !== workspace.branch) {
325
- throw new Error(`WORK_CONTINUE_RECONSTRUCTION_REVISION_MISMATCH: ${workId}`);
323
+ if (!reconstructedStatus.clean || reconstructedStatus.head !== candidateRevision || reconstructedStatus.branch !== workspace.branch) {
324
+ throw new Error(`WORK_CONTINUE_COMMITTED_CANDIDATE_RECONSTRUCTION_REVISION_MISMATCH: ${work.workId}`);
326
325
  }
327
326
 
328
- updateWorkContract(store, workId, {
327
+ const at = new Date().toISOString();
328
+ const store = { controllerHome, repoId: repository.repoId };
329
+ updateWorkContract(store, work.workId, {
329
330
  checkoutId: workspace.checkoutId,
330
331
  worktreeRef: workspace.root,
331
- baseRevision,
332
332
  controllerInstanceId: identity.controllerInstanceId,
333
- continuationPrompt: `Continue work ${repository.repoId}: ${work.objective.slice(0, 500)}. The prior managed checkout was absent; Forge reconstructed an exact zero-delta checkout at ${baseRevision}.`,
333
+ ...(deliveryBaseCommit !== baseRevision
334
+ ? {
335
+ scopeEvidence: {
336
+ initialLikelyPaths: work.scopeEvidence?.initialLikelyPaths ?? [],
337
+ inspectedPaths: work.scopeEvidence?.inspectedPaths ?? [],
338
+ actualChangedPaths: workOwnedChangedPaths,
339
+ recordedAt: at,
340
+ },
341
+ }
342
+ : {}),
343
+ continuationPrompt: `Continue work ${repository.repoId}: ${work.objective.slice(0, 500)}. Forge rehydrated exact pending candidate ${candidateRevision}; rerun verification before delivery.`,
334
344
  });
335
- const updatedAt = new Date().toISOString();
345
+ transitionWorkContractPhase(store, work.workId, {
346
+ phase: 'verification',
347
+ state: 'active',
348
+ dispatchState: 'running',
349
+ summary: `Pending candidate ${candidateRevision} was rehydrated after validation-process loss; fresh verification is required before delivery.`,
350
+ });
351
+ if (work.evidenceState === 'partial' || work.evidenceState === 'valid') {
352
+ recordWorkEvidenceState(store, work.workId, 'stale');
353
+ }
336
354
  writeWorkHandle(controllerHome, {
337
355
  ...handle,
338
356
  principalId: identity.principalId,
@@ -341,169 +359,165 @@ export function ensureRunningRepositoryWorkCheckout(
341
359
  worktreePath: workspace.root,
342
360
  branch: workspace.branch,
343
361
  sourceCheckoutId: repository.activeCheckoutId,
362
+ deliveryTargetBranch: targetBranch,
344
363
  managedWorktree: true,
345
364
  baseCommit: baseRevision,
346
- deliveryBaseCommit: baseRevision,
347
- expectedHead: baseRevision,
348
- state: 'prepared',
365
+ deliveryBaseCommit,
366
+ expectedHead: candidateRevision,
367
+ state: 'validating',
349
368
  validatedInputFingerprint: undefined,
350
369
  failureReason: undefined,
351
370
  cleanupReceipt: undefined,
352
- finalization: { validation: 'pending', commit: 'pending', merge: 'pending', branchCleanup: 'pending', worktreeCleanup: 'pending' },
353
- updatedAt,
371
+ updatedAt: at,
372
+ finalization: {
373
+ validation: 'pending',
374
+ commit: 'done',
375
+ merge: 'pending',
376
+ branchCleanup: 'pending',
377
+ worktreeCleanup: 'pending',
378
+ },
354
379
  });
355
380
  return { reconstructedCheckout: true };
356
381
  }
357
382
 
358
383
  /**
359
- * Canonical orchestration authority for explicitly re-authorizing the exact
360
- * retained cancelled repository Work. Transport adapters provide authenticated
361
- * identity and typed user intent only; they must not duplicate these lifecycle,
362
- * ownership, zero-delta, or reconstruction rules.
384
+ * Re-establish the checkout binding for a still-running isolated Work only
385
+ * when durable and Git evidence prove that the missing checkout carried no
386
+ * repository delta. Any dirty, divergent, committed, or cleaned evidence
387
+ * fails closed so recovery never becomes permission to discard source.
363
388
  */
364
- export function reauthorizeRetainedCancelledRepositoryWork(
365
- input: ReauthorizeRetainedCancelledWorkInput,
389
+ export function ensureRunningRepositoryWorkCheckout(
390
+ input: EnsureRunningRepositoryWorkCheckoutInput,
366
391
  ): { reconstructedCheckout: boolean } {
367
392
  const { controllerHome, repository, workId, identity } = input;
368
393
  const store = { controllerHome, repoId: repository.repoId };
369
- let work = getWorkContract(store, workId);
370
- if (!work || work.status !== 'cancelled') return { reconstructedCheckout: false };
371
- if (input.approvalConfirmed !== true || input.requestedBy !== 'user') {
372
- throw new Error(`WORK_CANCELLED_RESUME_REAUTHORIZATION_REQUIRED: ${workId}; use exact work_id with requested_by=user and approval_confirmed=true`);
373
- }
374
- if (!work.principalId?.trim() || work.principalId.trim() !== identity.principalId) {
375
- throw new Error(`WORK_CANCELLED_RESUME_PRINCIPAL_MISMATCH: ${workId}`);
376
- }
377
- const owner = getControllerSession(store, workId);
378
- if (owner && (owner.principalId?.trim() || owner.controllerId) !== identity.principalId) {
379
- throw new Error(`WORK_CANCELLED_RESUME_CONTROLLER_OWNERSHIP_MISMATCH: ${workId}`);
380
- }
381
- if (work.completionReceipt || work.completionOutcome) throw new Error(`WORK_CANCELLED_RESUME_COMPLETION_CONFLICT: ${workId}`);
382
- if (work.reconciliations.length > 0) throw new Error(`WORK_CANCELLED_RESUME_DELIVERY_HISTORY_AMBIGUOUS: ${workId}`);
383
- if (work.phase !== 'cleanup' || work.phaseEvidence.cleanup.state !== 'skipped' || work.phaseEvidence.cleanup.source !== 'recorded') {
384
- throw new Error(`WORK_CANCELLED_RESUME_HISTORY_AMBIGUOUS: ${workId}`);
385
- }
386
- if (work.workKind !== 'repository_change' || work.worktreePolicy.required !== true) {
387
- throw new Error(`WORK_CANCELLED_RESUME_ISOLATED_REPOSITORY_WORK_REQUIRED: ${workId}`);
388
- }
394
+ const work = getWorkContract(store, workId);
395
+ if (!work || work.semanticState !== 'open') return { reconstructedCheckout: false };
396
+ if (work.workKind !== 'repository_change') return { reconstructedCheckout: false };
397
+ const handle = readWorkHandle(controllerHome, repository.repoId, workId);
398
+ const hasManagedPlacement = handle?.managedWorktree === true
399
+ && Boolean(handle.checkoutId?.trim())
400
+ && Boolean(handle.worktreePath?.trim());
401
+ if (work.worktreePolicy.required !== true && !hasManagedPlacement) return { reconstructedCheckout: false };
402
+ // A settled physical delivery may intentionally outlive its managed checkout
403
+ // while semantic Work remains open. Do not reconstruct or reject source that
404
+ // the finalizer has already integrated and cleaned; Controller semantic
405
+ // judgment is the only remaining authority.
406
+ if (hasSettledWorkDeliveryReceipt(work)) return { reconstructedCheckout: false };
389
407
 
390
- let handle = readWorkHandle(controllerHome, repository.repoId, workId);
391
- if (handle) {
392
- if (handle.repositoryId !== repository.repoId || (handle.workContractId && handle.workContractId !== workId)) {
393
- throw new Error(`WORK_CANCELLED_RESUME_HANDLE_IDENTITY_MISMATCH: ${workId}`);
394
- }
395
- if (handle.principalId !== identity.principalId) throw new Error(`WORK_CANCELLED_RESUME_HANDLE_PRINCIPAL_MISMATCH: ${workId}`);
396
- if (['committed', 'merged', 'cleaned', 'failed_terminal_cleanup'].includes(handle.state)
397
- || handle.finalization.commit === 'done'
398
- || handle.finalization.merge === 'done'
399
- || handle.cleanupReceipt?.complete === true) {
400
- throw new Error(`WORK_CANCELLED_RESUME_DELIVERY_OR_CLEANUP_CONFLICT: ${workId}`);
401
- }
402
- }
408
+ const recordedCheckoutId = handle?.checkoutId?.trim() || work.checkoutId?.trim();
409
+ const recordedWorktree = handle?.worktreePath?.trim() || work.worktreeRef?.trim();
410
+ if (!recordedCheckoutId || !recordedWorktree) return { reconstructedCheckout: false };
403
411
 
404
412
  const registryRepository = listRepositories(controllerHome, { includeRemoved: true })
405
413
  .find((candidate) => candidate.repoId === repository.repoId);
406
- if (!registryRepository) throw new Error(`WORK_CANCELLED_RESUME_REPOSITORY_MISSING: ${workId}`);
407
- const recordedCheckoutId = work.checkoutId?.trim();
408
- const recordedWorktree = work.worktreeRef?.trim();
409
- const checkoutRecord = recordedCheckoutId
410
- ? registryRepository.checkouts.find((candidate) => candidate.checkoutId === recordedCheckoutId)
411
- : undefined;
412
- const checkoutActive = checkoutRecord?.lifecycle === 'active';
413
- const worktreePresent = Boolean(recordedWorktree && existsSync(recordedWorktree));
414
-
415
- if (checkoutActive && worktreePresent && recordedCheckoutId && recordedWorktree) {
416
- const retained = selectRepositoryCheckout(registryRepository, recordedCheckoutId);
417
- if (resolve(retained.canonicalRoot) !== resolve(recordedWorktree)) {
418
- throw new Error(`WORK_CANCELLED_RESUME_CHECKOUT_REUSED: ${workId}`);
419
- }
420
- if (!handle) throw new Error(`WORK_CANCELLED_RESUME_HANDLE_REQUIRED: ${workId}`);
421
- if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
422
- throw new Error(`WORK_CANCELLED_RESUME_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
423
- }
424
- const status = repositoryGitStatus(retained);
425
- if (!status.branch || status.branch !== handle.branch) throw new Error(`WORK_CANCELLED_RESUME_BRANCH_OWNERSHIP_MISMATCH: ${workId}`);
426
- writeWorkHandle(controllerHome, {
427
- ...handle,
414
+ if (!registryRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
415
+ const checkoutRecord = registryRepository.checkouts.find((candidate) => candidate.checkoutId === recordedCheckoutId);
416
+ const checkoutActive = checkoutRecord ? repositoryCheckoutLifecycle(checkoutRecord) === 'active' : false;
417
+ const worktreePresent = existsSync(recordedWorktree);
418
+ if (checkoutActive && worktreePresent) {
419
+ if (!handle || handle.state !== 'failed') return { reconstructedCheckout: false };
420
+ rearmFailedPreservedWorkHandle({
421
+ controllerHome,
422
+ repository,
423
+ workId,
424
+ contract: work,
425
+ handle,
428
426
  principalId: identity.principalId,
429
427
  sessionId: identity.sessionId,
430
- updatedAt: new Date().toISOString(),
431
- });
432
- resumeRetainedCancelledWorkContract(store, workId, {
433
- principalId: identity.principalId,
434
- controllerInstanceId: identity.controllerInstanceId,
435
- summary: 'Explicit current user re-authorized the same retained cancelled Work; exact managed checkout ownership was revalidated.',
436
428
  });
437
429
  return { reconstructedCheckout: false };
438
430
  }
431
+ if (checkoutActive) throw new Error(`WORK_CONTINUE_CHECKOUT_PRESERVATION_AMBIGUOUS: ${workId}`);
439
432
 
440
- if (checkoutActive) throw new Error(`WORK_CANCELLED_RESUME_PRESERVATION_AMBIGUOUS: ${workId}`);
441
- if (!recordedCheckoutId || !recordedWorktree || !handle) throw new Error(`WORK_CANCELLED_RESUME_HANDLE_REQUIRED: ${workId}`);
433
+ if (!handle) throw new Error(`WORK_CONTINUE_HANDLE_REQUIRED: ${workId}`);
434
+ if (handle.repositoryId !== repository.repoId || (handle.workContractId && handle.workContractId !== workId)) {
435
+ throw new Error(`WORK_CONTINUE_HANDLE_IDENTITY_MISMATCH: ${workId}`);
436
+ }
437
+ if (handle.principalId !== identity.principalId) throw new Error(`WORK_CONTINUE_HANDLE_PRINCIPAL_MISMATCH: ${workId}`);
438
+ if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
439
+ throw new Error(`WORK_CONTINUE_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
440
+ }
441
+ const archivedDelivery = restoreArchivedBlockedDeliveryCheckout({
442
+ controllerHome, repository, work, handle, identity, prepareDependencies: input.prepareDependencies,
443
+ });
444
+ if (archivedDelivery) return archivedDelivery;
445
+ const pendingCandidate = restoreArchivedPendingCandidateCheckout({
446
+ controllerHome, repository, work, handle, identity,
447
+ });
448
+ if (pendingCandidate) return pendingCandidate;
449
+ if (['committed', 'merged', 'cleaned', 'failed_terminal_cleanup'].includes(handle.state)
450
+ || handle.finalization.commit === 'done'
451
+ || handle.finalization.merge === 'done'
452
+ || handle.cleanupReceipt?.complete === true) {
453
+ throw new Error(`WORK_CONTINUE_DELIVERY_OR_CLEANUP_CONFLICT: ${workId}`);
454
+ }
442
455
 
443
456
  const actualChangedPaths = work.scopeEvidence?.actualChangedPaths;
457
+ // `work.checks` is a declaration of verification obligations, not evidence
458
+ // that any verification or repository mutation already occurred. Only
459
+ // durable checkRefs participate in the zero-delta recovery proof.
444
460
  if (!actualChangedPaths || actualChangedPaths.length !== 0
445
- || work.checks.length !== 0
446
461
  || work.checkRefs.length !== 0
447
462
  || work.evidenceState !== 'none') {
448
- throw new Error(`WORK_CANCELLED_RESUME_ZERO_DELTA_PROOF_REQUIRED: ${workId}`);
463
+ throw new Error(`WORK_CONTINUE_ZERO_DELTA_PROOF_REQUIRED: ${workId}`);
449
464
  }
450
465
  const recordedBase = work.baseRevision?.trim();
451
- if (!recordedBase) throw new Error(`WORK_CANCELLED_RESUME_BASE_REVISION_REQUIRED: ${workId}`);
466
+ if (!recordedBase) throw new Error(`WORK_CONTINUE_BASE_REVISION_REQUIRED: ${workId}`);
452
467
  const baseRevision = gitCommitAtRef(repository.canonicalRoot, recordedBase);
453
- if (!baseRevision) throw new Error(`WORK_CANCELLED_RESUME_BASE_REVISION_MISSING: ${workId}`);
468
+ if (!baseRevision) throw new Error(`WORK_CONTINUE_BASE_REVISION_MISSING: ${workId}`);
454
469
  const handleBase = handle.baseCommit ? gitCommitAtRef(repository.canonicalRoot, handle.baseCommit) : undefined;
455
470
  const handleHead = handle.expectedHead ? gitCommitAtRef(repository.canonicalRoot, handle.expectedHead) : undefined;
456
471
  if ((handle.baseCommit && handleBase !== baseRevision) || (handle.expectedHead && handleHead !== baseRevision)) {
457
- throw new Error(`WORK_CANCELLED_RESUME_REVISION_AMBIGUOUS: ${workId}`);
458
- }
459
- if (handle.checkoutId !== recordedCheckoutId || resolve(handle.worktreePath) !== resolve(recordedWorktree)) {
460
- throw new Error(`WORK_CANCELLED_RESUME_CHECKOUT_OWNERSHIP_MISMATCH: ${workId}`);
472
+ throw new Error(`WORK_CONTINUE_REVISION_AMBIGUOUS: ${workId}`);
461
473
  }
462
474
  if (handle.branch) {
463
475
  const historicalBranchHead = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${handle.branch}`);
464
476
  if (historicalBranchHead && historicalBranchHead !== baseRevision) {
465
- throw new Error(`WORK_CANCELLED_RESUME_UNIQUE_COMMIT_CONFLICT: ${workId}`);
477
+ throw new Error(`WORK_CONTINUE_UNIQUE_COMMIT_CONFLICT: ${workId}`);
466
478
  }
467
479
  }
468
480
  if (worktreePresent) {
469
481
  const retainedSnapshot = gitWorktreeSnapshot(recordedWorktree);
470
482
  if (!retainedSnapshot || !retainedSnapshot.clean || retainedSnapshot.head !== baseRevision || (handle.branch && retainedSnapshot.branch !== handle.branch)) {
471
- throw new Error(`WORK_CANCELLED_RESUME_ZERO_DELTA_PHYSICAL_CONFLICT: ${workId}`);
483
+ throw new Error(`WORK_CONTINUE_ZERO_DELTA_PHYSICAL_CONFLICT: ${workId}`);
472
484
  }
473
485
  }
474
486
 
475
487
  const branchName = `work/resume-${workId.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 42)}-${baseRevision.slice(0, 12)}`;
476
488
  const existingResumeBranch = gitCommitAtRef(repository.canonicalRoot, `refs/heads/${branchName}`);
477
489
  if (existingResumeBranch && existingResumeBranch !== baseRevision) {
478
- throw new Error(`WORK_CANCELLED_RESUME_RECONSTRUCTION_BRANCH_CONFLICT: ${workId}`);
490
+ throw new Error(`WORK_CONTINUE_RECONSTRUCTION_BRANCH_CONFLICT: ${workId}`);
479
491
  }
480
492
  const workspace = ensureManagedWorkspace(controllerHome, repository, {
481
- requestId: `${workId}:explicit-user-resume:${baseRevision}`,
482
- title: `${work.objective} explicit user resume`,
493
+ requestId: `${workId}:active-checkout-recovery:${baseRevision}`,
494
+ title: `${work.objective} checkout recovery`,
495
+ associatedWorkId: workId,
483
496
  branchName,
484
497
  baseRef: baseRevision,
485
498
  prepareDependencies: input.prepareDependencies === true,
486
499
  });
487
500
  if (!workspace.managed || !workspace.checkoutId || !workspace.root || !workspace.branch) {
488
- throw new Error(`WORK_CANCELLED_RESUME_RECONSTRUCTION_FAILED: ${workId}`);
501
+ throw new Error(`WORK_CONTINUE_RECONSTRUCTION_FAILED: ${workId}`);
489
502
  }
490
503
  const refreshedRepository = listRepositories(controllerHome, { includeRemoved: true })
491
504
  .find((candidate) => candidate.repoId === repository.repoId);
492
- if (!refreshedRepository) throw new Error(`WORK_CANCELLED_RESUME_REPOSITORY_MISSING: ${workId}`);
505
+ if (!refreshedRepository) throw new Error(`WORK_CONTINUE_REPOSITORY_MISSING: ${workId}`);
493
506
  const reconstructed = selectRepositoryCheckout(refreshedRepository, workspace.checkoutId);
494
507
  const reconstructedStatus = repositoryGitStatus(reconstructed);
495
508
  if (!reconstructedStatus.clean || reconstructedStatus.head !== baseRevision || reconstructedStatus.branch !== workspace.branch) {
496
- throw new Error(`WORK_CANCELLED_RESUME_RECONSTRUCTION_REVISION_MISMATCH: ${workId}`);
509
+ throw new Error(`WORK_CONTINUE_RECONSTRUCTION_REVISION_MISMATCH: ${workId}`);
497
510
  }
498
511
 
499
- work = updateWorkContract(store, workId, {
512
+ updateWorkContract(store, workId, {
500
513
  checkoutId: workspace.checkoutId,
501
514
  worktreeRef: workspace.root,
502
515
  baseRevision,
503
516
  controllerInstanceId: identity.controllerInstanceId,
517
+ continuationPrompt: `Continue work ${repository.repoId}: ${work.objective.slice(0, 500)}. The prior managed checkout was absent; Forge reconstructed an exact zero-delta checkout at ${baseRevision}.`,
504
518
  });
505
- const now = new Date().toISOString();
506
- handle = writeWorkHandle(controllerHome, {
519
+ const updatedAt = new Date().toISOString();
520
+ writeWorkHandle(controllerHome, {
507
521
  ...handle,
508
522
  principalId: identity.principalId,
509
523
  sessionId: identity.sessionId,
@@ -520,14 +534,7 @@ export function reauthorizeRetainedCancelledRepositoryWork(
520
534
  failureReason: undefined,
521
535
  cleanupReceipt: undefined,
522
536
  finalization: { validation: 'pending', commit: 'pending', merge: 'pending', branchCleanup: 'pending', worktreeCleanup: 'pending' },
523
- updatedAt: now,
524
- });
525
- resumeRetainedCancelledWorkContract(store, workId, {
526
- principalId: identity.principalId,
527
- controllerInstanceId: identity.controllerInstanceId,
528
- summary: 'Explicit current user re-authorized the same cancelled Work; prior managed checkout was absent and a fresh isolated checkout was reconstructed at the exact zero-delta base revision.',
529
- checkoutId: workspace.checkoutId,
530
- worktreeRef: workspace.root,
537
+ updatedAt,
531
538
  });
532
539
  return { reconstructedCheckout: true };
533
540
  }
@@ -4,7 +4,12 @@ import { join } from 'path';
4
4
  import { ensureControllerHome } from '../../../cli/repositories/controller-home';
5
5
  import { readJsonFile, sanitizeFileComponent } from '../../shared/json-files';
6
6
  import type { GoalDelegation } from '../governance/authorization';
7
- import { readOrImportControlPlaneRecord, writeControlPlaneRecord } from '../persistence/sqlite-store';
7
+ import {
8
+ readControlPlaneRecordWithinTransaction,
9
+ readOrImportControlPlaneRecord,
10
+ writeControlPlaneRecord,
11
+ type SqliteDatabase,
12
+ } from '../persistence/sqlite-store';
8
13
 
9
14
  export interface ExecutionSessionContext {
10
15
  schemaVersion: 1;
@@ -71,6 +76,31 @@ export function peekExecutionSession(controllerHome: string, sessionId: string):
71
76
  return session.sessionId === normalizedSessionId ? session : undefined;
72
77
  }
73
78
 
79
+ /**
80
+ * Transaction-safe execution-session projection. It never imports legacy
81
+ * state while another control-plane write transaction is open. A legacy JSON
82
+ * file may still be read as evidence and is imported later by the ordinary
83
+ * non-transactional session path.
84
+ */
85
+ export function peekExecutionSessionWithinTransaction(
86
+ database: SqliteDatabase,
87
+ controllerHome: string,
88
+ sessionId: string,
89
+ ): ExecutionSessionContext | undefined {
90
+ const normalizedSessionId = sessionId.trim();
91
+ if (!normalizedSessionId) return undefined;
92
+ const stored = readControlPlaneRecordWithinTransaction<ExecutionSessionContext>(
93
+ database,
94
+ 'execution_session',
95
+ 'controller',
96
+ sanitizeFileComponent(normalizedSessionId),
97
+ )?.value;
98
+ const legacyPath = sessionPath(controllerHome, normalizedSessionId);
99
+ const session = stored ?? (existsSync(legacyPath) ? readJsonFile<ExecutionSessionContext>(legacyPath) : undefined);
100
+ if (!session) return undefined;
101
+ return session.sessionId === normalizedSessionId ? session : undefined;
102
+ }
103
+
74
104
  export function readExecutionSession(controllerHome: string, identity: SessionIdentity): ExecutionSessionContext | undefined {
75
105
  const sessionId = identity.sessionId?.trim();
76
106
  if (!sessionId) return undefined;