@moretea-labs/forge 1.7.2 → 1.8.0

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 (685) hide show
  1. package/AGENTS.md +58 -62
  2. package/CHANGELOG.md +26 -0
  3. package/CLAUDE.md +42 -62
  4. package/README.md +2 -2
  5. package/SKILL.md +0 -1
  6. package/THIRD_PARTY_NOTICES.md +5 -2
  7. package/adapters/browser/index.ts +2 -0
  8. package/adapters/chatgpt/browser-delivery-host.ts +71 -0
  9. package/adapters/chatgpt/browser-delivery-runtime.ts +783 -0
  10. package/adapters/chatgpt/controller-binding-store.ts +55 -0
  11. package/adapters/chatgpt/controller-host.ts +119 -0
  12. package/adapters/chatgpt/controller-round-host.ts +78 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +45 -0
  14. package/adapters/chatgpt/provider-delivery.ts +113 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +192 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/desktop-operator-contract.ts +7 -0
  18. package/adapters/computer/desktop-operator-discovery.ts +201 -0
  19. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  20. package/adapters/computer/desktop-operator-provider.ts +312 -0
  21. package/adapters/computer/index.ts +1 -0
  22. package/adapters/computer/interaction-target-authority.ts +944 -0
  23. package/adapters/controller-process/binding-store.ts +34 -0
  24. package/adapters/controller-process/controller-host.ts +26 -0
  25. package/adapters/mcp/access-mode.ts +132 -0
  26. package/adapters/mcp/audit.ts +32 -0
  27. package/adapters/mcp/auth.ts +407 -0
  28. package/adapters/mcp/controller-round-compatibility.ts +184 -0
  29. package/adapters/mcp/frozen-client-semantic-compatibility.ts +292 -0
  30. package/adapters/mcp/instructions.ts +36 -0
  31. package/adapters/mcp/legacy-context.ts +18 -0
  32. package/adapters/mcp/multi-repository.ts +437 -0
  33. package/adapters/mcp/oauth.ts +391 -0
  34. package/adapters/mcp/paths.ts +140 -0
  35. package/adapters/mcp/policy.ts +232 -0
  36. package/adapters/mcp/proxy-env.ts +62 -0
  37. package/adapters/mcp/readiness-projection.ts +24 -0
  38. package/adapters/mcp/redaction.ts +21 -0
  39. package/adapters/mcp/repo.ts +24 -0
  40. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  41. package/adapters/mcp/runtime-gateway/context-adapter.ts +829 -0
  42. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +191 -0
  43. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +147 -0
  44. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  45. package/adapters/mcp/runtime-gateway/execution-tools.ts +207 -0
  46. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  47. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +411 -0
  48. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  49. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  50. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  51. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  52. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +308 -0
  53. package/adapters/mcp/runtime-gateway/process-tools.ts +289 -0
  54. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +76 -0
  55. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +268 -0
  56. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  57. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  58. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +110 -0
  59. package/adapters/mcp/runtime-gateway/result-adapter.ts +108 -0
  60. package/adapters/mcp/runtime-gateway/router.ts +728 -0
  61. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1251 -0
  62. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +634 -0
  63. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  64. package/adapters/mcp/runtime-gateway/runtime-tools.ts +68 -0
  65. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +186 -0
  66. package/adapters/mcp/runtime-gateway/shared-adapter.ts +25 -0
  67. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +870 -0
  68. package/adapters/mcp/runtime-gateway/work-adapter.ts +3186 -0
  69. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +502 -0
  70. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  71. package/adapters/mcp/server.ts +1048 -0
  72. package/adapters/mcp/setup.ts +791 -0
  73. package/adapters/mcp/tool-capability-cache.ts +87 -0
  74. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  75. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5265 -0
  76. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +150 -0
  77. package/adapters/mcp/tool-mapping/repository-tools.ts +1691 -0
  78. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  79. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  80. package/adapters/mcp/toolset-names.ts +74 -0
  81. package/adapters/mcp/toolset-selection.ts +41 -0
  82. package/adapters/mcp/toolset.ts +336 -0
  83. package/adapters/mcp/transports/http.ts +1456 -0
  84. package/adapters/mcp/transports/session-registry.ts +513 -0
  85. package/adapters/mcp/transports/stdio.ts +8 -0
  86. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +139 -0
  87. package/adapters/mcp/types.ts +41 -0
  88. package/assets/AGENTS.md +2 -16
  89. package/assets/CLAUDE.md +2 -16
  90. package/assets/hooks/AGENTS.md +3 -14
  91. package/assets/hooks/CLAUDE.md +3 -14
  92. package/assets/hooks/hook-input.sh +9 -2
  93. package/assets/hooks/lib/workflow-state.sh +28 -10
  94. package/assets/hooks/prompt-guard.sh +63 -37
  95. package/assets/hooks/security-sentinel.sh +2 -1
  96. package/assets/hooks/session-start-context.sh +7 -5
  97. package/assets/hooks/stop-orchestrator.sh +13 -3
  98. package/assets/initializer-question-pack.v4.json +11 -7
  99. package/assets/partials/05-workflow.partial.md +18 -73
  100. package/assets/partials/07-footer.partial.md +1 -1
  101. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  102. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  103. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  104. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  105. package/assets/plan-map.json +11 -11
  106. package/assets/plugin-registry.v1.json +9 -3
  107. package/assets/plugin-trust-policy.v1.json +6 -0
  108. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  109. package/assets/recovery/forge-wsl-rescue +271 -0
  110. package/assets/reference-configs/development-protocol.md +11 -15
  111. package/assets/reference-configs/document-generation.md +1 -1
  112. package/assets/reference-configs/global-working-rules.md +9 -1
  113. package/assets/reference-configs/harness-overview.md +22 -112
  114. package/assets/reference-configs/hook-operations.md +1 -1
  115. package/assets/reference-configs/sprint-contracts.md +2 -2
  116. package/assets/skill-version.json +2 -2
  117. package/assets/templates/helpers/architecture-event.ts +3 -34
  118. package/assets/templates/helpers/architecture-queue.sh +61 -10
  119. package/assets/templates/helpers/archive-workflow.sh +90 -180
  120. package/assets/templates/helpers/capability-config.ts +8 -11
  121. package/assets/templates/helpers/capability-resolver.ts +37 -19
  122. package/assets/templates/helpers/capture-plan.sh +2 -2
  123. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  124. package/assets/templates/helpers/check-task-sync.sh +82 -11
  125. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  126. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  127. package/assets/templates/helpers/contract-worktree.sh +26 -24
  128. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  129. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  130. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  131. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  132. package/assets/templates/helpers/new-plan.sh +2 -2
  133. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  134. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  135. package/assets/templates/helpers/switch-plan.sh +1 -1
  136. package/assets/templates/helpers/workflow-contract.ts +1 -0
  137. package/assets/workflow-contract.v1.json +63 -171
  138. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  139. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  140. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  141. package/docs/architecture/CURRENT.md +148 -13
  142. package/docs/architecture/EVOLUTION.md +13 -0
  143. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  144. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  145. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  146. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  147. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +35 -0
  148. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +296 -0
  149. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  150. package/docs/architecture/domains/verification.md +7 -0
  151. package/docs/architecture/domains/workflow-engine.md +1 -1
  152. package/docs/architecture/index.md +3 -3
  153. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  154. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  155. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  156. package/docs/forge-plugin-management.md +20 -4
  157. package/docs/forge-runtime-self-healing-loop.md +2 -0
  158. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  159. package/docs/operations/controller-browser-plugin.md +3 -1
  160. package/docs/operations/homebrew.md +2 -2
  161. package/docs/operations/platform-support.md +16 -8
  162. package/docs/operations/platform-support.zh-CN.md +2 -2
  163. package/docs/operations/standalone-disaster-recovery.md +26 -1
  164. package/docs/operations/uu-remote-rescue.md +41 -0
  165. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  166. package/docs/public-usage-guide.md +1 -1
  167. package/docs/public-usage-guide.zh-CN.md +1 -1
  168. package/docs/tutorials/01-install-and-start.md +1 -1
  169. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  170. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  171. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  172. package/docs/wiki/Implementation.md +1 -1
  173. package/package.json +23 -14
  174. package/packages/kernel/controller/api/index.ts +2 -0
  175. package/packages/kernel/controller/application/controller-round-service.ts +29 -0
  176. package/packages/kernel/controller/application/controller-service.ts +30 -0
  177. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +308 -0
  178. package/packages/kernel/controller/domain/controller-round.ts +107 -0
  179. package/packages/kernel/controller/domain/execution-quality.ts +133 -0
  180. package/packages/kernel/controller/domain/types.ts +56 -0
  181. package/packages/kernel/controller/index.ts +1 -0
  182. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  183. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1384 -0
  184. package/packages/kernel/controller/infrastructure/controller-session-store.ts +578 -0
  185. package/packages/kernel/controller/ports/controller-host.ts +16 -0
  186. package/packages/kernel/goal/api/index.ts +1 -0
  187. package/packages/kernel/goal/domain/types.ts +40 -0
  188. package/packages/kernel/goal/index.ts +1 -0
  189. package/packages/kernel/identity/api/index.ts +5 -0
  190. package/packages/kernel/identity/application/identity-service.ts +67 -0
  191. package/packages/kernel/identity/domain/scope.ts +63 -0
  192. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  193. package/packages/kernel/identity/domain/types.ts +44 -0
  194. package/packages/kernel/identity/domain/workspace.ts +56 -0
  195. package/packages/kernel/identity/index.ts +1 -0
  196. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  197. package/packages/kernel/memory/api/index.ts +5 -0
  198. package/packages/kernel/memory/application/experience-service.ts +118 -0
  199. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  200. package/packages/kernel/memory/domain/experience.ts +103 -0
  201. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  202. package/packages/kernel/memory/index.ts +1 -0
  203. package/packages/kernel/progression/api/index.ts +2 -0
  204. package/packages/kernel/progression/application/projector.ts +211 -0
  205. package/packages/kernel/progression/domain/types.ts +116 -0
  206. package/packages/kernel/progression/index.ts +1 -0
  207. package/packages/kernel/scheduler/api/index.ts +6 -0
  208. package/packages/kernel/scheduler/application/continuation-service.ts +212 -0
  209. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  210. package/packages/kernel/scheduler/application/schedule-service.ts +24 -0
  211. package/packages/kernel/scheduler/application/settlement.ts +197 -0
  212. package/packages/kernel/scheduler/domain/continuation.ts +38 -0
  213. package/packages/kernel/scheduler/domain/schedule.ts +149 -0
  214. package/packages/kernel/scheduler/index.ts +1 -0
  215. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +38 -0
  216. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +785 -0
  217. package/packages/kernel/work/api/index.ts +15 -0
  218. package/packages/kernel/work/application/work-service.ts +148 -0
  219. package/packages/kernel/work/domain/admission-policy.ts +34 -0
  220. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  221. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  222. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  223. package/packages/kernel/work/domain/engineering-design.ts +281 -0
  224. package/packages/kernel/work/domain/engineering-profile.ts +242 -0
  225. package/packages/kernel/work/domain/execution-concurrency.ts +254 -0
  226. package/packages/kernel/work/domain/execution-snapshot.ts +33 -0
  227. package/packages/kernel/work/domain/implementation-review.ts +510 -0
  228. package/packages/kernel/work/domain/project-engineering-contract.ts +202 -0
  229. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  230. package/packages/kernel/work/domain/state-machine.ts +259 -0
  231. package/packages/kernel/work/domain/types.ts +528 -0
  232. package/packages/kernel/work/index.ts +1 -0
  233. package/packages/kernel/work/infrastructure/work-contract-store.ts +1876 -0
  234. package/packages/kernel/work/ports/work-contract-store.ts +18 -0
  235. package/packages/plugin-runtime/browser/index.ts +3 -0
  236. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  237. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  238. package/packages/plugin-runtime/browser/session-authority.ts +61 -0
  239. package/packages/plugin-runtime/computer/index.ts +6 -0
  240. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  241. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  242. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  243. package/packages/plugin-runtime/computer/provider.ts +19 -0
  244. package/packages/plugin-runtime/computer/target-authority.ts +190 -0
  245. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  246. package/packages/plugin-runtime/external/index.ts +1 -0
  247. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +457 -0
  248. package/packages/plugin-runtime/index.ts +3 -0
  249. package/packages/protocols/browser/index.ts +1 -0
  250. package/packages/protocols/browser/session.ts +98 -0
  251. package/packages/protocols/computer/contract.ts +199 -0
  252. package/packages/protocols/computer/index.ts +1 -0
  253. package/packages/protocols/failure/contract.ts +158 -0
  254. package/packages/protocols/failure/index.ts +1 -0
  255. package/packages/protocols/handoff/index.ts +1 -0
  256. package/packages/protocols/handoff/status.ts +22 -0
  257. package/packages/protocols/mcp/execution-context.ts +11 -0
  258. package/packages/protocols/mcp/index.ts +2 -0
  259. package/packages/protocols/mcp/tool-contract.ts +42 -0
  260. package/packages/workflow-runtime/api/index.ts +2 -0
  261. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  262. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  263. package/packages/workflow-runtime/index.ts +1 -0
  264. package/scripts/assemble-template.ts +1 -1
  265. package/scripts/benchmark-computer-hotpath.ts +255 -0
  266. package/scripts/benchmark-controller-round2.ts +54 -2
  267. package/scripts/benchmark-ios-agent-device.ts +3 -6
  268. package/scripts/benchmark-mcp-transport.ts +3 -4
  269. package/scripts/benchmark-operational-memory-activation.ts +235 -0
  270. package/scripts/benchmark-operational-shadow.ts +28 -0
  271. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  272. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  273. package/scripts/canary-controller-semantic-wait.ts +195 -0
  274. package/scripts/canary-global-hook.sh +2 -2
  275. package/scripts/check-mcp-compatibility.ts +173 -7
  276. package/scripts/check-platform-support.mjs +28 -2
  277. package/scripts/check-public-docs.sh +1 -1
  278. package/scripts/check-release-readiness.sh +1 -1
  279. package/scripts/check-repository-hygiene.mjs +92 -0
  280. package/scripts/check-runtime-architecture.mjs +1206 -95
  281. package/scripts/check-source-duplication.mjs +9 -1
  282. package/scripts/check-tarball-install-smoke.sh +98 -15
  283. package/scripts/controller-ngrok-rotation.sh +5 -4
  284. package/scripts/create-project-dirs.sh +10 -74
  285. package/scripts/forge-local-recovery-helper.mjs +204 -0
  286. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  287. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  288. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  289. package/scripts/hook-shim.sh +2 -2
  290. package/scripts/init-project.sh +12 -70
  291. package/scripts/install-desktop-operator-registration.ts +4 -2
  292. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  293. package/scripts/install-standalone-recovery.ts +122 -10
  294. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  295. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  296. package/scripts/lib/controller-home-env.sh +6 -3
  297. package/scripts/lib/project-init-lib.sh +39 -582
  298. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  299. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  300. package/scripts/open-source-audit-allowlist.txt +12 -1
  301. package/scripts/portability-bindings.mjs +70 -0
  302. package/scripts/run-bounded-command.mjs +55 -0
  303. package/scripts/run-bun-test-file.ts +22 -6
  304. package/scripts/run-governed-gate.ts +4 -1
  305. package/scripts/smoke-mcp-http-runtime.ts +1 -1
  306. package/scripts/smoke-runtime-recovery.ts +34 -1
  307. package/scripts/smoke-schedule-engine.ts +1 -1
  308. package/scripts/stage-runtime-release.ts +6 -1
  309. package/scripts/test-governance.ts +51 -2
  310. package/src/cli/agent-jobs/job-manager.ts +10 -1
  311. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  312. package/src/cli/chatgpt-browser/binding.ts +20 -10
  313. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  314. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  315. package/src/cli/chatgpt-browser/engine.ts +10 -11
  316. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  317. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  318. package/src/cli/chatgpt-browser/types.ts +1 -0
  319. package/src/cli/commands/bootstrap-control.ts +334 -0
  320. package/src/cli/commands/brain-assistant.ts +38 -0
  321. package/src/cli/commands/brain.ts +193 -40
  322. package/src/cli/commands/chatgpt.ts +127 -0
  323. package/src/cli/commands/computer.ts +437 -0
  324. package/src/cli/commands/doctor.ts +18 -1
  325. package/src/cli/commands/init-hook.ts +71 -61
  326. package/src/cli/commands/init.ts +3 -1
  327. package/src/cli/commands/mcp.ts +16 -10
  328. package/src/cli/commands/plugin.ts +38 -12
  329. package/src/cli/commands/recovery.ts +493 -80
  330. package/src/cli/commands/runtime.ts +9 -4
  331. package/src/cli/commands/setup-profile.ts +89 -39
  332. package/src/cli/commands/status.ts +2 -1
  333. package/src/cli/controller/check-runner.ts +487 -98
  334. package/src/cli/controller/context/types.ts +7 -1
  335. package/src/cli/controller/context-pack.ts +23 -3
  336. package/src/cli/controller/issue-store.ts +1 -1
  337. package/src/cli/controller/systemd-user.ts +110 -0
  338. package/src/cli/controller/types.ts +10 -70
  339. package/src/cli/controller/worklog.ts +67 -13
  340. package/src/cli/editing/edit-operation-contract.ts +92 -0
  341. package/src/cli/editing/edit-session.ts +289 -13
  342. package/src/cli/github/plugin.ts +17 -12
  343. package/src/cli/hook/route-registry.ts +3 -5
  344. package/src/cli/hook/runtime.ts +49 -3
  345. package/src/cli/index.ts +3 -0
  346. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  347. package/src/cli/local-bridge/console-automations.ts +2 -2
  348. package/src/cli/local-bridge/facade-api.ts +41 -14
  349. package/src/cli/local-bridge/job-store.ts +1 -1
  350. package/src/cli/local-bridge/server.ts +24 -27
  351. package/src/cli/mcp/access-mode.ts +2 -132
  352. package/src/cli/mcp/access-tools.ts +2 -387
  353. package/src/cli/mcp/audit.ts +2 -32
  354. package/src/cli/mcp/auth.ts +2 -404
  355. package/src/cli/mcp/instructions.ts +2 -34
  356. package/src/cli/mcp/legacy-context.ts +2 -16
  357. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  358. package/src/cli/mcp/multi-repository.ts +2 -436
  359. package/src/cli/mcp/oauth.ts +2 -375
  360. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  361. package/src/cli/mcp/paths.ts +2 -140
  362. package/src/cli/mcp/policy.ts +2 -232
  363. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  364. package/src/cli/mcp/proxy-env.ts +2 -62
  365. package/src/cli/mcp/readiness-projection.ts +2 -24
  366. package/src/cli/mcp/redaction.ts +2 -21
  367. package/src/cli/mcp/repo.ts +2 -24
  368. package/src/cli/mcp/repository-tools.ts +2 -1613
  369. package/src/cli/mcp/server.ts +2 -951
  370. package/src/cli/mcp/setup.ts +2 -737
  371. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  372. package/src/cli/mcp/tool-contract.ts +2 -14
  373. package/src/cli/mcp/tools.ts +2 -9
  374. package/src/cli/mcp/toolset-names.ts +2 -70
  375. package/src/cli/mcp/toolset-selection.ts +2 -41
  376. package/src/cli/mcp/toolset.ts +2 -336
  377. package/src/cli/mcp/transports/AGENTS.md +1 -10
  378. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  379. package/src/cli/mcp/transports/http.ts +2 -1414
  380. package/src/cli/mcp/transports/session-registry.ts +2 -490
  381. package/src/cli/mcp/transports/stdio.ts +2 -8
  382. package/src/cli/mcp/types.ts +2 -41
  383. package/src/cli/mcp/umbrella-tools.ts +2 -117
  384. package/src/cli/repositories/command-executor.ts +64 -18
  385. package/src/cli/repositories/command-scope.ts +117 -1
  386. package/src/cli/repositories/controller-home.ts +119 -1
  387. package/src/cli/repositories/identity.ts +13 -0
  388. package/src/cli/repositories/registry.ts +68 -49
  389. package/src/cli/repositories/repository-snapshot.ts +53 -7
  390. package/src/cli/repositories/runtime-storage.ts +27 -2
  391. package/src/cli/repositories/safe-patch.ts +34 -38
  392. package/src/cli/repositories/selected-path-actions.ts +22 -2
  393. package/src/cli/repositories/structured-git.ts +105 -25
  394. package/src/cli/runtime/helper-runner.ts +7 -0
  395. package/src/cli/runtime-invocation.ts +8 -1
  396. package/src/cli/tools/codegraph.ts +44 -25
  397. package/src/core/adoption/manifest-templates.ts +1 -1
  398. package/src/core/adoption/plan.ts +3 -26
  399. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  400. package/src/effects/process-runner.ts +8 -14
  401. package/src/runtime/context/assistant-context.ts +154 -0
  402. package/src/runtime/context/assistant-work-context.ts +147 -0
  403. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  404. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  405. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  406. package/src/runtime/context/context-closure.ts +268 -0
  407. package/src/runtime/context/context-plane.ts +211 -0
  408. package/src/runtime/context/project-engineering-contract.ts +60 -0
  409. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  410. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  411. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  412. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  413. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  414. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  415. package/src/runtime/control-plane/cleanup-artifact-retention.ts +328 -0
  416. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  417. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +320 -0
  418. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +169 -0
  419. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +350 -0
  420. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +85 -0
  421. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +369 -99
  422. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +103 -15
  423. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  424. package/src/runtime/control-plane/execution/repository-work-attribution.ts +2 -2
  425. package/src/runtime/control-plane/execution/retained-work-resume.ts +336 -6
  426. package/src/runtime/control-plane/execution/validation.ts +28 -3
  427. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +116 -0
  428. package/src/runtime/control-plane/execution/work-completion-authority.ts +44 -2
  429. package/src/runtime/control-plane/execution/work-evidence-policy.ts +34 -3
  430. package/src/runtime/control-plane/execution/work-execution-support.ts +42 -22
  431. package/src/runtime/control-plane/execution/work-finalization-service.ts +1103 -166
  432. package/src/runtime/control-plane/execution/work-handle-authority.ts +219 -22
  433. package/src/runtime/control-plane/execution/work-handle-store.ts +77 -0
  434. package/src/runtime/control-plane/execution/work-head-settlement.ts +75 -0
  435. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +145 -23
  436. package/src/runtime/control-plane/execution/work-operation-service.ts +49 -13
  437. package/src/runtime/control-plane/execution/work-preparation-service.ts +31 -15
  438. package/src/runtime/control-plane/execution/work-remote-delivery.ts +1 -1
  439. package/src/runtime/control-plane/execution/work-task-receipt.ts +20 -1
  440. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +407 -76
  441. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +88 -18
  442. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  443. package/src/runtime/control-plane/execution/work-verification-service.ts +258 -4
  444. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +200 -15
  445. package/src/runtime/control-plane/facade/capability-registry.ts +21 -10
  446. package/src/runtime/control-plane/facade/controller-round-relay.ts +3 -1118
  447. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  448. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -3
  449. package/src/runtime/control-plane/facade/goal-workloop.ts +972 -137
  450. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +158 -0
  451. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +10 -0
  452. package/src/runtime/control-plane/facade/index.ts +4 -2
  453. package/src/runtime/control-plane/facade/operation-digest.ts +22 -58
  454. package/src/runtime/control-plane/facade/plan-contract-store.ts +1004 -38
  455. package/src/runtime/control-plane/facade/repository-work-admission.ts +19 -1
  456. package/src/runtime/control-plane/facade/requirement-authority.ts +218 -0
  457. package/src/runtime/control-plane/facade/requirement-board.ts +6 -1
  458. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +48 -0
  459. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  460. package/src/runtime/control-plane/facade/suggested-actions.ts +4 -1
  461. package/src/runtime/control-plane/facade/types.ts +189 -532
  462. package/src/runtime/control-plane/facade/work-admission-policy.ts +84 -35
  463. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  464. package/src/runtime/control-plane/facade/work-implementation-review.ts +2 -0
  465. package/src/runtime/control-plane/facade/work-state-machine.ts +2 -250
  466. package/src/runtime/control-plane/generated-cache-retention.ts +239 -18
  467. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +12 -1
  468. package/src/runtime/control-plane/global-scheduler/maintenance.ts +76 -13
  469. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  470. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  471. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -1
  472. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  473. package/src/runtime/control-plane/global-scheduler/scheduler.ts +173 -81
  474. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  475. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +397 -0
  476. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  477. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +301 -560
  478. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +20 -4
  479. package/src/runtime/control-plane/launcher/thin-launcher.ts +50 -4
  480. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  481. package/src/runtime/control-plane/persistence/experience-store.ts +169 -0
  482. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  483. package/src/runtime/control-plane/persistence/requirement-store.ts +30 -22
  484. package/src/runtime/control-plane/persistence/sqlite-store.ts +545 -76
  485. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  486. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  487. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  488. package/src/runtime/control-plane/release-retention.ts +56 -16
  489. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  490. package/src/runtime/control-plane/routing/route-policy.ts +19 -0
  491. package/src/runtime/control-plane/runtime-cleanup.ts +574 -37
  492. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  493. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +465 -0
  494. package/src/runtime/control-plane/workspace/workspace-store.ts +80 -0
  495. package/src/runtime/diagnostics/incident-repair.ts +406 -0
  496. package/src/runtime/diagnostics/mcp-timing.ts +125 -6
  497. package/src/runtime/diagnostics/performance.ts +6 -14
  498. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  499. package/src/runtime/evidence/artifact-store.ts +65 -2
  500. package/src/runtime/evidence/operational-shadow.ts +38 -0
  501. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  502. package/src/runtime/evidence/sensitive-output.ts +4 -4
  503. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  504. package/src/runtime/execution/jobs/store.ts +121 -2
  505. package/src/runtime/execution/managed-workspace.ts +55 -5
  506. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  507. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  508. package/src/runtime/execution/process-runtime/check-facade.ts +23 -9
  509. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  510. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  511. package/src/runtime/execution/process-runtime/check-result.ts +73 -2
  512. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +42 -3
  513. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  514. package/src/runtime/execution/process-runtime/command-facade.ts +38 -87
  515. package/src/runtime/execution/process-runtime/index.ts +1 -0
  516. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  517. package/src/runtime/execution/process-runtime/lightweight-managed.ts +32 -1
  518. package/src/runtime/execution/process-runtime/persisted-check.ts +128 -21
  519. package/src/runtime/execution/process-runtime/resource-claims.ts +60 -3
  520. package/src/runtime/execution/process-runtime/runtime.ts +132 -15
  521. package/src/runtime/execution/process-runtime/types.ts +22 -0
  522. package/src/runtime/execution/workers/executor.ts +16 -13
  523. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  524. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  525. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  526. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  527. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  528. package/src/runtime/gateway/mcp/router.ts +2 -1125
  529. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  530. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  531. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  532. package/src/runtime/maintenance/cleanup.ts +38 -24
  533. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  534. package/src/runtime/platform/computer-platform.ts +14 -0
  535. package/src/runtime/platform/executable-discovery.ts +54 -0
  536. package/src/runtime/platform/fetch-http-server.ts +90 -0
  537. package/src/runtime/platform/service-manager.ts +138 -0
  538. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  539. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  540. package/src/runtime/plugins/action-application.ts +135 -0
  541. package/src/runtime/plugins/app-store-connect-adapter.ts +9 -21
  542. package/src/runtime/plugins/browser-adapter.ts +140 -100
  543. package/src/runtime/plugins/browser-automation-service.ts +15 -36
  544. package/src/runtime/plugins/browser-macos-bridge.ts +69 -21
  545. package/src/runtime/plugins/browser-manifest-surface.ts +30 -6
  546. package/src/runtime/plugins/browser-native-session-service.ts +1 -1
  547. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  548. package/src/runtime/plugins/browser-registration.ts +16 -0
  549. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  550. package/src/runtime/plugins/browser-runtime.ts +41 -9
  551. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  552. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  553. package/src/runtime/plugins/browser-session-store.ts +229 -36
  554. package/src/runtime/plugins/browser-session-types.ts +2 -98
  555. package/src/runtime/plugins/capability-authorization-grants.ts +17 -0
  556. package/src/runtime/plugins/catalog-trust.ts +82 -0
  557. package/src/runtime/plugins/computer-registration.ts +839 -0
  558. package/src/runtime/plugins/config-store.ts +119 -0
  559. package/src/runtime/plugins/desktop-operator-external-policy.ts +932 -0
  560. package/src/runtime/plugins/desktop-operator-registration.ts +111 -8
  561. package/src/runtime/plugins/errors.ts +8 -1
  562. package/src/runtime/plugins/external-adapter.ts +45 -322
  563. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  564. package/src/runtime/plugins/external-registration.ts +9 -1
  565. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  566. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  567. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  568. package/src/runtime/plugins/first-party-registry.ts +3 -1
  569. package/src/runtime/plugins/github-adapter.ts +1 -2
  570. package/src/runtime/plugins/gmail-adapter.ts +6 -6
  571. package/src/runtime/plugins/google-calendar-adapter.ts +6 -6
  572. package/src/runtime/plugins/google-shared.ts +31 -46
  573. package/src/runtime/plugins/google-tasks-adapter.ts +6 -6
  574. package/src/runtime/plugins/ios-adapter.ts +1 -2
  575. package/src/runtime/plugins/local-system-adapter.ts +180 -0
  576. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  577. package/src/runtime/plugins/resend-adapter.ts +15 -24
  578. package/src/runtime/plugins/store.ts +493 -51
  579. package/src/runtime/plugins/types.ts +8 -1
  580. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  581. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  582. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  583. package/src/runtime/plugins/xiaohongshu-publish.ts +86 -430
  584. package/src/runtime/projections/controller-context.ts +12 -6
  585. package/src/runtime/projections/git-status-sampler.ts +73 -22
  586. package/src/runtime/projections/materialized-view.ts +14 -8
  587. package/src/runtime/recovery/capability-action-application.ts +228 -0
  588. package/src/runtime/recovery/index.ts +3 -0
  589. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  590. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  591. package/src/runtime/recovery/maintenance-executor.ts +358 -76
  592. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  593. package/src/runtime/release/identity.ts +6 -0
  594. package/src/runtime/resources/leases/store.ts +1 -1
  595. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  596. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  597. package/src/runtime/root/browser-session-composition.ts +59 -0
  598. package/src/runtime/root/computer-composition.ts +191 -0
  599. package/src/runtime/root/computer-target-composition.ts +16 -0
  600. package/src/runtime/root/computer-target-persistence.ts +39 -0
  601. package/src/runtime/root/controller-round-composition.ts +107 -0
  602. package/src/runtime/root/controller-services.ts +2 -0
  603. package/src/runtime/root/entry.ts +4 -3
  604. package/src/runtime/root/gateway-adapter.ts +3 -3
  605. package/src/runtime/root/local-bridge.ts +5 -2
  606. package/src/runtime/root/mcp-transport.ts +5 -5
  607. package/src/runtime/root/package-connector-service.ts +108 -56
  608. package/src/runtime/root/package-runtime-release.ts +85 -18
  609. package/src/runtime/root/package-runtime-service.ts +60 -97
  610. package/src/runtime/root/release-execution-canary.ts +71 -0
  611. package/src/runtime/root/release-loader.ts +68 -0
  612. package/src/runtime/root/release-manifest.ts +106 -2
  613. package/src/runtime/root/release-materialize.ts +103 -4
  614. package/src/runtime/root/release-store.ts +31 -2
  615. package/src/runtime/root/runtime.ts +240 -25
  616. package/src/runtime/root/scheduled-controller-composition.ts +51 -0
  617. package/src/runtime/root/scheduler.ts +12 -4
  618. package/src/runtime/root/service-runner.ts +1 -1
  619. package/src/runtime/root/service.ts +41 -16
  620. package/src/runtime/root/status.ts +1 -0
  621. package/src/runtime/root/types.ts +24 -1
  622. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  623. package/src/runtime/shared/process-environment.ts +19 -4
  624. package/src/runtime/shared/storage-capacity.ts +68 -0
  625. package/src/runtime/standalone-recovery/controller-home-migration.ts +1116 -0
  626. package/src/runtime/standalone-recovery/core.ts +984 -230
  627. package/src/runtime/standalone-recovery/entry.ts +182 -51
  628. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  629. package/src/runtime/standalone-recovery/installer.ts +212 -104
  630. package/src/runtime/standalone-recovery/mcp-server.ts +243 -0
  631. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  632. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  633. package/src/runtime/standalone-recovery/performance.ts +135 -0
  634. package/src/runtime/standalone-recovery/release.ts +5 -0
  635. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  636. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -1
  637. package/src/runtime/workflow/schedules/engine.ts +191 -343
  638. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  639. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  640. package/src/runtime/workflow/schedules/store.ts +2 -607
  641. package/src/runtime/workflow/schedules/types.ts +2 -127
  642. package/src/runtime/workflow/schedules/work-continuation.ts +180 -15
  643. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  644. package/src/runtime/workflows/runtime.ts +486 -0
  645. package/src/testing/test-governance.ts +90 -29
  646. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  647. package/docs/architecture/history/README.md +0 -7
  648. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  649. package/docs/architecture/history/global-hook-runtime.md +0 -166
  650. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  651. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  652. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  653. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  654. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  655. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  656. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  657. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  658. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  659. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  660. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  661. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  662. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  663. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  664. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  665. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  666. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  667. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  668. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  669. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  670. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  671. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  672. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  673. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  674. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  675. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  676. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  677. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  678. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  679. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  680. package/docs/architecture/requests/archive/2026/root.md +0 -68
  681. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  682. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  683. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  684. package/scripts/archive-architecture-request.sh +0 -4
  685. package/scripts/run-skill-evals.ts +0 -1022
