@moretea-labs/forge 1.7.1 → 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 +39 -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 -1585
  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 +417 -100
  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 +267 -16
  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 -6651
  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 +86 -18
  609. package/src/runtime/root/package-runtime-service.ts +63 -86
  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
@@ -1,1043 +1,2 @@
1
- import { createHash, randomUUID } from 'crypto';
2
- import { existsSync, mkdirSync } from 'fs';
3
- import { join } from 'path';
4
- import { ensureControllerHome, repositoryControllerRoot } from '../../../cli/repositories/controller-home';
5
- import { withControllerLock } from '../../../cli/repositories/locks';
6
- import { readJsonFile, sanitizeFileComponent, writeJsonAtomic } from '../../shared/json-files';
7
- import {
8
- listControlPlaneRecords,
9
- readControlPlaneRecord,
10
- readControlPlaneRecordWithinTransaction,
11
- withControlPlaneTransaction,
12
- writeControlPlaneRecordWithinTransaction,
13
- } from '../persistence/sqlite-store';
14
- import { assertWorkAdmissionAllowed } from './work-admission-policy';
15
- import { phaseIndex, suggestedActionsForStatus, transitionPhaseEvidence, validateWorkSemanticTransition, validateWorkSemantics } from './work-state-machine';
16
- import {
17
- type EvidenceRef,
18
- type CompletionOutcome,
19
- type DispatchState,
20
- type EvidenceState,
21
- type PolicyDecision,
22
- type SuggestedNextAction,
23
- type VerificationRecord,
24
- type WorkReconciliationRecord,
25
- type SubmittedWorkOperation,
26
- type WorkContract,
27
- type WorkContractStatus,
28
- type WorkRisk,
29
- type WorkKind,
30
- type WorkPhase,
31
- type WorkPhaseEvidence,
32
- type WorkPhaseEvidenceMap,
33
- type WorkPhaseEvidenceState,
34
- type WorkContractStore,
35
- isDirectEditWorkCompletionReceipt,
36
- isRepositoryCompletionReceipt,
37
- isTerminalWorkContractStatus,
38
- } from './types';
39
-
40
- export interface WorkContractStoreLocation {
41
- controllerHome?: string;
42
- repoId?: string;
43
- root?: string;
44
- }
45
-
46
- export interface WorkContractStoreOptions extends WorkContractStoreLocation {
47
- now?: () => string;
48
- }
49
-
50
- export type CreateWorkContractInput = Omit<
51
- WorkContract,
52
- 'schemaVersion' | 'status' | 'createdAt' | 'updatedAt' | 'risk' | 'workKind' | 'dispatchState' | 'evidenceState' | 'completionOutcome' | 'phase' | 'phaseEvidence' | 'completionReceipt' | 'evidenceRefs' | 'handoffRefs' | 'suggestedNextActions' | 'policyDecisions' | 'checkRefs' | 'reconciliations' | 'driver' | 'worktreePolicy' | 'evidencePolicy' | 'approvalPolicy' | 'recoveryPolicy'
53
- > & {
54
- risk?: WorkRisk;
55
- status?: WorkContractStatus;
56
- createdAt?: string;
57
- updatedAt?: string;
58
- workKind?: WorkKind;
59
- dispatchState?: DispatchState;
60
- evidenceState?: EvidenceState;
61
- completionOutcome?: CompletionOutcome;
62
- phase?: WorkContract['phase'];
63
- completionReceipt?: WorkContract['completionReceipt'];
64
- evidenceRefs?: EvidenceRef[];
65
- handoffRefs?: string[];
66
- suggestedNextActions?: SuggestedNextAction[];
67
- policyDecisions?: PolicyDecision[];
68
- checkRefs?: VerificationRecord[];
69
- reconciliations?: WorkReconciliationRecord[];
70
- driver?: WorkContract['driver'];
71
- worktreePolicy?: WorkContract['worktreePolicy'];
72
- evidencePolicy?: WorkContract['evidencePolicy'];
73
- approvalPolicy?: WorkContract['approvalPolicy'];
74
- recoveryPolicy?: WorkContract['recoveryPolicy'];
75
- };
76
-
77
- export interface ListWorkContractOptions extends WorkContractStoreOptions {
78
- status?: WorkContractStatus | 'active' | 'all';
79
- limit?: number;
80
- detailLevel?: 'summary' | 'detail' | 'raw';
81
- }
82
-
83
- export type WorktreeAvailability = 'active' | 'inactive' | 'missing' | 'unknown';
84
-
85
- export interface WorkContractReconciliationInput {
86
- activeExecutionJobs: number;
87
- activeLocalJobs: number;
88
- activeLeases: number;
89
- staleAfterMs?: number;
90
- now?: string;
91
- worktreeAvailability?: (worktreeRef: string) => WorktreeAvailability;
92
- }
93
-
94
- export interface WorkContractReconciliationResult {
95
- scanned: number;
96
- reconciled: number;
97
- paused: number;
98
- cancelled: number;
99
- skippedForActiveOwnership: boolean;
100
- workIds: string[];
101
- }
102
-
103
- export interface WorkContractSummary {
104
- workId: string;
105
- repoId: string;
106
- mode: WorkContract['mode'];
107
- phase: WorkContract['phase'];
108
- status: WorkContractStatus;
109
- objective: string;
110
- updatedAt: string;
111
- handoffCount: number;
112
- evidenceCount: number;
113
- checkCount: number;
114
- }
115
-
116
- function nowIso(options: WorkContractStoreOptions): string {
117
- return options.now?.() ?? new Date().toISOString();
118
- }
119
-
120
- export function workContractRoot(location: WorkContractStoreLocation): string {
121
- if (location.root) {
122
- mkdirSync(location.root, { recursive: true });
123
- return location.root;
124
- }
125
- if (!location.controllerHome || !location.repoId) {
126
- throw new Error('work contract store requires either root or controllerHome + repoId');
127
- }
128
- const root = join(repositoryControllerRoot(location.controllerHome, location.repoId), 'work-contracts');
129
- mkdirSync(root, { recursive: true });
130
- return root;
131
- }
132
-
133
- export function workContractStorePath(location: WorkContractStoreLocation): string {
134
- return join(workContractRoot(location), 'index.json');
135
- }
136
-
137
- export function emptyWorkContractStore(updatedAt: string): WorkContractStore {
138
- return { schemaVersion: 2, updatedAt, contracts: [] };
139
- }
140
-
141
- function inferredDispatchState(status: WorkContractStatus): DispatchState {
142
- if (status === 'open' || status === 'ready') return 'not_dispatched';
143
- if (status === 'running') return 'running';
144
- if (status === 'blocked') return 'blocked';
145
- return 'terminal';
146
- }
147
-
148
- function inferredPhase(status: WorkContractStatus): WorkContract['phase'] {
149
- if (status === 'ready') return 'verification';
150
- if (status === 'completed' || status === 'failed' || status === 'cancelled') return 'cleanup';
151
- return 'implementation';
152
- }
153
-
154
- /** Legacy status writes are normalized into the bounded Work phase projection. */
155
- function phaseForStatusUpdate(current: WorkContract['phase'], status: WorkContractStatus | undefined): WorkContract['phase'] {
156
- if (!status) return current;
157
- if (status === 'ready') return 'verification';
158
- if (status === 'completed' || status === 'failed' || status === 'cancelled') return 'cleanup';
159
- return current;
160
- }
161
-
162
- function dispatchStateForStatusUpdate(current: DispatchState, status: WorkContractStatus | undefined): DispatchState {
163
- // `ready` means evidence/approval readiness in the legacy projection; it
164
- // does not mean a running dispatch was never launched.
165
- if (!status || status === 'ready') return current;
166
- return inferredDispatchState(status);
167
- }
168
-
169
- function inferredEvidenceState(status: WorkContractStatus): EvidenceState {
170
- if (status === 'failed') return 'failed';
171
- // A legacy completed status never proves that its evidence remains current.
172
- if (status === 'completed') return 'partial';
173
- return 'none';
174
- }
175
-
176
- function legacyPhaseEvidence(
177
- contract: Pick<WorkContract, 'phase' | 'status' | 'evidenceRefs' | 'completionReceipt' | 'updatedAt'>,
178
- source: WorkPhaseEvidence['source'] = 'legacy_inferred',
179
- ): WorkPhaseEvidenceMap {
180
- const currentIndex = phaseIndex(contract.phase);
181
- const completedByReceipt = Boolean(contract.completionReceipt);
182
- return Object.fromEntries((['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]).map((phase) => {
183
- const index = phaseIndex(phase);
184
- let state: WorkPhaseEvidenceState = index < currentIndex ? 'satisfied' : index === currentIndex ? 'active' : 'pending';
185
- if (completedByReceipt) state = 'satisfied';
186
- else if (contract.status === 'failed' && phase === contract.phase) state = 'failed';
187
- else if (contract.status === 'cancelled' && phase === contract.phase) state = 'skipped';
188
- const receiptId = contract.completionReceipt && (phase === 'delivery' || phase === 'cleanup')
189
- ? contract.completionReceipt.receiptId
190
- : undefined;
191
- return [phase, {
192
- state,
193
- source: completedByReceipt ? 'recorded' : source,
194
- summary: completedByReceipt
195
- ? `Phase ${phase} satisfied by Work completion receipt ${contract.completionReceipt!.receiptId}.`
196
- : index < currentIndex
197
- ? `Legacy Work advanced beyond ${phase}.`
198
- : `Legacy Work phase ${phase} is ${state}.`,
199
- evidenceRefs: contract.evidenceRefs.slice(0, 20),
200
- recordedAt: contract.updatedAt,
201
- ...(receiptId ? { receiptId } : {}),
202
- } satisfies WorkPhaseEvidence];
203
- })) as WorkPhaseEvidenceMap;
204
- }
205
-
206
- function sqliteBacked(options: WorkContractStoreOptions): options is WorkContractStoreOptions & { controllerHome: string; repoId: string } {
207
- // A caller-provided root is a test/portable compatibility store. Runtime
208
- // controller state always carries controllerHome + repoId and is SQLite.
209
- return Boolean(!options.root && options.controllerHome?.trim() && options.repoId?.trim());
210
- }
211
-
212
- function normalizeWorkContractStore(store: WorkContractStore): WorkContractStore {
213
- // Read legacy facade records without retaining the old state machine.
214
- return {
215
- ...store,
216
- contracts: store.contracts.map((legacy) => {
217
- const mappedStatus = ({ pending: 'open', waiting_for_review: 'ready', succeeded: 'completed' } as Record<string, WorkContractStatus>)[String(legacy.status)] ?? legacy.status;
218
- // Historical terminal labels without the Work-owned receipt are not
219
- // completion authority. Reopen them at delivery so callers can obtain an
220
- // exact receipt instead of projecting an unproven success.
221
- const status = mappedStatus === 'completed' && !legacy.completionReceipt ? 'ready' : mappedStatus;
222
- const phase = legacy.completionReceipt
223
- ? 'cleanup'
224
- : mappedStatus === 'completed'
225
- ? 'delivery'
226
- : legacy.phase ?? inferredPhase(status);
227
- return validateWorkSemantics({
228
- ...legacy,
229
- schemaVersion: legacy.schemaVersion ?? 1,
230
- status,
231
- phase,
232
- phaseEvidence: legacy.phaseEvidence ?? legacyPhaseEvidence({
233
- phase,
234
- status,
235
- evidenceRefs: legacy.evidenceRefs ?? [],
236
- completionReceipt: legacy.completionReceipt,
237
- updatedAt: legacy.updatedAt,
238
- }),
239
- risk: legacy.risk ?? 'medium',
240
- workKind: legacy.workKind ?? 'repository_change',
241
- dispatchState: legacy.dispatchState ?? inferredDispatchState(status),
242
- evidenceState: legacy.evidenceState ?? inferredEvidenceState(status),
243
- suggestedNextActions: suggestedActionsForStatus(status, legacy.suggestedNextActions ?? []),
244
- reconciliations: legacy.reconciliations ?? [],
245
- driver: (legacy.driver as unknown as { preferred?: string } | undefined)?.preferred === 'codex_worker'
246
- ? { ...legacy.driver, preferred: 'external_controller', allowWorker: false }
247
- : legacy.driver,
248
- });
249
- }),
250
- };
251
- }
252
-
253
- export function readWorkContractStore(options: WorkContractStoreOptions): WorkContractStore {
254
- if (!sqliteBacked(options)) {
255
- return normalizeWorkContractStore(readJsonFile<WorkContractStore>(workContractStorePath(options), emptyWorkContractStore(nowIso(options))));
256
- }
257
- const records = listControlPlaneRecords<WorkContract>(options.controllerHome, {
258
- namespace: 'work_contract',
259
- scope: options.repoId,
260
- limit: 5_000,
261
- });
262
- if (records.length > 0) {
263
- return normalizeWorkContractStore({
264
- schemaVersion: 2,
265
- updatedAt: records[0]?.updatedAt ?? nowIso(options),
266
- contracts: records.map((record) => record.value),
267
- });
268
- }
269
-
270
- // One-time import only. Once a per-Work row exists, legacy index/file data is
271
- // never consulted again and is never written back.
272
- const legacyRecord = readControlPlaneRecord<WorkContractStore>(
273
- options.controllerHome,
274
- 'work_contract_store',
275
- options.repoId,
276
- 'index',
277
- );
278
- const legacy = legacyRecord?.value
279
- ?? readJsonFile<WorkContractStore>(workContractStorePath(options), emptyWorkContractStore(nowIso(options)));
280
- const normalized = normalizeWorkContractStore(legacy);
281
- if (normalized.contracts.length > 0) {
282
- withControlPlaneTransaction(options.controllerHome, (database) => {
283
- for (const contract of normalized.contracts) {
284
- if (readControlPlaneRecordWithinTransaction<WorkContract>(database, 'work_contract', options.repoId, contract.workId)) continue;
285
- writeControlPlaneRecordWithinTransaction(database, {
286
- namespace: 'work_contract',
287
- scope: options.repoId,
288
- key: contract.workId,
289
- schemaVersion: 2,
290
- value: contract,
291
- action: 'work_contract_legacy_import',
292
- expectedRevision: null,
293
- });
294
- }
295
- });
296
- }
297
- return normalized;
298
- }
299
-
300
- export function writeWorkContractStore(options: WorkContractStoreOptions, store: WorkContractStore): WorkContractStore {
301
- if (!sqliteBacked(options)) {
302
- writeJsonAtomic(workContractStorePath(options), store);
303
- return store;
304
- }
305
- withControlPlaneTransaction(options.controllerHome, (database) => {
306
- for (const contract of store.contracts) {
307
- const current = readControlPlaneRecordWithinTransaction<WorkContract>(
308
- database,
309
- 'work_contract',
310
- options.repoId,
311
- contract.workId,
312
- );
313
- writeControlPlaneRecordWithinTransaction(database, {
314
- namespace: 'work_contract',
315
- scope: options.repoId,
316
- key: contract.workId,
317
- schemaVersion: 2,
318
- value: contract,
319
- action: 'work_contract_write',
320
- expectedRevision: current?.revision ?? null,
321
- });
322
- }
323
- });
324
- return store;
325
- }
326
-
327
- function withWorkContractStoreWrite<T>(options: WorkContractStoreOptions, operation: () => T): T {
328
- if (!sqliteBacked(options)) return operation();
329
- return withControllerLock(
330
- options.controllerHome,
331
- { scope: 'global', resource: `work-contract-store-${sanitizeFileComponent(options.repoId)}` },
332
- `work-contract-store:${options.repoId}`,
333
- operation,
334
- undefined,
335
- 5_000,
336
- );
337
- }
338
-
339
- function defaultDriver(mode: WorkContract['mode']): WorkContract['driver'] {
340
- if (mode === 'direct_control') {
341
- return { preferred: 'direct_edit', allowWorker: false, allowDirectEdit: true };
342
- }
343
- if (mode === 'handoff_only') {
344
- return { preferred: 'handoff_only', allowWorker: false, allowDirectEdit: false };
345
- }
346
- return { preferred: 'direct_edit', allowWorker: false, allowDirectEdit: true };
347
- }
348
-
349
- export function createWorkContract(options: WorkContractStoreOptions, input: CreateWorkContractInput): WorkContract {
350
- if (options.controllerHome) {
351
- assertWorkAdmissionAllowed(options.controllerHome, { operation: 'create', workId: input.workId });
352
- }
353
- if (input.status === 'completed' || input.completionReceipt || input.completionOutcome) {
354
- throw new Error('WORK_COMPLETION_REQUIRES_RECORD_API');
355
- }
356
- const create = (): WorkContract => {
357
- const at = input.createdAt ?? input.updatedAt ?? nowIso(options);
358
- const workId = sanitizeFileComponent(input.workId);
359
- const contract: WorkContract = validateWorkSemantics({
360
- schemaVersion: 2,
361
- workId,
362
- repoId: input.repoId,
363
- checkoutId: input.checkoutId,
364
- principalId: input.principalId,
365
- controllerInstanceId: input.controllerInstanceId,
366
- baseRevision: input.baseRevision,
367
- workspaceFingerprint: input.workspaceFingerprint,
368
- routeDecisionFingerprint: input.routeDecisionFingerprint,
369
- routeDecision: input.routeDecision,
370
- mode: input.mode,
371
- objective: input.objective.slice(0, 2_000),
372
- acceptanceCriteria: (input.acceptanceCriteria ?? []).slice(0, 20).map((item) => item.slice(0, 500)),
373
- constraints: input.constraints ?? { requireHandoffOnAmbiguity: true },
374
- risk: input.risk ?? 'medium',
375
- workKind: input.workKind ?? 'repository_change',
376
- lifecycleRole: input.lifecycleRole ?? 'primary',
377
- parentWorkId: input.parentWorkId?.trim() || undefined,
378
- dispatchState: input.dispatchState ?? inferredDispatchState(input.status ?? 'open'),
379
- evidenceState: input.evidenceState ?? inferredEvidenceState(input.status ?? 'open'),
380
- completionOutcome: input.completionOutcome,
381
- phase: input.phase ?? inferredPhase(input.status ?? 'open'),
382
- phaseEvidence: legacyPhaseEvidence({
383
- phase: input.phase ?? inferredPhase(input.status ?? 'open'),
384
- status: input.status ?? 'open',
385
- evidenceRefs: input.evidenceRefs ?? [],
386
- completionReceipt: input.completionReceipt,
387
- updatedAt: input.updatedAt ?? at,
388
- }, 'recorded'),
389
- completionReceipt: input.completionReceipt,
390
- status: input.status ?? 'open',
391
- createdAt: at,
392
- updatedAt: input.updatedAt ?? at,
393
- issueId: input.issueId,
394
- taskId: input.taskId,
395
- requirementId: input.requirementId,
396
- planId: input.planId,
397
- planStepId: input.planStepId,
398
- planSourceRevision: input.planSourceRevision,
399
- scopeSummary: input.scopeSummary?.slice(0, 1_000),
400
- scopeEvidence: input.scopeEvidence ? {
401
- initialLikelyPaths: [...new Set(input.scopeEvidence.initialLikelyPaths)].slice(0, 100),
402
- inspectedPaths: [...new Set(input.scopeEvidence.inspectedPaths)].slice(0, 500),
403
- actualChangedPaths: [...new Set(input.scopeEvidence.actualChangedPaths)].slice(0, 500),
404
- recordedAt: input.scopeEvidence.recordedAt,
405
- } : undefined,
406
- allowedPaths: (input.allowedPaths ?? []).slice(0, 50),
407
- forbiddenPaths: (input.forbiddenPaths ?? []).slice(0, 50),
408
- checks: (input.checks ?? []).slice(0, 30),
409
- driver: input.driver ?? defaultDriver(input.mode),
410
- worktreePolicy: input.worktreePolicy ?? {
411
- required: input.mode === 'goal_workloop',
412
- reason: input.mode === 'goal_workloop' ? 'Goal workloop defaults to isolated worktree execution.' : undefined,
413
- },
414
- evidencePolicy: input.evidencePolicy ?? {
415
- defaultDetailLevel: 'summary',
416
- allowRawOptIn: true,
417
- maxEvidenceRefs: 20,
418
- },
419
- approvalPolicy: input.approvalPolicy ?? { required: false, reasons: [], confirmed: false },
420
- recoveryPolicy: input.recoveryPolicy ?? {
421
- allowSelfHealing: false,
422
- maxInfrastructureRetries: 0,
423
- handoffOnAmbiguity: true,
424
- },
425
- requestedBy: input.requestedBy ?? 'chatgpt',
426
- evidenceRefs: (input.evidenceRefs ?? []).slice(0, 20),
427
- handoffRefs: (input.handoffRefs ?? []).slice(0, 20),
428
- suggestedNextActions: (input.suggestedNextActions ?? []).slice(0, 8),
429
- policyDecisions: (input.policyDecisions ?? []).slice(0, 20),
430
- checkRefs: (input.checkRefs ?? []).slice(0, 50),
431
- reconciliations: (input.reconciliations ?? []).slice(0, 20),
432
- continuationPrompt: input.continuationPrompt?.slice(0, 2_000),
433
- worktreeRef: input.worktreeRef,
434
- workerRef: input.workerRef,
435
- requestId: input.requestId?.trim() || undefined,
436
- submittedOperation: input.submittedOperation,
437
- });
438
-
439
- if (sqliteBacked(options)) {
440
- withControlPlaneTransaction(options.controllerHome, (database) => {
441
- if (readControlPlaneRecordWithinTransaction<WorkContract>(database, 'work_contract', options.repoId, contract.workId)) {
442
- throw new Error(`work contract already exists: ${contract.workId}`);
443
- }
444
- writeControlPlaneRecordWithinTransaction(database, {
445
- namespace: 'work_contract',
446
- scope: options.repoId,
447
- key: contract.workId,
448
- schemaVersion: 2,
449
- value: contract,
450
- action: 'work_contract_created',
451
- expectedRevision: null,
452
- });
453
- });
454
- return contract;
455
- }
456
- const store = readWorkContractStore(options);
457
- if (store.contracts.some((existing) => existing.workId === contract.workId)) {
458
- throw new Error(`work contract already exists: ${contract.workId}`);
459
- }
460
- const nextStore: WorkContractStore = {
461
- schemaVersion: 2,
462
- updatedAt: contract.updatedAt,
463
- contracts: [contract, ...store.contracts],
464
- };
465
- writeWorkContractStore(options, nextStore);
466
- return contract;
467
- };
468
- return create();
469
- }
470
-
471
- interface WorkRequestIndexRecord {
472
- requestId: string;
473
- repoId: string;
474
- workId: string;
475
- semanticKey: string;
476
- createdAt: string;
477
- }
478
-
479
- function workRequestIndexPath(controllerHome: string, requestId: string): string {
480
- const hash = createHash('sha256').update(requestId).digest('hex');
481
- const root = join(ensureControllerHome(controllerHome), 'indexes', 'work-contracts', 'requests');
482
- mkdirSync(root, { recursive: true });
483
- return join(root, `${hash}.json`);
484
- }
485
-
486
- export function getWorkContractByRequestId(
487
- controllerHome: string,
488
- requestId: string,
489
- expectedRepoId?: string,
490
- ): WorkContract | undefined {
491
- const normalizedRequestId = requestId.trim();
492
- if (!normalizedRequestId) return undefined;
493
- const recordPath = workRequestIndexPath(controllerHome, normalizedRequestId);
494
- if (!existsSync(recordPath)) return undefined;
495
- try {
496
- const record = readJsonFile<WorkRequestIndexRecord>(recordPath);
497
- if (record.requestId !== normalizedRequestId) return undefined;
498
- if (expectedRepoId && record.repoId !== expectedRepoId) return undefined;
499
- return getWorkContract({ controllerHome, repoId: record.repoId }, record.workId);
500
- } catch {
501
- return undefined;
502
- }
503
- }
504
-
505
- /**
506
- * Create or reuse the execution-child Work used by typed callers. This is not
507
- * a generic MCP submission authority and never creates an ExecutionJob.
508
- */
509
- export function acceptSubmittedWorkContract(
510
- controllerHome: string,
511
- input: AcceptSubmittedWorkInput,
512
- options: WorkContractStoreOptions = {},
513
- ): { contract: WorkContract; deduplicated: boolean } {
514
- const home = ensureControllerHome(controllerHome);
515
- const requestId = input.requestId.trim();
516
- const semanticKey = input.semanticKey.trim();
517
- if (!requestId) throw new Error('INVALID_ARGUMENT: typed execution is missing request_id');
518
- if (!semanticKey) throw new Error('INVALID_ARGUMENT: typed execution requires a semantic operation key');
519
- if (!input.repoId.trim()) throw new Error('INVALID_ARGUMENT: typed execution is missing repo_id');
520
- if (!input.operation?.name?.trim()) throw new Error('INVALID_ARGUMENT: typed execution is missing operation');
521
- const parentWorkId = input.parentWorkId?.trim() || undefined;
522
- if (parentWorkId) {
523
- const parent = getWorkContract({ controllerHome: home, repoId: input.repoId, now: options.now }, parentWorkId);
524
- if (!parent) throw new Error(`PARENT_WORK_NOT_FOUND: ${parentWorkId}`);
525
- if (isTerminalWorkContractStatus(parent.status)) throw new Error(`PARENT_WORK_TERMINAL: ${parentWorkId}:${parent.status}`);
526
- if ((parent.lifecycleRole ?? 'primary') !== 'primary') throw new Error(`PARENT_WORK_NOT_PRIMARY: ${parentWorkId}`);
527
- }
528
- const lockId = createHash('sha256').update(requestId).digest('hex').slice(0, 24);
529
- return withControllerLock(home, { scope: 'global', resource: `work-request-${lockId}` }, `accept-work:${requestId}`, () => {
530
- const recordPath = workRequestIndexPath(home, requestId);
531
- if (existsSync(recordPath)) {
532
- const record = readJsonFile<WorkRequestIndexRecord>(recordPath);
533
- if (record.repoId !== input.repoId) throw new Error(`REQUEST_ID_REPO_CONFLICT: ${requestId} already belongs to repository ${record.repoId}`);
534
- if (record.semanticKey !== semanticKey) throw new Error(`REQUEST_ID_CONFLICT: ${requestId} already belongs to ${record.semanticKey}`);
535
- const existing = getWorkContract({ controllerHome: home, repoId: record.repoId, now: options.now }, record.workId);
536
- if (!existing) throw new Error(`WORK_ACCEPTANCE_LOST: request ${requestId} is indexed without a readable WorkContract`);
537
- return { contract: existing, deduplicated: true };
538
- }
539
- const contract = createWorkContract({ controllerHome: home, repoId: input.repoId, now: options.now }, {
540
- workId: `WORK-${Date.now()}-${randomUUID().slice(0, 8)}`,
541
- repoId: input.repoId,
542
- principalId: input.principalId,
543
- controllerInstanceId: input.controllerInstanceId,
544
- mode: input.mode ?? 'direct_control',
545
- lifecycleRole: 'execution_child',
546
- parentWorkId,
547
- objective: (input.objective ?? `Typed operation ${input.operation.name}`).slice(0, 2_000),
548
- acceptanceCriteria: input.acceptanceCriteria ?? [],
549
- workKind: input.workKind,
550
- risk: input.risk,
551
- constraints: input.constraints ?? { requireHandoffOnAmbiguity: true },
552
- allowedPaths: input.allowedPaths ?? [],
553
- forbiddenPaths: input.forbiddenPaths ?? [],
554
- checks: input.checks ?? [],
555
- requestedBy: input.requestedBy ?? 'chatgpt',
556
- status: 'open',
557
- requestId,
558
- submittedOperation: input.operation,
559
- driver: { preferred: 'external_controller', allowWorker: false, allowDirectEdit: input.operation.mode === 'readonly' || input.operation.mode === 'mutating' },
560
- suggestedNextActions: [{
561
- label: 'Claim controller ownership',
562
- tool: 'rh_work',
563
- operation: 'controller_claim',
564
- risk: 'readonly',
565
- confidence: 'high',
566
- reason: 'Claim this Work before launching an external SuperController or Process Runtime command.',
567
- }],
568
- });
569
- writeJsonAtomic(recordPath, { requestId, repoId: input.repoId, workId: contract.workId, semanticKey, createdAt: contract.createdAt } satisfies WorkRequestIndexRecord);
570
- return { contract, deduplicated: false };
571
- });
572
- }
573
-
574
- export function listWorkContracts(options: ListWorkContractOptions): WorkContract[] {
575
- const store = readWorkContractStore(options);
576
- const status = options.status ?? 'active';
577
- const limit = Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100));
578
- return store.contracts
579
- .filter((contract) => {
580
- if (status === 'all') return true;
581
- if (status === 'active') return !isTerminalWorkContractStatus(contract.status);
582
- return contract.status === status;
583
- })
584
- .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt))
585
- .slice(0, limit);
586
- }
587
-
588
- const RECONCILIATION_EVIDENCE_TITLE = 'runtime reconciliation required';
589
- const SYSTEM_ONLY_EVIDENCE_TITLES = new Set([
590
- RECONCILIATION_EVIDENCE_TITLE,
591
- 'work contract created',
592
- ]);
593
-
594
- function wasPausedByRuntimeReconciliation(contract: WorkContract): boolean {
595
- return contract.evidenceRefs.some((evidence) => evidence.title === RECONCILIATION_EVIDENCE_TITLE);
596
- }
597
-
598
- function hasReviewableWorkOutput(contract: WorkContract): boolean {
599
- if (contract.checkRefs.length > 0 || contract.handoffRefs.length > 0) return true;
600
- if ((contract.scopeEvidence?.inspectedPaths.length ?? 0) > 0) return true;
601
- if ((contract.readOnlyReviewEvidence?.inspectedPaths.length ?? 0) > 0 || (contract.readOnlyReviewEvidence?.findings.length ?? 0) > 0) return true;
602
- return contract.evidenceRefs.some((evidence) =>
603
- Boolean(evidence.artifactId || evidence.evidenceId)
604
- || !SYSTEM_ONLY_EVIDENCE_TITLES.has(evidence.title));
605
- }
606
-
607
- function unavailableReconciledWorktree(
608
- contract: WorkContract,
609
- input: WorkContractReconciliationInput,
610
- ): boolean {
611
- if (!contract.worktreeRef) return true;
612
- const availability = input.worktreeAvailability?.(contract.worktreeRef) ?? 'unknown';
613
- return availability === 'inactive' || availability === 'missing';
614
- }
615
-
616
- export function reconcileStaleWorkContracts(
617
- options: WorkContractStoreOptions,
618
- input: WorkContractReconciliationInput,
619
- ): WorkContractReconciliationResult {
620
- return withWorkContractStoreWrite(options, () => reconcileStaleWorkContractsLocked(options, input));
621
- }
622
-
623
- function reconcileStaleWorkContractsLocked(
624
- options: WorkContractStoreOptions,
625
- input: WorkContractReconciliationInput,
626
- ): WorkContractReconciliationResult {
627
- const store = readWorkContractStore(options);
628
- const running = store.contracts.filter((contract) => contract.status === 'running');
629
- const reconciledReviews = store.contracts.filter((contract) =>
630
- contract.status === 'blocked' && wasPausedByRuntimeReconciliation(contract));
631
- const candidates = [...running, ...reconciledReviews];
632
- const activeOwnership = input.activeExecutionJobs > 0 || input.activeLocalJobs > 0 || input.activeLeases > 0;
633
- if (activeOwnership || candidates.length === 0) {
634
- return {
635
- scanned: candidates.length,
636
- reconciled: 0,
637
- paused: 0,
638
- cancelled: 0,
639
- skippedForActiveOwnership: activeOwnership,
640
- workIds: [],
641
- };
642
- }
643
-
644
- const now = input.now ?? nowIso(options);
645
- const nowMs = Date.parse(now);
646
- const staleAfterMs = Math.max(60_000, Math.trunc(input.staleAfterMs ?? 30 * 60_000));
647
- if (!Number.isFinite(nowMs)) {
648
- return {
649
- scanned: candidates.length,
650
- reconciled: 0,
651
- paused: 0,
652
- cancelled: 0,
653
- skippedForActiveOwnership: false,
654
- workIds: [],
655
- };
656
- }
657
-
658
- const workIds: string[] = [];
659
- let paused = 0;
660
- let cancelled = 0;
661
- const contracts = store.contracts.map((contract) => {
662
- if (contract.status !== 'running' && contract.status !== 'blocked') return contract;
663
- const updatedMs = Date.parse(contract.updatedAt);
664
- if (!Number.isFinite(updatedMs) || nowMs - updatedMs < staleAfterMs) return contract;
665
-
666
- const shouldCancel = contract.status === 'blocked'
667
- && wasPausedByRuntimeReconciliation(contract)
668
- && !hasReviewableWorkOutput(contract)
669
- && unavailableReconciledWorktree(contract, input);
670
- if (shouldCancel) {
671
- workIds.push(contract.workId);
672
- cancelled += 1;
673
- const evidence: EvidenceRef = {
674
- title: 'runtime reconciliation cancelled orphaned work',
675
- summary: contract.worktreeRef
676
- ? 'Work remained ownerless without reviewable output and its isolated checkout is no longer recoverable.'
677
- : 'Work remained ownerless without reviewable output and has no recoverable worktree reference.',
678
- detailLevel: 'summary',
679
- };
680
- return {
681
- ...contract,
682
- status: 'cancelled' as const,
683
- updatedAt: now,
684
- evidenceRefs: [evidence, ...contract.evidenceRefs].slice(0, contract.evidencePolicy.maxEvidenceRefs),
685
- suggestedNextActions: [],
686
- continuationPrompt: `Runtime reconciliation cancelled orphaned work ${contract.workId}; no reviewable output or recoverable checkout remains.`.slice(0, 2_000),
687
- };
688
- }
689
-
690
- if (contract.status !== 'running') return contract;
691
- workIds.push(contract.workId);
692
- paused += 1;
693
- const evidence: EvidenceRef = {
694
- title: RECONCILIATION_EVIDENCE_TITLE,
695
- summary: 'Work was marked running but no active Execution Job, Local Job, or lease owns this repository. Automatic replay was not attempted.',
696
- detailLevel: 'summary',
697
- };
698
- const inspectAction: SuggestedNextAction = {
699
- label: 'Inspect reconciled work',
700
- tool: 'rh_context',
701
- operation: 'get',
702
- payload: { work_id: contract.workId },
703
- risk: 'readonly',
704
- confidence: 'high',
705
- reason: 'Review retained evidence before continuing, finalizing, or stopping this stale work.',
706
- };
707
- return {
708
- ...contract,
709
- status: 'blocked' as const,
710
- updatedAt: now,
711
- evidenceRefs: [evidence, ...contract.evidenceRefs].slice(0, contract.evidencePolicy.maxEvidenceRefs),
712
- suggestedNextActions: [inspectAction, ...contract.suggestedNextActions]
713
- .filter((action, index, actions) => actions.findIndex((candidate) => candidate.tool === action.tool && candidate.operation === action.operation) === index)
714
- .slice(0, 8),
715
- continuationPrompt: `Runtime reconciliation paused stale running work ${contract.workId}; inspect evidence and decide whether to continue, finalize, or stop.`.slice(0, 2_000),
716
- };
717
- });
718
-
719
- if (workIds.length > 0) {
720
- writeWorkContractStore(options, { schemaVersion: 2, updatedAt: now, contracts });
721
- }
722
- return {
723
- scanned: candidates.length,
724
- reconciled: workIds.length,
725
- paused,
726
- cancelled,
727
- skippedForActiveOwnership: false,
728
- workIds,
729
- };
730
- }
731
-
732
- export function getWorkContract(options: WorkContractStoreOptions, workId: string): WorkContract | undefined {
733
- const sanitizedId = sanitizeFileComponent(workId);
734
- return readWorkContractStore(options).contracts.find((contract) => contract.workId === sanitizedId);
735
- }
736
-
737
- export function summarizeWorkContract(contract: WorkContract): WorkContractSummary {
738
- return {
739
- workId: contract.workId,
740
- repoId: contract.repoId,
741
- mode: contract.mode,
742
- phase: contract.phase,
743
- status: contract.status,
744
- objective: contract.objective.slice(0, 240),
745
- updatedAt: contract.updatedAt,
746
- handoffCount: contract.handoffRefs.length,
747
- evidenceCount: contract.evidenceRefs.length,
748
- checkCount: contract.checkRefs.length,
749
- };
750
- }
751
-
752
- function updateWorkContractInternal(
753
- options: WorkContractStoreOptions,
754
- workId: string,
755
- patch: Partial<Omit<WorkContract, 'schemaVersion' | 'workId' | 'repoId' | 'createdAt'>>,
756
- allowCompletionWrite: boolean,
757
- allowPhaseWrite = false,
758
- allowRetainedCancelledResume = false,
759
- ): WorkContract {
760
- return withWorkContractStoreWrite(options, () => {
761
- const sanitizedId = sanitizeFileComponent(workId);
762
- const store = readWorkContractStore(options);
763
- const index = store.contracts.findIndex((contract) => contract.workId === sanitizedId);
764
- if (index < 0) throw new Error(`work contract not found: ${sanitizedId}`);
765
- const at = nowIso(options);
766
- const current = store.contracts[index];
767
- if (options.controllerHome) {
768
- assertWorkAdmissionAllowed(options.controllerHome, {
769
- operation: patch.status !== undefined && isTerminalWorkContractStatus(patch.status)
770
- ? 'maintenance'
771
- : 'continue',
772
- workId: sanitizedId,
773
- });
774
- }
775
- const writesCompletionReceipt = Object.prototype.hasOwnProperty.call(patch, 'completionReceipt');
776
- const changesCompletionOutcome = patch.completionOutcome !== undefined && patch.completionOutcome !== current.completionOutcome;
777
- const writesPhase = Object.prototype.hasOwnProperty.call(patch, 'phase') || Object.prototype.hasOwnProperty.call(patch, 'phaseEvidence');
778
- if (!allowPhaseWrite && writesPhase) throw new Error('WORK_PHASE_REQUIRES_TRANSITION_API');
779
- const projectedPhase = patch.phase ?? phaseForStatusUpdate(current.phase, patch.status);
780
- const projectedPhaseEvidence = patch.phaseEvidence ?? (
781
- patch.status !== undefined && projectedPhase !== current.phase
782
- ? transitionPhaseEvidence(current, projectedPhase, {
783
- status: patch.status,
784
- summary: `Compatibility status transition ${current.status} -> ${patch.status}.`,
785
- evidenceRefs: patch.evidenceRefs ?? current.evidenceRefs,
786
- recordedAt: at,
787
- })
788
- : current.phaseEvidence
789
- );
790
- if (!allowCompletionWrite && (writesCompletionReceipt || changesCompletionOutcome || (patch.status === 'completed' && current.status !== 'completed'))) {
791
- throw new Error('WORK_COMPLETION_REQUIRES_RECORD_API');
792
- }
793
- if (patch.status === 'completed' && !current.completionReceipt && !patch.completionReceipt) {
794
- throw new Error('WORK_COMPLETION_RECEIPT_REQUIRED');
795
- }
796
- if (writesCompletionReceipt && patch.completionReceipt === undefined && current.completionReceipt) {
797
- throw new Error('WORK_COMPLETION_RECEIPT_IMMUTABLE');
798
- }
799
- const next: WorkContract = validateWorkSemanticTransition(current, validateWorkSemantics({
800
- ...current,
801
- ...patch,
802
- schemaVersion: 2,
803
- workId: current.workId,
804
- repoId: current.repoId,
805
- createdAt: current.createdAt,
806
- updatedAt: at,
807
- risk: patch.risk ?? current.risk,
808
- workKind: patch.workKind ?? current.workKind,
809
- phase: projectedPhase,
810
- phaseEvidence: projectedPhaseEvidence,
811
- dispatchState: patch.dispatchState ?? dispatchStateForStatusUpdate(current.dispatchState, patch.status),
812
- evidenceState: patch.evidenceState ?? current.evidenceState,
813
- completionOutcome: patch.completionOutcome ?? current.completionOutcome,
814
- evidenceRefs: (patch.evidenceRefs ?? current.evidenceRefs).slice(0, current.evidencePolicy.maxEvidenceRefs),
815
- handoffRefs: (patch.handoffRefs ?? current.handoffRefs).slice(0, 20),
816
- suggestedNextActions: suggestedActionsForStatus(patch.status ?? current.status, patch.suggestedNextActions ?? current.suggestedNextActions),
817
- policyDecisions: (patch.policyDecisions ?? current.policyDecisions).slice(0, 20),
818
- checkRefs: (patch.checkRefs ?? current.checkRefs).slice(0, 50),
819
- reconciliations: (patch.reconciliations ?? current.reconciliations ?? []).slice(0, 20),
820
- objective: (patch.objective ?? current.objective).slice(0, 2_000),
821
- continuationPrompt: (patch.continuationPrompt ?? current.continuationPrompt)?.slice(0, 2_000),
822
- }), { allowRetainedCancelledResume });
823
- const contracts = [...store.contracts];
824
- contracts[index] = next;
825
- writeWorkContractStore(options, { schemaVersion: 2, updatedAt: at, contracts });
826
- return next;
827
- });
828
- }
829
-
830
- export function updateWorkContract(
831
- options: WorkContractStoreOptions,
832
- workId: string,
833
- patch: Partial<Omit<WorkContract, 'schemaVersion' | 'workId' | 'repoId' | 'createdAt'>>,
834
- ): WorkContract {
835
- return updateWorkContractInternal(options, workId, patch, false);
836
- }
837
-
838
- /**
839
- * Reopen one explicitly retained cancelled repository Work after the facade has
840
- * reauthenticated the same principal and revalidated physical Work ownership.
841
- * Generic mutation APIs intentionally cannot perform terminal -> running.
842
- */
843
- export function resumeRetainedCancelledWorkContract(
844
- options: WorkContractStoreOptions,
845
- workId: string,
846
- input: {
847
- principalId: string;
848
- controllerInstanceId: string;
849
- summary: string;
850
- checkoutId?: string;
851
- worktreeRef?: string;
852
- },
853
- ): WorkContract {
854
- const current = getWorkContract(options, workId);
855
- if (!current) throw new Error(`work contract not found: ${workId}`);
856
- if (current.status !== 'cancelled' || current.dispatchState !== 'terminal' || current.phase !== 'cleanup') {
857
- throw new Error(`WORK_CANCELLED_RESUME_STATUS_INVALID: ${workId}`);
858
- }
859
- if (current.workKind !== 'repository_change') throw new Error(`WORK_CANCELLED_RESUME_KIND_INVALID: ${workId}`);
860
- if (current.completionReceipt || current.completionOutcome) throw new Error(`WORK_CANCELLED_RESUME_COMPLETION_CONFLICT: ${workId}`);
861
- if (current.phaseEvidence.cleanup.state !== 'skipped' || current.phaseEvidence.cleanup.source !== 'recorded') {
862
- throw new Error(`WORK_CANCELLED_RESUME_HISTORY_AMBIGUOUS: ${workId}`);
863
- }
864
- const originalPrincipal = current.principalId?.trim();
865
- if (!originalPrincipal || originalPrincipal !== input.principalId.trim()) {
866
- throw new Error(`WORK_CANCELLED_RESUME_PRINCIPAL_MISMATCH: ${workId}`);
867
- }
868
- const at = nowIso(options);
869
- const evidenceRefs = [...current.evidenceRefs, {
870
- title: 'explicit current-user Work reauthorization',
871
- summary: input.summary.trim().slice(0, 1_000),
872
- detailLevel: 'summary' as const,
873
- }].slice(-current.evidencePolicy.maxEvidenceRefs);
874
- const phaseEvidence = transitionPhaseEvidence({ ...current, evidenceRefs }, 'implementation', {
875
- status: 'running',
876
- summary: input.summary,
877
- evidenceRefs,
878
- recordedAt: at,
879
- source: 'recorded',
880
- });
881
- return updateWorkContractInternal(options, workId, {
882
- status: 'running',
883
- phase: 'implementation',
884
- phaseEvidence,
885
- dispatchState: 'running',
886
- evidenceRefs,
887
- checkoutId: input.checkoutId ?? current.checkoutId,
888
- worktreeRef: input.worktreeRef ?? current.worktreeRef,
889
- controllerInstanceId: input.controllerInstanceId,
890
- continuationPrompt: input.summary,
891
- }, false, true, true);
892
- }
893
-
894
- /** Merge non-authoritative discovery/change evidence without changing policy fences. */
895
- export function recordWorkScopeEvidence(
896
- options: WorkContractStoreOptions,
897
- workId: string,
898
- input: { initialLikelyPaths?: string[]; inspectedPaths?: string[]; actualChangedPaths?: string[] },
899
- ): WorkContract {
900
- const current = getWorkContract(options, workId);
901
- if (!current) throw new Error(`work contract not found: ${workId}`);
902
- const previous = current.scopeEvidence ?? {
903
- initialLikelyPaths: [], inspectedPaths: [], actualChangedPaths: [], recordedAt: current.createdAt,
904
- };
905
- return updateWorkContract(options, workId, {
906
- scopeEvidence: {
907
- initialLikelyPaths: [...new Set([...previous.initialLikelyPaths, ...(input.initialLikelyPaths ?? [])])].slice(0, 100),
908
- inspectedPaths: [...new Set([...previous.inspectedPaths, ...(input.inspectedPaths ?? [])])].slice(0, 500),
909
- actualChangedPaths: [...new Set([...previous.actualChangedPaths, ...(input.actualChangedPaths ?? [])])].slice(0, 500),
910
- recordedAt: nowIso(options),
911
- },
912
- });
913
- }
914
-
915
- export function transitionWorkContractPhase(
916
- options: WorkContractStoreOptions,
917
- workId: string,
918
- input: {
919
- phase: WorkPhase;
920
- status: WorkContractStatus;
921
- state?: Exclude<WorkPhaseEvidenceState, 'pending'>;
922
- summary: string;
923
- evidenceRefs?: EvidenceRef[];
924
- },
925
- ): WorkContract {
926
- const current = getWorkContract(options, workId);
927
- if (!current) throw new Error(`work contract not found: ${workId}`);
928
- const at = nowIso(options);
929
- const phaseEvidence = transitionPhaseEvidence(current, input.phase, {
930
- status: input.status,
931
- summary: input.summary,
932
- evidenceRefs: input.evidenceRefs,
933
- recordedAt: at,
934
- });
935
- if (input.state) phaseEvidence[input.phase] = { ...phaseEvidence[input.phase], state: input.state };
936
- return updateWorkContractInternal(options, workId, {
937
- phase: input.phase,
938
- phaseEvidence,
939
- status: input.status,
940
- }, false, true);
941
- }
942
-
943
- export function appendWorkEvidence(
944
- options: WorkContractStoreOptions,
945
- workId: string,
946
- evidence: EvidenceRef,
947
- ): WorkContract {
948
- const current = getWorkContract(options, workId);
949
- if (!current) throw new Error(`work contract not found: ${workId}`);
950
- return updateWorkContract(options, workId, {
951
- evidenceRefs: [evidence, ...current.evidenceRefs].slice(0, current.evidencePolicy.maxEvidenceRefs),
952
- });
953
- }
954
-
955
- export function appendWorkHandoffRef(
956
- options: WorkContractStoreOptions,
957
- workId: string,
958
- handoffId: string,
959
- ): WorkContract {
960
- const current = getWorkContract(options, workId);
961
- if (!current) throw new Error(`work contract not found: ${workId}`);
962
- const handoffRefs = [sanitizeFileComponent(handoffId), ...current.handoffRefs.filter((id) => id !== sanitizeFileComponent(handoffId))].slice(0, 20);
963
- return updateWorkContract(options, workId, { handoffRefs });
964
- }
965
-
966
- export function appendVerificationRecord(
967
- options: WorkContractStoreOptions,
968
- workId: string,
969
- record: VerificationRecord,
970
- ): WorkContract {
971
- const current = getWorkContract(options, workId);
972
- if (!current) throw new Error(`work contract not found: ${workId}`);
973
- const checkRefs = [record, ...current.checkRefs].slice(0, 50);
974
- return updateWorkContract(options, workId, { checkRefs });
975
- }
976
-
977
- /**
978
- * The only supported path for turning Work evidence into a completion receipt.
979
- * Task/Run/Process callers may supply evidence, but they cannot manufacture a
980
- * receipt or a terminal Work projection without this identity and cleanup gate.
981
- */
982
- export function recordWorkCompletionReceipt(
983
- options: WorkContractStoreOptions,
984
- workId: string,
985
- receipt: NonNullable<WorkContract['completionReceipt']>,
986
- completionOutcome: NonNullable<WorkContract['completionOutcome']>,
987
- completionWorkKind?: WorkKind,
988
- ): WorkContract {
989
- const current = getWorkContract(options, workId);
990
- if (!current) throw new Error(`work contract not found: ${workId}`);
991
- if (receipt.workId !== current.workId) throw new Error('WORK_COMPLETION_RECEIPT_IDENTITY_MISMATCH');
992
- if (current.completionReceipt) {
993
- if (current.completionReceipt.receiptId !== receipt.receiptId) throw new Error('WORK_COMPLETION_RECEIPT_ALREADY_RECORDED');
994
- return current;
995
- }
996
- const recordedAt = receipt.recordedAt;
997
- const receiptChangedPaths = isRepositoryCompletionReceipt(receipt) || isDirectEditWorkCompletionReceipt(receipt)
998
- ? receipt.changedPaths
999
- : [];
1000
- const phaseEvidence = Object.fromEntries((['implementation', 'verification', 'delivery', 'cleanup'] as WorkPhase[]).map((phase) => [phase, {
1001
- state: 'satisfied',
1002
- source: 'recorded',
1003
- summary: `Phase ${phase} accepted by Work completion receipt ${receipt.receiptId}.`,
1004
- evidenceRefs: current.evidenceRefs.slice(0, 20),
1005
- recordedAt,
1006
- ...(phase === 'delivery' || phase === 'cleanup' ? { receiptId: receipt.receiptId } : {}),
1007
- } satisfies WorkPhaseEvidence])) as WorkPhaseEvidenceMap;
1008
- return updateWorkContractInternal(options, current.workId, {
1009
- phase: 'cleanup',
1010
- phaseEvidence,
1011
- status: 'completed',
1012
- dispatchState: 'terminal',
1013
- evidenceState: 'valid',
1014
- completionOutcome,
1015
- ...(completionWorkKind ? { workKind: completionWorkKind } : {}),
1016
- completionReceipt: receipt,
1017
- scopeEvidence: {
1018
- initialLikelyPaths: current.scopeEvidence?.initialLikelyPaths ?? current.allowedPaths,
1019
- inspectedPaths: current.scopeEvidence?.inspectedPaths ?? [],
1020
- actualChangedPaths: [...new Set(receiptChangedPaths)].slice(0, 500),
1021
- recordedAt,
1022
- },
1023
- }, true, true);
1024
- }
1025
- export interface AcceptSubmittedWorkInput {
1026
- requestId: string;
1027
- repoId: string;
1028
- parentWorkId?: string;
1029
- semanticKey: string;
1030
- operation: SubmittedWorkOperation;
1031
- objective?: string;
1032
- mode?: WorkContract['mode'];
1033
- requestedBy?: WorkContract['requestedBy'];
1034
- principalId?: string;
1035
- controllerInstanceId?: string;
1036
- workKind?: WorkKind;
1037
- risk?: WorkRisk;
1038
- allowedPaths?: string[];
1039
- forbiddenPaths?: string[];
1040
- checks?: string[];
1041
- acceptanceCriteria?: string[];
1042
- constraints?: WorkContract['constraints'];
1043
- }
1
+ /** @deprecated Kernel V2 compatibility shim. Use packages/kernel/work/api. */
2
+ export * from '../../../../packages/kernel/work/application/work-service';