@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,18 +1,20 @@
1
1
  import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'fs';
2
2
  import { basename, dirname, join, relative, resolve } from 'path';
3
3
  import { tmpdir } from 'os';
4
+ import { assertStorageHeadroom } from '../shared/storage-capacity';
4
5
  import { runProcess } from '../../effects/process-runner';
5
- import { cleanupEditSession, getEditSession, listEditSessions, reconcileEditSession } from '../../cli/editing/edit-session';
6
+ import { cleanupEditSession, getEditSession, listEditSessions } from '../../cli/editing/edit-session';
6
7
  import { ensureRepositoryRuntimeStorage, type RepositoryRuntimeStorageReport } from '../../cli/repositories/runtime-storage';
8
+ import { getRepository, selectRepositoryCheckout, setRepositoryCheckoutLifecycle } from '../../cli/repositories/registry';
7
9
  import type { RepositoryRecord } from '../../cli/repositories/types';
8
10
  import { rebuildRepositoryProjection } from '../projections/materialized-view';
9
- import { getWorkContract, readWorkContractStore, transitionWorkContractPhase } from '../control-plane/facade/work-contract-store';
10
- import { getControllerSession, withControllerSessionTerminalizationFence } from '../control-plane/facade/controller-session-store';
11
+ import { cancelWorkContract, getWorkContract, readWorkContractStore, updateWorkContract } from '../../../packages/kernel/work/api/index';
12
+ import { getControllerSession, listControllerSessions, withControllerSessionTerminalizationFence } from '../../../packages/kernel/controller/api/index';
11
13
  import { listPlanContracts } from '../control-plane/facade/plan-contract-store';
12
14
  import { readRequirement } from '../control-plane/persistence/requirement-store';
13
15
  import { listControlPlaneRecords, type ControlPlaneRecord } from '../control-plane/persistence/sqlite-store';
14
16
  import { isTerminalWorkContractStatus, type WorkContract } from '../control-plane/facade/types';
15
- import { listSchedules } from '../workflow/schedules/store';
17
+ import { listSchedules } from '../../../packages/kernel/scheduler/api/index';
16
18
  import {
17
19
  collectRuntimeProcesses,
18
20
  removeRuntimeTempEntry,
@@ -26,6 +28,16 @@ import {
26
28
  type RuntimeStorageRepairPreview,
27
29
  } from './local-jobs-repair';
28
30
  import { gcTerminalProcesses, type ProcessGcResult } from '../execution/process-runtime/gc';
31
+ import { cleanupStaleWorkVerificationSnapshots, type WorkVerificationSnapshotRetentionReport } from '../control-plane/execution/work-verification-snapshot';
32
+ import {
33
+ cleanupRuntimeQuarantine,
34
+ quarantineRuntimePath,
35
+ runtimeLegacyCheckQuarantineRoot,
36
+ type RuntimeQuarantineRetentionReport,
37
+ } from './quarantine-retention';
38
+ import { readWorkHandle, resolveWorkDeliveryTargetBranch } from '../control-plane/execution/work-handle-store';
39
+ import { listRecoverableProcessRecords } from '../execution/process-runtime/store';
40
+ import { isManagedProcessActive } from '../execution/process-runtime/types';
29
41
 
30
42
  export type RuntimeMaintenanceActionId =
31
43
  | 'local_jobs_reconcile'
@@ -137,6 +149,8 @@ export interface RuntimeMaintenanceApplyResult extends Omit<RuntimeMaintenanceSt
137
149
  runtimeStorageRepairApply?: RuntimeStorageRepairApplyResult;
138
150
  /** Existing bounded terminal-process retention, run only during explicit full maintenance. */
139
151
  processGc?: ProcessGcResult;
152
+ verificationSnapshotGc?: WorkVerificationSnapshotRetentionReport;
153
+ quarantineGc?: RuntimeQuarantineRetentionReport;
140
154
  projection?: unknown;
141
155
  }
142
156
 
@@ -189,10 +203,16 @@ function readJson(path: string): unknown {
189
203
  }
190
204
 
