@moretea-labs/forge 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (685) hide show
  1. package/AGENTS.md +58 -62
  2. package/CHANGELOG.md +26 -0
  3. package/CLAUDE.md +42 -62
  4. package/README.md +2 -2
  5. package/SKILL.md +0 -1
  6. package/THIRD_PARTY_NOTICES.md +5 -2
  7. package/adapters/browser/index.ts +2 -0
  8. package/adapters/chatgpt/browser-delivery-host.ts +71 -0
  9. package/adapters/chatgpt/browser-delivery-runtime.ts +783 -0
  10. package/adapters/chatgpt/controller-binding-store.ts +55 -0
  11. package/adapters/chatgpt/controller-host.ts +119 -0
  12. package/adapters/chatgpt/controller-round-host.ts +78 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +45 -0
  14. package/adapters/chatgpt/provider-delivery.ts +113 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +192 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/desktop-operator-contract.ts +7 -0
  18. package/adapters/computer/desktop-operator-discovery.ts +201 -0
  19. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  20. package/adapters/computer/desktop-operator-provider.ts +312 -0
  21. package/adapters/computer/index.ts +1 -0
  22. package/adapters/computer/interaction-target-authority.ts +944 -0
  23. package/adapters/controller-process/binding-store.ts +34 -0
  24. package/adapters/controller-process/controller-host.ts +26 -0
  25. package/adapters/mcp/access-mode.ts +132 -0
  26. package/adapters/mcp/audit.ts +32 -0
  27. package/adapters/mcp/auth.ts +407 -0
  28. package/adapters/mcp/controller-round-compatibility.ts +184 -0
  29. package/adapters/mcp/frozen-client-semantic-compatibility.ts +292 -0
  30. package/adapters/mcp/instructions.ts +36 -0
  31. package/adapters/mcp/legacy-context.ts +18 -0
  32. package/adapters/mcp/multi-repository.ts +437 -0
  33. package/adapters/mcp/oauth.ts +391 -0
  34. package/adapters/mcp/paths.ts +140 -0
  35. package/adapters/mcp/policy.ts +232 -0
  36. package/adapters/mcp/proxy-env.ts +62 -0
  37. package/adapters/mcp/readiness-projection.ts +24 -0
  38. package/adapters/mcp/redaction.ts +21 -0
  39. package/adapters/mcp/repo.ts +24 -0
  40. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  41. package/adapters/mcp/runtime-gateway/context-adapter.ts +829 -0
  42. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +191 -0
  43. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +147 -0
  44. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  45. package/adapters/mcp/runtime-gateway/execution-tools.ts +207 -0
  46. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  47. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +411 -0
  48. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  49. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  50. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  51. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  52. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +308 -0
  53. package/adapters/mcp/runtime-gateway/process-tools.ts +289 -0
  54. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +76 -0
  55. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +268 -0
  56. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  57. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  58. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +110 -0
  59. package/adapters/mcp/runtime-gateway/result-adapter.ts +108 -0
  60. package/adapters/mcp/runtime-gateway/router.ts +728 -0
  61. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1251 -0
  62. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +634 -0
  63. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  64. package/adapters/mcp/runtime-gateway/runtime-tools.ts +68 -0
  65. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +186 -0
  66. package/adapters/mcp/runtime-gateway/shared-adapter.ts +25 -0
  67. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +870 -0
  68. package/adapters/mcp/runtime-gateway/work-adapter.ts +3186 -0
  69. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +502 -0
  70. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  71. package/adapters/mcp/server.ts +1048 -0
  72. package/adapters/mcp/setup.ts +791 -0
  73. package/adapters/mcp/tool-capability-cache.ts +87 -0
  74. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  75. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5265 -0
  76. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +150 -0
  77. package/adapters/mcp/tool-mapping/repository-tools.ts +1691 -0
  78. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  79. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  80. package/adapters/mcp/toolset-names.ts +74 -0
  81. package/adapters/mcp/toolset-selection.ts +41 -0
  82. package/adapters/mcp/toolset.ts +336 -0
  83. package/adapters/mcp/transports/http.ts +1456 -0
  84. package/adapters/mcp/transports/session-registry.ts +513 -0
  85. package/adapters/mcp/transports/stdio.ts +8 -0
  86. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +139 -0
  87. package/adapters/mcp/types.ts +41 -0
  88. package/assets/AGENTS.md +2 -16
  89. package/assets/CLAUDE.md +2 -16
  90. package/assets/hooks/AGENTS.md +3 -14
  91. package/assets/hooks/CLAUDE.md +3 -14
  92. package/assets/hooks/hook-input.sh +9 -2
  93. package/assets/hooks/lib/workflow-state.sh +28 -10
  94. package/assets/hooks/prompt-guard.sh +63 -37
  95. package/assets/hooks/security-sentinel.sh +2 -1
  96. package/assets/hooks/session-start-context.sh +7 -5
  97. package/assets/hooks/stop-orchestrator.sh +13 -3
  98. package/assets/initializer-question-pack.v4.json +11 -7
  99. package/assets/partials/05-workflow.partial.md +18 -73
  100. package/assets/partials/07-footer.partial.md +1 -1
  101. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  102. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  103. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  104. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  105. package/assets/plan-map.json +11 -11
  106. package/assets/plugin-registry.v1.json +9 -3
  107. package/assets/plugin-trust-policy.v1.json +6 -0
  108. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  109. package/assets/recovery/forge-wsl-rescue +271 -0
  110. package/assets/reference-configs/development-protocol.md +11 -15
  111. package/assets/reference-configs/document-generation.md +1 -1
  112. package/assets/reference-configs/global-working-rules.md +9 -1
  113. package/assets/reference-configs/harness-overview.md +22 -112
  114. package/assets/reference-configs/hook-operations.md +1 -1
  115. package/assets/reference-configs/sprint-contracts.md +2 -2
  116. package/assets/skill-version.json +2 -2
  117. package/assets/templates/helpers/architecture-event.ts +3 -34
  118. package/assets/templates/helpers/architecture-queue.sh +61 -10
  119. package/assets/templates/helpers/archive-workflow.sh +90 -180
  120. package/assets/templates/helpers/capability-config.ts +8 -11
  121. package/assets/templates/helpers/capability-resolver.ts +37 -19
  122. package/assets/templates/helpers/capture-plan.sh +2 -2
  123. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  124. package/assets/templates/helpers/check-task-sync.sh +82 -11
  125. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  126. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  127. package/assets/templates/helpers/contract-worktree.sh +26 -24
  128. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  129. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  130. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  131. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  132. package/assets/templates/helpers/new-plan.sh +2 -2
  133. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  134. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  135. package/assets/templates/helpers/switch-plan.sh +1 -1
  136. package/assets/templates/helpers/workflow-contract.ts +1 -0
  137. package/assets/workflow-contract.v1.json +63 -171
  138. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  139. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  140. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  141. package/docs/architecture/CURRENT.md +148 -13
  142. package/docs/architecture/EVOLUTION.md +13 -0
  143. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  144. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  145. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  146. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  147. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +35 -0
  148. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +296 -0
  149. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  150. package/docs/architecture/domains/verification.md +7 -0
  151. package/docs/architecture/domains/workflow-engine.md +1 -1
  152. package/docs/architecture/index.md +3 -3
  153. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  154. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  155. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  156. package/docs/forge-plugin-management.md +20 -4
  157. package/docs/forge-runtime-self-healing-loop.md +2 -0
  158. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  159. package/docs/operations/controller-browser-plugin.md +3 -1
  160. package/docs/operations/homebrew.md +2 -2
  161. package/docs/operations/platform-support.md +16 -8
  162. package/docs/operations/platform-support.zh-CN.md +2 -2
  163. package/docs/operations/standalone-disaster-recovery.md +26 -1
  164. package/docs/operations/uu-remote-rescue.md +41 -0
  165. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  166. package/docs/public-usage-guide.md +1 -1
  167. package/docs/public-usage-guide.zh-CN.md +1 -1
  168. package/docs/tutorials/01-install-and-start.md +1 -1
  169. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  170. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  171. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  172. package/docs/wiki/Implementation.md +1 -1
  173. package/package.json +23 -14
  174. package/packages/kernel/controller/api/index.ts +2 -0
  175. package/packages/kernel/controller/application/controller-round-service.ts +29 -0
  176. package/packages/kernel/controller/application/controller-service.ts +30 -0
  177. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +308 -0
  178. package/packages/kernel/controller/domain/controller-round.ts +107 -0
  179. package/packages/kernel/controller/domain/execution-quality.ts +133 -0
  180. package/packages/kernel/controller/domain/types.ts +56 -0
  181. package/packages/kernel/controller/index.ts +1 -0
  182. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  183. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1384 -0
  184. package/packages/kernel/controller/infrastructure/controller-session-store.ts +578 -0
  185. package/packages/kernel/controller/ports/controller-host.ts +16 -0
  186. package/packages/kernel/goal/api/index.ts +1 -0
  187. package/packages/kernel/goal/domain/types.ts +40 -0
  188. package/packages/kernel/goal/index.ts +1 -0
  189. package/packages/kernel/identity/api/index.ts +5 -0
  190. package/packages/kernel/identity/application/identity-service.ts +67 -0
  191. package/packages/kernel/identity/domain/scope.ts +63 -0
  192. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  193. package/packages/kernel/identity/domain/types.ts +44 -0
  194. package/packages/kernel/identity/domain/workspace.ts +56 -0
  195. package/packages/kernel/identity/index.ts +1 -0
  196. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  197. package/packages/kernel/memory/api/index.ts +5 -0
  198. package/packages/kernel/memory/application/experience-service.ts +118 -0
  199. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  200. package/packages/kernel/memory/domain/experience.ts +103 -0
  201. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  202. package/packages/kernel/memory/index.ts +1 -0
  203. package/packages/kernel/progression/api/index.ts +2 -0
  204. package/packages/kernel/progression/application/projector.ts +211 -0
  205. package/packages/kernel/progression/domain/types.ts +116 -0
  206. package/packages/kernel/progression/index.ts +1 -0
  207. package/packages/kernel/scheduler/api/index.ts +6 -0
  208. package/packages/kernel/scheduler/application/continuation-service.ts +212 -0
  209. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  210. package/packages/kernel/scheduler/application/schedule-service.ts +24 -0
  211. package/packages/kernel/scheduler/application/settlement.ts +197 -0
  212. package/packages/kernel/scheduler/domain/continuation.ts +38 -0
  213. package/packages/kernel/scheduler/domain/schedule.ts +149 -0
  214. package/packages/kernel/scheduler/index.ts +1 -0
  215. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +38 -0
  216. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +785 -0
  217. package/packages/kernel/work/api/index.ts +15 -0
  218. package/packages/kernel/work/application/work-service.ts +148 -0
  219. package/packages/kernel/work/domain/admission-policy.ts +34 -0
  220. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  221. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  222. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  223. package/packages/kernel/work/domain/engineering-design.ts +281 -0
  224. package/packages/kernel/work/domain/engineering-profile.ts +242 -0
  225. package/packages/kernel/work/domain/execution-concurrency.ts +254 -0
  226. package/packages/kernel/work/domain/execution-snapshot.ts +33 -0
  227. package/packages/kernel/work/domain/implementation-review.ts +510 -0
  228. package/packages/kernel/work/domain/project-engineering-contract.ts +202 -0
  229. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  230. package/packages/kernel/work/domain/state-machine.ts +259 -0
  231. package/packages/kernel/work/domain/types.ts +528 -0
  232. package/packages/kernel/work/index.ts +1 -0
  233. package/packages/kernel/work/infrastructure/work-contract-store.ts +1876 -0
  234. package/packages/kernel/work/ports/work-contract-store.ts +18 -0
  235. package/packages/plugin-runtime/browser/index.ts +3 -0
  236. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  237. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  238. package/packages/plugin-runtime/browser/session-authority.ts +61 -0
  239. package/packages/plugin-runtime/computer/index.ts +6 -0
  240. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  241. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  242. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  243. package/packages/plugin-runtime/computer/provider.ts +19 -0
  244. package/packages/plugin-runtime/computer/target-authority.ts +190 -0
  245. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  246. package/packages/plugin-runtime/external/index.ts +1 -0
  247. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +457 -0
  248. package/packages/plugin-runtime/index.ts +3 -0
  249. package/packages/protocols/browser/index.ts +1 -0
  250. package/packages/protocols/browser/session.ts +98 -0
  251. package/packages/protocols/computer/contract.ts +199 -0
  252. package/packages/protocols/computer/index.ts +1 -0
  253. package/packages/protocols/failure/contract.ts +158 -0
  254. package/packages/protocols/failure/index.ts +1 -0
  255. package/packages/protocols/handoff/index.ts +1 -0
  256. package/packages/protocols/handoff/status.ts +22 -0
  257. package/packages/protocols/mcp/execution-context.ts +11 -0
  258. package/packages/protocols/mcp/index.ts +2 -0
  259. package/packages/protocols/mcp/tool-contract.ts +42 -0
  260. package/packages/workflow-runtime/api/index.ts +2 -0
  261. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  262. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  263. package/packages/workflow-runtime/index.ts +1 -0
  264. package/scripts/assemble-template.ts +1 -1
  265. package/scripts/benchmark-computer-hotpath.ts +255 -0
  266. package/scripts/benchmark-controller-round2.ts +54 -2
  267. package/scripts/benchmark-ios-agent-device.ts +3 -6
  268. package/scripts/benchmark-mcp-transport.ts +3 -4
  269. package/scripts/benchmark-operational-memory-activation.ts +235 -0
  270. package/scripts/benchmark-operational-shadow.ts +28 -0
  271. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  272. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  273. package/scripts/canary-controller-semantic-wait.ts +195 -0
  274. package/scripts/canary-global-hook.sh +2 -2
  275. package/scripts/check-mcp-compatibility.ts +173 -7
  276. package/scripts/check-platform-support.mjs +28 -2
  277. package/scripts/check-public-docs.sh +1 -1
  278. package/scripts/check-release-readiness.sh +1 -1
  279. package/scripts/check-repository-hygiene.mjs +92 -0
  280. package/scripts/check-runtime-architecture.mjs +1206 -95
  281. package/scripts/check-source-duplication.mjs +9 -1
  282. package/scripts/check-tarball-install-smoke.sh +98 -15
  283. package/scripts/controller-ngrok-rotation.sh +5 -4
  284. package/scripts/create-project-dirs.sh +10 -74
  285. package/scripts/forge-local-recovery-helper.mjs +204 -0
  286. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  287. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  288. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  289. package/scripts/hook-shim.sh +2 -2
  290. package/scripts/init-project.sh +12 -70
  291. package/scripts/install-desktop-operator-registration.ts +4 -2
  292. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  293. package/scripts/install-standalone-recovery.ts +122 -10
  294. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  295. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  296. package/scripts/lib/controller-home-env.sh +6 -3
  297. package/scripts/lib/project-init-lib.sh +39 -582
  298. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  299. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  300. package/scripts/open-source-audit-allowlist.txt +12 -1
  301. package/scripts/portability-bindings.mjs +70 -0
  302. package/scripts/run-bounded-command.mjs +55 -0
  303. package/scripts/run-bun-test-file.ts +22 -6
  304. package/scripts/run-governed-gate.ts +4 -1
  305. package/scripts/smoke-mcp-http-runtime.ts +1 -1
  306. package/scripts/smoke-runtime-recovery.ts +34 -1
  307. package/scripts/smoke-schedule-engine.ts +1 -1
  308. package/scripts/stage-runtime-release.ts +6 -1
  309. package/scripts/test-governance.ts +51 -2
  310. package/src/cli/agent-jobs/job-manager.ts +10 -1
  311. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  312. package/src/cli/chatgpt-browser/binding.ts +20 -10
  313. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  314. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  315. package/src/cli/chatgpt-browser/engine.ts +10 -11
  316. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  317. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  318. package/src/cli/chatgpt-browser/types.ts +1 -0
  319. package/src/cli/commands/bootstrap-control.ts +334 -0
  320. package/src/cli/commands/brain-assistant.ts +38 -0
  321. package/src/cli/commands/brain.ts +193 -40
  322. package/src/cli/commands/chatgpt.ts +127 -0
  323. package/src/cli/commands/computer.ts +437 -0
  324. package/src/cli/commands/doctor.ts +18 -1
  325. package/src/cli/commands/init-hook.ts +71 -61
  326. package/src/cli/commands/init.ts +3 -1
  327. package/src/cli/commands/mcp.ts +16 -10
  328. package/src/cli/commands/plugin.ts +38 -12
  329. package/src/cli/commands/recovery.ts +493 -80
  330. package/src/cli/commands/runtime.ts +9 -4
  331. package/src/cli/commands/setup-profile.ts +89 -39
  332. package/src/cli/commands/status.ts +2 -1
  333. package/src/cli/controller/check-runner.ts +487 -98
  334. package/src/cli/controller/context/types.ts +7 -1
  335. package/src/cli/controller/context-pack.ts +23 -3
  336. package/src/cli/controller/issue-store.ts +1 -1
  337. package/src/cli/controller/systemd-user.ts +110 -0
  338. package/src/cli/controller/types.ts +10 -70
  339. package/src/cli/controller/worklog.ts +67 -13
  340. package/src/cli/editing/edit-operation-contract.ts +92 -0
  341. package/src/cli/editing/edit-session.ts +289 -13
  342. package/src/cli/github/plugin.ts +17 -12
  343. package/src/cli/hook/route-registry.ts +3 -5
  344. package/src/cli/hook/runtime.ts +49 -3
  345. package/src/cli/index.ts +3 -0
  346. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  347. package/src/cli/local-bridge/console-automations.ts +2 -2
  348. package/src/cli/local-bridge/facade-api.ts +41 -14
  349. package/src/cli/local-bridge/job-store.ts +1 -1
  350. package/src/cli/local-bridge/server.ts +24 -27
  351. package/src/cli/mcp/access-mode.ts +2 -132
  352. package/src/cli/mcp/access-tools.ts +2 -387
  353. package/src/cli/mcp/audit.ts +2 -32
  354. package/src/cli/mcp/auth.ts +2 -404
  355. package/src/cli/mcp/instructions.ts +2 -34
  356. package/src/cli/mcp/legacy-context.ts +2 -16
  357. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  358. package/src/cli/mcp/multi-repository.ts +2 -436
  359. package/src/cli/mcp/oauth.ts +2 -375
  360. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  361. package/src/cli/mcp/paths.ts +2 -140
  362. package/src/cli/mcp/policy.ts +2 -232
  363. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  364. package/src/cli/mcp/proxy-env.ts +2 -62
  365. package/src/cli/mcp/readiness-projection.ts +2 -24
  366. package/src/cli/mcp/redaction.ts +2 -21
  367. package/src/cli/mcp/repo.ts +2 -24
  368. package/src/cli/mcp/repository-tools.ts +2 -1613
  369. package/src/cli/mcp/server.ts +2 -951
  370. package/src/cli/mcp/setup.ts +2 -737
  371. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  372. package/src/cli/mcp/tool-contract.ts +2 -14
  373. package/src/cli/mcp/tools.ts +2 -9
  374. package/src/cli/mcp/toolset-names.ts +2 -70
  375. package/src/cli/mcp/toolset-selection.ts +2 -41
  376. package/src/cli/mcp/toolset.ts +2 -336
  377. package/src/cli/mcp/transports/AGENTS.md +1 -10
  378. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  379. package/src/cli/mcp/transports/http.ts +2 -1414
  380. package/src/cli/mcp/transports/session-registry.ts +2 -490
  381. package/src/cli/mcp/transports/stdio.ts +2 -8
  382. package/src/cli/mcp/types.ts +2 -41
  383. package/src/cli/mcp/umbrella-tools.ts +2 -117
  384. package/src/cli/repositories/command-executor.ts +64 -18
  385. package/src/cli/repositories/command-scope.ts +117 -1
  386. package/src/cli/repositories/controller-home.ts +119 -1
  387. package/src/cli/repositories/identity.ts +13 -0
  388. package/src/cli/repositories/registry.ts +68 -49
  389. package/src/cli/repositories/repository-snapshot.ts +53 -7
  390. package/src/cli/repositories/runtime-storage.ts +27 -2
  391. package/src/cli/repositories/safe-patch.ts +34 -38
  392. package/src/cli/repositories/selected-path-actions.ts +22 -2
  393. package/src/cli/repositories/structured-git.ts +105 -25
  394. package/src/cli/runtime/helper-runner.ts +7 -0
  395. package/src/cli/runtime-invocation.ts +8 -1
  396. package/src/cli/tools/codegraph.ts +44 -25
  397. package/src/core/adoption/manifest-templates.ts +1 -1
  398. package/src/core/adoption/plan.ts +3 -26
  399. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  400. package/src/effects/process-runner.ts +8 -14
  401. package/src/runtime/context/assistant-context.ts +154 -0
  402. package/src/runtime/context/assistant-work-context.ts +147 -0
  403. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  404. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  405. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  406. package/src/runtime/context/context-closure.ts +268 -0
  407. package/src/runtime/context/context-plane.ts +211 -0
  408. package/src/runtime/context/project-engineering-contract.ts +60 -0
  409. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  410. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  411. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  412. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  413. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  414. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  415. package/src/runtime/control-plane/cleanup-artifact-retention.ts +328 -0
  416. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  417. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +320 -0
  418. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +169 -0
  419. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +350 -0
  420. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +85 -0
  421. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +369 -99
  422. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +103 -15
  423. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  424. package/src/runtime/control-plane/execution/repository-work-attribution.ts +2 -2
  425. package/src/runtime/control-plane/execution/retained-work-resume.ts +336 -6
  426. package/src/runtime/control-plane/execution/validation.ts +28 -3
  427. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +116 -0
  428. package/src/runtime/control-plane/execution/work-completion-authority.ts +44 -2
  429. package/src/runtime/control-plane/execution/work-evidence-policy.ts +34 -3
  430. package/src/runtime/control-plane/execution/work-execution-support.ts +42 -22
  431. package/src/runtime/control-plane/execution/work-finalization-service.ts +1103 -166
  432. package/src/runtime/control-plane/execution/work-handle-authority.ts +219 -22
  433. package/src/runtime/control-plane/execution/work-handle-store.ts +77 -0
  434. package/src/runtime/control-plane/execution/work-head-settlement.ts +75 -0
  435. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +145 -23
  436. package/src/runtime/control-plane/execution/work-operation-service.ts +49 -13
  437. package/src/runtime/control-plane/execution/work-preparation-service.ts +31 -15
  438. package/src/runtime/control-plane/execution/work-remote-delivery.ts +1 -1
  439. package/src/runtime/control-plane/execution/work-task-receipt.ts +20 -1
  440. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +407 -76
  441. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +88 -18
  442. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  443. package/src/runtime/control-plane/execution/work-verification-service.ts +258 -4
  444. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +200 -15
  445. package/src/runtime/control-plane/facade/capability-registry.ts +21 -10
  446. package/src/runtime/control-plane/facade/controller-round-relay.ts +3 -1118
  447. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  448. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -3
  449. package/src/runtime/control-plane/facade/goal-workloop.ts +972 -137
  450. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +158 -0
  451. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +10 -0
  452. package/src/runtime/control-plane/facade/index.ts +4 -2
  453. package/src/runtime/control-plane/facade/operation-digest.ts +22 -58
  454. package/src/runtime/control-plane/facade/plan-contract-store.ts +1004 -38
  455. package/src/runtime/control-plane/facade/repository-work-admission.ts +19 -1
  456. package/src/runtime/control-plane/facade/requirement-authority.ts +218 -0
  457. package/src/runtime/control-plane/facade/requirement-board.ts +6 -1
  458. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +48 -0
  459. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  460. package/src/runtime/control-plane/facade/suggested-actions.ts +4 -1
  461. package/src/runtime/control-plane/facade/types.ts +189 -532
  462. package/src/runtime/control-plane/facade/work-admission-policy.ts +84 -35
  463. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  464. package/src/runtime/control-plane/facade/work-implementation-review.ts +2 -0
  465. package/src/runtime/control-plane/facade/work-state-machine.ts +2 -250
  466. package/src/runtime/control-plane/generated-cache-retention.ts +239 -18
  467. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +12 -1
  468. package/src/runtime/control-plane/global-scheduler/maintenance.ts +76 -13
  469. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  470. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  471. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -1
  472. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  473. package/src/runtime/control-plane/global-scheduler/scheduler.ts +173 -81
  474. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  475. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +397 -0
  476. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  477. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +301 -560
  478. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +20 -4
  479. package/src/runtime/control-plane/launcher/thin-launcher.ts +50 -4
  480. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  481. package/src/runtime/control-plane/persistence/experience-store.ts +169 -0
  482. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  483. package/src/runtime/control-plane/persistence/requirement-store.ts +30 -22
  484. package/src/runtime/control-plane/persistence/sqlite-store.ts +545 -76
  485. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  486. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  487. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  488. package/src/runtime/control-plane/release-retention.ts +56 -16
  489. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  490. package/src/runtime/control-plane/routing/route-policy.ts +19 -0
  491. package/src/runtime/control-plane/runtime-cleanup.ts +574 -37
  492. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  493. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +465 -0
  494. package/src/runtime/control-plane/workspace/workspace-store.ts +80 -0
  495. package/src/runtime/diagnostics/incident-repair.ts +406 -0
  496. package/src/runtime/diagnostics/mcp-timing.ts +125 -6
  497. package/src/runtime/diagnostics/performance.ts +6 -14
  498. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  499. package/src/runtime/evidence/artifact-store.ts +65 -2
  500. package/src/runtime/evidence/operational-shadow.ts +38 -0
  501. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  502. package/src/runtime/evidence/sensitive-output.ts +4 -4
  503. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  504. package/src/runtime/execution/jobs/store.ts +121 -2
  505. package/src/runtime/execution/managed-workspace.ts +55 -5
  506. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  507. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  508. package/src/runtime/execution/process-runtime/check-facade.ts +23 -9
  509. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  510. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  511. package/src/runtime/execution/process-runtime/check-result.ts +73 -2
  512. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +42 -3
  513. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  514. package/src/runtime/execution/process-runtime/command-facade.ts +38 -87
  515. package/src/runtime/execution/process-runtime/index.ts +1 -0
  516. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  517. package/src/runtime/execution/process-runtime/lightweight-managed.ts +32 -1
  518. package/src/runtime/execution/process-runtime/persisted-check.ts +128 -21
  519. package/src/runtime/execution/process-runtime/resource-claims.ts +60 -3
  520. package/src/runtime/execution/process-runtime/runtime.ts +132 -15
  521. package/src/runtime/execution/process-runtime/types.ts +22 -0
  522. package/src/runtime/execution/workers/executor.ts +16 -13
  523. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  524. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  525. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  526. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  527. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  528. package/src/runtime/gateway/mcp/router.ts +2 -1125
  529. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  530. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  531. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  532. package/src/runtime/maintenance/cleanup.ts +38 -24
  533. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  534. package/src/runtime/platform/computer-platform.ts +14 -0
  535. package/src/runtime/platform/executable-discovery.ts +54 -0
  536. package/src/runtime/platform/fetch-http-server.ts +90 -0
  537. package/src/runtime/platform/service-manager.ts +138 -0
  538. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  539. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  540. package/src/runtime/plugins/action-application.ts +135 -0
  541. package/src/runtime/plugins/app-store-connect-adapter.ts +9 -21
  542. package/src/runtime/plugins/browser-adapter.ts +140 -100
  543. package/src/runtime/plugins/browser-automation-service.ts +15 -36
  544. package/src/runtime/plugins/browser-macos-bridge.ts +69 -21
  545. package/src/runtime/plugins/browser-manifest-surface.ts +30 -6
  546. package/src/runtime/plugins/browser-native-session-service.ts +1 -1
  547. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  548. package/src/runtime/plugins/browser-registration.ts +16 -0
  549. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  550. package/src/runtime/plugins/browser-runtime.ts +41 -9
  551. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  552. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  553. package/src/runtime/plugins/browser-session-store.ts +229 -36
  554. package/src/runtime/plugins/browser-session-types.ts +2 -98
  555. package/src/runtime/plugins/capability-authorization-grants.ts +17 -0
  556. package/src/runtime/plugins/catalog-trust.ts +82 -0
  557. package/src/runtime/plugins/computer-registration.ts +839 -0
  558. package/src/runtime/plugins/config-store.ts +119 -0
  559. package/src/runtime/plugins/desktop-operator-external-policy.ts +932 -0
  560. package/src/runtime/plugins/desktop-operator-registration.ts +111 -8
  561. package/src/runtime/plugins/errors.ts +8 -1
  562. package/src/runtime/plugins/external-adapter.ts +45 -322
  563. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  564. package/src/runtime/plugins/external-registration.ts +9 -1
  565. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  566. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  567. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  568. package/src/runtime/plugins/first-party-registry.ts +3 -1
  569. package/src/runtime/plugins/github-adapter.ts +1 -2
  570. package/src/runtime/plugins/gmail-adapter.ts +6 -6
  571. package/src/runtime/plugins/google-calendar-adapter.ts +6 -6
  572. package/src/runtime/plugins/google-shared.ts +31 -46
  573. package/src/runtime/plugins/google-tasks-adapter.ts +6 -6
  574. package/src/runtime/plugins/ios-adapter.ts +1 -2
  575. package/src/runtime/plugins/local-system-adapter.ts +180 -0
  576. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  577. package/src/runtime/plugins/resend-adapter.ts +15 -24
  578. package/src/runtime/plugins/store.ts +493 -51
  579. package/src/runtime/plugins/types.ts +8 -1
  580. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  581. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  582. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  583. package/src/runtime/plugins/xiaohongshu-publish.ts +86 -430
  584. package/src/runtime/projections/controller-context.ts +12 -6
  585. package/src/runtime/projections/git-status-sampler.ts +73 -22
  586. package/src/runtime/projections/materialized-view.ts +14 -8
  587. package/src/runtime/recovery/capability-action-application.ts +228 -0
  588. package/src/runtime/recovery/index.ts +3 -0
  589. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  590. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  591. package/src/runtime/recovery/maintenance-executor.ts +358 -76
  592. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  593. package/src/runtime/release/identity.ts +6 -0
  594. package/src/runtime/resources/leases/store.ts +1 -1
  595. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  596. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  597. package/src/runtime/root/browser-session-composition.ts +59 -0
  598. package/src/runtime/root/computer-composition.ts +191 -0
  599. package/src/runtime/root/computer-target-composition.ts +16 -0
  600. package/src/runtime/root/computer-target-persistence.ts +39 -0
  601. package/src/runtime/root/controller-round-composition.ts +107 -0
  602. package/src/runtime/root/controller-services.ts +2 -0
  603. package/src/runtime/root/entry.ts +4 -3
  604. package/src/runtime/root/gateway-adapter.ts +3 -3
  605. package/src/runtime/root/local-bridge.ts +5 -2
  606. package/src/runtime/root/mcp-transport.ts +5 -5
  607. package/src/runtime/root/package-connector-service.ts +108 -56
  608. package/src/runtime/root/package-runtime-release.ts +85 -18
  609. package/src/runtime/root/package-runtime-service.ts +60 -97
  610. package/src/runtime/root/release-execution-canary.ts +71 -0
  611. package/src/runtime/root/release-loader.ts +68 -0
  612. package/src/runtime/root/release-manifest.ts +106 -2
  613. package/src/runtime/root/release-materialize.ts +103 -4
  614. package/src/runtime/root/release-store.ts +31 -2
  615. package/src/runtime/root/runtime.ts +240 -25
  616. package/src/runtime/root/scheduled-controller-composition.ts +51 -0
  617. package/src/runtime/root/scheduler.ts +12 -4
  618. package/src/runtime/root/service-runner.ts +1 -1
  619. package/src/runtime/root/service.ts +41 -16
  620. package/src/runtime/root/status.ts +1 -0
  621. package/src/runtime/root/types.ts +24 -1
  622. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  623. package/src/runtime/shared/process-environment.ts +19 -4
  624. package/src/runtime/shared/storage-capacity.ts +68 -0
  625. package/src/runtime/standalone-recovery/controller-home-migration.ts +1116 -0
  626. package/src/runtime/standalone-recovery/core.ts +984 -230
  627. package/src/runtime/standalone-recovery/entry.ts +182 -51
  628. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  629. package/src/runtime/standalone-recovery/installer.ts +212 -104
  630. package/src/runtime/standalone-recovery/mcp-server.ts +243 -0
  631. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  632. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  633. package/src/runtime/standalone-recovery/performance.ts +135 -0
  634. package/src/runtime/standalone-recovery/release.ts +5 -0
  635. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  636. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -1
  637. package/src/runtime/workflow/schedules/engine.ts +191 -343
  638. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  639. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  640. package/src/runtime/workflow/schedules/store.ts +2 -607
  641. package/src/runtime/workflow/schedules/types.ts +2 -127
  642. package/src/runtime/workflow/schedules/work-continuation.ts +180 -15
  643. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  644. package/src/runtime/workflows/runtime.ts +486 -0
  645. package/src/testing/test-governance.ts +90 -29
  646. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  647. package/docs/architecture/history/README.md +0 -7
  648. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  649. package/docs/architecture/history/global-hook-runtime.md +0 -166
  650. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  651. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  652. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  653. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  654. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  655. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  656. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  657. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  658. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  659. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  660. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  661. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  662. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  663. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  664. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  665. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  666. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  667. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  668. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  669. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  670. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  671. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  672. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  673. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  674. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  675. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  676. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  677. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  678. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  679. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  680. package/docs/architecture/requests/archive/2026/root.md +0 -68
  681. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  682. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  683. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  684. package/scripts/archive-architecture-request.sh +0 -4
  685. package/scripts/run-skill-evals.ts +0 -1022