@@ -12,14 +12,21 @@ import { repoLocalNoIndexControllerHome, repositoryControllerRoot } from '../../
12
12
  import {
13
13
  getRepository,
14
14
  listRepositories,
15
+ RepositoryCheckoutSelectionError,
15
16
  selectRepositoryCheckout,
16
17
  setRepositoryCheckoutLifecycle,
17
18
  } from '../../../cli/repositories/registry';
18
19
  import { managedPathInside, managedWorktreeStorageRoot } from '../../../cli/repositories/worktree-storage';
19
20
  import { markRepositoryProjectionDirty } from '../../projections/invalidation';
20
21
  import { listControlPlaneRecords } from '../persistence/sqlite-store';
21
- import { getWorkContract } from '../facade/work-contract-store';
22
- import { getControllerSession, releaseObservedControllerSession } from '../facade/controller-session-store';
22
+ import { getWorkContract } from '../../../../packages/kernel/work/api/index';
23
+ import {
24
+ controllerTerminalizationAuthorityFromSession,
25
+ getControllerSession,
26
+ releaseControllerSessionWithAuthority,
27
+ releaseObservedControllerSession,
28
+ type ControllerTerminalizationAuthority,
29
+ } from '../../../../packages/kernel/controller/api/index';
23
30
  import { isRepositoryCompletionReceipt, isTerminalWorkContractStatus, type WorkContract } from '../facade/types';