191
205
  function writeJsonAtomic(path: string, value: unknown): void {
206
+ const content = `${JSON.stringify(value, null, 2)}\n`;
207
+ assertStorageHeadroom(path, {
208
+ operation: 'runtime_maintenance_state_write',
209
+ requiredBytes: Buffer.byteLength(content),
210
+ reserveBytes: 16 * 1024 * 1024,
211
+ });
192
212
  mkdirSync(dirname(path), { recursive: true });
193
213
  const temporaryPath = `${path}.${process.pid}.${Date.now()}.tmp`;
194
214
  try {
195
- writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
215
+ writeFileSync(temporaryPath, content, { encoding: 'utf8', mode: 0o600 });
196
216
  renameSync(temporaryPath, path);
197
217
  } finally {
198
218
  rmSync(temporaryPath, { force: true });
@@ -484,10 +504,117 @@ interface StaleWorkSourceInspection {
484
504
  detail: string;
485
505
  }
486
506
 
507
+ interface StaleWorkDeliveryTargetResolution {
508
+ targetBranch: string;
509
+ handle?: NonNullable<ReturnType<typeof readWorkHandle>>;
510
+ identityMismatch: boolean;
511
+ }
512
+
513
+ function resolveStaleWorkDeliveryTarget(
514
+ repository: RuntimeMaintenanceRepository,
515
+ controllerHome: string,
516
+ contract: WorkContract,
517
+ ): StaleWorkDeliveryTargetResolution {
518
+ const handle = readWorkHandle(controllerHome, repository.repoId, contract.workId);
519
+ if (!handle) {
520
+ return { targetBranch: repository.defaultBranch?.trim() || 'main', identityMismatch: false };
521
+ }
522
+ if (!contract.checkoutId || handle.checkoutId !== contract.checkoutId) {
523
+ return {
524
+ targetBranch: repository.defaultBranch?.trim() || 'main',
525
+ handle,
526
+ identityMismatch: true,
527
+ };
528
+ }
529
+ return {
530
+ targetBranch: resolveWorkDeliveryTargetBranch(handle, repository.defaultBranch),
531
+ handle,
532
+ identityMismatch: false,
533
+ };
534
+ }
535
+
536
+ function isLegacyImplicitRemoteEffectPlacement(contract: WorkContract): boolean {
537
+ if (contract.workKind !== 'remote_effect' || contract.worktreePolicy.required !== true || !contract.worktreeRef || !contract.checkoutId) return false;
538
+ if (contract.routeDecision?.requiresIsolation === true) return false;
539
+ const reason = contract.worktreePolicy.reason?.trim() ?? '';
540
+ if (/Typed placement|Route Policy requires isolated execution/i.test(reason)) return false;
541
+ return true;
542
+ }
543
+
544
+ interface LegacyRemoteEffectPlacementInspection {
545
+ safe: boolean;
546
+ path?: string;
547
+ detail: string;
548
+ checkoutId?: string;
549
+ canonicalCheckoutId?: string;
550
+ branch?: string;
551
+ canonicalBranch?: string;
552
+ }
553
+
554
+ function inspectLegacyRemoteEffectPlacement(
555
+ repository: RuntimeMaintenanceRepository,
556
+ controllerHome: string,
557
+ contract: WorkContract,
558
+ ): LegacyRemoteEffectPlacementInspection | undefined {
559
+ if (!isLegacyImplicitRemoteEffectPlacement(contract)) return undefined;
560
+ const recordedPath = contract.worktreeRef?.trim();
561
+ if (!recordedPath) return undefined;
562
+ const path = resolve(recordedPath);
563
+ if (!looksLikeForgeManagedWorktree(path)) return { safe: false, path, detail: 'Legacy remote_effect placement is outside Forge-managed worktree storage; automatic resource detachment is forbidden.' };
564
+ if (readWorkHandle(controllerHome, repository.repoId, contract.workId)) return { safe: false, path, detail: 'Legacy remote_effect placement unexpectedly has a WorkHandle; repository source authority must be reconciled explicitly.' };
565
+ let registered;
566
+ try { registered = getRepository(repository.repoId, controllerHome, { includeRemoved: true }); } catch (error) {
567
+ return { safe: false, path, detail: `Repository registry could not be read for legacy remote_effect placement: ${error instanceof Error ? error.message : String(error)}` };
568
+ }
569
+ const checkout = registered.checkouts.find((candidate) => candidate.checkoutId === contract.checkoutId);
570
+ if (!checkout) return { safe: false, path, detail: 'Legacy remote_effect checkout identity is missing from the Repository Registry.' };
571
+ if ((checkout.lifecycle ?? 'active') !== 'active' || checkout.worktree !== true) return { safe: false, path, detail: `Legacy remote_effect checkout ${checkout.checkoutId} is not an active registered worktree.` };
572
+ const registeredPath = resolve(checkout.canonicalRoot);
573
+ if (registeredPath !== path && resolve(checkout.localRoot) !== path) return { safe: false, path, detail: 'Legacy remote_effect WorkContract path does not match its registered checkout identity.' };
574
+ const otherOwner = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts.find((candidate) =>
575
+ candidate.workId !== contract.workId
576
+ && !isTerminalWorkContractStatus(candidate.status)
577
+ && candidate.worktreeRef
578
+ && resolve(candidate.worktreeRef) === path);
579
+ if (otherOwner) return { safe: false, path, detail: `Managed worktree is also owned by active Work ${otherOwner.workId}; resource detachment is fenced.` };
580
+ if (!existsSync(path)) return { safe: false, path, detail: 'Legacy remote_effect managed worktree path is absent; registry/source reconciliation is required before detachment.' };
581
+ const status = runProcess('git', ['status', '--porcelain', '--untracked-files=all'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 500_000 });
582
+ if (!status.ok || status.stdout.trim()) return { safe: false, path, detail: status.ok ? 'Legacy remote_effect managed worktree is dirty; live source must be preserved.' : 'Legacy remote_effect managed worktree status could not be read.' };
583
+ const head = runProcess('git', ['rev-parse', 'HEAD'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 100_000 });
584
+ const baseRevision = contract.baseRevision?.trim();
585
+ if (!head.ok || !head.stdout.trim() || !baseRevision || head.stdout.trim() !== baseRevision) return { safe: false, path, detail: 'Legacy remote_effect worktree HEAD does not exactly equal the Work base revision; repository delta ownership is ambiguous.' };
586
+ const branch = runProcess('git', ['branch', '--show-current'], { cwd: path, timeoutMs: 10_000, maxOutputBytes: 100_000 });
587
+ if (!branch.ok || !branch.stdout.trim()) return { safe: false, path, detail: 'Legacy remote_effect managed worktree branch could not be resolved.' };
588
+ let canonical;
589
+ try { canonical = selectRepositoryCheckout(registered, registered.activeCheckoutId); } catch (error) {
590
+ return { safe: false, path, detail: `Canonical repository checkout could not be resolved: ${error instanceof Error ? error.message : String(error)}` };
591
+ }
592
+ if (canonical.activeCheckoutId === checkout.checkoutId) return { safe: false, path, detail: 'Legacy remote_effect placement unexpectedly points at the canonical active checkout; automatic detachment is forbidden.' };
593
+ const canonicalBranch = runProcess('git', ['branch', '--show-current'], { cwd: canonical.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
594
+ if (!canonicalBranch.ok || !canonicalBranch.stdout.trim()) return { safe: false, path, detail: 'Canonical integration branch could not be resolved for legacy remote_effect detachment.' };
595
+ const contained = runProcess('git', ['merge-base', '--is-ancestor', baseRevision, `refs/heads/${canonicalBranch.stdout.trim()}`], { cwd: canonical.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
596
+ if (!contained.ok) return { safe: false, path, detail: `Legacy remote_effect base revision ${baseRevision} is not contained in canonical branch ${canonicalBranch.stdout.trim()}; source preservation remains required.` };
597
+ return {
598
+ safe: true, path, checkoutId: checkout.checkoutId, canonicalCheckoutId: canonical.activeCheckoutId,
599
+ branch: branch.stdout.trim(), canonicalBranch: canonicalBranch.stdout.trim(),
600
+ detail: `Legacy remote_effect owns a clean no-delta managed worktree at base revision ${baseRevision}, which is already contained in canonical branch ${canonicalBranch.stdout.trim()}; repository placement may be detached without changing Work semantics.`,
601
+ };
602
+ }
603
+
487
604
  function inspectStaleWorkRepositorySource(
488
605
  repository: RuntimeMaintenanceRepository,
606
+ controllerHome: string,
489
607
  contract: WorkContract,
490
608
  ): StaleWorkSourceInspection {
609
+ const legacyRemoteEffect = inspectLegacyRemoteEffectPlacement(repository, controllerHome, contract);
610
+ if (legacyRemoteEffect) {
611
+ return {
612
+ safeToCancel: legacyRemoteEffect.safe,
613
+ state: legacyRemoteEffect.safe ? 'clean_integrated' : 'source_state_unknown',
614
+ path: legacyRemoteEffect.path,
615
+ detail: legacyRemoteEffect.detail,
616
+ };
617
+ }
491
618
  const recordedPath = contract.worktreeRef?.trim();
492
619
  if (!recordedPath) {
493
620
  return {
@@ -506,11 +633,62 @@ function inspectStaleWorkRepositorySource(
506
633
  };
507
634
  }
508
635
  if (!existsSync(path)) {
636
+ const deliveryTarget = resolveStaleWorkDeliveryTarget(repository, controllerHome, contract);
637
+ const handle = deliveryTarget.handle;
638
+ const expectedHead = handle?.expectedHead?.trim();
639
+ if (deliveryTarget.identityMismatch || !handle || !expectedHead) {
640
+ return {
641
+ safeToCancel: false,
642
+ state: 'source_state_unknown',
643
+ path,
644
+ detail: 'Recorded managed worktree path is absent and no identity-matched durable WorkHandle head can prove source preservation; destructive stale-Work cancellation is fenced.',
645
+ };
646
+ }
647
+ const targetBranch = deliveryTarget.targetBranch;
648
+ const head = runProcess('git', ['rev-parse', '--verify', `${expectedHead}^{commit}`], {
649
+ cwd: repository.canonicalRoot,
650
+ timeoutMs: 10_000,
651
+ maxOutputBytes: 100_000,
652
+ });
653
+ const target = runProcess('git', ['rev-parse', '--verify', `refs/heads/${targetBranch}`], {
654
+ cwd: repository.canonicalRoot,
655
+ timeoutMs: 10_000,
656
+ maxOutputBytes: 100_000,
657
+ });
658
+ if (!head.ok || !head.stdout.trim() || !target.ok || !target.stdout.trim()) {
659
+ return {
660
+ safeToCancel: false,
661
+ state: 'source_state_unknown',
662
+ path,
663
+ detail: `Recorded managed worktree path is absent and durable source head/target ${targetBranch} could not be resolved; destructive stale-Work cancellation is fenced.`,
664
+ };
665
+ }
666
+ const unique = runProcess('git', ['rev-list', '--count', `${target.stdout.trim()}..${head.stdout.trim()}`], {
667
+ cwd: repository.canonicalRoot,
668
+ timeoutMs: 10_000,
669
+ maxOutputBytes: 100_000,
670
+ });
671
+ if (!unique.ok || !/^\d+$/.test(unique.stdout.trim())) {
672
+ return {
673
+ safeToCancel: false,
674
+ state: 'source_state_unknown',
675
+ path,
676
+ detail: 'Durable WorkHandle source head could not be compared with its delivery target; destructive stale-Work cancellation is fenced.',
677
+ };
678
+ }
679
+ if (Number(unique.stdout.trim()) > 0) {
680
+ return {
681
+ safeToCancel: false,
682
+ state: 'unintegrated_commits',
683
+ path,
684
+ detail: `Managed worktree is absent, but durable WorkHandle head ${expectedHead} has ${unique.stdout.trim()} commit(s) not reachable from ${targetBranch}; exact source remains preserved in Git and requires explicit adoption or cleanup authority.`,
685
+ };
686
+ }
509
687
  return {
510
- safeToCancel: false,
511
- state: 'source_state_unknown',
688
+ safeToCancel: true,
689
+ state: 'clean_integrated',
512
690
  path,
513
- detail: 'Recorded managed worktree path is absent, so maintenance cannot prove that no unique branch/source remains recoverable through Git or checkout metadata; destructive stale-Work cancellation is fenced.',
691
+ detail: `Managed worktree is absent, but its identity-matched durable WorkHandle head ${expectedHead} is already reachable from ${targetBranch}; no unique source is being discarded.`,
514
692
  };
515
693
  }
516
694
 
@@ -541,7 +719,16 @@ function inspectStaleWorkRepositorySource(
541
719
  timeoutMs: 10_000,
542
720
  maxOutputBytes: 100_000,
543
721
  });
544
- const targetBranch = repository.defaultBranch?.trim() || 'main';
722
+ const deliveryTarget = resolveStaleWorkDeliveryTarget(repository, controllerHome, contract);
723
+ if (deliveryTarget.identityMismatch) {
724
+ return {
725
+ safeToCancel: false,
726
+ state: 'source_state_unknown',
727
+ path,
728
+ detail: 'Managed worktree has a durable WorkHandle whose checkout identity does not match the WorkContract; source containment cannot be proven against that handle and destructive stale-Work cancellation is fenced.',
729
+ };
730
+ }
731
+ const targetBranch = deliveryTarget.targetBranch;
545
732
  const target = runProcess('git', ['rev-parse', '--verify', `refs/heads/${targetBranch}`], {
546
733
  cwd: repository.canonicalRoot,
547
734
  timeoutMs: 10_000,
@@ -701,26 +888,68 @@ function normalizedOptions(options: RuntimeMaintenanceOptions = {}): Required<Ru
701
888
  };
702
889
  }
703
890
 
704
- function activeWorkAuthorityRefs(
891
+ interface RuntimeMaintenanceAuthoritySnapshot {
892
+ contracts: WorkContract[];
893
+ workById: Map<string, WorkContract>;
894
+ controllerWorkIds: Set<string>;
895
+ planByWorkId: Map<string, string>;
896
+ activeRequirementStateById: Map<string, string>;
897
+ scheduleByWorkId: Map<string, string>;
898
+ processByWorkId: Map<string, string>;
899
+ }
900
+
901
+ /**
902
+ * Build one bounded read snapshot for a maintenance status pass. Discovery must
903
+ * never turn N candidate Works/EditSessions into N full Plan/Schedule/Process
904
+ * scans. Process liveness comes from Process Runtime's recovery index instead of
905
+ * enumerating terminal process history. This snapshot is advisory only; mutation
906
+ * paths still re-read current authority before terminalization.
907
+ */
908
+ function buildRuntimeMaintenanceAuthoritySnapshot(
705
909
  repository: RuntimeMaintenanceRepository,
706
910
  controllerHome: string,
707
- contract: WorkContract,
708
- ): string[] {
911
+ ): RuntimeMaintenanceAuthoritySnapshot {
912
+ const contracts = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts;
913
+ const workById = new Map(contracts.map((contract) => [contract.workId, contract]));
914
+ const controllerWorkIds = new Set(listControllerSessions({ controllerHome, repoId: repository.repoId }).map((session) => session.workId));
915
+ const planByWorkId = new Map<string, string>();
916
+ for (const plan of listPlanContracts({ controllerHome, repoId: repository.repoId, status: 'active', limit: 100 })) {
917
+ for (const step of plan.steps) if (step.workId) planByWorkId.set(step.workId, plan.planId);
918
+ if (plan.planId) {
919
+ for (const contract of contracts) if (contract.planId === plan.planId) planByWorkId.set(contract.workId, plan.planId);
920
+ }
921
+ }
922
+ const activeRequirementStateById = new Map<string, string>();
923
+ for (const requirementId of new Set(contracts.flatMap((contract) => contract.requirementId ? [contract.requirementId] : []))) {
924
+ const requirement = readRequirement({ controllerHome }, requirementId)?.value;
925
+ if (requirement && !['done', 'cancelled'].includes(requirement.state)) activeRequirementStateById.set(requirementId, requirement.state);
926
+ }
927
+ const scheduleByWorkId = new Map<string, string>();
928
+ for (const schedule of listSchedules(controllerHome, repository.repoId)) {
929
+ if (!schedule.enabled) continue;
930
+ const workId = String((schedule.action.arguments as Record<string, unknown> | undefined)?.work_id ?? '').trim();
931
+ if (workId && !scheduleByWorkId.has(workId)) scheduleByWorkId.set(workId, schedule.scheduleId);
932
+ }
933
+ const processByWorkId = new Map<string, string>();
934
+ for (const process of listRecoverableProcessRecords(controllerHome, repository.repoId)) {
935
+ if (process.workId && isManagedProcessActive(process) && !processByWorkId.has(process.workId)) processByWorkId.set(process.workId, process.processId);
936
+ }
937
+ return { contracts, workById, controllerWorkIds, planByWorkId, activeRequirementStateById, scheduleByWorkId, processByWorkId };
938
+ }
939
+
940
+ function activeWorkAuthorityRefs(contract: WorkContract, snapshot: RuntimeMaintenanceAuthoritySnapshot): string[] {
709
941
  const refs: string[] = [];
710
- if (getControllerSession({ controllerHome, repoId: repository.repoId }, contract.workId)) refs.push('controller_session');
711
- const activePlans = listPlanContracts({ controllerHome, repoId: repository.repoId, status: 'active', limit: 100 });
712
- const plan = activePlans.find((candidate) => candidate.planId === contract.planId || candidate.steps.some((step) => step.workId === contract.workId));
713
- if (plan) refs.push(`plan:${plan.planId}`);
942
+ if (snapshot.controllerWorkIds.has(contract.workId)) refs.push('controller_session');
943
+ const planId = snapshot.planByWorkId.get(contract.workId);
944
+ if (planId) refs.push(`plan:${planId}`);
714
945
  if (contract.requirementId) {
715
- const requirement = readRequirement({ controllerHome }, contract.requirementId)?.value;
716
- if (requirement && !['done', 'cancelled'].includes(requirement.state)) refs.push(`requirement:${requirement.requirementId}:${requirement.state}`);
946
+ const state = snapshot.activeRequirementStateById.get(contract.requirementId);
947
+ if (state) refs.push(`requirement:${contract.requirementId}:${state}`);
717
948
  }
718
- const boundSchedule = listSchedules(controllerHome, repository.repoId).find((schedule) => {
719
- if (!schedule.enabled) return false;
720
- const args = schedule.action.arguments as Record<string, unknown> | undefined;
721
- return args?.work_id === contract.workId;
722
- });
723
- if (boundSchedule) refs.push(`schedule:${boundSchedule.scheduleId}`);
949
+ const scheduleId = snapshot.scheduleByWorkId.get(contract.workId);
950
+ if (scheduleId) refs.push(`schedule:${scheduleId}`);
951
+ const processId = snapshot.processByWorkId.get(contract.workId);
952
+ if (processId) refs.push(`process:${processId}`);
724
953
  return refs;
725
954
  }
726
955
 
@@ -728,9 +957,10 @@ function scanStaleWorkContractCandidates(
728
957
  repository: RuntimeMaintenanceRepository,
729
958
  controllerHome: string,
730
959
  options: Required<RuntimeMaintenanceOptions>,
960
+ snapshot: RuntimeMaintenanceAuthoritySnapshot,
731
961
  ): RuntimeMaintenanceCandidate[] {
732
962
  const nowMs = Date.now();
733
- return readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts
963
+ return snapshot.contracts
734
964
  .filter((contract) => !isTerminalWorkContractStatus(contract.status))
735
965
  .map((contract) => {
736
966
  const updatedMs = Date.parse(contract.updatedAt);
@@ -738,38 +968,80 @@ function scanStaleWorkContractCandidates(
738
968
  return { contract, ageMinutes };
739
969
  })
740
970
  .filter(({ ageMinutes }) => ageMinutes >= options.minAgeMinutes)
741
- .flatMap(({ contract, ageMinutes }) => {
742
- const authorityRefs = activeWorkAuthorityRefs(repository, controllerHome, contract);
743
- // A live Plan/Requirement/Schedule/Controller reference is lifecycle authority,
744
- // not maintenance debt. Keep the Work fenced until that authority disappears;
745
- // if it later becomes unowned, the next scan will surface it as stale.
746
- if (authorityRefs.length > 0) return [];
747
- return [{ contract, ageMinutes, source: inspectStaleWorkRepositorySource(repository, contract) }];
971
+ .filter(({ contract }) => {
972
+ // A live Plan/Requirement/Schedule/Controller/Process reference is lifecycle authority,
973
+ // not maintenance debt. The authority inventory was read once for this status pass.
974
+ return activeWorkAuthorityRefs(contract, snapshot).length === 0;
748
975
  })
749
976
  .sort((left, right) => right.ageMinutes - left.ageMinutes)
977
+ // Expensive Git source inspection belongs after the visible candidate budget.
750
978
  .slice(0, options.maxCandidates)
979
+ .map(({ contract, ageMinutes }) => ({
980
+ contract, ageMinutes, source: inspectStaleWorkRepositorySource(repository, controllerHome, contract),
981
+ }))
751
982
  .map(({ contract, ageMinutes, source }) => {
983
+ const legacyRemotePlacement = isLegacyImplicitRemoteEffectPlacement(contract);
752
984
  const semanticReady = staleWorkSemanticTerminalizationReady(contract);
753
985
  return {
754
986
  kind: 'stale_work_contract' as const,
755
987
  id: contract.workId,
756
988
  path: source.path,
757
989
  status: contract.status,
758
- safe: source.safeToCancel && semanticReady,
759
- reason: staleWorkCandidateReason(source, semanticReady),
990
+ safe: legacyRemotePlacement ? source.safeToCancel : source.safeToCancel && semanticReady,
991
+ reason: legacyRemotePlacement ? source.detail : staleWorkCandidateReason(source, semanticReady),
760
992
  ageMinutes,
761
993
  suggestedAction: 'full_maintenance_pass' as const,
762
994
  ownershipStatus: 'explicit' as const,
763
995
  sourceState: source.state,
764
996
  disposition: !source.safeToCancel
765
997
  ? ('source_preservation_required' as const)
766
- : !semanticReady
998
+ : !legacyRemotePlacement && !semanticReady
767
999
  ? ('semantic_completion_required' as const)
768
1000
  : undefined,
769
1001
  };
770
1002
  });
771
1003
  }
772
1004
 
1005
+ function detachLegacyRemoteEffectPlacement(
1006
+ repository: RuntimeMaintenanceRepository,
1007
+ controllerHome: string,
1008
+ current: WorkContract,
1009
+ candidate: RuntimeMaintenanceCandidate,
1010
+ ): RuntimeMaintenanceCandidate & { applied: boolean; result: string } {
1011
+ const inspection = inspectLegacyRemoteEffectPlacement(repository, controllerHome, current);
1012
+ if (!inspection || !inspection.safe || !inspection.path || !inspection.checkoutId || !inspection.canonicalCheckoutId || !inspection.branch || !inspection.canonicalBranch) {
1013
+ return { ...candidate, safe: false, reason: inspection?.detail ?? 'Legacy remote_effect placement is no longer eligible for resource detachment.', sourceState: 'source_state_unknown', disposition: 'source_preservation_required', applied: false, result: 'legacy_remote_effect_placement_preserved' };
1014
+ }
1015
+ const store = { controllerHome, repoId: repository.repoId };
1016
+ const previous = { checkoutId: current.checkoutId, worktreeRef: current.worktreeRef, constraints: current.constraints, driver: current.driver, worktreePolicy: current.worktreePolicy };
1017
+ updateWorkContract(store, current.workId, {
1018
+ checkoutId: inspection.canonicalCheckoutId,
1019
+ worktreeRef: undefined,
1020
+ constraints: { ...current.constraints, workspaceMode: 'auto', requireWorktree: false },
1021
+ driver: { ...current.driver, preferred: 'direct_edit', allowDirectEdit: true },
1022
+ worktreePolicy: { required: false, reason: 'Legacy pure remote_effect repository placement detached by explicit runtime maintenance; external-effect execution has no repository source authority.' },
1023
+ });
1024
+ try {
1025
+ setRepositoryCheckoutLifecycle({ controllerHome, repoId: repository.repoId, checkoutId: inspection.checkoutId, lifecycle: 'removed', reason: `Legacy remote_effect placement detached for ${current.workId}.` });
1026
+ const removed = runProcess('git', ['worktree', 'remove', '--force', inspection.path], { cwd: repository.canonicalRoot, timeoutMs: 60_000, maxOutputBytes: 500_000 });
1027
+ if (!removed.ok && existsSync(inspection.path)) throw new Error(`LEGACY_REMOTE_EFFECT_WORKTREE_REMOVE_FAILED: ${removed.stderr || removed.stdout}`);
1028
+ if (inspection.branch !== inspection.canonicalBranch) {
1029
+ const deleted = runProcess('git', ['branch', '--delete', inspection.branch], { cwd: repository.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
1030
+ if (!deleted.ok) {
1031
+ const forced = runProcess('git', ['branch', '--delete', '--force', inspection.branch], { cwd: repository.canonicalRoot, timeoutMs: 10_000, maxOutputBytes: 100_000 });
1032
+ if (!forced.ok) return { ...candidate, safe: true, reason: inspection.detail, sourceState: 'clean_integrated', disposition: undefined, applied: true, result: `legacy_remote_effect_placement_detached_branch_retained:${inspection.branch}` };
1033
+ }
1034
+ }
1035
+ return { ...candidate, safe: true, reason: inspection.detail, sourceState: 'clean_integrated', disposition: undefined, applied: true, result: 'legacy_remote_effect_placement_detached' };
1036
+ } catch (error) {
1037
+ if (existsSync(inspection.path)) {
1038
+ try { setRepositoryCheckoutLifecycle({ controllerHome, repoId: repository.repoId, checkoutId: inspection.checkoutId, lifecycle: 'active', reason: `Rollback failed legacy remote_effect detach for ${current.workId}.` }); } catch { /* preserve primary failure */ }
1039
+ try { updateWorkContract(store, current.workId, previous); } catch { /* preserve primary failure */ }
1040
+ }
1041
+ throw error;
1042
+ }
1043
+ }
1044
+
773
1045
  export function applyStaleWorkContractMaintenanceCandidate(
774
1046
  repository: RuntimeMaintenanceRepository,
775
1047
  controllerHome: string,
@@ -793,7 +1065,7 @@ export function applyStaleWorkContractMaintenanceCandidate(
793
1065
  if (!current || isTerminalWorkContractStatus(current.status)) {
794
1066
  return { ...candidate, applied: false, result: 'already_terminal' };
795
1067
  }
796
- const authorityRefs = activeWorkAuthorityRefs(repository, controllerHome, current);
1068
+ const authorityRefs = activeWorkAuthorityRefs(current, buildRuntimeMaintenanceAuthoritySnapshot(repository, controllerHome));
797
1069
  if (authorityRefs.length > 0) {
798
1070
  return {
799
1071
  ...candidate,
@@ -805,19 +1077,22 @@ export function applyStaleWorkContractMaintenanceCandidate(
805
1077
  // Re-probe the live worktree while the canonical ControllerSession fence is
806
1078
  // held so neither a newer Controller claim nor a late source write can be
807
1079
  // raced by stale maintenance terminalization.
808
- const source = inspectStaleWorkRepositorySource(repository, current);
1080
+ const source = inspectStaleWorkRepositorySource(repository, controllerHome, current);
809
1081
  if (!source.safeToCancel) {
810
1082
  return {
811
1083
  ...candidate,
812
1084
  path: source.path ?? candidate.path,
813
1085
  safe: false,
814
- reason: staleWorkCandidateReason(source, staleWorkSemanticTerminalizationReady(current)),
1086
+ reason: isLegacyImplicitRemoteEffectPlacement(current) ? source.detail : staleWorkCandidateReason(source, staleWorkSemanticTerminalizationReady(current)),
815
1087
  sourceState: source.state,
816
1088
  disposition: 'source_preservation_required' as const,
817
1089
  applied: false,
818
1090
  result: `work_source_preserved:${source.state}`,
819
1091
  };
820
1092
  }
1093
+ if (isLegacyImplicitRemoteEffectPlacement(current)) {
1094
+ return detachLegacyRemoteEffectPlacement(repository, controllerHome, current, candidate);
1095
+ }
821
1096
  const semanticReady = staleWorkSemanticTerminalizationReady(current);
822
1097
  if (!semanticReady) {
823
1098
  return {
@@ -831,13 +1106,14 @@ export function applyStaleWorkContractMaintenanceCandidate(
831
1106
  result: 'work_semantic_completion_required',
832
1107
  };
833
1108
  }
834
- transitionWorkContractPhase({ controllerHome, repoId: repository.repoId }, current.workId, {
835
- phase: 'cleanup',
836
- status: 'cancelled',
837
- state: 'skipped',
838
- summary: 'Cancelled by explicit full maintenance after the Work had already reached cleanup with prior semantic phases satisfied and no unique live repository source remained; durable evidence retained.',
839
- evidenceRefs: current.evidenceRefs,
840
- });
1109
+ cancelWorkContract(
1110
+ { controllerHome, repoId: repository.repoId },
1111
+ current.workId,
1112
+ {
1113
+ summary: 'Cancelled by explicit full maintenance after the Work had already reached cleanup with prior semantic phases satisfied and no unique live repository source remained; durable evidence retained.',
1114
+ evidenceRefs: current.evidenceRefs,
1115
+ },
1116
+ );
841
1117
  return {
842
1118
  ...candidate,
843
1119
  path: source.path ?? candidate.path,
@@ -863,35 +1139,26 @@ export function applyStaleWorkContractMaintenanceCandidate(
863
1139
 
864
1140
  function scanStaleEditSessionCandidates(
865
1141
  repository: RuntimeMaintenanceRepository,
866
- controllerHome: string,
867
1142
  options: Required<RuntimeMaintenanceOptions>,
1143
+ snapshot: RuntimeMaintenanceAuthoritySnapshot,
868
1144
  ): RuntimeMaintenanceCandidate[] {
869
1145
  const nowMs = Date.now();
870
1146
  return listEditSessions(repository.canonicalRoot, Math.min(options.maxCandidates * 3, 500))
871
1147
  .filter((summary) => ['open', 'dirty', 'checked', 'check_failed'].includes(summary.status))
872
- .flatMap((summary) => {
873
- try {
874
- const session = reconcileEditSession(repository.canonicalRoot, summary.sessionId, {
875
- reviewer: 'runtime-maintenance',
876
- note: 'Reconciled during maintenance discovery; source files were not modified.',
877
- });
878
- if (['finalized', 'superseded', 'rolled_back'].includes(session.status)) return [];
879
- const updatedMs = Date.parse(session.updatedAt);
880
- const ageMinutes = Number.isFinite(updatedMs) ? Math.max(0, Math.floor((nowMs - updatedMs) / 60_000)) : 0;
881
- return [{ session, ageMinutes }];
882
- } catch {
883
- return [];
884
- }
1148
+ // Status discovery is read-only. Workspace hashing/Git reconciliation belongs
1149
+ // exclusively to explicit full maintenance for the selected candidate.
1150
+ .map((session) => {
1151
+ const updatedMs = Date.parse(session.updatedAt);
1152
+ const ageMinutes = Number.isFinite(updatedMs) ? Math.max(0, Math.floor((nowMs - updatedMs) / 60_000)) : 0;
1153
+ return { session, ageMinutes };
885
1154
  })
886
1155
  .filter(({ ageMinutes }) => ageMinutes >= options.minAgeMinutes)
887
1156
  .sort((left, right) => right.ageMinutes - left.ageMinutes)
888
1157
  .slice(0, options.maxCandidates)
889
1158
  .flatMap(({ session, ageMinutes }) => {
890
- const work = session.workId
891
- ? getWorkContract({ controllerHome, repoId: repository.repoId }, session.workId)
892
- : undefined;
1159
+ const work = session.workId ? snapshot.workById.get(session.workId) : undefined;
893
1160
  const terminalWork = Boolean(work && isTerminalWorkContractStatus(work.status));
894
- if (work && !terminalWork && activeWorkAuthorityRefs(repository, controllerHome, work).length > 0) {
1161
+ if (work && !terminalWork && activeWorkAuthorityRefs(work, snapshot).length > 0) {
895
1162
  // The Edit Session inherits the live Work lifecycle authority. Reporting it
896
1163
  // as stale maintenance debt while that authority is active would duplicate
897
1164
  // ownership and can permanently block release readiness for valid long work.
@@ -952,7 +1219,10 @@ export function buildRuntimeMaintenanceStatus(
952
1219
  options: RuntimeMaintenanceOptions = {},
953
1220
  ): RuntimeMaintenanceStatus {
954
1221
  const normalized = normalizedOptions(options);
1222
+ // Runtime-storage binding is the compatibility cutover authority for legacy test/
1223
+ // migrated repositories. Read lifecycle owners only after that binding is resolved.
955
1224
  const storage = safeRuntimeStorage(repository, controllerHome);
1225
+ const authoritySnapshot = buildRuntimeMaintenanceAuthoritySnapshot(repository, controllerHome);
956
1226
  const runtimeStorageRepair = previewRuntimeStorageRepair(coerceRepository(repository), controllerHome, {
957
1227
  minAgeMinutes: normalized.minAgeMinutes,
958
1228
  maxCandidates: normalized.maxCandidates,
@@ -960,8 +1230,8 @@ export function buildRuntimeMaintenanceStatus(
960
1230
  const localJobCandidates = scanLocalJobCandidates(repository.canonicalRoot, normalized);
961
1231
  const storageCandidates = runtimeStorageCandidates(storage.report);
962
1232
  const tempCandidates = scanRuntimeTempCandidates(repository, normalized.maxCandidates);
963
- const staleWorkCandidates = scanStaleWorkContractCandidates(repository, controllerHome, normalized);
964
- const staleEditCandidates = scanStaleEditSessionCandidates(repository, controllerHome, normalized);
1233
+ const staleWorkCandidates = scanStaleWorkContractCandidates(repository, controllerHome, normalized, authoritySnapshot);
1234
+ const staleEditCandidates = scanStaleEditSessionCandidates(repository, normalized, authoritySnapshot);
965
1235
  const retainedWorktreeCandidates = scanRetainedWorktreeCandidates(repository, controllerHome, normalized.maxCandidates);
966
1236
  const candidates = [...localJobCandidates, ...storageCandidates, ...staleWorkCandidates, ...staleEditCandidates, ...retainedWorktreeCandidates, ...tempCandidates].slice(0, normalized.maxCandidates);
967
1237
  const summary = summarize(candidates);
@@ -1110,11 +1380,6 @@ export function previewAutomaticRuntimeMaintenance(
1110
1380
  };
1111
1381
  }
1112
1382
 
1113
- function quarantinePath(repoRoot: string, id: string): string {
1114
- const stamp = now().replace(/[:.]/g, '-');
1115
- return join(repoRoot, '.ai', 'harness', 'local-jobs-quarantine', `${stamp}-${safeId(id)}`);
1116
- }
1117
-
1118
1383
  function terminalizeLocalJob(candidate: RuntimeMaintenanceCandidate, status: 'orphaned' | 'cancelled' = 'orphaned'): string {
1119
1384
  if (!candidate.path) throw new Error('LOCAL_JOB_PATH_MISSING');
1120
1385
  const jobPath = join(candidate.path, 'job.json');
@@ -1132,14 +1397,11 @@ function terminalizeLocalJob(candidate: RuntimeMaintenanceCandidate, status: 'or
1132
1397
  return status;
1133
1398
  }
1134
1399
 
1135
- function quarantineLocalJob(repoRoot: string, candidate: RuntimeMaintenanceCandidate): string {
1400
+ function quarantineLocalJob(controllerHome: string, repoId: string, repoRoot: string, candidate: RuntimeMaintenanceCandidate): string {
1136
1401
  if (!candidate.path) throw new Error('LOCAL_JOB_PATH_MISSING');
1137
1402
  const root = localJobsRoot(repoRoot);
1138
1403
  if (!isWithin(root, candidate.path)) throw new Error('LOCAL_JOB_PATH_OUTSIDE_ROOT');
1139
- const destination = quarantinePath(repoRoot, candidate.id);
1140
- mkdirSync(dirname(destination), { recursive: true });
1141
- renameSync(candidate.path, destination);
1142
- return destination;
1404
+ return quarantineRuntimePath(controllerHome, repoId, candidate.path, candidate.id);
1143
1405
  }
1144
1406
 
1145
1407
  function rebuildActiveIndex(repoRoot: string): void {
@@ -1204,7 +1466,7 @@ export function applyRuntimeMaintenance(
1204
1466
  return { ...candidate, applied: true, result: terminalizeLocalJob(candidate, 'cancelled') };
1205
1467
  }
1206
1468
  if (candidate.kind === 'unreadable_local_job' || candidate.kind === 'missing_job_metadata') {
1207
- return { ...candidate, applied: true, result: quarantineLocalJob(repository.canonicalRoot, candidate) };
1469
+ return { ...candidate, applied: true, result: quarantineLocalJob(controllerHome, repository.repoId, repository.canonicalRoot, candidate) };
1208
1470
  }
1209
1471
  if (candidate.kind === 'stale_runtime_temp_entry') {
1210
1472
  if (!candidate.path) throw new Error('RUNTIME_TEMP_PATH_MISSING');
@@ -1242,6 +1504,24 @@ export function applyRuntimeMaintenance(
1242
1504
  const processGc = options.actionId === 'full_maintenance_pass'
1243
1505
  ? gcTerminalProcesses({ controllerHome, repoId: repository.repoId })
1244
1506
  : undefined;
1507
+ const currentWork = readWorkContractStore({ controllerHome, repoId: repository.repoId }).contracts;
1508
+ const protectedWorkIds = currentWork
1509
+ .filter((contract) => !isTerminalWorkContractStatus(contract.status))
1510
+ .map((contract) => contract.workId);
1511
+ const verificationSnapshotGc = options.actionId === 'full_maintenance_pass'
1512
+ ? cleanupStaleWorkVerificationSnapshots(controllerHome, repository.repoId, {
1513
+ protectedWorkIds,
1514
+ maxEntries: Math.max(100, (options.maxCandidates ?? 50) * 3),
1515
+ maxRemovals: Math.max(1, options.maxCandidates ?? 50),
1516
+ })
1517
+ : undefined;
1518
+ const quarantineGc = options.actionId === 'full_maintenance_pass'
1519
+ ? cleanupRuntimeQuarantine(controllerHome, repository.repoId, repository.canonicalRoot, {
1520
+ maxEntries: Math.max(100, (options.maxCandidates ?? 50) * 3),
1521
+ maxRemovals: Math.max(1, options.maxCandidates ?? 50),
1522
+ additionalRoots: [runtimeLegacyCheckQuarantineRoot(controllerHome, repository.repoId)],
1523
+ })
1524
+ : undefined;
1245
1525
 
1246
1526
  if (options.actionId === 'runtime_storage_finalize_relocation' || options.actionId === 'full_maintenance_pass' || applied.some((candidate) => candidate.applied) || runtimeStorageRepairApply) {
1247
1527
  rebuildActiveIndex(repository.canonicalRoot);
@@ -1259,6 +1539,8 @@ export function applyRuntimeMaintenance(
1259
1539
  applied,
1260
1540
  runtimeStorageRepairApply,
1261
1541
  processGc,
1542
+ verificationSnapshotGc,
1543
+ quarantineGc,
1262
1544
  projection,
1263
1545
  };
1264
1546
  }