@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
@@ -1,655 +0,0 @@
1
- import { createHash } from 'crypto';
2
- import { existsSync } from 'fs';
3
- import { resolve } from 'path';
4
- import { getEditSession, listEditSessions, type EditSession } from '../../../cli/editing/edit-session';
5
- import { repositoryGitStatus } from '../../../cli/repositories/structured-git';
6
- import type { RepositoryRecord } from '../../../cli/repositories/types';
7
- import { runProcess } from '../../../effects/process-runner';
8
- import { getWorkContract, implementationReviewChangedPathDigest, updateWorkContract } from '../../../../packages/kernel/work/api/index';
9
- import { completeWorkWithReceipt } from './work-completion-authority';
10
- import { isDirectEditWorkCompletionReceipt, isTerminalWorkContractStatus, type DirectEditWorkCompletionReceipt, type WorkContract, type WorkReconciliationRecord } from '../facade/types';
11
- import { historicalVerificationEvidenceAtRevision, workspaceValidationFingerprint } from './verification-evidence';
12
- import { readWorkHandle, transitionWorkHandle, type WorkHandleState } from './work-handle-store';
13
- import { assertWorkPathsWithinScope, findWorkPathScopeViolation } from './work-path-scope';
14
- import { implementationReviewContentFingerprint, implementationReviewIndexFingerprint } from './implementation-review-content';
15
- import { transferReviewedWorkAuthorityAcrossContentEquivalentCommit } from './content-equivalent-commit-authority';
16
- import {
17
- assertImplementationReviewPreDeliveryBoundary,
18
- authoritativeImplementationReviewVerificationEvidence,
19
- latestImplementationReview,
20
- normalizeImplementationReviewChangedPaths,
21
- type ImplementationReviewCandidateIdentity,
22
- } from '../../../../packages/kernel/work/api/index';
23
-
24
- export interface DirectEditWorkCompletionReconciliation {
25
- completedWorkIds: string[];
26
- examinedSessionIds: string[];
27
- skipped: Array<{ sessionId: string; workId?: string; reason: string }>;
28
- targetBranch?: string;
29
- targetRevision?: string;
30
- }
31
-
32
- function git(repoRoot: string, args: string[]): { ok: boolean; stdout: string; stderr: string } {
33
- const result = runProcess('git', args, { cwd: repoRoot, timeoutMs: 10_000, maxOutputBytes: 4 * 1024 * 1024 });
34
- return { ok: result.ok, stdout: result.stdout, stderr: result.stderr || result.error || '' };
35
- }
36
-
37
- function changedPaths(session: EditSession): string[] {
38
- return Array.from(new Set(session.operations.map((operation) => operation.path).filter(Boolean)))
39
- .sort((left, right) => left.localeCompare(right));
40
- }
41
-
42
- function latestOperations(session: EditSession): Map<string, EditSession['operations'][number]> {
43
- const latest = new Map<string, EditSession['operations'][number]>();
44
- for (const operation of session.operations) latest.set(operation.path, operation);
45
- return latest;
46
- }
47
-
48
- function revisionMismatches(repoRoot: string, revision: string, session: EditSession): string[] {
49
- const mismatches: string[] = [];
50
- for (const operation of latestOperations(session).values()) {
51
- const object = `${revision}:${operation.path}`;
52
- if (operation.type === 'delete') {
53
- if (git(repoRoot, ['cat-file', '-e', object]).ok) mismatches.push(operation.path);
54
- continue;
55
- }
56
- const content = git(repoRoot, ['show', object]);
57
- if (!content.ok || !operation.afterSha256 || createHash('sha256').update(content.stdout).digest('hex') !== operation.afterSha256) {
58
- mismatches.push(operation.path);
59
- }
60
- }
61
- return mismatches;
62
- }
63
-
64
- function requestedChecksPassed(session: EditSession): boolean {
65
- return session.requestedChecks.every((checkId) => session.checkResults.some((result) => result.checkId === checkId && result.ok));
66
- }
67
-
68
-
69
- function samePaths(left: readonly string[], right: readonly string[]): boolean {
70
- const a = normalizeImplementationReviewChangedPaths(left);
71
- const b = normalizeImplementationReviewChangedPaths(right);
72
- return a.length === b.length && a.every((path, index) => path === b[index]);
73
- }
74
-
75
- export interface ReviewedDirectEditWorkCommitPlan {
76
- workId: string;
77
- editSessionId: string;
78
- changedPaths: string[];
79
- preCommitCandidate: ImplementationReviewCandidateIdentity;
80
- preCommitContentFingerprint: string;
81
- }
82
-
83
- /**
84
- * Resolve and gate the only Work-bound Direct Edit candidate whose complete
85
- * reviewed path set is staged. This runs from selected-paths' beforeCommitGuard,
86
- * after exact index discovery and before the first physical commit side effect.
87
- */
88
- export function prepareReviewedDirectEditWorkCommit(input: {
89
- controllerHome: string;
90
- repository: RepositoryRecord;
91
- stagedPaths: string[];
92
- currentHead: string | null;
93
- }): ReviewedDirectEditWorkCommitPlan | undefined {
94
- const stagedPaths = normalizeImplementationReviewChangedPaths(input.stagedPaths);
95
- const overlapping = listEditSessions(input.repository.canonicalRoot, 200)
96
- .map((summary) => getEditSession(input.repository.canonicalRoot, summary.sessionId))
97
- .filter((session) => session.status === 'finalized' && Boolean(session.workId))
98
- .filter((session) => changedPaths(session).some((path) => stagedPaths.includes(path)));
99
- if (overlapping.length === 0) return undefined;
100
- if (overlapping.length !== 1) {
101
- throw new Error(`DIRECT_EDIT_WORK_COMMIT_AMBIGUOUS: staged paths overlap ${overlapping.length} finalized Work-bound Edit Sessions`);
102
- }
103
- const session = overlapping[0]!;
104
- const paths = changedPaths(session);
105
- if (!samePaths(paths, stagedPaths)) {
106
- throw new Error('DIRECT_EDIT_WORK_COMMIT_SCOPE_MISMATCH: commit must materialize the complete reviewed Work path set with no mixed paths');
107
- }
108
- if (session.repoId && session.repoId !== input.repository.repoId) throw new Error('DIRECT_EDIT_WORK_COMMIT_REPOSITORY_MISMATCH');
109
- if (session.checkoutId && session.checkoutId !== input.repository.activeCheckoutId) throw new Error('DIRECT_EDIT_WORK_COMMIT_CHECKOUT_MISMATCH');
110
- const workId = session.workId!;
111
- const work = getWorkContract({ controllerHome: input.controllerHome, repoId: input.repository.repoId }, workId);
112
- if (!work || work.completionReceipt || isTerminalWorkContractStatus(work.status)) throw new Error(`DIRECT_EDIT_WORK_COMMIT_WORK_NOT_ACTIVE: ${workId}`);
113
- if (work.checkoutId && work.checkoutId !== input.repository.activeCheckoutId) throw new Error('DIRECT_EDIT_WORK_COMMIT_WORK_CHECKOUT_MISMATCH');
114
- assertWorkPathsWithinScope(work, paths, {
115
- forbidden: 'DIRECT_EDIT_WORK_COMMIT_FORBIDDEN_PATH',
116
- outOfScope: 'DIRECT_EDIT_WORK_COMMIT_PATH_OUT_OF_SCOPE',
117
- });
118
- const status = repositoryGitStatus(input.repository);
119
- const sourceRevision = status.head?.trim();
120
- if (!sourceRevision) throw new Error('DIRECT_EDIT_WORK_COMMIT_SOURCE_REVISION_REQUIRED');
121
- if (!input.currentHead?.trim() || sourceRevision !== input.currentHead.trim()) {
122
- throw new Error('DIRECT_EDIT_WORK_COMMIT_SOURCE_REVISION_CHANGED');
123
- }
124
- const latestReview = latestImplementationReview(work.implementationReviews);
125
- if (!latestReview) throw new Error(`WORK_IMPLEMENTATION_REVIEW_REQUIRED: ${workId}`);
126
- const contentFingerprint = implementationReviewContentFingerprint(input.repository.canonicalRoot, paths);
127
- const indexFingerprint = implementationReviewIndexFingerprint(input.repository.canonicalRoot, paths);
128
- if (contentFingerprint !== indexFingerprint) {
129
- throw new Error('DIRECT_EDIT_WORK_COMMIT_INDEX_CONTENT_MISMATCH: staged index must equal the exact approved review content');
130
- }
131
- const verification = authoritativeImplementationReviewVerificationEvidence({
132
- repoId: input.repository.repoId,
133
- workId,
134
- requiredCheckIds: work.checks,
135
- records: work.checkRefs,
136
- sourceRevision,
137
- workspaceFingerprint: latestReview.verificationWorkspaceFingerprint,
138
- });
139
- if (verification.missingCheckIds.length > 0) {
140
- throw new Error(`WORK_IMPLEMENTATION_REVIEW_VERIFICATION_REQUIRED: ${verification.missingCheckIds.join(', ')}`);
141
- }
142
- const candidate: ImplementationReviewCandidateIdentity = {
143
- sourceRevision,
144
- workspaceFingerprint: contentFingerprint,
145
- verificationWorkspaceFingerprint: latestReview.verificationWorkspaceFingerprint,
146
- changedPaths: paths,
147
- verificationEvidence: verification.evidence,
148
- architectureEvidence: latestReview.architectureEvidence,
149
- };
150
- assertImplementationReviewPreDeliveryBoundary({
151
- repoId: input.repository.repoId,
152
- workId,
153
- workKind: work.workKind,
154
- reviews: work.implementationReviews,
155
- candidate,
156
- requiredCheckIds: work.checks,
157
- verificationRecords: work.checkRefs,
158
- });
159
- return { workId, editSessionId: session.sessionId, changedPaths: paths, preCommitCandidate: candidate, preCommitContentFingerprint: contentFingerprint };
160
- }
161
-
162
- /** Complete the exact pre-gated Direct Edit Work after the physical commit. */
163
- export function completeReviewedDirectEditWorkAfterCommit(input: {
164
- controllerHome: string;
165
- repository: RepositoryRecord;
166
- plan: ReviewedDirectEditWorkCommitPlan;
167
- fallbackBranch?: string;
168
- }): DirectEditWorkCompletionReconciliation {
169
- const work = getWorkContract({ controllerHome: input.controllerHome, repoId: input.repository.repoId }, input.plan.workId);
170
- if (!work || work.completionReceipt || isTerminalWorkContractStatus(work.status)) {
171
- throw new Error(`DIRECT_EDIT_WORK_COMMIT_WORK_NOT_ACTIVE: ${input.plan.workId}`);
172
- }
173
- const postStatus = repositoryGitStatus(input.repository);
174
- const targetRevision = postStatus.head?.trim();
175
- if (!targetRevision || targetRevision === input.plan.preCommitCandidate.sourceRevision) {
176
- throw new Error('DIRECT_EDIT_WORK_COMMIT_TARGET_REVISION_REQUIRED');
177
- }
178
- const actualCommittedPaths = comparedRevisionPaths(input.repository.canonicalRoot, input.plan.preCommitCandidate.sourceRevision, targetRevision);
179
- if (!samePaths(actualCommittedPaths, input.plan.changedPaths)) {
180
- throw new Error('DIRECT_EDIT_WORK_COMMIT_RESULT_SCOPE_MISMATCH');
181
- }
182
- const targetBranch = postStatus.branch?.trim() || input.fallbackBranch?.trim();
183
- if (!targetBranch) throw new Error('DIRECT_EDIT_WORK_COMMIT_TARGET_BRANCH_REQUIRED');
184
- const postVerificationWorkspaceFingerprint = workspaceValidationFingerprint(input.repository.canonicalRoot, postStatus);
185
- const postContentFingerprint = implementationReviewContentFingerprint(input.repository.canonicalRoot, input.plan.changedPaths);
186
- const transfer = transferReviewedWorkAuthorityAcrossContentEquivalentCommit({
187
- controllerHome: input.controllerHome,
188
- repository: input.repository,
189
- workId: input.plan.workId,
190
- preCommitCandidate: input.plan.preCommitCandidate,
191
- preCommitDirtyPaths: input.plan.changedPaths,
192
- committedPaths: actualCommittedPaths,
193
- preCommitContentDigest: input.plan.preCommitContentFingerprint,
194
- postCommitSourceRevision: targetRevision,
195
- postCommitContentDigest: postContentFingerprint,
196
- postCommitVerificationWorkspaceFingerprint: postVerificationWorkspaceFingerprint,
197
- postCommitChangedPaths: input.plan.changedPaths,
198
- });
199
- if (transfer.invalidatedCheckIds.length > 0) {
200
- throw new Error(`DIRECT_EDIT_WORK_COMMIT_REVALIDATION_REQUIRED: ${transfer.invalidatedCheckIds.join(', ')}`);
201
- }
202
- if (!transfer.transferred || !transfer.derivedReview) {
203
- throw new Error('DIRECT_EDIT_WORK_COMMIT_AUTHORITY_TRANSFER_REQUIRED');
204
- }
205
- const recordedAt = transfer.recordedAt;
206
- const receipt: DirectEditWorkCompletionReceipt = {
207
- schemaVersion: 1,
208
- receiptId: `REC-direct-edit-work-${createHash('sha256').update(`${input.repository.repoId}\0${input.plan.workId}\0${input.plan.editSessionId}\0${targetRevision}`).digest('hex').slice(0, 20)}`,
209
- source: 'direct_edit_work',
210
- workId: input.plan.workId,
211
- editSessionId: input.plan.editSessionId,
212
- targetBranch,
213
- targetRevision,
214
- sourceRevision: targetRevision,
215
- baseRevision: input.plan.preCommitCandidate.sourceRevision,
216
- changedPaths: input.plan.changedPaths,
217
- delivery: { kind: 'commit', status: 'integrated', strategy: 'edit_session_commit', reachable: true, recordedAt },
218
- cleanup: { status: 'complete', warnings: [], blockers: [], recordedAt },
219
- verifiedAt: recordedAt,
220
- recordedAt,
221
- };
222
- completeWorkWithReceipt(
223
- { controllerHome: input.controllerHome, repoId: input.repository.repoId },
224
- input.plan.workId,
225
- receipt,
226
- 'completed_changed',
227
- 'repository_change',
228
- );
229
- return {
230
- completedWorkIds: [input.plan.workId],
231
- examinedSessionIds: [input.plan.editSessionId],
232
- skipped: [],
233
- targetBranch,
234
- targetRevision,
235
- };
236
- }
237
-
238
- export function reconcileFinalizedDirectEditWorksAfterCommit(input: {
239
- controllerHome: string;
240
- repoId: string;
241
- checkoutId: string;
242
- repoRoot: string;
243
- committedPaths: string[];
244
- fallbackBranch?: string;
245
- limit?: number;
246
- }): DirectEditWorkCompletionReconciliation {
247
- const targetRevisionResult = git(input.repoRoot, ['rev-parse', '--verify', 'HEAD']);
248
- const targetRevision = targetRevisionResult.ok ? targetRevisionResult.stdout.trim() : undefined;
249
- const branchResult = git(input.repoRoot, ['branch', '--show-current']);
250
- const targetBranch = branchResult.ok && branchResult.stdout.trim()
251
- ? branchResult.stdout.trim()
252
- : input.fallbackBranch?.trim();
253
- const committedPathSet = new Set(input.committedPaths);
254
- const examinedSessionIds: string[] = [];
255
- const skipped: DirectEditWorkCompletionReconciliation['skipped'] = [];
256
- for (const summary of listEditSessions(input.repoRoot, input.limit ?? 200)) {
257
- const session = getEditSession(input.repoRoot, summary.sessionId);
258
- if (session.status !== 'finalized' || !session.workId) continue;
259
- if (session.repoId && session.repoId !== input.repoId) continue;
260
- if (session.checkoutId && session.checkoutId !== input.checkoutId) continue;
261
- const paths = changedPaths(session);
262
- if (paths.length === 0 || !paths.some((path) => committedPathSet.has(path))) continue;
263
- examinedSessionIds.push(session.sessionId);
264
- skipped.push({
265
- sessionId: session.sessionId,
266
- workId: session.workId,
267
- reason: 'postcommit_completion_authority_retired_use_precommit_review_gate_or_explicit_historical_reconciliation',
268
- });
269
- }
270
- // Historical helper intentionally never completes new Work. New delivery must
271
- // pass prepareReviewedDirectEditWorkCommit() before commit and
272
- // completeReviewedDirectEditWorkAfterCommit() afterward. Already-delivered
273
- // recovery remains explicit through acceptReviewedDirectEditWorkReconciliation,
274
- // whose completion receipt is cross-bound to a durable reconciliationId.
275
- return { completedWorkIds: [], examinedSessionIds, skipped, targetBranch, targetRevision };
276
- }
277
-
278
- export interface ReviewedDirectEditWorkReconciliationInput {
279
- controllerHome: string;
280
- repoId: string;
281
- checkoutId: string;
282
- repoRoot: string;
283
- workId: string;
284
- targetBranch: string;
285
- targetRevision: string;
286
- comparedPaths: string[];
287
- reviewer: string;
288
- rationale: string;
289
- cleanupOwnershipProof: string;
290
- reviewedAt?: string;
291
- }
292
-
293
- function exactCommit(repoRoot: string, revision: string, label: string): string {
294
- const result = git(repoRoot, ['rev-parse', '--verify', `${revision}^{commit}`]);
295
- if (!result.ok || !result.stdout.trim()) throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_${label}_INVALID`);
296
- return result.stdout.trim();
297
- }
298
-
299
- function assertRemoteContainmentIfApplicable(repoRoot: string, targetBranch: string, targetRevision: string): void {
300
- const remoteResult = git(repoRoot, ['config', '--get', `branch.${targetBranch}.remote`]);
301
- const remote = remoteResult.ok ? remoteResult.stdout.trim() : '';
302
- if (!remote || remote === '.') return;
303
- const mergeResult = git(repoRoot, ['config', '--get', `branch.${targetBranch}.merge`]);
304
- const mergeRef = mergeResult.ok ? mergeResult.stdout.trim() : '';
305
- if (!mergeRef.startsWith('refs/heads/')) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_REMOTE_TRACKING_REQUIRED');
306
- const remoteRef = `refs/remotes/${remote}/${mergeRef.slice('refs/heads/'.length)}`;
307
- const remoteRevision = git(repoRoot, ['rev-parse', '--verify', `${remoteRef}^{commit}`]);
308
- if (!remoteRevision.ok || !remoteRevision.stdout.trim()) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_REMOTE_TRACKING_REQUIRED');
309
- if (!git(repoRoot, ['merge-base', '--is-ancestor', targetRevision, remoteRevision.stdout.trim()]).ok) {
310
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_REMOTE_CONTAINMENT_REQUIRED');
311
- }
312
- }
313
-
314
- function comparedRevisionPaths(repoRoot: string, baseRevision: string, targetRevision: string): string[] {
315
- const result = git(repoRoot, ['diff', '--name-only', '-z', baseRevision, targetRevision]);
316
- if (!result.ok) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_CHANGED_PATHS_UNAVAILABLE');
317
- return [...new Set(result.stdout.split('\0').filter(Boolean))].sort((left, right) => left.localeCompare(right));
318
- }
319
-
320
- function normalizedComparedPaths(paths: string[]): string[] {
321
- const normalized = [...new Set(paths.map((path) => path.trim()))].sort((left, right) => left.localeCompare(right));
322
- if (normalized.length === 0 || normalized.length > 100 || normalized.some((path) => !path || path.startsWith('/') || path.includes('\0') || path.split('/').some((part) => part === '' || part === '.' || part === '..'))) {
323
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_PATHS_INVALID');
324
- }
325
- return normalized;
326
- }
327
-
328
- function unresolvedRepositorySourcePaths(repoRoot: string): string[] {
329
- const tracked = [
330
- git(repoRoot, ['diff', '--name-only', '-z']),
331
- git(repoRoot, ['diff', '--cached', '--name-only', '-z']),
332
- ];
333
- if (tracked.some((result) => !result.ok)) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_EFFECT_SOURCE_STATUS_UNAVAILABLE');
334
- const untracked = git(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z']);
335
- if (!untracked.ok) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_EFFECT_SOURCE_STATUS_UNAVAILABLE');
336
- return [...new Set([
337
- ...tracked.flatMap((result) => result.stdout.split('\0').filter(Boolean)),
338
- ...untracked.stdout.split('\0').filter((path) => path && !path.startsWith('.ai/harness/')),
339
- ])].sort((left, right) => left.localeCompare(right));
340
- }
341
-
342
- export function isFailedReviewedDirectEditWorkRecovery(
343
- work: WorkContract,
344
- handle?: WorkHandleState,
345
- ): handle is WorkHandleState {
346
- return work.workKind === 'repository_change'
347
- && work.status === 'failed'
348
- && handle?.managedWorktree === false
349
- && handle.state === 'failed'
350
- && handle.finalization.validation === 'failed'
351
- && handle.finalization.failureCode === 'WORK_HANDLE_HEAD_CHANGED';
352
- }
353
-
354
- function isStalePreMutationDirectOwnershipRecovery(
355
- work: WorkContract,
356
- handle: WorkHandleState | undefined,
357
- input: { repoRoot: string; checkoutId: string; targetBranch: string; targetRevision: string },
358
- ): handle is WorkHandleState {
359
- const baseRevision = work.baseRevision?.trim();
360
- const target = input.targetRevision.trim();
361
- const targetBranch = input.targetBranch.trim();
362
- if (
363
- work.workKind !== 'repository_change'
364
- || isTerminalWorkContractStatus(work.status)
365
- || !baseRevision
366
- || !target
367
- || !targetBranch
368
- || !handle
369
- || handle.managedWorktree
370
- || handle.state !== 'prepared'
371
- || handle.repositoryId !== work.repoId
372
- || handle.checkoutId !== input.checkoutId
373
- || resolve(handle.worktreePath) !== resolve(input.repoRoot)
374
- || handle.branch !== targetBranch
375
- || (handle.deliveryTargetBranch !== undefined && handle.deliveryTargetBranch !== targetBranch)
376
- ) return false;
377
-
378
- const handleBase = handle.baseCommit?.trim();
379
- const deliveryBase = (handle.deliveryBaseCommit ?? handle.baseCommit)?.trim();
380
- const expectedHead = handle.expectedHead?.trim();
381
- if (!handleBase || handleBase !== baseRevision || deliveryBase !== baseRevision || expectedHead !== baseRevision) return false;
382
-
383
- const review = latestImplementationReview(work.implementationReviews);
384
- return review?.decision === 'approved' && review.sourceRevision.trim() === target;
385
- }
386
-
387
-
388
- function reviewedMaterializedDirectOwnershipRecovery(
389
- work: WorkContract,
390
- handle: WorkHandleState | undefined,
391
- input: { repoRoot: string; checkoutId: string; targetBranch: string; targetRevision: string },
392
- ): { comparisonBaseRevision: string } | undefined {
393
- const originalBase = work.baseRevision?.trim();
394
- const target = input.targetRevision.trim();
395
- const targetBranch = input.targetBranch.trim();
396
- if (
397
- work.workKind !== 'repository_change'
398
- || isTerminalWorkContractStatus(work.status)
399
- || !originalBase
400
- || !target
401
- || !targetBranch
402
- || !handle
403
- || handle.managedWorktree
404
- || !['prepared', 'editing'].includes(handle.state)
405
- || handle.repositoryId !== work.repoId
406
- || handle.checkoutId !== input.checkoutId
407
- || resolve(handle.worktreePath) !== resolve(input.repoRoot)
408
- || handle.branch !== targetBranch
409
- || (handle.deliveryTargetBranch !== undefined && handle.deliveryTargetBranch !== targetBranch)
410
- ) return undefined;
411
-
412
- const handleBase = handle.baseCommit?.trim();
413
- const deliveryBase = (handle.deliveryBaseCommit ?? handle.baseCommit)?.trim();
414
- const expectedHead = handle.expectedHead?.trim();
415
- if (
416
- !handleBase
417
- || handleBase !== originalBase
418
- || !deliveryBase
419
- || deliveryBase === originalBase
420
- || expectedHead !== deliveryBase
421
- || deliveryBase === target
422
- ) return undefined;
423
- if (!git(input.repoRoot, ['merge-base', '--is-ancestor', originalBase, deliveryBase]).ok) return undefined;
424
- if (!git(input.repoRoot, ['merge-base', '--is-ancestor', deliveryBase, target]).ok) return undefined;
425
-
426
- const materializedPaths = comparedRevisionPaths(input.repoRoot, deliveryBase, target);
427
- if (materializedPaths.length === 0) return undefined;
428
- const materializedPathDigest = implementationReviewChangedPathDigest(materializedPaths);
429
- for (const review of work.implementationReviews) {
430
- if (review.decision !== 'approved' || review.sourceRevision.trim() !== deliveryBase) continue;
431
- const reviewedPaths = normalizeImplementationReviewChangedPaths(review.changedPaths);
432
- if (review.changedPathDigest !== implementationReviewChangedPathDigest(reviewedPaths)) continue;
433
- if (review.changedPathDigest !== materializedPathDigest) continue;
434
- if (reviewedPaths.length !== materializedPaths.length || reviewedPaths.some((path, index) => path !== materializedPaths[index])) continue;
435
- let currentContentFingerprint: string;
436
- try {
437
- currentContentFingerprint = implementationReviewContentFingerprint(input.repoRoot, reviewedPaths);
438
- } catch {
439
- continue;
440
- }
441
- if (currentContentFingerprint !== review.workspaceFingerprint) continue;
442
- return { comparisonBaseRevision: deliveryBase };
443
- }
444
- return undefined;
445
- }
446
-
447
- export function hasReviewedDirectEditReconciliationOwnership(input: {
448
- work: WorkContract;
449
- handle?: WorkHandleState;
450
- activeOwnerPrincipal?: string;
451
- callerPrincipal: string;
452
- }): boolean {
453
- const callerPrincipal = input.callerPrincipal.trim();
454
- if (!callerPrincipal) return false;
455
- const activeOwnerPrincipal = input.activeOwnerPrincipal?.trim();
456
- if (activeOwnerPrincipal) return activeOwnerPrincipal === callerPrincipal;
457
- return isFailedReviewedDirectEditWorkRecovery(input.work, input.handle)
458
- && input.handle.principalId.trim() === callerPrincipal;
459
- }
460
-
461
- /**
462
- * Explicitly close a historically delivered Direct Edit Work whose original
463
- * edit-session binding was missed. This is never inferred: the caller must
464
- * supply the exact accepted revision and the complete reviewed path set.
465
- */
466
- export function acceptReviewedDirectEditWorkReconciliation(input: ReviewedDirectEditWorkReconciliationInput): {
467
- workId: string;
468
- reconciliation: WorkReconciliationRecord;
469
- receipt: DirectEditWorkCompletionReceipt;
470
- } {
471
- const work = getWorkContract({ controllerHome: input.controllerHome, repoId: input.repoId }, input.workId);
472
- if (!work || work.repoId !== input.repoId) throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_WORK_NOT_FOUND: ${input.workId}`);
473
- if (work.checkoutId && work.checkoutId !== input.checkoutId) throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_CHECKOUT_MISMATCH: ${input.workId}`);
474
- if (work.completionReceipt) {
475
- const completionReceipt = work.completionReceipt;
476
- if (isDirectEditWorkCompletionReceipt(completionReceipt) && completionReceipt.reconciliationId) {
477
- const existing = work.reconciliations.find((entry) => entry.reconciliationId === completionReceipt.reconciliationId);
478
- if (existing) return { workId: work.workId, reconciliation: existing, receipt: completionReceipt };
479
- }
480
- throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_WORK_TERMINAL: ${input.workId}`);
481
- }
482
- const currentHandle = readWorkHandle(input.controllerHome, input.repoId, input.workId);
483
- const failedReviewedRecovery = isFailedReviewedDirectEditWorkRecovery(work, currentHandle);
484
- const stalePreMutationOwnershipRecovery = isStalePreMutationDirectOwnershipRecovery(work, currentHandle, {
485
- repoRoot: input.repoRoot,
486
- checkoutId: input.checkoutId,
487
- targetBranch: input.targetBranch,
488
- targetRevision: input.targetRevision,
489
- });
490
- const materializedReviewedRecovery = reviewedMaterializedDirectOwnershipRecovery(work, currentHandle, {
491
- repoRoot: input.repoRoot,
492
- checkoutId: input.checkoutId,
493
- targetBranch: input.targetBranch,
494
- targetRevision: input.targetRevision,
495
- });
496
- const historicalEffectRecovery = !currentHandle
497
- && !isTerminalWorkContractStatus(work.status)
498
- && (work.workKind === 'local_effect' || work.workKind === 'remote_effect');
499
- if ((isTerminalWorkContractStatus(work.status) && !failedReviewedRecovery)
500
- || (work.workKind !== 'repository_change' && !historicalEffectRecovery)) {
501
- throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_WORK_NOT_ELIGIBLE: ${input.workId}`);
502
- }
503
- if ((historicalEffectRecovery || stalePreMutationOwnershipRecovery) && work.checks.length === 0) {
504
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_CHECK_EVIDENCE_REQUIRED');
505
- }
506
- if (!work.baseRevision?.trim()) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_BASE_REVISION_MISSING');
507
-
508
- const baseRevision = exactCommit(input.repoRoot, work.baseRevision, 'BASE_REVISION');
509
- const targetRevision = exactCommit(input.repoRoot, input.targetRevision.trim(), 'TARGET_REVISION');
510
- const targetBranch = input.targetBranch.trim();
511
- if (!targetBranch) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_TARGET_BRANCH_REQUIRED');
512
- if (!git(input.repoRoot, ['merge-base', '--is-ancestor', baseRevision, targetRevision]).ok) {
513
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_TARGET_NOT_DESCENDANT');
514
- }
515
- if (!git(input.repoRoot, ['merge-base', '--is-ancestor', targetRevision, targetBranch]).ok) {
516
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_TARGET_UNREACHABLE');
517
- }
518
- // Ordinary historical reconciliation must prove remote containment. The stale
519
- // pre-mutation ownership repair is different: it repairs an active Direct Work
520
- // already contained by the current local target branch, matching normal local
521
- // finalize semantics without turning push state into a second ownership gate.
522
- if (!stalePreMutationOwnershipRecovery && !materializedReviewedRecovery) {
523
- assertRemoteContainmentIfApplicable(input.repoRoot, targetBranch, targetRevision);
524
- }
525
-
526
- const comparedPaths = normalizedComparedPaths(input.comparedPaths);
527
- let comparisonBaseRevision = baseRevision;
528
- if (materializedReviewedRecovery) {
529
- comparisonBaseRevision = materializedReviewedRecovery.comparisonBaseRevision;
530
- } else if (failedReviewedRecovery || stalePreMutationOwnershipRecovery) {
531
- const targetParent = exactCommit(input.repoRoot, `${targetRevision}^`, 'TARGET_PARENT_REVISION');
532
- if (!git(input.repoRoot, ['merge-base', '--is-ancestor', baseRevision, targetParent]).ok) {
533
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_TARGET_PARENT_NOT_DESCENDANT');
534
- }
535
- comparisonBaseRevision = targetParent;
536
- }
537
- const actualPaths = comparedRevisionPaths(input.repoRoot, comparisonBaseRevision, targetRevision);
538
- if (comparedPaths.length !== actualPaths.length || comparedPaths.some((path, index) => path !== actualPaths[index])) {
539
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_PATH_COMPARISON_MISMATCH');
540
- }
541
- assertWorkPathsWithinScope(work, comparedPaths, {
542
- forbidden: 'DIRECT_EDIT_WORK_RECONCILIATION_FORBIDDEN_PATH',
543
- outOfScope: 'DIRECT_EDIT_WORK_RECONCILIATION_PATH_OUT_OF_SCOPE',
544
- });
545
- const dirty = git(input.repoRoot, ['status', '--porcelain=v1', '--', ...comparedPaths]);
546
- if (!dirty.ok || dirty.stdout.trim()) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_OWNED_PATHS_DIRTY');
547
- if (historicalEffectRecovery) {
548
- const separateOwnedWorktree = Boolean(work.worktreeRef?.trim())
549
- && resolve(work.worktreeRef!) !== resolve(input.repoRoot)
550
- && existsSync(work.worktreeRef!);
551
- if (separateOwnedWorktree) throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_EFFECT_CLEANUP_REQUIRED');
552
- if (unresolvedRepositorySourcePaths(input.repoRoot).length > 0) {
553
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_EFFECT_SOURCE_DELTA_UNRESOLVED');
554
- }
555
- }
556
-
557
- let verifiedAt = new Date().toISOString();
558
- for (const checkId of work.checks) {
559
- const candidates = historicalVerificationEvidenceAtRevision(work.checkRefs, {
560
- sourceRevision: targetRevision,
561
- repoId: input.repoId,
562
- workId: work.workId,
563
- checkoutId: work.checkoutId,
564
- checkId,
565
- requestedChecks: work.checks,
566
- }).filter((entry) => entry.current && entry.record.outcome === 'valid_pass');
567
- const distinctReceipts = new Map(candidates.map((entry) => [entry.record.receipt!.receiptId, entry]));
568
- if (distinctReceipts.size === 0) throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_CHECK_EVIDENCE_STALE: ${checkId}`);
569
- if (distinctReceipts.size > 1) throw new Error(`DIRECT_EDIT_WORK_RECONCILIATION_CHECK_EVIDENCE_AMBIGUOUS: ${checkId}`);
570
- const current = [...distinctReceipts.values()][0]!;
571
- verifiedAt = current.record.completedAt ?? current.record.recordedAt ?? verifiedAt;
572
- }
573
-
574
- const reviewer = input.reviewer.trim();
575
- const rationale = input.rationale.trim();
576
- const cleanupOwnershipProof = input.cleanupOwnershipProof.trim();
577
- const reviewedAt = input.reviewedAt ?? new Date().toISOString();
578
- if (!reviewer || !rationale || !cleanupOwnershipProof || Number.isNaN(Date.parse(reviewedAt))) {
579
- throw new Error('DIRECT_EDIT_WORK_RECONCILIATION_REVIEW_METADATA_INVALID');
580
- }
581
- const reconciliationId = `RECNC-${createHash('sha256').update([input.repoId, input.workId, baseRevision, targetRevision, comparedPaths.join('\0'), reviewer, reviewedAt].join('\0')).digest('hex').slice(0, 16)}`;
582
- const reconciliation: WorkReconciliationRecord = {
583
- schemaVersion: 1,
584
- reconciliationId,
585
- originalExpectedRevision: targetRevision,
586
- observedTargetRevision: targetRevision,
587
- baseRevision,
588
- targetBranch,
589
- reachable: true,
590
- method: 'owned_path_tree',
591
- comparedPaths,
592
- reviewer: reviewer.slice(0, 200),
593
- reviewedAt,
594
- unrecoverableStages: ['receipt'],
595
- cleanupOwnershipProof: cleanupOwnershipProof.slice(0, 2_000),
596
- rationale: rationale.slice(0, 2_000),
597
- outcome: 'accepted_equivalence',
598
- };
599
- updateWorkContract({ controllerHome: input.controllerHome, repoId: input.repoId }, input.workId, {
600
- reconciliations: [reconciliation, ...work.reconciliations.filter((entry) => entry.reconciliationId !== reconciliationId)],
601
- });
602
-
603
- const recordedAt = new Date().toISOString();
604
- const receipt: DirectEditWorkCompletionReceipt = {
605
- schemaVersion: 1,
606
- receiptId: `REC-direct-edit-reconciled-${createHash('sha256').update(`${input.repoId}\0${input.workId}\0${reconciliationId}\0${targetRevision}`).digest('hex').slice(0, 20)}`,
607
- source: 'direct_edit_work',
608
- workId: input.workId,
609
- reconciliationId,
610
- targetBranch,
611
- targetRevision,
612
- sourceRevision: targetRevision,
613
- baseRevision,
614
- changedPaths: comparedPaths,
615
- delivery: { kind: 'commit', status: 'integrated', strategy: 'already_integrated', reachable: true, recordedAt },
616
- cleanup: { status: 'complete', warnings: [], blockers: [], recordedAt },
617
- verifiedAt,
618
- recordedAt,
619
- };
620
- completeWorkWithReceipt(
621
- { controllerHome: input.controllerHome, repoId: input.repoId },
622
- input.workId,
623
- receipt,
624
- 'completed_changed',
625
- 'repository_change',
626
- );
627
-
628
- // WorkHandle is the physical repository-delivery projection of the same
629
- // accepted reconciliation. Keep that projection inside this completion
630
- // authority so MCP adapters cannot independently infer or persist lifecycle
631
- // state after the semantic completion receipt is durable.
632
- if (currentHandle && currentHandle.state !== 'cleaned') {
633
- const finalization: WorkHandleState['finalization'] = currentHandle.managedWorktree
634
- ? currentHandle.finalization
635
- : { validation: 'done', commit: 'done', merge: 'skipped', branchCleanup: 'skipped', worktreeCleanup: 'skipped' };
636
- const delivered = currentHandle.state === 'committed' || currentHandle.state === 'merged' || currentHandle.state === 'failed_terminal_cleanup'
637
- ? currentHandle
638
- : transitionWorkHandle(input.controllerHome, currentHandle, 'committed', {
639
- expectedHead: receipt.targetRevision,
640
- finalization,
641
- failureReason: undefined,
642
- });
643
- // Managed reconciliation records semantic delivery first, then ordinary
644
- // terminal cleanup removes the exact owned checkout. Direct/canonical Work
645
- // has no separate managed cleanup resource and may close the projection now.
646
- if (!currentHandle.managedWorktree) {
647
- transitionWorkHandle(input.controllerHome, delivered, 'cleaned', {
648
- expectedHead: receipt.targetRevision,
649
- finalization,
650
- failureReason: undefined,
651
- });
652
- }
653
- }
654
- return { workId: input.workId, reconciliation, receipt };
655
- }