24
31
  import {
25
32
  cancelProcess,
@@ -33,12 +40,14 @@ import { getProcessRecord, listProcessRecords } from '../../execution/process-ru
33
40
  import {
34
41
  listWorkHandles,
35
42
  readWorkHandle,
43
+ resolveWorkDeliveryTargetBranch,
36
44
  transitionWorkHandle,
37
45
  writeWorkHandle,
38
46
  type WorkCleanupReceipt,
39
47
  type WorkHandleState,
40
48
  type WorkTerminalOutcome,
41
49
  } from './work-handle-store';
50
+ import { proveWorkPreservationContained } from '../cleanup-artifact-retention';
42
51
 
43
52
  const CHECKPOINT_MESSAGE = 'chore(checkpoint): preserve terminal work before cleanup';
44
53
 
@@ -383,8 +392,9 @@ function selectTerminalCleanupTarget(repository: ReturnType<typeof getRepository
383
392
  try {
384
393
  return selectRepositoryCheckout(repository, sourceCheckoutId, { allowArchived: true });
385
394
  } catch (error) {
386
- const message = error instanceof Error ? error.message : String(error);
387
- if (!message.startsWith('CHECKOUT_NOT_ACTIVE:') && !message.startsWith('checkout not found for ')) throw error;
395
+ const unavailable = error instanceof RepositoryCheckoutSelectionError
396
+ && (error.code === 'CHECKOUT_NOT_FOUND' || (error.code === 'CHECKOUT_NOT_ACTIVE' && error.lifecycle === 'removed'));
397
+ if (!unavailable) throw error;
388
398
  }
389
399
  }
390
400
  // Terminal cleanup only performs repository-common Git administration after
@@ -482,7 +492,10 @@ export function recoverTerminalWorkHandle(
482
492
 
483
493
  const head = git(worktreePath, ['rev-parse', 'HEAD']);
484
494
  if (!head.ok || !head.stdout) return undefined;
485
- const targetBranch = repository.defaultBranch || 'main';
495
+ const receiptTargetBranch = contract.completionReceipt && isRepositoryCompletionReceipt(contract.completionReceipt)
496
+ ? contract.completionReceipt.targetBranch?.trim()
497
+ : undefined;
498
+ const targetBranch = receiptTargetBranch || repository.defaultBranch || 'main';
486
499
  const targetExists = branchExists(repository.canonicalRoot, targetBranch);
487
500
  const contained = targetExists
488
501
  ? git(repository.canonicalRoot, ['merge-base', '--is-ancestor', head.stdout, `refs/heads/${targetBranch}`]).ok
@@ -499,6 +512,7 @@ export function recoverTerminalWorkHandle(
499
512
  repositoryId,
500
513
  checkoutId,
501
514
  sourceCheckoutId: repository.activeCheckoutId,
515
+ ...(receiptTargetBranch ? { deliveryTargetBranch: receiptTargetBranch } : {}),
502
516
  worktreePath,
503
517
  branch,
504
518
  managedWorktree: true,
@@ -529,13 +543,229 @@ function cleanupRetainedByRequest(contract: WorkContract, handle: WorkHandleStat
529
543
  // completion-receipt warning as the delivery authority.
530
544
  if (
531
545
  handle.terminalResourceDisposition?.mode === 'retained_by_request'
532
- && handle.terminalResourceDisposition.retainWorktree === true
546
+ && (handle.terminalResourceDisposition.retainWorktree === true
547
+ || handle.terminalResourceDisposition.retainBranch === true)
533
548
  ) return true;
534
549
  const receipt = contract.completionReceipt;
535
550
  if (!receipt || !isRepositoryCompletionReceipt(receipt)) return false;
536
551
  return receipt.cleanup.warnings.some((warning) => warning.code === 'cleanup_retained_by_request');
537
552
  }
538
553
 
554
+ function cleanedManagedBranchRetirementCandidate(
555
+ repository: ReturnType<typeof getRepository>,
556
+ contract: WorkContract,
557
+ handle: WorkHandleState,
558
+ targetBranch: string,
559
+ deleteBranch: boolean,
560
+ ): boolean {
561
+ const receipt = handle.cleanupReceipt;
562
+ if (
563
+ handle.state !== 'cleaned'
564
+ || !handle.managedWorktree
565
+ || !deleteBranch
566
+ || !receipt
567
+ || receipt.targetBranch !== targetBranch
568
+ || cleanupRetainedByRequest(contract, handle)
569
+ ) return false;
570
+ if (!['removed', 'already_removed'].includes(receipt.worktree.status)
571
+ || !['removed', 'already_removed'].includes(receipt.checkoutRegistry.status)
572
+ || receipt.prune.status !== 'done'
573
+ || !['retained', 'failed', 'pending'].includes(receipt.branchCleanup.status)) return false;
574
+ // A crash may occur after branch deletion but before the final cleanup receipt
575
+ // is persisted. The unsettled branchCleanup status is sufficient residue to
576
+ // re-enter cleanup; applyManagedBranchCleanup will converge an absent branch
577
+ // to already_deleted without reopening semantic Work state.
578
+ return handle.branch !== targetBranch;
579
+ }
580
+
581
+ function prepareManagedBranchPreservation(
582
+ input: TerminalWorkCleanupInput,
583
+ receipt: WorkCleanupReceipt,
584
+ current: WorkHandleState,
585
+ target: ReturnType<typeof getRepository>,
586
+ targetBranch: string,
587
+ ): { uniqueCommits: number; branchPreserved: boolean } {
588
+ let uniqueCommits = 0;
589
+ if (branchExists(target.canonicalRoot, current.branch)) {
590
+ if (!branchExists(target.canonicalRoot, targetBranch)) {
591
+ addBlocker(receipt, `TARGET_BRANCH_MISSING: ${targetBranch}`);
592
+ } else {
593
+ const unique = git(target.canonicalRoot, ['rev-list', '--count', `refs/heads/${targetBranch}..refs/heads/${current.branch}`]);
594
+ if (!unique.ok || !/^\d+$/.test(unique.stdout)) addBlocker(receipt, `BRANCH_UNIQUENESS_UNKNOWN: ${unique.stderr || unique.stdout}`);
595
+ else uniqueCommits = Number(unique.stdout);
596
+ }
597
+ }
598
+ receipt.branchCleanup.uniqueCommits = uniqueCommits;
599
+
600
+ let branchPreserved = Boolean(
601
+ receipt.preservation.bundleRetirement?.status === 'not_needed'
602
+ || receipt.preservation.bundleRetirement?.status === 'removed',
603
+ );
604
+ if (receipt.preservation.bundlePath && !branchPreserved) {
605
+ try {
606
+ const bundle = createVerifiedBundle(input.controllerHome, current, target.canonicalRoot);
607
+ if (receipt.preservation.bundleSha256 && receipt.preservation.bundleSha256 !== bundle.sha256) {
608
+ throw new Error(`stored bundle digest ${receipt.preservation.bundleSha256} does not match ${bundle.sha256}`);
609
+ }
610
+ receipt.preservation.bundleSha256 = bundle.sha256;
611
+ branchPreserved = true;
612
+ } catch (error) {
613
+ addBlocker(receipt, `BRANCH_BUNDLE_FAILED: ${error instanceof Error ? error.message : String(error)}`);
614
+ }
615
+ }
616
+ if (uniqueCommits > 0 && !branchPreserved && receipt.blockers.length === 0) {
617
+ const proof = proveWorkPreservationContained(target.canonicalRoot, { ...current, cleanupReceipt: receipt }, targetBranch);
618
+ if (proof.contained) {
619
+ receipt.preservation.bundleRetirement = {
620
+ status: 'not_needed',
621
+ reason: proof.reason === 'no_source_delta' ? 'no_source_delta' : 'target_and_remote_content_contained',
622
+ protectedRevision: proof.protectedRevision!,
623
+ targetRevision: proof.targetRevision,
624
+ remoteRevision: proof.remoteRevision,
625
+ comparedPaths: proof.comparedPaths,
626
+ provedAt: nowIso(),
627
+ };
628
+ receipt.preservation.recoveryInstructions = `Branch bundle not created after ${proof.reason}; exact proof is stored in cleanupReceipt.preservation.bundleRetirement.`;
629
+ branchPreserved = true;
630
+ } else {
631
+ try {
632
+ const bundle = createVerifiedBundle(input.controllerHome, current, target.canonicalRoot);
633
+ receipt.preservation.bundlePath = bundle.path;
634
+ receipt.preservation.bundleSha256 = bundle.sha256;
635
+ receipt.preservation.recoveryInstructions = [
636
+ receipt.preservation.recoveryInstructions,
637
+ `Recover branch commits with: git fetch ${bundle.path} refs/heads/${current.branch}:refs/heads/${current.branch}`,
638
+ ].filter(Boolean).join(' ');
639
+ branchPreserved = true;
640
+ } catch (error) {
641
+ addBlocker(receipt, `BRANCH_BUNDLE_FAILED: ${error instanceof Error ? error.message : String(error)}`);
642
+ }
643
+ }
644
+ }
645
+ return { uniqueCommits, branchPreserved };
646
+ }
647
+
648
+ function applyManagedBranchCleanup(
649
+ target: ReturnType<typeof getRepository>,
650
+ current: WorkHandleState,
651
+ targetBranch: string,
652
+ deleteBranch: boolean,
653
+ receipt: WorkCleanupReceipt,
654
+ uniqueCommits: number,
655
+ branchPreserved: boolean,
656
+ ): void {
657
+ if (!deleteBranch) {
658
+ receipt.branchCleanup.status = 'retained';
659
+ receipt.branchCleanup.reason = 'Branch retention was explicitly requested.';
660
+ } else if (!branchExists(target.canonicalRoot, current.branch)) {
661
+ receipt.branchCleanup.status = 'already_deleted';
662
+ receipt.branchCleanup.reason = undefined;
663
+ } else if (current.branch === targetBranch) {
664
+ receipt.branchCleanup.status = 'retained';
665
+ receipt.branchCleanup.reason = 'Refusing to delete the target branch.';
666
+ addBlocker(receipt, `BRANCH_IS_TARGET: ${targetBranch}`);
667
+ } else if (branchUsedByAnotherWorktree(target.canonicalRoot, current.branch, current.worktreePath)) {
668
+ receipt.branchCleanup.status = 'retained';
669
+ receipt.branchCleanup.reason = 'Branch is checked out by another worktree.';
670
+ addBlocker(receipt, `BRANCH_IN_USE: ${current.branch}`);
671
+ } else if (uniqueCommits > 0 && !branchPreserved) {
672
+ receipt.branchCleanup.status = 'retained';
673
+ receipt.branchCleanup.reason = 'Unique commits are not archived.';
674
+ addBlocker(receipt, `BRANCH_UNPRESERVED: ${current.branch}`);
675
+ } else {
676
+ // We already proved the exact branch relation against targetBranch above.
677
+ // `git branch -d` instead consults the checkout's current HEAD, which may be
678
+ // an older/stale source checkout and can falsely reject a branch that is
679
+ // fully contained in the explicit target branch. After that target-branch
680
+ // proof (or a verified archive for unique commits), delete the ref directly.
681
+ const deleted = git(target.canonicalRoot, ['branch', '-D', current.branch]);
682
+ if (!deleted.ok && branchExists(target.canonicalRoot, current.branch)) {
683
+ receipt.branchCleanup.status = 'failed';
684
+ receipt.branchCleanup.reason = deleted.stderr || 'branch delete failed';
685
+ addBlocker(receipt, `BRANCH_DELETE_FAILED: ${receipt.branchCleanup.reason}`);
686
+ } else {
687
+ receipt.branchCleanup.status = uniqueCommits > 0 && receipt.preservation.bundlePath ? 'archived' : 'deleted';
688
+ receipt.branchCleanup.reason = undefined;
689
+ }
690
+ }
691
+ }
692
+
693
+ function cleanupReceiptComplete(receipt: WorkCleanupReceipt, deleteBranch: boolean): boolean {
694
+ return receipt.blockers.length === 0
695
+ && ['removed', 'already_removed'].includes(receipt.worktree.status)
696
+ && ['removed', 'already_removed'].includes(receipt.checkoutRegistry.status)
697
+ && (deleteBranch
698
+ ? ['deleted', 'already_deleted', 'archived'].includes(receipt.branchCleanup.status)
699
+ : receipt.branchCleanup.status === 'retained');
700
+ }
701
+
702
+ function reconcileCleanedManagedBranchRetirement(
703
+ input: TerminalWorkCleanupInput,
704
+ repository: ReturnType<typeof getRepository>,
705
+ targetBranch: string,
706
+ deleteBranch: boolean,
707
+ current: WorkHandleState,
708
+ receipt: WorkCleanupReceipt,
709
+ ): TerminalWorkCleanupResult | undefined {
710
+ const workId = current.workContractId ?? current.workId;
711
+ const contract = getWorkContract({ controllerHome: input.controllerHome, repoId: current.repositoryId }, workId);
712
+ if (!contract || !isTerminalWorkContractStatus(contract.status)
713
+ || !cleanedManagedBranchRetirementCandidate(repository, contract, current, targetBranch, deleteBranch)) return undefined;
714
+
715
+ const target = selectTerminalCleanupTarget(repository, current);
716
+ receipt.blockers = [];
717
+ receipt.partial = false;
718
+ receipt.complete = false;
719
+ receipt.completedAt = undefined;
720
+ receipt.branchCleanup.status = 'pending';
721
+ receipt.branchCleanup.reason = undefined;
722
+
723
+ const preservation = prepareManagedBranchPreservation(input, receipt, current, target, targetBranch);
724
+ current = persist(input.controllerHome, current, receipt);
725
+ if (receipt.blockers.length === 0) {
726
+ applyManagedBranchCleanup(
727
+ target,
728
+ current,
729
+ targetBranch,
730
+ deleteBranch,
731
+ receipt,
732
+ preservation.uniqueCommits,
733
+ preservation.branchPreserved,
734
+ );
735
+ } else if (receipt.branchCleanup.status === 'pending') {
736
+ receipt.branchCleanup.status = 'retained';
737
+ receipt.branchCleanup.reason = 'Branch retirement proof could not be re-established.';
738
+ }
739
+
740
+ const pruned = git(target.canonicalRoot, ['worktree', 'prune']);
741
+ receipt.prune.status = pruned.ok ? 'done' : 'failed';
742
+ if (!pruned.ok) {
743
+ receipt.prune.reason = pruned.stderr || 'git worktree prune failed';
744
+ addBlocker(receipt, `WORKTREE_PRUNE_FAILED: ${receipt.prune.reason}`);
745
+ } else {
746
+ receipt.prune.reason = undefined;
747
+ }
748
+
749
+ receipt.complete = cleanupReceiptComplete(receipt, deleteBranch);
750
+ receipt.partial = !receipt.complete;
751
+ if (receipt.complete) receipt.completedAt = nowIso();
752
+ const finalization = {
753
+ ...current.finalization,
754
+ branchCleanup: receipt.complete ? 'done' as const : 'failed' as const,
755
+ worktreeCleanup: 'done' as const,
756
+ };
757
+ current = writeWorkHandle(input.controllerHome, {
758
+ ...current,
759
+ state: 'cleaned',
760
+ cleanupReceipt: receipt,
761
+ finalization,
762
+ });
763
+ if (receipt.complete) {
764
+ markRepositoryProjectionDirty(input.controllerHome, current.repositoryId, `cleanup:${current.workId}:terminal-branch-retirement`);
765
+ }
766
+ return { handle: current, receipt };
767
+ }
768
+
539
769
  function reconcileLegacyTerminalBranchDrift(
540
770
  controllerHome: string,
541
771
  repository: ReturnType<typeof getRepository>,
@@ -585,7 +815,7 @@ function reconcileLegacyTerminalBranchDrift(
585
815
 
586
816
  export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Promise<TerminalWorkCleanupResult> {
587
817
  const repository = getRepository(input.handle.repositoryId, input.controllerHome, { includeRemoved: true });
588
- const targetBranch = input.targetBranch?.trim() || repository.defaultBranch || 'main';
818
+ const targetBranch = resolveWorkDeliveryTargetBranch(input.handle, repository.defaultBranch, input.targetBranch);
589
819
  const deleteBranch = input.deleteBranch !== false;
590
820
  let current = input.handle;
591
821
  const landed = current.state === 'merged' || current.finalization.merge === 'done';
@@ -598,7 +828,44 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
598
828
  || receipt.workId !== current.workId
599
829
  ) throw new Error('WORK_CLEANUP_RECEIPT_IDENTITY_MISMATCH');
600
830
 
601
- if (current.state === 'cleaned' && receipt.complete) return { handle: current, receipt };
831
+ if (current.state === 'cleaned') {
832
+ const branchRetirement = reconcileCleanedManagedBranchRetirement(
833
+ input,
834
+ repository,
835
+ targetBranch,
836
+ deleteBranch,
837
+ current,
838
+ receipt,
839
+ );
840
+ if (branchRetirement) return branchRetirement;
841
+ if (!receipt.complete) {
842
+ receipt.complete = true;
843
+ receipt.partial = false;
844
+ receipt.completedAt = receipt.completedAt ?? current.updatedAt ?? nowIso();
845
+ receipt.blockers = [];
846
+ receipt.processes.allTerminal = true;
847
+ if (receipt.ownership.controllerLease === 'pending') receipt.ownership.controllerLease = 'already_released';
848
+ if (receipt.ownership.processLeases === 'pending') receipt.ownership.processLeases = 'released';
849
+ if (receipt.worktree.status === 'pending' || receipt.worktree.status === 'failed') {
850
+ receipt.worktree.status = 'already_removed';
851
+ receipt.worktree.reason = 'Reconciled from durable cleaned WorkHandle state.';
852
+ }
853
+ if (receipt.checkoutRegistry.status === 'pending' || receipt.checkoutRegistry.status === 'failed') {
854
+ receipt.checkoutRegistry.status = 'already_removed';
855
+ receipt.checkoutRegistry.reason = 'Reconciled from durable cleaned WorkHandle state.';
856
+ }
857
+ if (receipt.prune.status === 'pending' || receipt.prune.status === 'failed') {
858
+ receipt.prune.status = 'done';
859
+ receipt.prune.reason = 'Reconciled from durable cleaned WorkHandle state.';
860
+ }
861
+ if (receipt.branchCleanup.status === 'pending' || receipt.branchCleanup.status === 'failed') {
862
+ receipt.branchCleanup.status = 'retained';
863
+ receipt.branchCleanup.reason = 'Historical cleaned state does not prove branch deletion; branch is conservatively retained.';
864
+ }
865
+ current = writeWorkHandle(input.controllerHome, { ...current, cleanupReceipt: receipt });
866
+ }
867
+ return { handle: current, receipt };
868
+ }
602
869
 
603
870
  // Retryable blockers are observations, not permanent vetoes. Recompute them
604
871
  // from durable Work/Process/Git state after a controller restart or retry.
@@ -649,7 +916,11 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
649
916
  }
650
917
 
651
918
  await settleProcesses(input, receipt);
652
- assertNoOtherLiveWork(input, receipt);
919
+ // The selected/current repository checkout is shared infrastructure, not a
920
+ // disposable Work-owned resource. Other live Works may legitimately share it;
921
+ // only a managed Work checkout requires exclusive lifecycle ownership before
922
+ // physical removal.
923
+ if (current.managedWorktree) assertNoOtherLiveWork(input, receipt);
653
924
  current = persist(input.controllerHome, current, receipt);
654
925
  if (receipt.blockers.length > 0) return { handle: current, receipt };
655
926
 
@@ -732,31 +1003,13 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
732
1003
  receipt.worktree.status = 'already_removed';
733
1004
  }
734
1005
 
735
- let uniqueCommits = 0;
736
- if (branchExists(target.canonicalRoot, current.branch)) {
737
- if (!branchExists(target.canonicalRoot, targetBranch)) {
738
- addBlocker(receipt, `TARGET_BRANCH_MISSING: ${targetBranch}`);
739
- } else {
740
- const unique = git(target.canonicalRoot, ['rev-list', '--count', `refs/heads/${targetBranch}..refs/heads/${current.branch}`]);
741
- if (!unique.ok || !/^\d+$/.test(unique.stdout)) addBlocker(receipt, `BRANCH_UNIQUENESS_UNKNOWN: ${unique.stderr || unique.stdout}`);
742
- else uniqueCommits = Number(unique.stdout);
743
- }
744
- }
745
- receipt.branchCleanup.uniqueCommits = uniqueCommits;
746
-
747
- if (uniqueCommits > 0 && !receipt.preservation.bundlePath) {
748
- try {
749
- const bundle = createVerifiedBundle(input.controllerHome, current, target.canonicalRoot);
750
- receipt.preservation.bundlePath = bundle.path;
751
- receipt.preservation.bundleSha256 = bundle.sha256;
752
- receipt.preservation.recoveryInstructions = [
753
- receipt.preservation.recoveryInstructions,
754
- `Recover branch commits with: git fetch ${bundle.path} refs/heads/${current.branch}:refs/heads/${current.branch}`,
755
- ].filter(Boolean).join(' ');
756
- } catch (error) {
757
- addBlocker(receipt, `BRANCH_BUNDLE_FAILED: ${error instanceof Error ? error.message : String(error)}`);
758
- }
759
- }
1006
+ const { uniqueCommits, branchPreserved } = prepareManagedBranchPreservation(
1007
+ input,
1008
+ receipt,
1009
+ current,
1010
+ target,
1011
+ targetBranch,
1012
+ );
760
1013
  current = persist(input.controllerHome, current, receipt);
761
1014
  if (receipt.blockers.length > 0) {
762
1015
  receipt.worktree.status = existsSync(current.worktreePath) ? 'retained' : receipt.worktree.status;
@@ -802,38 +1055,15 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
802
1055
  receipt.checkoutRegistry.reason = 'Checkout metadata was absent after Controller Home migration; canonical managed-worktree and Git identity checks passed before cleanup.';
803
1056
  }
804
1057
 
805
- if (!deleteBranch) {
806
- receipt.branchCleanup.status = 'retained';
807
- receipt.branchCleanup.reason = 'Branch retention was explicitly requested.';
808
- } else if (!branchExists(target.canonicalRoot, current.branch)) {
809
- receipt.branchCleanup.status = 'already_deleted';
810
- } else if (current.branch === targetBranch) {
811
- receipt.branchCleanup.status = 'retained';
812
- receipt.branchCleanup.reason = 'Refusing to delete the target branch.';
813
- addBlocker(receipt, `BRANCH_IS_TARGET: ${targetBranch}`);
814
- } else if (branchUsedByAnotherWorktree(target.canonicalRoot, current.branch, current.worktreePath)) {
815
- receipt.branchCleanup.status = 'retained';
816
- receipt.branchCleanup.reason = 'Branch is checked out by another worktree.';
817
- addBlocker(receipt, `BRANCH_IN_USE: ${current.branch}`);
818
- } else if (uniqueCommits > 0 && !receipt.preservation.bundlePath) {
819
- receipt.branchCleanup.status = 'retained';
820
- receipt.branchCleanup.reason = 'Unique commits are not archived.';
821
- addBlocker(receipt, `BRANCH_UNPRESERVED: ${current.branch}`);
822
- } else {
823
- // We already proved the exact branch relation against targetBranch above.
824
- // `git branch -d` instead consults the checkout's current HEAD, which may be
825
- // an older/stale source checkout and can falsely reject a branch that is
826
- // fully contained in the explicit target branch. After that target-branch
827
- // proof (or a verified archive for unique commits), delete the ref directly.
828
- const deleted = git(target.canonicalRoot, ['branch', '-D', current.branch]);
829
- if (!deleted.ok && branchExists(target.canonicalRoot, current.branch)) {
830
- receipt.branchCleanup.status = 'failed';
831
- receipt.branchCleanup.reason = deleted.stderr || 'branch delete failed';
832
- addBlocker(receipt, `BRANCH_DELETE_FAILED: ${receipt.branchCleanup.reason}`);
833
- } else {
834
- receipt.branchCleanup.status = uniqueCommits > 0 ? 'archived' : 'deleted';
835
- }
836
- }
1058
+ applyManagedBranchCleanup(
1059
+ target,
1060
+ current,
1061
+ targetBranch,
1062
+ deleteBranch,
1063
+ receipt,
1064
+ uniqueCommits,
1065
+ branchPreserved,
1066
+ );
837
1067
 
838
1068
  const pruned = git(target.canonicalRoot, ['worktree', 'prune']);
839
1069
  receipt.prune.status = pruned.ok ? 'done' : 'failed';
@@ -842,12 +1072,7 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
842
1072
  addBlocker(receipt, `WORKTREE_PRUNE_FAILED: ${receipt.prune.reason}`);
843
1073
  }
844
1074
 
845
- receipt.complete = receipt.blockers.length === 0
846
- && ['removed', 'already_removed'].includes(receipt.worktree.status)
847
- && ['removed', 'already_removed'].includes(receipt.checkoutRegistry.status)
848
- && (deleteBranch
849
- ? ['deleted', 'already_deleted', 'archived'].includes(receipt.branchCleanup.status)
850
- : receipt.branchCleanup.status === 'retained');
1075
+ receipt.complete = cleanupReceiptComplete(receipt, deleteBranch);
851
1076
  receipt.partial = !receipt.complete;
852
1077
  if (receipt.complete) receipt.completedAt = receipt.completedAt ?? nowIso();
853
1078
 
@@ -880,6 +1105,91 @@ export async function cleanupTerminalWork(input: TerminalWorkCleanupInput): Prom
880
1105
  return { handle: current, receipt };
881
1106
  }
882
1107
 
1108
+ export interface SingleTerminalWorkCleanupResult {
1109
+ status: 'cleaned' | 'retained' | 'blocked' | 'no_handle' | 'not_terminal';
1110
+ workId: string;
1111
+ handle?: WorkHandleState;
1112
+ receipt?: WorkCleanupReceipt;
1113
+ reason?: string;
1114
+ }
1115
+
1116
+ /**
1117
+ * Reconcile physical resources for one already-terminal Work without reviving its
1118
+ * historical execution principal. WorkContract remains the terminal outcome
1119
+ * authority; this path owns only resource cleanup and refuses unproven active
1120
+ * Controller ownership or unsafe branch drift. A caller proving the exact
1121
+ * leftover owner epoch may release it before physical cleanup.
1122
+ */
1123
+ export async function reconcileSingleTerminalWorkCleanup(
1124
+ controllerHome: string,
1125
+ repositoryId: string,
1126
+ workId: string,
1127
+ options: {
1128
+ targetBranch?: string;
1129
+ deleteBranch?: boolean;
1130
+ /** Recovery authority for the narrow crash window after semantic terminalization but before owner release. */
1131
+ controllerAuthority?: ControllerTerminalizationAuthority;
1132
+ } = {},
1133
+ ): Promise<SingleTerminalWorkCleanupResult> {
1134
+ const repository = getRepository(repositoryId, controllerHome, { includeRemoved: true });
1135
+ const contract = getWorkContract({ controllerHome, repoId: repositoryId }, workId);
1136
+ if (!contract || !isTerminalWorkContractStatus(contract.status)) {
1137
+ return { status: 'not_terminal', workId, reason: 'Work is not terminal.' };
1138
+ }
1139
+ let controllerLease: WorkCleanupReceipt['ownership']['controllerLease'] = 'already_released';
1140
+ const owner = getControllerSession({ controllerHome, repoId: repositoryId }, workId);
1141
+ if (owner) {
1142
+ const authority = options.controllerAuthority;
1143
+ if (!authority) return { status: 'blocked', workId, reason: 'Active Controller ownership still exists.' };
1144
+ const ownerAuthority = controllerTerminalizationAuthorityFromSession(owner);
1145
+ if (!ownerAuthority
1146
+ || ownerAuthority.controllerId !== authority.controllerId
1147
+ || ownerAuthority.controllerType !== authority.controllerType
1148
+ || ownerAuthority.principalId !== authority.principalId
1149
+ || ownerAuthority.controllerInstanceId !== authority.controllerInstanceId
1150
+ || ownerAuthority.claimGeneration !== authority.claimGeneration) {
1151
+ return { status: 'blocked', workId, reason: 'Active Controller ownership does not match the cleanup authority.' };
1152
+ }
1153
+ const released = releaseControllerSessionWithAuthority(
1154
+ { controllerHome, repoId: repositoryId },
1155
+ { workId, actor: `terminal-cleanup:${workId}`, authority },
1156
+ );
1157
+ if (!released.allowed) {
1158
+ return { status: 'blocked', workId, reason: `Active Controller ownership release fenced: ${released.reason}.` };
1159
+ }
1160
+ controllerLease = 'released';
1161
+ }
1162
+ const originalHandle = readWorkHandle(controllerHome, repositoryId, workId)
1163
+ ?? recoverTerminalWorkHandle(controllerHome, repositoryId, workId);
1164
+ if (!originalHandle) return { status: 'no_handle', workId };
1165
+ if (cleanupRetainedByRequest(contract, originalHandle)) {
1166
+ return { status: 'retained', workId, handle: originalHandle, receipt: originalHandle.cleanupReceipt };
1167
+ }
1168
+ const targetBranch = resolveWorkDeliveryTargetBranch(originalHandle, repository.defaultBranch, options.targetBranch);
1169
+ const drift = reconcileLegacyTerminalBranchDrift(controllerHome, repository, originalHandle, targetBranch);
1170
+ if (drift.blocker) return { status: 'blocked', workId, handle: drift.handle, reason: drift.blocker };
1171
+ const cleaned = await cleanupTerminalWork({
1172
+ controllerHome,
1173
+ handle: drift.handle,
1174
+ targetBranch,
1175
+ deleteBranch: options.deleteBranch !== false,
1176
+ terminalOutcome: terminalOutcomeForContract(contract),
1177
+ failureReason: drift.handle.failureReason ?? drift.handle.finalization.lastError,
1178
+ });
1179
+ cleaned.receipt.ownership.controllerLease = controllerLease;
1180
+ const persisted = writeWorkHandle(controllerHome, { ...cleaned.handle, cleanupReceipt: cleaned.receipt });
1181
+ if (!cleaned.receipt.complete) {
1182
+ return {
1183
+ status: 'blocked',
1184
+ workId,
1185
+ handle: persisted,
1186
+ receipt: cleaned.receipt,
1187
+ reason: cleaned.receipt.blockers.join('; ') || cleaned.receipt.worktree.reason || cleaned.receipt.branchCleanup.reason || 'terminal cleanup incomplete',
1188
+ };
1189
+ }
1190
+ return { status: 'cleaned', workId, handle: persisted, receipt: cleaned.receipt };
1191
+ }
1192
+
883
1193
  export async function reconcileTerminalWorkCleanups(
884
1194
  controllerHome: string,
885
1195
  options: TerminalWorkCleanupReconcileOptions = {},
@@ -915,7 +1225,13 @@ export async function reconcileTerminalWorkCleanups(
915
1225
  const contract = record.value;
916
1226
  if (knownWorkIds.has(contract.workId) || !isTerminalWorkContractStatus(contract.status)) continue;
917
1227
  if (!contract.worktreeRef?.trim() || !existsSync(contract.worktreeRef)) continue;
918
- const recovered = recoverTerminalWorkHandle(controllerHome, repository.repoId, contract.workId);
1228
+ let recovered: WorkHandleState | undefined;
1229
+ try {
1230
+ recovered = recoverTerminalWorkHandle(controllerHome, repository.repoId, contract.workId);
1231
+ } catch (error) {
1232
+ report.errors.push({ workId: contract.workId, error: error instanceof Error ? error.message : String(error) });
1233
+ continue;
1234
+ }
919
1235
  if (!recovered) continue;
920
1236
  handles.push(recovered);
921
1237
  knownWorkIds.add(recovered.workId);
@@ -924,16 +1240,31 @@ export async function reconcileTerminalWorkCleanups(
924
1240
  handles.sort((left, right) => left.updatedAt.localeCompare(right.updatedAt));
925
1241
  for (const originalHandle of handles) {
926
1242
  report.scanned += 1;
927
- const contract = getWorkContract({ controllerHome, repoId: repository.repoId }, originalHandle.workContractId ?? originalHandle.workId);
1243
+ let contract: WorkContract | undefined;
1244
+ try {
1245
+ contract = getWorkContract({ controllerHome, repoId: repository.repoId }, originalHandle.workContractId ?? originalHandle.workId);
1246
+ } catch (error) {
1247
+ report.errors.push({ workId: originalHandle.workId, error: error instanceof Error ? error.message : String(error) });
1248
+ continue;
1249
+ }
928
1250
  if (!contract || !isTerminalWorkContractStatus(contract.status)) {
929
1251
  report.skippedNonTerminal.push(originalHandle.workId);
930
1252
  continue;
931
1253
  }
932
- if (originalHandle.state === 'cleaned' && originalHandle.cleanupReceipt?.complete === true) continue;
933
1254
  if (cleanupRetainedByRequest(contract, originalHandle)) {
934
1255
  report.skippedRetained.push(originalHandle.workId);
935
1256
  continue;
936
1257
  }
1258
+ if (originalHandle.state === 'cleaned' && originalHandle.cleanupReceipt?.complete === true) {
1259
+ const targetBranch = resolveWorkDeliveryTargetBranch(originalHandle, repository.defaultBranch);
1260
+ if (!cleanedManagedBranchRetirementCandidate(
1261
+ repository,
1262
+ contract,
1263
+ originalHandle,
1264
+ targetBranch,
1265
+ true,
1266
+ )) continue;
1267
+ }
937
1268
  // Reconstructing a missing handle is metadata recovery, not new Work activity.
938
1269
  // Do not let that write reset the terminal-age grace period indefinitely.
939
1270
  const terminalAt = recoveredWorkIds.has(originalHandle.workId)
@@ -950,7 +1281,7 @@ export async function reconcileTerminalWorkCleanups(
950
1281
  }
951
1282
  report.attempted += 1;
952
1283
  try {
953
- const targetBranch = repository.defaultBranch || 'main';
1284
+ const targetBranch = resolveWorkDeliveryTargetBranch(originalHandle, repository.defaultBranch);
954
1285
  const drift = reconcileLegacyTerminalBranchDrift(controllerHome, repository, originalHandle, targetBranch);
955
1286
  if (drift.blocker) {
956
1287
  report.blocked.push({ workId: originalHandle.workId, reason: drift.blocker });