@@ -0,0 +1,578 @@
1
+ import { createHash, randomUUID, timingSafeEqual } from 'crypto';
2
+ import { join } from 'path';
3
+ import { repositoryControllerRoot } from '../../../../src/cli/repositories/controller-home';
4
+ import { withControllerLock } from '../../../../src/cli/repositories/locks';
5
+ import { peekExecutionSession } from '../../../../src/runtime/control-plane/execution/session-store';
6
+ import { readJsonFile } from '../../../../src/runtime/shared/json-files';
7
+ import { readControlPlaneRecord, readOrImportControlPlaneRecord, writeControlPlaneRecord } from '../../../../src/runtime/control-plane/persistence/sqlite-store';
8
+ import { getWorkContract, isTerminalWorkContractStatus } from '../../work/api/index';
9
+ import { type ControllerSession, type ControllerSessionStore, type ControllerType } from '../domain/types';
10
+
11
+ export interface ControllerSessionStoreOptions { controllerHome: string; repoId: string; now?: () => string; }
12
+
13
+ export interface ControllerSessionClaimInput {
14
+ workId: string;
15
+ controllerId: string;
16
+ controllerType: ControllerType;
17
+ sessionId: string;
18
+ /** Optional digest of the Work-bound controller capability. Plaintext is never persisted in ControllerSession. */
19
+ authorityDigest?: string;
20
+ principalId?: string;
21
+ controllerInstanceId?: string;
22
+ /** Optional compare-and-swap fence supplied by a recovering caller. */
23
+ expectedClaimGeneration?: number;
24
+ /**
25
+ * Permit a different authenticated controller epoch to recover this Work only
26
+ * after the canonical execution/activity grace has elapsed. Callers must pair
27
+ * this with expectedClaimGeneration from the owner they observed.
28
+ */
29
+ allowStaleRecovery?: boolean;
30
+ leaseMs?: number;
31
+ }
32
+
33
+ function path(options: ControllerSessionStoreOptions): string {
34
+ return join(repositoryControllerRoot(options.controllerHome, options.repoId), 'controller-sessions.json');
35
+ }
36
+
37
+ function now(options: ControllerSessionStoreOptions): string { return options.now?.() ?? new Date().toISOString(); }
38
+
39
+ function read(options: ControllerSessionStoreOptions): ControllerSessionStore {
40
+ const legacyPath = path(options);
41
+ return readOrImportControlPlaneRecord<ControllerSessionStore>(options.controllerHome, {
42
+ namespace: 'controller_session_claim_store',
43
+ scope: options.repoId,
44
+ key: 'index',
45
+ schemaVersion: 1,
46
+ readLegacy: () => readJsonFile<ControllerSessionStore>(legacyPath, { schemaVersion: 1, updatedAt: now(options), sessions: [] }),
47
+ })?.value ?? { schemaVersion: 1, updatedAt: now(options), sessions: [] };
48
+ }
49
+
50
+ function write(options: ControllerSessionStoreOptions, store: ControllerSessionStore): void {
51
+ writeControlPlaneRecord(options.controllerHome, {
52
+ namespace: 'controller_session_claim_store',
53
+ scope: options.repoId,
54
+ key: 'index',
55
+ schemaVersion: 1,
56
+ value: store,
57
+ action: 'controller_session_claim_write',
58
+ });
59
+ }
60
+
61
+ const RETAINED_SESSION_NAMESPACE = 'controller_session_identity';
62
+
63
+ interface RetainedControllerSessionRecord {
64
+ schemaVersion: 1;
65
+ session: ControllerSession;
66
+ retainedAt: string;
67
+ releasedAt?: string;
68
+ }
69
+
70
+ function persistRetainedControllerSession(
71
+ options: ControllerSessionStoreOptions,
72
+ session: ControllerSession,
73
+ releasedAt?: string,
74
+ ): void {
75
+ const retainedAt = now(options);
76
+ writeControlPlaneRecord(options.controllerHome, {
77
+ namespace: RETAINED_SESSION_NAMESPACE,
78
+ scope: options.repoId,
79
+ key: session.workId,
80
+ schemaVersion: 1,
81
+ value: { schemaVersion: 1, session, retainedAt, ...(releasedAt ? { releasedAt } : {}) } satisfies RetainedControllerSessionRecord,
82
+ action: releasedAt ? 'controller_session_identity_released' : 'controller_session_identity_retained',
83
+ });
84
+ }
85
+
86
+ /** Durable session identity survives transport/lease release; it is not an ownership lease. */
87
+ export function getRetainedControllerSession(
88
+ options: ControllerSessionStoreOptions,
89
+ workId: string,
90
+ ): ControllerSession | undefined {
91
+ const retained = readControlPlaneRecord<RetainedControllerSessionRecord>(
92
+ options.controllerHome,
93
+ RETAINED_SESSION_NAMESPACE,
94
+ options.repoId,
95
+ workId,
96
+ )?.value.session;
97
+ if (retained) return retained;
98
+ return read(options).sessions.find((entry) => entry.workId === workId);
99
+ }
100
+
101
+ const DEFAULT_CONTROLLER_RECOVERY_GRACE_MS = 5 * 60_000;
102
+ const MAX_CONTROLLER_RECOVERY_GRACE_MS = 60 * 60_000;
103
+ const DEFAULT_CONTROLLER_LEASE_MS = 60 * 60_000;
104
+ const MAX_CONTROLLER_LEASE_MS = 60 * 60_000;
105
+
106
+ function optionsNowMs(options: ControllerSessionStoreOptions): number {
107
+ const parsed = Date.parse(now(options));
108
+ return Number.isFinite(parsed) ? parsed : Date.now();
109
+ }
110
+
111
+ function activeSession(store: ControllerSessionStore, workId: string, atMs: number = Date.now()): ControllerSession | undefined {
112
+ return store.sessions.find((session) => session.workId === workId && Date.parse(session.leaseExpiresAt) > atMs);
113
+ }
114
+
115
+ function sessionBlocksRecovery(
116
+ options: ControllerSessionStoreOptions,
117
+ owner: ControllerSession,
118
+ input: { nowMs: number; graceMs?: number },
119
+ ): boolean {
120
+ const execution = peekExecutionSession(options.controllerHome, owner.sessionId);
121
+ const graceMs = Math.max(60_000, Math.min(input.graceMs ?? DEFAULT_CONTROLLER_RECOVERY_GRACE_MS, MAX_CONTROLLER_RECOVERY_GRACE_MS));
122
+ if (execution?.invalidatedAt) {
123
+ const invalidatedAtMs = Date.parse(execution.invalidatedAt);
124
+ if (!Number.isFinite(invalidatedAtMs)) return true;
125
+ return input.nowMs - invalidatedAtMs < graceMs;
126
+ }
127
+ if (execution?.activeWorkId && execution.activeWorkId !== owner.workId) return false;
128
+ const activityMs = [execution?.lastValidatedAt, execution?.updatedAt, owner.claimedAt]
129
+ .map((value) => value ? Date.parse(value) : Number.NaN)
130
+ .filter(Number.isFinite)
131
+ .reduce((latest, value) => Math.max(latest, value), Number.NEGATIVE_INFINITY);
132
+ if (!Number.isFinite(activityMs)) return false;
133
+ return input.nowMs - activityMs < graceMs;
134
+ }
135
+
136
+ export function controllerSessionBlocksRecovery(
137
+ options: ControllerSessionStoreOptions,
138
+ workId: string,
139
+ input: { nowMs?: number; graceMs?: number } = {},
140
+ ): boolean {
141
+ const nowMs = input.nowMs ?? Date.now();
142
+ const owner = activeSession(read(options), workId, nowMs);
143
+ if (!owner) return false;
144
+ return sessionBlocksRecovery(options, owner, { nowMs, graceMs: input.graceMs });
145
+ }
146
+
147
+ function assertIdentity(input: ControllerSessionClaimInput): void {
148
+ if (!input.workId.trim() || !input.controllerId.trim() || !input.sessionId.trim()) {
149
+ throw new Error('CONTROLLER_SESSION_IDENTITY_REQUIRED');
150
+ }
151
+ }
152
+
153
+ function assertWorkClaimable(options: ControllerSessionStoreOptions, workId: string): void {
154
+ const work = getWorkContract({ controllerHome: options.controllerHome, repoId: options.repoId }, workId);
155
+ if (work && isTerminalWorkContractStatus(work.status)) {
156
+ throw new Error(`WORK_CONTROLLER_CLAIM_TERMINAL: ${work.workId}:${work.status}`);
157
+ }
158
+ }
159
+
160
+ function claimedSession(
161
+ options: ControllerSessionStoreOptions,
162
+ input: ControllerSessionClaimInput,
163
+ claimedAt: string,
164
+ previous?: ControllerSession,
165
+ ): ControllerSession {
166
+ const leaseExpiresAt = new Date(
167
+ Date.parse(claimedAt) + Math.max(1_000, Math.min(input.leaseMs ?? DEFAULT_CONTROLLER_LEASE_MS, MAX_CONTROLLER_LEASE_MS)),
168
+ ).toISOString();
169
+ const previousPrincipal = previous?.principalId?.trim() || previous?.controllerId;
170
+ const inputPrincipal = input.principalId?.trim() || input.controllerId;
171
+ const sameOwner = previous?.controllerId === input.controllerId
172
+ && previous?.controllerType === input.controllerType
173
+ && previousPrincipal === inputPrincipal
174
+ && (previous.controllerInstanceId ?? '') === (input.controllerInstanceId?.trim() ?? '');
175
+ const claimGeneration = sameOwner
176
+ ? Math.max(1, previous?.claimGeneration ?? 1)
177
+ : Math.max(0, previous?.claimGeneration ?? 0) + 1;
178
+ const authorityDigest = input.authorityDigest?.trim() || (sameOwner ? previous?.authorityDigest?.trim() : '') || '';
179
+ return {
180
+ schemaVersion: 1,
181
+ workId: input.workId,
182
+ controllerId: input.controllerId,
183
+ controllerType: input.controllerType,
184
+ sessionId: input.sessionId,
185
+ ...(authorityDigest ? { authorityDigest } : {}),
186
+ ...(input.principalId?.trim() ? { principalId: input.principalId.trim() } : {}),
187
+ ...(input.controllerInstanceId?.trim() ? { controllerInstanceId: input.controllerInstanceId.trim() } : {}),
188
+ claimGeneration,
189
+ claimedAt,
190
+ leaseExpiresAt,
191
+ };
192
+ }
193
+
194
+ function assertExpectedGeneration(input: ControllerSessionClaimInput, current: ControllerSession | undefined): void {
195
+ if (input.expectedClaimGeneration === undefined) return;
196
+ const actual = current?.claimGeneration ?? 0;
197
+ if (actual !== input.expectedClaimGeneration) {
198
+ throw new Error(`WORK_CLAIM_GENERATION_MISMATCH: ${input.workId} expected=${input.expectedClaimGeneration} actual=${actual}`);
199
+ }
200
+ }
201
+
202
+ function persistClaim(
203
+ options: ControllerSessionStoreOptions,
204
+ store: ControllerSessionStore,
205
+ input: ControllerSessionClaimInput,
206
+ previous?: ControllerSession,
207
+ ): ControllerSession {
208
+ const claimedAt = now(options);
209
+ const claimedAtMs = Date.parse(claimedAt);
210
+ const session = claimedSession(options, input, claimedAt, previous);
211
+ const sessions = [
212
+ ...store.sessions.filter((entry) => entry.workId !== input.workId && Date.parse(entry.leaseExpiresAt) > claimedAtMs),
213
+ session,
214
+ ];
215
+ write(options, { schemaVersion: 1, updatedAt: claimedAt, sessions });
216
+ persistRetainedControllerSession(options, session);
217
+ return session;
218
+ }
219
+
220
+ export function getControllerSession(options: ControllerSessionStoreOptions, workId: string): ControllerSession | undefined {
221
+ return activeSession(read(options), workId, optionsNowMs(options));
222
+ }
223
+
224
+ export function listControllerSessions(options: ControllerSessionStoreOptions): ControllerSession[] {
225
+ const at = optionsNowMs(options);
226
+ return read(options).sessions.filter((session) => Date.parse(session.leaseExpiresAt) > at);
227
+ }
228
+
229
+ export interface ControllerOwnershipAuthority {
230
+ controllerId: string;
231
+ controllerType: ControllerType;
232
+ principalId: string;
233
+ controllerInstanceId: string;
234
+ claimGeneration: number;
235
+ }
236
+
237
+ export type ControllerTerminalizationAuthority = ControllerOwnershipAuthority;
238
+
239
+ export function controllerSessionPrincipalId(
240
+ owner: Pick<ControllerSession, 'principalId' | 'controllerId'>,
241
+ ): string {
242
+ return owner.principalId?.trim() || owner.controllerId;
243
+ }
244
+
245
+ function digestControllerAuthority(authorityId: string): string {
246
+ return createHash('sha256').update(authorityId).digest('hex');
247
+ }
248
+
249
+ /** Mint a non-relay Work-bound capability. Only the digest belongs in durable ControllerSession state. */
250
+ export function mintControllerSessionAuthority(): { authorityId: string; authorityDigest: string } {
251
+ const authorityId = `ctrl_${randomUUID().replace(/-/g, '')}`;
252
+ return { authorityId, authorityDigest: digestControllerAuthority(authorityId) };
253
+ }
254
+
255
+ /** Bind an already-authorized opaque capability without persisting its plaintext value. */
256
+ export function controllerSessionAuthorityDigest(authorityId: string): string {
257
+ const normalized = authorityId.trim();
258
+ if (!normalized) throw new Error('WORK_CONTROLLER_AUTHORITY_REQUIRED');
259
+ return digestControllerAuthority(normalized);
260
+ }
261
+
262
+ /** Verify an opaque capability without exposing or persisting its plaintext value. */
263
+ export function controllerSessionAuthorityMatches(owner: ControllerSession, authorityId: string | undefined): boolean {
264
+ const expected = owner.authorityDigest?.trim() || '';
265
+ const candidate = authorityId?.trim() || '';
266
+ if (!expected || !candidate) return false;
267
+ const actual = digestControllerAuthority(candidate);
268
+ if (expected.length !== actual.length) return false;
269
+ return timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(actual, 'hex'));
270
+ }
271
+
272
+ export function requireControllerOwnershipAuthority(
273
+ owner: ControllerSession,
274
+ workId: string = owner.workId,
275
+ ): ControllerOwnershipAuthority {
276
+ const principalId = controllerSessionPrincipalId(owner);
277
+ const controllerInstanceId = owner.controllerInstanceId?.trim() || '';
278
+ if (!controllerInstanceId) throw new Error(`WORK_CONTROLLER_INSTANCE_MISMATCH: ${workId}`);
279
+ if (typeof owner.claimGeneration !== 'number' || owner.claimGeneration < 1) {
280
+ throw new Error(`WORK_CONTROLLER_CLAIM_GENERATION_REQUIRED: ${workId}`);
281
+ }
282
+ return {
283
+ controllerId: owner.controllerId,
284
+ controllerType: owner.controllerType,
285
+ principalId,
286
+ controllerInstanceId,
287
+ claimGeneration: owner.claimGeneration,
288
+ };
289
+ }
290
+
291
+ export function assertControllerOwnershipAuthority(
292
+ owner: ControllerSession,
293
+ expected: {
294
+ workId?: string;
295
+ controllerId: string;
296
+ principalId: string;
297
+ controllerInstanceId?: string;
298
+ controllerType?: ControllerType;
299
+ },
300
+ ): ControllerOwnershipAuthority {
301
+ const workId = expected.workId ?? owner.workId;
302
+ const authority = requireControllerOwnershipAuthority(owner, workId);
303
+ if (authority.controllerId !== expected.controllerId.trim()) {
304
+ throw new Error(`WORK_CONTROLLER_OWNER_MISMATCH: ${workId} is owned by ${owner.controllerId}`);
305
+ }
306
+ if (expected.controllerType && authority.controllerType !== expected.controllerType) {
307
+ throw new Error(`WORK_CONTROLLER_TYPE_MISMATCH: ${workId} is owned by ${owner.controllerType}`);
308
+ }
309
+ if (authority.principalId !== expected.principalId.trim()) {
310
+ throw new Error(`WORK_CONTROLLER_PRINCIPAL_MISMATCH: ${workId}`);
311
+ }
312
+ if (expected.controllerInstanceId !== undefined
313
+ && authority.controllerInstanceId !== expected.controllerInstanceId.trim()) {
314
+ throw new Error(`WORK_CONTROLLER_INSTANCE_MISMATCH: ${workId}`);
315
+ }
316
+ return authority;
317
+ }
318
+
319
+ export type ControllerTerminalizationFenceReason =
320
+ | 'active_controller_claim'
321
+ | 'stale_controller_authority'
322
+ | 'controller_claim_missing';
323
+
324
+ export type ControllerTerminalizationFenceResult<T> =
325
+ | { allowed: true; value: T; owner?: ControllerSession }
326
+ | { allowed: false; reason: ControllerTerminalizationFenceReason; owner?: ControllerSession };
327
+
328
+ export function controllerTerminalizationAuthorityFromSession(
329
+ owner: ControllerSession,
330
+ ): ControllerTerminalizationAuthority | undefined {
331
+ try {
332
+ return requireControllerOwnershipAuthority(owner);
333
+ } catch {
334
+ return undefined;
335
+ }
336
+ }
337
+
338
+ function controllerTerminalizationAuthorityMatches(
339
+ owner: ControllerSession,
340
+ authority: ControllerTerminalizationAuthority,
341
+ ): boolean {
342
+ const ownerPrincipal = controllerSessionPrincipalId(owner);
343
+ const ownerInstanceId = owner.controllerInstanceId?.trim() || '';
344
+ return owner.controllerId === authority.controllerId
345
+ && owner.controllerType === authority.controllerType
346
+ && ownerPrincipal === authority.principalId.trim()
347
+ && ownerInstanceId === authority.controllerInstanceId.trim()
348
+ && owner.claimGeneration === authority.claimGeneration;
349
+ }
350
+
351
+ /**
352
+ * Serialize control-path Work terminalization against the same canonical
353
+ * ControllerSession task lock used by claim/resume/release. This is a fence,
354
+ * not a second lifecycle authority: WorkContract remains the terminal state
355
+ * authority and ControllerSession remains the ownership authority.
356
+ *
357
+ * A caller without Controller authority may terminalize only while the Work is
358
+ * unclaimed. A caller that observed a live owner must present that exact durable
359
+ * owner epoch. Transport session ids are intentionally not compared because MCP
360
+ * transports may rotate without moving Work ownership; controller instance plus
361
+ * claim generation fence stale controller epochs while preserving that rotation.
362
+ */
363
+ export function withControllerSessionTerminalizationFence<T>(
364
+ options: ControllerSessionStoreOptions,
365
+ input: {
366
+ workId: string;
367
+ actor: string;
368
+ authority?: ControllerTerminalizationAuthority;
369
+ },
370
+ operation: () => T,
371
+ ): ControllerTerminalizationFenceResult<T> {
372
+ return withControllerLock(
373
+ options.controllerHome,
374
+ { scope: 'task', repoId: options.repoId, taskId: `controller-session-${input.workId}` },
375
+ input.actor,
376
+ () => {
377
+ const owner = activeSession(read(options), input.workId, optionsNowMs(options));
378
+ if (!owner) {
379
+ if (input.authority) return { allowed: false, reason: 'controller_claim_missing' };
380
+ return { allowed: true, value: operation() };
381
+ }
382
+ if (!input.authority) return { allowed: false, reason: 'active_controller_claim', owner };
383
+
384
+ if (!controllerTerminalizationAuthorityMatches(owner, input.authority)) {
385
+ return { allowed: false, reason: 'stale_controller_authority', owner };
386
+ }
387
+ return { allowed: true, value: operation(), owner };
388
+ },
389
+ );
390
+ }
391
+
392
+ /**
393
+ * Release a live ControllerSession only when the caller still owns the exact
394
+ * durable controller epoch it observed. This closes the release-then-terminalize
395
+ * race without changing WorkContract lifecycle authority.
396
+ */
397
+ export function releaseControllerSessionWithAuthority(
398
+ options: ControllerSessionStoreOptions,
399
+ input: {
400
+ workId: string;
401
+ actor: string;
402
+ authority: ControllerTerminalizationAuthority;
403
+ },
404
+ ): ControllerTerminalizationFenceResult<void> {
405
+ return withControllerLock(
406
+ options.controllerHome,
407
+ { scope: 'task', repoId: options.repoId, taskId: `controller-session-${input.workId}` },
408
+ input.actor,
409
+ () => {
410
+ const store = read(options);
411
+ const owner = activeSession(store, input.workId, optionsNowMs(options));
412
+ if (!owner) return { allowed: false, reason: 'controller_claim_missing' };
413
+ if (!controllerTerminalizationAuthorityMatches(owner, input.authority)) {
414
+ return { allowed: false, reason: 'stale_controller_authority', owner };
415
+ }
416
+ const releasedAt = now(options);
417
+ persistRetainedControllerSession(options, owner, releasedAt);
418
+ const sessions = store.sessions.filter((entry) => entry.workId !== input.workId);
419
+ write(options, { schemaVersion: 1, updatedAt: releasedAt, sessions });
420
+ return { allowed: true, value: undefined, owner };
421
+ },
422
+ );
423
+ }
424
+
425
+ export function releaseObservedControllerSession(
426
+ options: ControllerSessionStoreOptions,
427
+ input: { workId: string; actor: string; owner: ControllerSession },
428
+ ): ControllerTerminalizationFenceResult<void> {
429
+ const authority = controllerTerminalizationAuthorityFromSession(input.owner);
430
+ if (!authority) return { allowed: false, reason: 'stale_controller_authority', owner: input.owner };
431
+ return releaseControllerSessionWithAuthority(options, {
432
+ workId: input.workId,
433
+ actor: input.actor,
434
+ authority,
435
+ });
436
+ }
437
+
438
+ /**
439
+ * Strict claim used for first ownership acquisition and explicit release/reclaim flows.
440
+ * A live claim with any different controller or transport session remains fenced.
441
+ */
442
+ export function claimControllerSession(
443
+ options: ControllerSessionStoreOptions,
444
+ input: ControllerSessionClaimInput,
445
+ ): ControllerSession {
446
+ assertIdentity(input);
447
+ return withControllerLock(
448
+ options.controllerHome,
449
+ { scope: 'task', repoId: options.repoId, taskId: `controller-session-${input.workId}` },
450
+ `controller-claim:${input.controllerId}:${input.sessionId}`,
451
+ () => {
452
+ assertWorkClaimable(options, input.workId);
453
+ const store = read(options);
454
+ const current = activeSession(store, input.workId, optionsNowMs(options));
455
+ const previous = current ?? store.sessions
456
+ .filter((entry) => entry.workId === input.workId)
457
+ .sort((left, right) => (right.claimGeneration ?? 0) - (left.claimGeneration ?? 0))[0];
458
+ assertExpectedGeneration(input, current);
459
+ if (current && (current.controllerId !== input.controllerId || current.sessionId !== input.sessionId)) {
460
+ throw new Error(`WORK_ALREADY_CLAIMED: ${input.workId} is owned by ${current.controllerId}`);
461
+ }
462
+ return persistClaim(options, store, input, previous);
463
+ },
464
+ );
465
+ }
466
+
467
+ /**
468
+ * Resume a claim after transport replacement. Durable Work ownership belongs to
469
+ * the authenticated principal/controller epoch, not to one MCP transport session.
470
+ * A same-principal session rotation therefore preserves ownership generation;
471
+ * a controller-epoch change is recovery and advances the generation fence.
472
+ */
473
+ export function resumeControllerSession(
474
+ options: ControllerSessionStoreOptions,
475
+ input: ControllerSessionClaimInput & { principalId: string; controllerInstanceId: string },
476
+ ): ControllerSession {
477
+ assertIdentity(input);
478
+ if (!input.principalId.trim() || !input.controllerInstanceId.trim()) {
479
+ throw new Error('CONTROLLER_RESUME_AUTHORITY_REQUIRED');
480
+ }
481
+ return withControllerLock(
482
+ options.controllerHome,
483
+ { scope: 'task', repoId: options.repoId, taskId: `controller-session-${input.workId}` },
484
+ `controller-resume:${input.controllerId}:${input.sessionId}`,
485
+ () => {
486
+ assertWorkClaimable(options, input.workId);
487
+ const store = read(options);
488
+ const currentNowMs = optionsNowMs(options);
489
+ const current = activeSession(store, input.workId, currentNowMs);
490
+ assertExpectedGeneration(input, current);
491
+ if (!current) {
492
+ const previous = store.sessions
493
+ .filter((entry) => entry.workId === input.workId)
494
+ .sort((left, right) => (right.claimGeneration ?? 0) - (left.claimGeneration ?? 0))[0];
495
+ return persistClaim(options, store, input, previous);
496
+ }
497
+ const priorExecution = peekExecutionSession(options.controllerHome, current.sessionId);
498
+ const currentPrincipal = current.principalId?.trim() || priorExecution?.principalId?.trim() || current.controllerId;
499
+ const staleRecoveryAllowed = input.allowStaleRecovery === true
500
+ && input.expectedClaimGeneration !== undefined
501
+ && !sessionBlocksRecovery(options, current, { nowMs: currentNowMs });
502
+ if (currentPrincipal !== input.principalId.trim() && !staleRecoveryAllowed) {
503
+ throw new Error(`WORK_CONTROLLER_PRINCIPAL_MISMATCH: ${input.workId} is owned by another authenticated principal`);
504
+ }
505
+ if (current.controllerId !== input.controllerId && !staleRecoveryAllowed) {
506
+ throw new Error(`WORK_ALREADY_CLAIMED: ${input.workId} is owned by ${current.controllerId}`);
507
+ }
508
+ if (current.controllerType !== input.controllerType && !staleRecoveryAllowed) {
509
+ throw new Error(`WORK_CONTROLLER_TYPE_MISMATCH: ${input.workId} is owned by ${current.controllerType}`);
510
+ }
511
+ return persistClaim(options, store, input, current);
512
+ },
513
+ );
514
+ }
515
+
516
+ /**
517
+ * Rebind one active Work to the authenticated Controller transport/Runtime that
518
+ * is serving the current request. Same-instance transport rollover needs only
519
+ * principal/controller proof. A Runtime-instance change additionally requires
520
+ * positive proof that the requested instance is the live canonical Runtime;
521
+ * this prevents a stale old Runtime request from migrating ownership backwards.
522
+ * The observed claim generation is always supplied as a CAS fence.
523
+ */
524
+ export function bindControllerSessionToCurrentRuntime(
525
+ options: ControllerSessionStoreOptions,
526
+ input: ControllerSessionClaimInput & {
527
+ principalId: string;
528
+ controllerInstanceId: string;
529
+ currentRuntimeInstanceId?: string;
530
+ allowClaimIfMissing?: boolean;
531
+ },
532
+ ): ControllerSession {
533
+ assertIdentity(input);
534
+ const current = getControllerSession(options, input.workId);
535
+ if (!current) {
536
+ if (input.allowClaimIfMissing !== true) throw new Error(`WORK_CONTROLLER_OWNER_REQUIRED: ${input.workId}`);
537
+ return claimControllerSession(options, { ...input, expectedClaimGeneration: 0 });
538
+ }
539
+ const currentPrincipal = controllerSessionPrincipalId(current);
540
+ if (current.controllerId !== input.controllerId) {
541
+ throw new Error(`WORK_CONTROLLER_OWNER_MISMATCH: ${input.workId} is owned by ${current.controllerId}`);
542
+ }
543
+ if (current.controllerType !== input.controllerType) {
544
+ throw new Error(`WORK_CONTROLLER_TYPE_MISMATCH: ${input.workId} is owned by ${current.controllerType}`);
545
+ }
546
+ if (currentPrincipal !== input.principalId.trim()) {
547
+ throw new Error(`WORK_CONTROLLER_PRINCIPAL_MISMATCH: ${input.workId}`);
548
+ }
549
+ const ownerInstanceId = current.controllerInstanceId?.trim() || '';
550
+ const requestedInstanceId = input.controllerInstanceId.trim();
551
+ if (ownerInstanceId !== requestedInstanceId) {
552
+ const currentRuntimeInstanceId = input.currentRuntimeInstanceId?.trim() || '';
553
+ if (!currentRuntimeInstanceId || currentRuntimeInstanceId !== requestedInstanceId) {
554
+ throw new Error(`WORK_CONTROLLER_INSTANCE_MISMATCH: ${input.workId}`);
555
+ }
556
+ }
557
+ if (ownerInstanceId === requestedInstanceId && current.sessionId === input.sessionId) return current;
558
+ return resumeControllerSession(options, {
559
+ ...input,
560
+ expectedClaimGeneration: current.claimGeneration,
561
+ });
562
+ }
563
+
564
+ export function releaseControllerSession(options: ControllerSessionStoreOptions, workId: string, controllerId: string): void {
565
+ withControllerLock(
566
+ options.controllerHome,
567
+ { scope: 'task', repoId: options.repoId, taskId: `controller-session-${workId}` },
568
+ `controller-release:${controllerId}`,
569
+ () => {
570
+ const store = read(options);
571
+ const owner = store.sessions.find((entry) => entry.workId === workId && entry.controllerId === controllerId);
572
+ const releasedAt = now(options);
573
+ if (owner) persistRetainedControllerSession(options, owner, releasedAt);
574
+ const sessions = store.sessions.filter((entry) => entry.workId !== workId || entry.controllerId !== controllerId);
575
+ write(options, { schemaVersion: 1, updatedAt: releasedAt, sessions });
576
+ },
577
+ );
578
+ }
@@ -0,0 +1,16 @@
1
+ import type { ControllerBinding, ControllerRoundContext } from '../domain/types';
2
+
3
+ export interface ControllerHostResumeResult {
4
+ accepted: boolean;
5
+ dispatchId?: string;
6
+ reason?: string;
7
+ /** Explicit provider/user blocker. Valid only when accepted=false; callers persist a resumable wait instead of terminal rejection. */
8
+ waitForUser?: boolean;
9
+ /** Durable user-action Handoff created by the provider adapter when waitForUser=true. */
10
+ handoffId?: string;
11
+ }
12
+
13
+ /** Provider-neutral continuation port. Implementations live in adapters/*. */
14
+ export interface ControllerHost {
15
+ resume(binding: ControllerBinding, roundContext: ControllerRoundContext): Promise<ControllerHostResumeResult> | ControllerHostResumeResult;
16
+ }
@@ -0,0 +1 @@
1
+ export * from '../domain/types';
@@ -0,0 +1,40 @@
1
+ export const REQUIREMENT_STATES = ['planned', 'active', 'waiting_for_user', 'done', 'cancelled'] as const;
2
+ export type RequirementState = (typeof REQUIREMENT_STATES)[number];
3
+
4
+ export const REQUIREMENT_STATE_TRANSITIONS: Readonly<Record<RequirementState, readonly RequirementState[]>> = {
5
+ planned: ['planned', 'active', 'waiting_for_user', 'cancelled'],
6
+ active: ['active', 'waiting_for_user', 'done', 'cancelled'],
7
+ waiting_for_user: ['waiting_for_user', 'planned', 'active', 'done', 'cancelled'],
8
+ done: ['done', 'cancelled'],
9
+ cancelled: ['cancelled'],
10
+ };
11
+
12
+ export const PLAN_CONTRACT_STATUSES = [
13
+ 'draft',
14
+ 'inspecting',
15
+ 'reviewing',
16
+ 'approved',
17
+ 'executing',
18
+ 'replanning',
19
+ 'verifying',
20
+ 'ready_to_finalize',
21
+ 'finalized',
22
+ 'superseded',
23
+ 'cancelled',
24
+ 'invalidated_by_drift',
25
+ ] as const;
26
+ export type PlanContractStatus = (typeof PLAN_CONTRACT_STATUSES)[number];
27
+
28
+ export const TERMINAL_PLAN_CONTRACT_STATUSES: readonly PlanContractStatus[] = [
29
+ 'finalized',
30
+ 'superseded',
31
+ 'cancelled',
32
+ 'invalidated_by_drift',
33
+ ];
34
+
35
+ export function isTerminalPlanContractStatus(status: PlanContractStatus): boolean {
36
+ return TERMINAL_PLAN_CONTRACT_STATUSES.includes(status);
37
+ }
38
+
39
+ export const PLAN_STEP_STATUSES = ['pending', 'ready', 'executing', 'validating', 'completed'] as const;
40
+ export type PlanStepStatus = (typeof PLAN_STEP_STATUSES)[number];
@@ -0,0 +1 @@
1
+ export * from './api/index';
@@ -0,0 +1,5 @@
1
+ export * from '../domain/types';
2
+ export * from '../domain/scope';
3
+ export * from '../application/identity-service';
4
+ export * from '../domain/workspace';
5
+ export * from '../domain/semantic-sync';