@moretea-labs/forge 1.7.2 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (900) hide show
  1. package/AGENTS.md +121 -62
  2. package/CHANGELOG.md +40 -0
  3. package/CLAUDE.md +57 -62
  4. package/CONTRIBUTING.md +3 -2
  5. package/README.md +2 -2
  6. package/SKILL.md +0 -1
  7. package/THIRD_PARTY_NOTICES.md +5 -2
  8. package/adapters/browser/index.ts +2 -0
  9. package/adapters/chatgpt/browser-delivery-host.ts +77 -0
  10. package/adapters/chatgpt/browser-delivery-runtime.ts +1256 -0
  11. package/adapters/chatgpt/controller-binding-store.ts +134 -0
  12. package/adapters/chatgpt/controller-round-host.ts +68 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +99 -0
  14. package/adapters/chatgpt/provider-delivery.ts +340 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +218 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  18. package/adapters/computer/chatgpt-target-router.ts +103 -0
  19. package/adapters/computer/chrome-extension/background.js +385 -0
  20. package/adapters/computer/chrome-extension/content.js +378 -0
  21. package/adapters/computer/chrome-extension/core.js +24 -0
  22. package/adapters/computer/chrome-extension/manifest.json +30 -0
  23. package/adapters/computer/desktop-operator-contract.ts +7 -0
  24. package/adapters/computer/desktop-operator-discovery.ts +181 -0
  25. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  26. package/adapters/computer/desktop-operator-provider.ts +312 -0
  27. package/adapters/computer/index.ts +1 -0
  28. package/adapters/computer/interaction-target-authority.ts +1068 -0
  29. package/adapters/controller-process/binding-store.ts +34 -0
  30. package/adapters/controller-process/controller-host.ts +26 -0
  31. package/adapters/mcp/access-mode.ts +132 -0
  32. package/adapters/mcp/audit.ts +32 -0
  33. package/adapters/mcp/auth.ts +406 -0
  34. package/adapters/mcp/instructions.ts +37 -0
  35. package/adapters/mcp/legacy-context.ts +18 -0
  36. package/adapters/mcp/multi-repository.ts +421 -0
  37. package/adapters/mcp/oauth.ts +464 -0
  38. package/adapters/mcp/paths.ts +143 -0
  39. package/adapters/mcp/policy.ts +232 -0
  40. package/adapters/mcp/proxy-env.ts +62 -0
  41. package/adapters/mcp/readiness-projection.ts +24 -0
  42. package/adapters/mcp/redaction.ts +21 -0
  43. package/adapters/mcp/repo.ts +24 -0
  44. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  45. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  46. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  47. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  48. package/adapters/mcp/runtime-gateway/context-adapter.ts +1167 -0
  49. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  50. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +206 -0
  51. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  52. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +130 -0
  53. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  54. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  55. package/adapters/mcp/runtime-gateway/execution-tools.ts +173 -0
  56. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  57. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +412 -0
  58. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  59. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  60. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  61. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  62. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +380 -0
  63. package/adapters/mcp/runtime-gateway/process-tools.ts +457 -0
  64. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +88 -0
  65. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +285 -0
  66. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  67. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  68. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +79 -0
  69. package/adapters/mcp/runtime-gateway/result-adapter.ts +114 -0
  70. package/adapters/mcp/runtime-gateway/router.ts +242 -0
  71. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  72. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1200 -0
  73. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  74. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +574 -0
  75. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  76. package/adapters/mcp/runtime-gateway/runtime-tools.ts +78 -0
  77. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +187 -0
  78. package/adapters/mcp/runtime-gateway/shared-adapter.ts +45 -0
  79. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +962 -0
  80. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  81. package/adapters/mcp/runtime-gateway/work-adapter.ts +325 -0
  82. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  83. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  84. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  85. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  86. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  87. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  88. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  89. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  90. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  91. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  92. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  93. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  94. package/adapters/mcp/server.ts +1092 -0
  95. package/adapters/mcp/setup.ts +789 -0
  96. package/adapters/mcp/tool-capability-cache.ts +87 -0
  97. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  98. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5139 -0
  99. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +145 -0
  100. package/adapters/mcp/tool-mapping/repository-tools.ts +1682 -0
  101. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  102. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  103. package/adapters/mcp/toolset-names.ts +79 -0
  104. package/adapters/mcp/toolset-selection.ts +41 -0
  105. package/adapters/mcp/toolset.ts +337 -0
  106. package/adapters/mcp/transports/http-observation.ts +365 -0
  107. package/adapters/mcp/transports/http.ts +933 -0
  108. package/adapters/mcp/transports/oauth-http.ts +322 -0
  109. package/adapters/mcp/transports/session-registry.ts +519 -0
  110. package/adapters/mcp/transports/stdio.ts +8 -0
  111. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +223 -0
  112. package/adapters/mcp/types.ts +41 -0
  113. package/assets/AGENTS.md +2 -16
  114. package/assets/CLAUDE.md +2 -16
  115. package/assets/hooks/AGENTS.md +3 -14
  116. package/assets/hooks/CLAUDE.md +3 -14
  117. package/assets/hooks/hook-input.sh +9 -2
  118. package/assets/hooks/lib/workflow-state.sh +28 -10
  119. package/assets/hooks/prompt-guard.sh +63 -37
  120. package/assets/hooks/security-sentinel.sh +2 -1
  121. package/assets/hooks/session-start-context.sh +7 -5
  122. package/assets/hooks/stop-orchestrator.sh +13 -3
  123. package/assets/initializer-question-pack.v4.json +11 -7
  124. package/assets/partials/05-workflow.partial.md +18 -73
  125. package/assets/partials/07-footer.partial.md +1 -1
  126. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  127. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  128. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  129. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  130. package/assets/plan-map.json +11 -11
  131. package/assets/plugin-registry.v1.json +11 -3
  132. package/assets/plugin-trust-policy.v1.json +6 -0
  133. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  134. package/assets/recovery/forge-wsl-rescue +271 -0
  135. package/assets/reference-configs/agentic-development-flow.md +25 -0
  136. package/assets/reference-configs/development-protocol.md +11 -15
  137. package/assets/reference-configs/document-generation.md +1 -1
  138. package/assets/reference-configs/global-working-rules.md +28 -1
  139. package/assets/reference-configs/harness-overview.md +22 -112
  140. package/assets/reference-configs/hook-operations.md +1 -1
  141. package/assets/reference-configs/sprint-contracts.md +2 -2
  142. package/assets/skill-version.json +2 -2
  143. package/assets/templates/helpers/architecture-event.ts +3 -34
  144. package/assets/templates/helpers/architecture-queue.sh +61 -10
  145. package/assets/templates/helpers/archive-workflow.sh +90 -180
  146. package/assets/templates/helpers/capability-config.ts +8 -11
  147. package/assets/templates/helpers/capability-resolver.ts +37 -19
  148. package/assets/templates/helpers/capture-plan.sh +2 -2
  149. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  150. package/assets/templates/helpers/check-task-sync.sh +82 -11
  151. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  152. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  153. package/assets/templates/helpers/contract-worktree.sh +26 -24
  154. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  155. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  156. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  157. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  158. package/assets/templates/helpers/new-plan.sh +2 -2
  159. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  160. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  161. package/assets/templates/helpers/switch-plan.sh +1 -1
  162. package/assets/templates/helpers/workflow-contract.ts +1 -0
  163. package/assets/workflow-contract.v1.json +63 -171
  164. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  165. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  166. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  167. package/docs/architecture/CURRENT.md +233 -28
  168. package/docs/architecture/EVOLUTION.md +13 -0
  169. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  170. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  171. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  172. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  173. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  174. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  175. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +37 -0
  176. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +311 -0
  177. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  178. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  179. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  180. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  181. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  182. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  183. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  184. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  185. package/docs/architecture/domains/verification.md +8 -0
  186. package/docs/architecture/domains/workflow-engine.md +7 -1
  187. package/docs/architecture/index.md +3 -3
  188. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  189. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  190. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  191. package/docs/forge-plugin-management.md +20 -4
  192. package/docs/forge-runtime-self-healing-loop.md +2 -0
  193. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  194. package/docs/operations/controller-browser-plugin.md +3 -1
  195. package/docs/operations/controller-performance-and-502.md +17 -0
  196. package/docs/operations/controller-reliability-runbook.md +2 -2
  197. package/docs/operations/features.md +1 -1
  198. package/docs/operations/features.zh-CN.md +1 -1
  199. package/docs/operations/homebrew.md +2 -2
  200. package/docs/operations/mcp-tool-exposure.md +2 -0
  201. package/docs/operations/platform-support.md +16 -8
  202. package/docs/operations/platform-support.zh-CN.md +2 -2
  203. package/docs/operations/releasing.md +2 -0
  204. package/docs/operations/standalone-disaster-recovery.md +38 -5
  205. package/docs/operations/uu-remote-rescue.md +41 -0
  206. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  207. package/docs/public-usage-guide.md +1 -1
  208. package/docs/public-usage-guide.zh-CN.md +1 -1
  209. package/docs/tutorials/01-install-and-start.md +1 -1
  210. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  211. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  212. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  213. package/docs/wiki/Implementation.md +1 -1
  214. package/package.json +46 -26
  215. package/packages/kernel/cognition/api/index.ts +6 -0
  216. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  217. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  218. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  219. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  220. package/packages/kernel/cognition/domain/learning.ts +106 -0
  221. package/packages/kernel/cognition/domain/memory.ts +254 -0
  222. package/packages/kernel/controller/api/index.ts +3 -0
  223. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  224. package/packages/kernel/controller/application/controller-round-service.ts +41 -0
  225. package/packages/kernel/controller/application/controller-service.ts +30 -0
  226. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +529 -0
  227. package/packages/kernel/controller/domain/controller-round.ts +110 -0
  228. package/packages/kernel/controller/domain/execution-quality.ts +135 -0
  229. package/packages/kernel/controller/domain/types.ts +56 -0
  230. package/packages/kernel/controller/index.ts +1 -0
  231. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  232. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1970 -0
  233. package/packages/kernel/controller/infrastructure/controller-session-store.ts +804 -0
  234. package/packages/kernel/controller/ports/controller-host.ts +18 -0
  235. package/packages/kernel/goal/api/index.ts +1 -0
  236. package/packages/kernel/goal/domain/types.ts +40 -0
  237. package/packages/kernel/goal/index.ts +1 -0
  238. package/packages/kernel/identity/api/index.ts +15 -0
  239. package/packages/kernel/identity/application/identity-service.ts +67 -0
  240. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  241. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  242. package/packages/kernel/identity/domain/grant.ts +72 -0
  243. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  244. package/packages/kernel/identity/domain/scope.ts +63 -0
  245. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  246. package/packages/kernel/identity/domain/types.ts +44 -0
  247. package/packages/kernel/identity/domain/user-request.ts +93 -0
  248. package/packages/kernel/identity/domain/workspace.ts +56 -0
  249. package/packages/kernel/identity/index.ts +1 -0
  250. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  251. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  252. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  253. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  254. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  255. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  256. package/packages/kernel/memory/api/index.ts +5 -0
  257. package/packages/kernel/memory/application/experience-service.ts +118 -0
  258. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  259. package/packages/kernel/memory/domain/experience.ts +103 -0
  260. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  261. package/packages/kernel/memory/index.ts +1 -0
  262. package/packages/kernel/scheduler/api/index.ts +4 -0
  263. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  264. package/packages/kernel/scheduler/application/schedule-service.ts +27 -0
  265. package/packages/kernel/scheduler/application/settlement.ts +182 -0
  266. package/packages/kernel/scheduler/domain/schedule.ts +236 -0
  267. package/packages/kernel/scheduler/index.ts +1 -0
  268. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +805 -0
  269. package/packages/kernel/work/api/index.ts +16 -0
  270. package/packages/kernel/work/application/work-service.ts +123 -0
  271. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  272. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  273. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  274. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  275. package/packages/kernel/work/domain/engineering-design.ts +286 -0
  276. package/packages/kernel/work/domain/engineering-profile.ts +238 -0
  277. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  278. package/packages/kernel/work/domain/execution-concurrency.ts +247 -0
  279. package/packages/kernel/work/domain/execution-snapshot.ts +2 -0
  280. package/packages/kernel/work/domain/implementation-review.ts +193 -0
  281. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  282. package/packages/kernel/work/domain/project-engineering-contract.ts +224 -0
  283. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  284. package/{src/runtime/control-plane/facade/work-state-machine.ts → packages/kernel/work/domain/state-machine.ts} +37 -66
  285. package/packages/kernel/work/domain/types.ts +534 -0
  286. package/packages/kernel/work/index.ts +1 -0
  287. package/packages/kernel/work/infrastructure/work-contract-store.ts +1967 -0
  288. package/packages/kernel/work/ports/work-contract-store.ts +21 -0
  289. package/packages/plugin-runtime/browser/index.ts +3 -0
  290. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  291. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  292. package/packages/plugin-runtime/browser/session-authority.ts +62 -0
  293. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  294. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  295. package/packages/plugin-runtime/computer/index.ts +8 -0
  296. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  297. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  298. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  299. package/packages/plugin-runtime/computer/provider.ts +19 -0
  300. package/packages/plugin-runtime/computer/target-authority.ts +215 -0
  301. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  302. package/packages/plugin-runtime/external/index.ts +1 -0
  303. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +581 -0
  304. package/packages/plugin-runtime/index.ts +3 -0
  305. package/packages/protocols/browser/index.ts +1 -0
  306. package/packages/protocols/browser/session.ts +98 -0
  307. package/packages/protocols/computer/contract.ts +225 -0
  308. package/packages/protocols/computer/index.ts +1 -0
  309. package/packages/protocols/failure/contract.ts +158 -0
  310. package/packages/protocols/failure/index.ts +1 -0
  311. package/packages/protocols/handoff/index.ts +1 -0
  312. package/packages/protocols/handoff/status.ts +22 -0
  313. package/packages/protocols/mcp/execution-context.ts +11 -0
  314. package/packages/protocols/mcp/index.ts +2 -0
  315. package/packages/protocols/mcp/tool-contract.ts +42 -0
  316. package/packages/workflow-runtime/api/index.ts +2 -0
  317. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  318. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  319. package/packages/workflow-runtime/index.ts +1 -0
  320. package/scripts/activate-source-baseline.ts +7 -9
  321. package/scripts/assemble-template.ts +1 -1
  322. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  323. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  324. package/scripts/canary-controller-semantic-wait.ts +183 -0
  325. package/scripts/canary-global-hook.sh +2 -2
  326. package/scripts/check-mcp-compatibility.ts +85 -7
  327. package/scripts/check-platform-support.mjs +28 -2
  328. package/scripts/check-public-docs.sh +1 -1
  329. package/scripts/check-repository-hygiene.mjs +92 -0
  330. package/scripts/check-runtime-architecture.mjs +1643 -127
  331. package/scripts/check-source-duplication.mjs +9 -1
  332. package/scripts/controller-ngrok-rotation.sh +5 -4
  333. package/scripts/create-project-dirs.sh +10 -74
  334. package/scripts/forge-local-recovery-helper.mjs +282 -0
  335. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  336. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  337. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  338. package/scripts/hook-shim.sh +2 -2
  339. package/scripts/init-project.sh +12 -70
  340. package/scripts/install-desktop-operator-registration.ts +4 -2
  341. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  342. package/scripts/install-standalone-recovery.ts +122 -10
  343. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  344. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  345. package/scripts/lib/controller-home-env.sh +6 -3
  346. package/scripts/lib/project-init-lib.sh +42 -582
  347. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  348. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  349. package/scripts/open-source-audit-allowlist.txt +11 -1
  350. package/scripts/portability-bindings.mjs +70 -0
  351. package/scripts/run-bounded-command.mjs +60 -0
  352. package/scripts/run-bun-test-file.ts +22 -6
  353. package/scripts/run-governed-gate.ts +4 -2
  354. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  355. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  356. package/scripts/smoke-mcp-http-runtime.ts +6 -1
  357. package/scripts/smoke-runtime-recovery.ts +13 -11
  358. package/scripts/smoke-schedule-engine.ts +24 -16
  359. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  360. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  361. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  362. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  363. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  364. package/scripts/smoke-workflow-supervisor.ts +103 -0
  365. package/scripts/test-governance.ts +51 -2
  366. package/scripts/verify-forge-runtime.sh +2 -1
  367. package/src/cli/agent-jobs/executor-health.ts +11 -34
  368. package/src/cli/agent-jobs/integration.ts +18 -49
  369. package/src/cli/agent-jobs/job-manager.ts +17 -4
  370. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  371. package/src/cli/chatgpt-browser/binding.ts +20 -10
  372. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  373. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  374. package/src/cli/chatgpt-browser/engine.ts +10 -11
  375. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  376. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  377. package/src/cli/chatgpt-browser/types.ts +1 -0
  378. package/src/cli/commands/bootstrap-control.ts +334 -0
  379. package/src/cli/commands/brain-assistant.ts +52 -0
  380. package/src/cli/commands/brain.ts +191 -40
  381. package/src/cli/commands/chatgpt.ts +32 -67
  382. package/src/cli/commands/computer.ts +437 -0
  383. package/src/cli/commands/doctor.ts +18 -1
  384. package/src/cli/commands/init-hook.ts +71 -61
  385. package/src/cli/commands/init.ts +3 -1
  386. package/src/cli/commands/mcp.ts +16 -10
  387. package/src/cli/commands/plugin.ts +38 -12
  388. package/src/cli/commands/recovery.ts +507 -80
  389. package/src/cli/commands/runtime.ts +12 -7
  390. package/src/cli/commands/setup-profile.ts +97 -39
  391. package/src/cli/commands/status.ts +2 -1
  392. package/src/cli/controller/check-runner.ts +500 -100
  393. package/src/cli/controller/completion-backlog.ts +3 -3
  394. package/src/cli/controller/completion-orchestrator.ts +4 -43
  395. package/src/cli/controller/completion-target.ts +3 -72
  396. package/src/cli/controller/context/source-materializer.ts +81 -100
  397. package/src/cli/controller/context/types.ts +7 -1
  398. package/src/cli/controller/context-pack.ts +28 -6
  399. package/src/cli/controller/execution-completion.ts +4 -7
  400. package/src/cli/controller/execution-policy.ts +36 -153
  401. package/src/cli/controller/governance.ts +2 -3
  402. package/src/cli/controller/issue-store.ts +4 -99
  403. package/src/cli/controller/launch-agents.ts +59 -18
  404. package/src/cli/controller/operational-plan.ts +24 -51
  405. package/src/cli/controller/runtime-config.ts +5 -1
  406. package/src/cli/controller/stuck-state-migration.ts +2 -3
  407. package/src/cli/controller/systemd-user.ts +148 -0
  408. package/src/cli/controller/types.ts +10 -70
  409. package/src/cli/controller/worklog.ts +67 -13
  410. package/src/cli/editing/edit-operation-contract.ts +92 -0
  411. package/src/cli/editing/edit-session.ts +290 -20
  412. package/src/cli/github/plugin.ts +17 -12
  413. package/src/cli/hook/route-registry.ts +3 -5
  414. package/src/cli/hook/runtime.ts +49 -3
  415. package/src/cli/index.ts +3 -0
  416. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  417. package/src/cli/local-bridge/console-automations.ts +20 -15
  418. package/src/cli/local-bridge/console-view-models.ts +3 -12
  419. package/src/cli/local-bridge/facade-api.ts +105 -205
  420. package/src/cli/local-bridge/job-store.ts +1 -1
  421. package/src/cli/local-bridge/server.ts +48 -174
  422. package/src/cli/local-bridge/types.ts +0 -1
  423. package/src/cli/mcp/access-mode.ts +2 -132
  424. package/src/cli/mcp/access-tools.ts +2 -387
  425. package/src/cli/mcp/audit.ts +2 -32
  426. package/src/cli/mcp/auth.ts +2 -404
  427. package/src/cli/mcp/instructions.ts +2 -34
  428. package/src/cli/mcp/legacy-context.ts +2 -16
  429. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  430. package/src/cli/mcp/multi-repository.ts +2 -436
  431. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  432. package/src/cli/mcp/oauth.ts +2 -375
  433. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  434. package/src/cli/mcp/paths.ts +2 -140
  435. package/src/cli/mcp/policy.ts +2 -232
  436. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  437. package/src/cli/mcp/proxy-env.ts +2 -62
  438. package/src/cli/mcp/readiness-projection.ts +2 -24
  439. package/src/cli/mcp/redaction.ts +2 -21
  440. package/src/cli/mcp/repo.ts +2 -24
  441. package/src/cli/mcp/repository-tools.ts +2 -1613
  442. package/src/cli/mcp/server.ts +2 -951
  443. package/src/cli/mcp/setup.ts +2 -737
  444. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  445. package/src/cli/mcp/tool-contract.ts +2 -14
  446. package/src/cli/mcp/tools.ts +2 -9
  447. package/src/cli/mcp/toolset-names.ts +2 -70
  448. package/src/cli/mcp/toolset-selection.ts +2 -41
  449. package/src/cli/mcp/toolset.ts +2 -336
  450. package/src/cli/mcp/transports/AGENTS.md +1 -10
  451. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  452. package/src/cli/mcp/transports/http.ts +2 -1414
  453. package/src/cli/mcp/transports/session-registry.ts +2 -490
  454. package/src/cli/mcp/transports/stdio.ts +2 -8
  455. package/src/cli/mcp/types.ts +2 -41
  456. package/src/cli/mcp/umbrella-tools.ts +2 -117
  457. package/src/cli/repositories/command-executor.ts +91 -39
  458. package/src/cli/repositories/command-scope.ts +139 -4
  459. package/src/cli/repositories/controller-home.ts +167 -1
  460. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  461. package/src/cli/repositories/git-command-executor.ts +2 -2
  462. package/src/cli/repositories/identity.ts +13 -0
  463. package/src/cli/repositories/registry.ts +145 -60
  464. package/src/cli/repositories/repository-snapshot.ts +53 -7
  465. package/src/cli/repositories/runtime-storage.ts +27 -2
  466. package/src/cli/repositories/safe-patch.ts +34 -38
  467. package/src/cli/repositories/selected-path-actions.ts +22 -2
  468. package/src/cli/repositories/structured-git.ts +167 -27
  469. package/src/cli/repository/session-cache.ts +92 -6
  470. package/src/cli/runtime/helper-runner.ts +7 -0
  471. package/src/cli/runtime-invocation.ts +8 -1
  472. package/src/cli/tools/codegraph.ts +44 -25
  473. package/src/core/adoption/manifest-templates.ts +1 -1
  474. package/src/core/adoption/plan.ts +3 -26
  475. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  476. package/src/effects/process-runner.ts +8 -14
  477. package/src/runtime/context/assistant-context.ts +167 -0
  478. package/src/runtime/context/assistant-work-context.ts +209 -0
  479. package/src/runtime/context/automatic-learning.ts +565 -0
  480. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  481. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  482. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  483. package/src/runtime/context/cognitive-attention.ts +173 -0
  484. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  485. package/src/runtime/context/context-closure.ts +305 -0
  486. package/src/runtime/context/context-pack-process.ts +103 -0
  487. package/src/runtime/context/context-plane.ts +203 -0
  488. package/src/runtime/context/direct-controller-learning.ts +298 -0
  489. package/src/runtime/context/project-engineering-contract.ts +60 -0
  490. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  491. package/src/runtime/context/semantic-navigation.ts +6 -34
  492. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  493. package/src/runtime/context/typescript-navigation.ts +89 -3
  494. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  495. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  496. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  497. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  498. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  499. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  500. package/src/runtime/control-plane/cleanup-artifact-retention.ts +531 -0
  501. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  502. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +282 -0
  503. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +380 -0
  504. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +113 -16
  505. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  506. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  507. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  508. package/src/runtime/control-plane/execution/retained-work-resume.ts +439 -102
  509. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  510. package/src/runtime/control-plane/execution/validation.ts +34 -11
  511. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +87 -0
  512. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  513. package/src/runtime/control-plane/execution/work-completion-authority.ts +31 -44
  514. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  515. package/src/runtime/control-plane/execution/work-evidence-policy.ts +46 -53
  516. package/src/runtime/control-plane/execution/work-execution-support.ts +85 -164
  517. package/src/runtime/control-plane/execution/work-handle-authority.ts +349 -73
  518. package/src/runtime/control-plane/execution/work-handle-store.ts +55 -2
  519. package/src/runtime/control-plane/execution/work-head-settlement.ts +108 -0
  520. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +173 -28
  521. package/src/runtime/control-plane/execution/work-operation-service.ts +92 -40
  522. package/src/runtime/control-plane/execution/work-preparation-service.ts +145 -269
  523. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  524. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  525. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +543 -225
  526. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +59 -45
  527. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  528. package/src/runtime/control-plane/execution/work-verification-service.ts +662 -52
  529. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +205 -16
  530. package/src/runtime/control-plane/facade/capability-registry.ts +380 -44
  531. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  532. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  533. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  534. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  535. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -22
  536. package/src/runtime/control-plane/facade/goal-workloop.ts +565 -1202
  537. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +145 -0
  538. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +266 -52
  539. package/src/runtime/control-plane/facade/index.ts +4 -3
  540. package/src/runtime/control-plane/facade/operation-digest.ts +34 -73
  541. package/src/runtime/control-plane/facade/plan-contract-store.ts +671 -245
  542. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  543. package/src/runtime/control-plane/facade/repository-work-admission.ts +31 -23
  544. package/src/runtime/control-plane/facade/requirement-authority.ts +121 -0
  545. package/src/runtime/control-plane/facade/requirement-board.ts +9 -4
  546. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +85 -0
  547. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  548. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  549. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -15
  550. package/src/runtime/control-plane/facade/types.ts +218 -620
  551. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  552. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  553. package/src/runtime/control-plane/generated-cache-retention.ts +336 -19
  554. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  555. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +13 -2
  556. package/src/runtime/control-plane/global-scheduler/maintenance.ts +274 -84
  557. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  558. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  559. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -2
  560. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  561. package/src/runtime/control-plane/global-scheduler/scheduler.ts +227 -109
  562. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  563. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  564. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  565. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  566. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +160 -0
  567. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  568. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +139 -670
  569. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  570. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +25 -6
  571. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -194
  572. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  573. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  574. package/src/runtime/control-plane/persistence/experience-store.ts +302 -0
  575. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  576. package/src/runtime/control-plane/persistence/requirement-store.ts +230 -80
  577. package/src/runtime/control-plane/persistence/sqlite-store.ts +654 -78
  578. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  579. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  580. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  581. package/src/runtime/control-plane/release-retention.ts +154 -26
  582. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  583. package/src/runtime/control-plane/runtime-cleanup.ts +844 -38
  584. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  585. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  586. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +479 -0
  587. package/src/runtime/control-plane/workspace/workspace-store.ts +249 -0
  588. package/src/runtime/diagnostics/incident-repair.ts +573 -0
  589. package/src/runtime/diagnostics/mcp-timing.ts +239 -6
  590. package/src/runtime/diagnostics/performance.ts +6 -14
  591. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  592. package/src/runtime/evidence/artifact-store.ts +216 -35
  593. package/src/runtime/evidence/evidence-store.ts +112 -8
  594. package/src/runtime/evidence/operational-shadow.ts +38 -0
  595. package/src/runtime/evidence/output-handle-index.ts +225 -0
  596. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  597. package/src/runtime/evidence/result-store.ts +158 -44
  598. package/src/runtime/evidence/sensitive-output.ts +4 -4
  599. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  600. package/src/runtime/execution/jobs/store.ts +124 -6
  601. package/src/runtime/execution/managed-workspace.ts +112 -5
  602. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  603. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  604. package/src/runtime/execution/process-runtime/check-facade.ts +24 -10
  605. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  606. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  607. package/src/runtime/execution/process-runtime/check-result.ts +177 -2
  608. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +58 -9
  609. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  610. package/src/runtime/execution/process-runtime/command-facade.ts +117 -114
  611. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  612. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  613. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  614. package/src/runtime/execution/process-runtime/index.ts +4 -0
  615. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  616. package/src/runtime/execution/process-runtime/lightweight-managed.ts +283 -73
  617. package/src/runtime/execution/process-runtime/persisted-check.ts +130 -23
  618. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  619. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  620. package/src/runtime/execution/process-runtime/resource-claims.ts +125 -64
  621. package/src/runtime/execution/process-runtime/runtime.ts +167 -17
  622. package/src/runtime/execution/process-runtime/store.ts +30 -2
  623. package/src/runtime/execution/process-runtime/types.ts +27 -0
  624. package/src/runtime/execution/workers/executor.ts +18 -19
  625. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  626. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  627. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  628. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  629. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  630. package/src/runtime/gateway/mcp/router.ts +2 -1125
  631. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  632. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  633. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  634. package/src/runtime/maintenance/cleanup.ts +38 -24
  635. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  636. package/src/runtime/platform/computer-platform.ts +14 -0
  637. package/src/runtime/platform/executable-discovery.ts +54 -0
  638. package/src/runtime/platform/fetch-http-server.ts +90 -0
  639. package/src/runtime/platform/service-inventory.ts +130 -0
  640. package/src/runtime/platform/service-manager.ts +146 -0
  641. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  642. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  643. package/src/runtime/plugins/action-application.ts +192 -0
  644. package/src/runtime/plugins/app-store-connect-adapter.ts +47 -35
  645. package/src/runtime/plugins/browser-adapter.ts +898 -135
  646. package/src/runtime/plugins/browser-automation-service.ts +33 -34
  647. package/src/runtime/plugins/browser-macos-bridge.ts +386 -46
  648. package/src/runtime/plugins/browser-manifest-surface.ts +75 -17
  649. package/src/runtime/plugins/browser-native-session-service.ts +64 -14
  650. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  651. package/src/runtime/plugins/browser-registration.ts +32 -0
  652. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  653. package/src/runtime/plugins/browser-runtime.ts +55 -10
  654. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  655. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  656. package/src/runtime/plugins/browser-session-store.ts +243 -80
  657. package/src/runtime/plugins/browser-session-types.ts +2 -98
  658. package/src/runtime/plugins/capability-authorization-grants.ts +272 -59
  659. package/src/runtime/plugins/catalog-trust.ts +82 -0
  660. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  661. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  662. package/src/runtime/plugins/computer-registration.ts +1050 -0
  663. package/src/runtime/plugins/config-store.ts +119 -0
  664. package/src/runtime/plugins/desktop-operator-external-policy.ts +964 -0
  665. package/src/runtime/plugins/desktop-operator-registration.ts +123 -12
  666. package/src/runtime/plugins/errors.ts +8 -1
  667. package/src/runtime/plugins/external-adapter.ts +82 -323
  668. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  669. package/src/runtime/plugins/external-registration.ts +30 -2
  670. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  671. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  672. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  673. package/src/runtime/plugins/first-party-registry.ts +3 -1
  674. package/src/runtime/plugins/github-adapter.ts +1 -2
  675. package/src/runtime/plugins/gmail-adapter.ts +29 -8
  676. package/src/runtime/plugins/google-calendar-adapter.ts +8 -8
  677. package/src/runtime/plugins/google-shared.ts +45 -53
  678. package/src/runtime/plugins/google-tasks-adapter.ts +8 -8
  679. package/src/runtime/plugins/ios-adapter.ts +2 -3
  680. package/src/runtime/plugins/lightweight-action.ts +208 -2
  681. package/src/runtime/plugins/local-system-adapter.ts +192 -2
  682. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  683. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  684. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  685. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  686. package/src/runtime/plugins/resend-adapter.ts +15 -24
  687. package/src/runtime/plugins/store.ts +1003 -387
  688. package/src/runtime/plugins/types.ts +28 -1
  689. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  690. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  691. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  692. package/src/runtime/plugins/xiaohongshu-publish.ts +102 -430
  693. package/src/runtime/projections/controller-context.ts +12 -6
  694. package/src/runtime/projections/git-status-sampler.ts +73 -22
  695. package/src/runtime/projections/invalidation.ts +7 -3
  696. package/src/runtime/projections/materialized-view.ts +93 -43
  697. package/src/runtime/recovery/actions.ts +3 -3
  698. package/src/runtime/recovery/capability-action-application.ts +229 -0
  699. package/src/runtime/recovery/index.ts +3 -0
  700. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  701. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  702. package/src/runtime/recovery/maintenance-executor.ts +701 -168
  703. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  704. package/src/runtime/recovery/store.ts +29 -11
  705. package/src/runtime/release/identity.ts +6 -0
  706. package/src/runtime/release/release-coordinator.ts +296 -0
  707. package/src/runtime/release/release-session.ts +716 -0
  708. package/src/runtime/release/release-state-migration.ts +25 -0
  709. package/src/runtime/resources/leases/store.ts +56 -25
  710. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  711. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  712. package/src/runtime/root/browser-session-composition.ts +59 -0
  713. package/src/runtime/root/computer-composition.ts +376 -0
  714. package/src/runtime/root/computer-target-composition.ts +16 -0
  715. package/src/runtime/root/computer-target-persistence.ts +39 -0
  716. package/src/runtime/root/controller-progression-composition.ts +192 -0
  717. package/src/runtime/root/controller-round-composition.ts +126 -0
  718. package/src/runtime/root/controller-services.ts +2 -0
  719. package/src/runtime/root/deployment-topology.ts +106 -0
  720. package/src/runtime/root/entry.ts +8 -6
  721. package/src/runtime/root/gateway-adapter.ts +3 -3
  722. package/src/runtime/root/known-good-recovery.ts +184 -0
  723. package/src/runtime/root/local-bridge.ts +5 -3
  724. package/src/runtime/root/mcp-transport.ts +116 -23
  725. package/src/runtime/root/ownership.ts +261 -9
  726. package/src/runtime/root/package-connector-service.ts +212 -74
  727. package/src/runtime/root/package-runtime-release.ts +199 -33
  728. package/src/runtime/root/package-runtime-service.ts +77 -108
  729. package/src/runtime/root/release-execution-canary.ts +103 -0
  730. package/src/runtime/root/release-loader.ts +150 -0
  731. package/src/runtime/root/release-manifest.ts +185 -7
  732. package/src/runtime/root/release-materialize.ts +474 -31
  733. package/src/runtime/root/release-store.ts +425 -37
  734. package/src/runtime/root/runtime-lane.ts +191 -0
  735. package/src/runtime/root/runtime.ts +379 -32
  736. package/src/runtime/root/scheduled-controller-composition.ts +76 -0
  737. package/src/runtime/root/scheduler.ts +12 -4
  738. package/src/runtime/root/service-runner.ts +3 -3
  739. package/src/runtime/root/service.ts +73 -45
  740. package/src/runtime/root/status.ts +49 -0
  741. package/src/runtime/root/types.ts +55 -3
  742. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  743. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  744. package/src/runtime/root/write-fence.ts +50 -2
  745. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  746. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  747. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  748. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  749. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  750. package/src/runtime/shared/process-environment.ts +36 -10
  751. package/src/runtime/shared/response-budget.ts +1 -3
  752. package/src/runtime/shared/storage-capacity.ts +68 -0
  753. package/src/runtime/standalone-recovery/controller-home-migration.ts +1108 -0
  754. package/src/runtime/standalone-recovery/core.ts +4609 -495
  755. package/src/runtime/standalone-recovery/entry.ts +642 -81
  756. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  757. package/src/runtime/standalone-recovery/installer.ts +399 -177
  758. package/src/runtime/standalone-recovery/mcp-server.ts +79 -0
  759. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  760. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  761. package/src/runtime/standalone-recovery/performance.ts +173 -0
  762. package/src/runtime/standalone-recovery/release.ts +58 -5
  763. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  764. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  765. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  766. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  767. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -4
  768. package/src/runtime/workflow/schedules/engine.ts +298 -484
  769. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  770. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  771. package/src/runtime/workflow/schedules/store.ts +2 -607
  772. package/src/runtime/workflow/schedules/types.ts +2 -127
  773. package/src/runtime/workflow/schedules/work-continuation.ts +220 -16
  774. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  775. package/src/runtime/workflows/runtime.ts +482 -0
  776. package/src/testing/test-governance.ts +95 -30
  777. package/supervisor/chatgpt-conversation.ts +23 -0
  778. package/supervisor/client.ts +201 -0
  779. package/supervisor/control-plane.ts +868 -0
  780. package/supervisor/entry.ts +15 -0
  781. package/supervisor/forge-validators.ts +80 -0
  782. package/supervisor/index.ts +5 -0
  783. package/supervisor/native-browser-adapter.ts +786 -0
  784. package/supervisor/native-messaging/host.ts +39 -0
  785. package/supervisor/native-messaging/manifest.ts +26 -0
  786. package/supervisor/native-messaging/protocol.ts +27 -0
  787. package/supervisor/paths.ts +18 -0
  788. package/supervisor/protocol.ts +202 -0
  789. package/supervisor/server.ts +404 -0
  790. package/supervisor/store.ts +1451 -0
  791. package/supervisor/tsconfig.json +8 -0
  792. package/supervisor/types.ts +255 -0
  793. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  794. package/docs/architecture/history/README.md +0 -7
  795. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  796. package/docs/architecture/history/global-hook-runtime.md +0 -166
  797. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  798. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  799. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  800. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  801. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  802. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  803. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  804. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  805. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  806. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  807. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  808. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  809. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  810. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  811. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  812. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  813. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  814. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  815. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  816. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  817. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  818. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  819. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  820. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  821. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  822. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  823. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  824. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  825. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  826. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  827. package/docs/architecture/requests/archive/2026/root.md +0 -68
  828. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  829. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  830. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  831. package/scripts/archive-architecture-request.sh +0 -4
  832. package/scripts/benchmark-background-check-overlap.ts +0 -228
  833. package/scripts/benchmark-controller-hotpath.ts +0 -212
  834. package/scripts/benchmark-controller-round2.ts +0 -139
  835. package/scripts/benchmark-ios-agent-device.ts +0 -514
  836. package/scripts/benchmark-mcp-host.sh +0 -117
  837. package/scripts/benchmark-mcp-transport.ts +0 -170
  838. package/scripts/benchmark-quality-harness.ts +0 -146
  839. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  840. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  841. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  842. package/scripts/benchmark-thin-harness.ts +0 -251
  843. package/scripts/benchmark-typescript-navigation.ts +0 -186
  844. package/scripts/benchmark-work-efficiency.ts +0 -334
  845. package/scripts/build-controller-ui.ts +0 -28
  846. package/scripts/check-npm-release.sh +0 -32
  847. package/scripts/check-public-release-surface.sh +0 -19
  848. package/scripts/check-release-published.sh +0 -57
  849. package/scripts/check-release-readiness.sh +0 -37
  850. package/scripts/check-release-version.mjs +0 -74
  851. package/scripts/check-tarball-install-smoke.sh +0 -67
  852. package/scripts/package-source-archive.sh +0 -147
  853. package/scripts/public-release-files.txt +0 -39
  854. package/scripts/public-release.ts +0 -174
  855. package/scripts/publish-release-tarball.sh +0 -27
  856. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  857. package/scripts/run-skill-evals.ts +0 -1022
  858. package/scripts/stage-runtime-release.ts +0 -39
  859. package/src/cli/controller/progress.ts +0 -656
  860. package/src/cli/controller/work-mode.ts +0 -181
  861. package/src/cli/local-bridge/console-assets.ts +0 -17
  862. package/src/cli/local-bridge/dashboard.ts +0 -17
  863. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  864. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  865. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  866. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  867. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  868. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  869. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  870. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  871. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  872. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  873. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  874. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  875. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  876. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  877. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  878. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  879. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  880. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  881. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  882. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  883. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  884. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  885. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  886. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  887. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  888. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  889. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  890. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  891. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -385
  892. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -1913
  893. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  894. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -449
  895. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -1118
  896. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -93
  897. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  898. package/src/runtime/control-plane/routing/index.ts +0 -1
  899. package/src/runtime/control-plane/routing/route-policy.ts +0 -382
  900. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomBytes } from 'crypto';
2
- import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'fs';
2
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'fs';
3
3
  import { dirname, join, relative } from 'path';
4
4
  import { atomicWriteFile } from '../../effects/fs-transaction';
5
5
  import { runProcess } from '../../effects/process-runner';
@@ -13,6 +13,8 @@ import { globMatches, resolveMcpPath } from '../mcp/paths';
13
13
  import type { McpPolicy } from '../mcp/types';
14
14
  import type { ProcessCheckCompletionReceipt, ProcessCheckReceiptStatus } from '../../runtime/execution/process-runtime/check-receipt';
15
15
  import { invalidateRepositoryReadCaches } from '../repository/inspector';
16
+ import type { EditOperation } from './edit-operation-contract';
17
+ export type { EditOperation } from './edit-operation-contract';
16
18
 
17
19
  export type EditSessionStatus =
18
20
  | 'open'
@@ -84,7 +86,6 @@ export interface EditSessionBinding {
84
86
  checkoutId?: string;
85
87
  principalId?: string;
86
88
  controllerInstanceId?: string;
87
- routeDecisionFingerprint?: string;
88
89
  }
89
90
 
90
91
  export interface EditSession {
@@ -97,7 +98,6 @@ export interface EditSession {
97
98
  checkoutId?: string;
98
99
  principalId?: string;
99
100
  controllerInstanceId?: string;
100
- routeDecisionFingerprint?: string;
101
101
  workspaceFingerprint?: string;
102
102
  assurance?: EditSessionAssurance;
103
103
  purpose: string;
@@ -129,6 +129,8 @@ export interface EditSession {
129
129
  export interface EditSessionSummary {
130
130
  sessionId: string;
131
131
  purpose: string;
132
+ /** Derived ownership identity for cheap lifecycle inventory; never a second Work authority. */
133
+ workId?: string;
132
134
  status: EditSessionStatus;
133
135
  issueId?: string;
134
136
  taskId?: string;
@@ -197,17 +199,39 @@ export class EditSessionPatchError extends Error {
197
199
  }
198
200
  }
199
201
 
200
- export type EditOperation =
201
- | { type: 'create'; path: string; content: string }
202
- | { type: 'write'; path: string; expectedSha256: string; content: string }
203
- | { type: 'replace'; path: string; expectedSha256: string; replacements: Array<{ oldText: string; newText: string; replaceAll?: boolean }> }
204
- | { type: 'insert_before' | 'insert_after'; path: string; expectedSha256: string; anchor: string; content: string; occurrence?: number }
205
- | { type: 'prepend' | 'append'; path: string; expectedSha256: string; content: string }
206
- | { type: 'delete'; path: string; expectedSha256: string };
207
-
208
202
  const SESSION_ROOT = '.ai/harness/edit-sessions';
203
+ const SESSION_OWNER_MARKER = '.forge-owner.json';
204
+
205
+ function hasDurableEditSessionStorageBinding(repoRoot: string, repoId: string): boolean {
206
+ const root = join(repoRoot, SESSION_ROOT);
207
+ try {
208
+ if (!lstatSync(root).isSymbolicLink()) return false;
209
+ const marker = JSON.parse(readFileSync(join(root, SESSION_OWNER_MARKER), 'utf-8')) as {
210
+ schemaVersion?: unknown;
211
+ repoId?: unknown;
212
+ binding?: unknown;
213
+ managedBy?: unknown;
214
+ };
215
+ return marker.schemaVersion === 1
216
+ && marker.repoId === repoId
217
+ && marker.binding === 'edit-sessions'
218
+ && marker.managedBy === 'forge';
219
+ } catch (_error) {
220
+ return false;
221
+ }
222
+ }
223
+
224
+ function assertDurableEditSessionStorageBound(repoRoot: string, repoId: string | undefined): void {
225
+ const normalizedRepoId = repoId?.trim();
226
+ if (!normalizedRepoId) return;
227
+ if (hasDurableEditSessionStorageBinding(repoRoot, normalizedRepoId)) return;
228
+ throw new Error(`EDIT_SESSION_STORAGE_NOT_BOUND: ${normalizedRepoId} requires Controller Home edit-sessions binding`);
229
+ }
230
+
209
231
  export const MAX_EDIT_PATCH_BATCH_OPERATIONS = 500;
210
232
  export const PREFERRED_EDIT_PATCH_BATCH_OPERATIONS = 100;
233
+ export const EDIT_SESSION_TERMINAL_RETENTION_MS = 7 * 24 * 60 * 60_000;
234
+ export const EDIT_SESSION_TERMINAL_MAX_RETAINED = 200;
211
235
 
212
236
  function hash(content: string): string {
213
237
  return createHash('sha256').update(content).digest('hex');
@@ -267,8 +291,7 @@ export function assertEditSessionDurableBinding(
267
291
  session.workId
268
292
  || session.repoId
269
293
  || session.checkoutId
270
- || session.principalId
271
- || session.routeDecisionFingerprint,
294
+ || session.principalId,
272
295
  );
273
296
  if (options.requireBoundIdentity === true && hasDurableIdentity && !binding) {
274
297
  throw new Error('EDIT_SESSION_IDENTITY_MISMATCH: binding');
@@ -279,7 +302,6 @@ export function assertEditSessionDurableBinding(
279
302
  ['repoId', session.repoId, binding.repoId],
280
303
  ['checkoutId', session.checkoutId, binding.checkoutId],
281
304
  ['principalId', session.principalId, binding.principalId],
282
- ['routeDecisionFingerprint', session.routeDecisionFingerprint, binding.routeDecisionFingerprint],
283
305
  ];
284
306
  for (const [field, expected, observed] of pairs) {
285
307
  if (expected && expected !== observed) throw new Error(`EDIT_SESSION_IDENTITY_MISMATCH: ${String(field)}`);
@@ -334,6 +356,7 @@ function revisionPatchPath(repoRoot: string, sessionId: string, revision: number
334
356
  }
335
357
 
336
358
  function writeSession(repoRoot: string, session: EditSession): void {
359
+ assertDurableEditSessionStorageBound(repoRoot, session.repoId);
337
360
  const path = sessionPath(repoRoot, session.sessionId);
338
361
  mkdirSync(dirname(path), { recursive: true });
339
362
  writeFileSync(path, `${JSON.stringify(session, null, 2)}\n`, 'utf-8');
@@ -377,7 +400,6 @@ function normalizeStoredSession(value: Partial<EditSession> & { sessionId: strin
377
400
  checkoutId: value.checkoutId,
378
401
  principalId: value.principalId,
379
402
  controllerInstanceId: value.controllerInstanceId,
380
- routeDecisionFingerprint: value.routeDecisionFingerprint,
381
403
  workspaceFingerprint: value.workspaceFingerprint,
382
404
  assurance: value.assurance,
383
405
  purpose: value.purpose ?? 'Direct edit',
@@ -617,6 +639,112 @@ function assertCurrentHashes(repoRoot: string, session: EditSession): void {
617
639
  if (path) throw new Error(`edited file changed outside the session after revision ${latestOperations(session).get(path)?.revision ?? session.currentRevision}: ${path}`);
618
640
  }
619
641
 
642
+ function committedChangedPathsBetween(repoRoot: string, baseRevision: string, targetRevision: string): string[] {
643
+ const ancestor = runProcess('git', ['merge-base', '--is-ancestor', baseRevision, targetRevision], {
644
+ cwd: repoRoot,
645
+ timeoutMs: 10_000,
646
+ maxOutputBytes: 64 * 1024,
647
+ });
648
+ if (!ancestor.ok) throw new Error('EDIT_SESSION_SUCCESSOR_HEAD_NOT_DESCENDANT');
649
+ const diff = runProcess('git', ['diff', '--name-status', '-z', '--find-renames', baseRevision, targetRevision, '--'], {
650
+ cwd: repoRoot,
651
+ timeoutMs: 10_000,
652
+ maxOutputBytes: 4 * 1024 * 1024,
653
+ });
654
+ if (!diff.ok) throw new Error(`EDIT_SESSION_SUCCESSOR_HEAD_DIFF_FAILED: ${diff.error || diff.stderr}`);
655
+ const tokens = diff.stdout.split('\0').filter(Boolean);
656
+ const paths = new Set<string>();
657
+ for (let index = 0; index < tokens.length;) {
658
+ const status = tokens[index++] ?? '';
659
+ const first = tokens[index++];
660
+ if (!first) break;
661
+ paths.add(first);
662
+ if (status.startsWith('R') || status.startsWith('C')) {
663
+ const second = tokens[index++];
664
+ if (second) paths.add(second);
665
+ }
666
+ }
667
+ return [...paths].sort((left, right) => left.localeCompare(right));
668
+ }
669
+
670
+ export function adoptEditSessionSuccessorHead(repoRoot: string, sessionId: string, input: {
671
+ binding?: EditSessionBinding;
672
+ reviewer?: string;
673
+ note?: string;
674
+ } = {}): EditSession {
675
+ let session = getEditSession(repoRoot, sessionId);
676
+ assertDurableEditSessionStorageBound(repoRoot, session.repoId);
677
+ if (!['dirty', 'checked', 'check_failed'].includes(session.status) || session.operations.length === 0) {
678
+ throw new Error(`EDIT_SESSION_SUCCESSOR_HEAD_NOT_ELIGIBLE: ${session.status}`);
679
+ }
680
+ assertEditSessionDurableBinding(session, input.binding, { requireBoundIdentity: true });
681
+ if (!session.workId || !session.repoId || !session.checkoutId || !session.principalId) {
682
+ throw new Error('EDIT_SESSION_SUCCESSOR_HEAD_WORK_BINDING_REQUIRED');
683
+ }
684
+ const previousBaseRevision = session.baseRevision?.trim();
685
+ const successorRevision = gitRevision(repoRoot)?.trim();
686
+ if (!previousBaseRevision || !successorRevision) throw new Error('EDIT_SESSION_SUCCESSOR_HEAD_REVISION_REQUIRED');
687
+ if (previousBaseRevision === successorRevision) return bindSessionControllerInstance(repoRoot, session, input.binding);
688
+
689
+ const committedPaths = committedChangedPathsBetween(repoRoot, previousBaseRevision, successorRevision);
690
+ const tracked = new Set(sessionTrackedPaths(session));
691
+ const overlaps = committedPaths.filter((path) => tracked.has(path));
692
+ if (overlaps.length > 0) {
693
+ throw new Error(`EDIT_SESSION_SUCCESSOR_HEAD_PATH_OVERLAP: ${overlaps.join(',')}`);
694
+ }
695
+ const mismatches = currentHashMismatches(repoRoot, session);
696
+ if (mismatches.length > 0) {
697
+ throw new Error(`EDIT_SESSION_SUCCESSOR_HEAD_CONTENT_DRIFT: ${mismatches.join(',')}`);
698
+ }
699
+
700
+ session = bindSessionControllerInstance(repoRoot, session, input.binding);
701
+ const revision = session.currentRevision + 1;
702
+ const revisionPatch = '';
703
+ const absoluteRevisionPatch = revisionPatchPath(repoRoot, session.sessionId, revision);
704
+ mkdirSync(dirname(absoluteRevisionPatch), { recursive: true });
705
+ writeFileSync(absoluteRevisionPatch, revisionPatch, 'utf-8');
706
+ const at = now();
707
+ session.revisions.push({
708
+ revision,
709
+ operations: [],
710
+ changedFiles: 0,
711
+ changedLines: 0,
712
+ patchPath: relative(repoRoot, absoluteRevisionPatch).replace(/\\/g, '/'),
713
+ patchSha256: hash(revisionPatch),
714
+ createdAt: at,
715
+ });
716
+ session.currentRevision = revision;
717
+ session.baseRevision = successorRevision;
718
+ session.status = 'dirty';
719
+ session.verifiedAt = undefined;
720
+ session.checkResults = [];
721
+ session.reviewer = undefined;
722
+ session.reviewNote = undefined;
723
+ session.assurance = calculateAssurance(session, at);
724
+ session.requestedChecks = session.assurance.requiredChecks;
725
+ session.workspaceFingerprint = workspaceFingerprint(repoRoot);
726
+ session.updatedAt = at;
727
+ writeSession(repoRoot, session);
728
+ tryAppendControllerWorklogEvent(repoRoot, {
729
+ category: 'edit',
730
+ action: 'edit_session_successor_head_adopted',
731
+ summary: `${session.purpose}: adopted non-overlapping successor HEAD`,
732
+ actor: input.reviewer?.trim() || undefined,
733
+ issueId: session.issueId,
734
+ taskId: session.taskId,
735
+ editSessionId: session.sessionId,
736
+ details: {
737
+ workId: session.workId,
738
+ previousBaseRevision,
739
+ successorRevision,
740
+ committedPaths,
741
+ revision,
742
+ note: input.note?.trim() || undefined,
743
+ },
744
+ });
745
+ return session;
746
+ }
747
+
620
748
  function markEditSessionSuperseded(repoRoot: string, session: EditSession, paths: string[], input: {
621
749
  reviewer?: string;
622
750
  note?: string;
@@ -999,6 +1127,7 @@ function sessionSummary(session: EditSession): EditSessionSummary {
999
1127
  return {
1000
1128
  sessionId: session.sessionId,
1001
1129
  purpose: session.purpose,
1130
+ workId: session.workId,
1002
1131
  status: session.status,
1003
1132
  issueId: session.issueId,
1004
1133
  taskId: session.taskId,
@@ -1060,6 +1189,7 @@ export function beginEditSession(repoRoot: string, input: {
1060
1189
  }): EditSession {
1061
1190
  const purpose = input.purpose.trim();
1062
1191
  if (!purpose) throw new Error('edit session purpose is required');
1192
+ assertDurableEditSessionStorageBound(repoRoot, input.binding?.repoId);
1063
1193
  const at = now();
1064
1194
  const session: EditSession = {
1065
1195
  schemaVersion: 3,
@@ -1071,7 +1201,6 @@ export function beginEditSession(repoRoot: string, input: {
1071
1201
  checkoutId: input.binding?.checkoutId?.trim() || undefined,
1072
1202
  principalId: input.binding?.principalId?.trim() || undefined,
1073
1203
  controllerInstanceId: input.binding?.controllerInstanceId?.trim() || undefined,
1074
- routeDecisionFingerprint: input.binding?.routeDecisionFingerprint?.trim() || undefined,
1075
1204
  workspaceFingerprint: workspaceFingerprint(repoRoot),
1076
1205
  purpose,
1077
1206
  status: 'open',
@@ -1125,6 +1254,135 @@ export function listEditSessions(repoRoot: string, limit = 100): EditSessionSumm
1125
1254
  .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
1126
1255
  }
1127
1256
 
1257
+
1258
+ export interface EditSessionRetentionResult {
1259
+ removedSessionIds: string[];
1260
+ reclaimedBytes: number;
1261
+ unknownReclaimedByteCount: number;
1262
+ inspected: number;
1263
+ eligible: number;
1264
+ attempted: number;
1265
+ retained: number;
1266
+ budgetExhausted: boolean;
1267
+ skippedByReason: Record<string, number>;
1268
+ errors: string[];
1269
+ }
1270
+
1271
+ function editSessionDirectoryBytes(path: string): { bytes: number; complete: boolean } {
1272
+ let bytes = 0;
1273
+ try {
1274
+ for (const entry of readdirSync(path, { withFileTypes: true })) {
1275
+ const entryPath = join(path, entry.name);
1276
+ if (entry.isDirectory()) {
1277
+ const nested = editSessionDirectoryBytes(entryPath);
1278
+ bytes += nested.bytes;
1279
+ if (!nested.complete) return { bytes, complete: false };
1280
+ } else if (entry.isFile()) {
1281
+ bytes += statSync(entryPath).size;
1282
+ }
1283
+ }
1284
+ return { bytes, complete: true };
1285
+ } catch {
1286
+ return { bytes, complete: false };
1287
+ }
1288
+ }
1289
+
1290
+ /**
1291
+ * Physically reclaim terminal EditSession artifacts after their Work no longer
1292
+ * owns live review/delivery authority. The repository-relative path may be the
1293
+ * runtime-storage compatibility link; deletion therefore follows the existing
1294
+ * Controller Home binding instead of creating a second persistence root.
1295
+ */
1296
+ export function cleanupTerminalEditSessionRecords(repoRoot: string, input: {
1297
+ nowMs?: number;
1298
+ retentionMs?: number;
1299
+ maxRetained?: number;
1300
+ maxEntries?: number;
1301
+ maxRemovals?: number;
1302
+ sequence?: number;
1303
+ protectedWorkIds?: Iterable<string>;
1304
+ } = {}): EditSessionRetentionResult {
1305
+ const root = join(repoRoot, SESSION_ROOT);
1306
+ const result: EditSessionRetentionResult = {
1307
+ removedSessionIds: [], reclaimedBytes: 0, unknownReclaimedByteCount: 0,
1308
+ inspected: 0, eligible: 0, attempted: 0, retained: 0, budgetExhausted: false,
1309
+ skippedByReason: {}, errors: [],
1310
+ };
1311
+ if (!existsSync(root)) return result;
1312
+ const nowMs = input.nowMs ?? Date.now();
1313
+ const retentionMs = Math.max(60_000, Math.trunc(input.retentionMs ?? EDIT_SESSION_TERMINAL_RETENTION_MS));
1314
+ const maxRetained = Math.max(0, Math.trunc(input.maxRetained ?? EDIT_SESSION_TERMINAL_MAX_RETAINED));
1315
+ const maxEntries = Math.max(1, Math.trunc(input.maxEntries ?? 2_000));
1316
+ const maxRemovals = Math.max(0, Math.trunc(input.maxRemovals ?? 50));
1317
+ const protectedWorkIds = new Set(Array.from(input.protectedWorkIds ?? [], (value) => String(value).trim()).filter(Boolean));
1318
+ const skip = (reason: string) => {
1319
+ result.retained += 1;
1320
+ result.skippedByReason[reason] = (result.skippedByReason[reason] ?? 0) + 1;
1321
+ };
1322
+ let entries;
1323
+ try {
1324
+ entries = readdirSync(root, { withFileTypes: true })
1325
+ .filter((entry) => entry.isDirectory() && existsSync(join(root, entry.name, 'session.json')))
1326
+ .sort((left, right) => right.name.localeCompare(left.name));
1327
+ } catch (error) {
1328
+ result.errors.push(`edit_session_root_unreadable:${error instanceof Error ? error.message : String(error)}`);
1329
+ return result;
1330
+ }
1331
+ if (entries.length === 0) return result;
1332
+ const rank = new Map(entries.map((entry, index) => [entry.name, index]));
1333
+ const start = (Math.max(0, Math.trunc(input.sequence ?? 0)) * maxEntries) % entries.length;
1334
+ const window = [...entries.slice(start), ...entries.slice(0, start)].slice(0, Math.min(maxEntries, entries.length));
1335
+ if (entries.length > window.length) result.budgetExhausted = true;
1336
+ for (const entry of window) {
1337
+ result.inspected += 1;
1338
+ let session: EditSession;
1339
+ try { session = getEditSession(repoRoot, entry.name); }
1340
+ catch (error) {
1341
+ result.errors.push(`edit_session_unreadable:${entry.name}:${error instanceof Error ? error.message : String(error)}`);
1342
+ skip('session_unreadable');
1343
+ continue;
1344
+ }
1345
+ if (!['finalized', 'superseded', 'rolled_back'].includes(session.status)) {
1346
+ skip('active_session');
1347
+ continue;
1348
+ }
1349
+ if (session.workId && protectedWorkIds.has(session.workId)) {
1350
+ skip('active_work');
1351
+ continue;
1352
+ }
1353
+ const updatedMs = Date.parse(session.updatedAt);
1354
+ if (!Number.isFinite(updatedMs)) {
1355
+ skip('terminal_timestamp_unknown');
1356
+ continue;
1357
+ }
1358
+ const beyondAge = nowMs - updatedMs >= retentionMs;
1359
+ const beyondCount = (rank.get(entry.name) ?? 0) >= maxRetained;
1360
+ if (!beyondAge && !beyondCount) {
1361
+ skip('within_retention');
1362
+ continue;
1363
+ }
1364
+ result.eligible += 1;
1365
+ if (result.attempted >= maxRemovals) {
1366
+ result.budgetExhausted = true;
1367
+ skip('cleanup_budget_exhausted');
1368
+ continue;
1369
+ }
1370
+ result.attempted += 1;
1371
+ const path = sessionDir(repoRoot, session.sessionId);
1372
+ const measurement = editSessionDirectoryBytes(path);
1373
+ if (measurement.complete) result.reclaimedBytes += measurement.bytes;
1374
+ else result.unknownReclaimedByteCount += 1;
1375
+ try {
1376
+ rmSync(path, { recursive: true, force: true });
1377
+ result.removedSessionIds.push(session.sessionId);
1378
+ } catch (error) {
1379
+ result.errors.push(`edit_session_remove_failed:${session.sessionId}:${error instanceof Error ? error.message : String(error)}`);
1380
+ }
1381
+ }
1382
+ result.removedSessionIds.sort();
1383
+ return result;
1384
+ }
1385
+
1128
1386
  export function getEditSessionDiff(repoRoot: string, sessionId: string): {
1129
1387
  sessionId: string;
1130
1388
  path?: string;
@@ -1144,6 +1402,7 @@ export function applyEditOperations(repoRoot: string, policy: McpPolicy, session
1144
1402
  binding?: EditSessionBinding;
1145
1403
  } = {}): EditSession {
1146
1404
  let session = getEditSession(repoRoot, sessionId);
1405
+ assertDurableEditSessionStorageBound(repoRoot, session.repoId);
1147
1406
  if (['finalized', 'rolled_back'].includes(session.status)) throw new Error(`edit session is closed: ${session.status}`);
1148
1407
  if (operations.length === 0) throw new Error('at least one edit operation is required');
1149
1408
  const maxBatchOperations = Math.max(1, Math.trunc(options.maxBatchOperations ?? MAX_EDIT_PATCH_BATCH_OPERATIONS));
@@ -1382,7 +1641,10 @@ export function applyEditOperations(repoRoot: string, policy: McpPolicy, session
1382
1641
  repoRoot,
1383
1642
  record.path,
1384
1643
  readFileSync(join(repoRoot, record.backupPath), 'utf-8'),
1385
- record.beforeMode === undefined ? {} : { mode: record.beforeMode },
1644
+ {
1645
+ backupRoot: `${SESSION_ROOT}/${session.sessionId}/atomic-backups/apply-rollback-r${revision}`,
1646
+ ...(record.beforeMode === undefined ? {} : { mode: record.beforeMode }),
1647
+ },
1386
1648
  );
1387
1649
  }
1388
1650
  const message = error instanceof Error ? error.message : String(error);
@@ -1531,7 +1793,7 @@ export async function verifyEditSessionAsync(repoRoot: string, sessionId: string
1531
1793
  });
1532
1794
  }
1533
1795
 
1534
- function restoreOperation(repoRoot: string, operation: EditSessionOperationRecord): void {
1796
+ function restoreOperation(repoRoot: string, operation: EditSessionOperationRecord, backupRoot: string): void {
1535
1797
  const absolute = join(repoRoot, operation.path);
1536
1798
  if (operation.type === 'create') {
1537
1799
  if (existsSync(absolute)) {
@@ -1554,7 +1816,10 @@ function restoreOperation(repoRoot: string, operation: EditSessionOperationRecor
1554
1816
  repoRoot,
1555
1817
  operation.path,
1556
1818
  readFileSync(join(repoRoot, operation.backupPath), 'utf-8'),
1557
- operation.beforeMode === undefined ? {} : { mode: operation.beforeMode },
1819
+ {
1820
+ backupRoot,
1821
+ ...(operation.beforeMode === undefined ? {} : { mode: operation.beforeMode }),
1822
+ },
1558
1823
  );
1559
1824
  }
1560
1825
 
@@ -1564,6 +1829,7 @@ export function rollbackEditSession(repoRoot: string, sessionId: string, input:
1564
1829
  allowFinalized?: boolean;
1565
1830
  } = {}): EditSession {
1566
1831
  const session = getEditSession(repoRoot, sessionId);
1832
+ assertDurableEditSessionStorageBound(repoRoot, session.repoId);
1567
1833
  if ((session.status === 'open' || (session.status === 'finalized' && input.allowFinalized)) && session.operations.length === 0) {
1568
1834
  const at = now();
1569
1835
  session.status = 'rolled_back';
@@ -1595,7 +1861,11 @@ export function rollbackEditSession(repoRoot: string, sessionId: string, input:
1595
1861
  try {
1596
1862
  for (const operation of reverted) {
1597
1863
  restoreAttempted = true;
1598
- restoreOperation(repoRoot, operation);
1864
+ restoreOperation(
1865
+ repoRoot,
1866
+ operation,
1867
+ `${SESSION_ROOT}/${session.sessionId}/atomic-backups/rollback-to-r${target}`,
1868
+ );
1599
1869
  }
1600
1870
  } finally {
1601
1871
  if (restoreAttempted) invalidateRepositoryReadCaches(repoRoot);
@@ -1,5 +1,5 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
- import { dirname, join } from "path";
1
+ import { existsSync, readFileSync, rmSync } from "fs";
2
+ import { join } from "path";
3
3
  import { getGitHubStatus, publishIssueToGitHub, refreshGitHubIssue, closeGitHubIssue } from "./github";
4
4
  import type { ControllerIssue } from "../controller/types";
5
5
  import { tryAppendControllerWorklogEvent } from "../controller/worklog";
@@ -104,6 +104,10 @@ function loadLegacyGitHubPluginConfig(repoRoot: string): GitHubPluginConfig | un
104
104
  }
105
105
  }
106
106
 
107
+ function retireLegacyGitHubPluginConfig(repoRoot: string): void {
108
+ rmSync(join(repoRoot, CONFIG_PATH), { force: true });
109
+ }
110
+
107
111
  function findRepositoryRecord(repoRoot: string): RepositoryRecord | undefined {
108
112
  const controllerHome = resolveRepoPreferredControllerHome(repoRoot);
109
113
  return listRepositories(controllerHome).find((record) =>
@@ -127,18 +131,18 @@ function configFromRepository(record: RepositoryRecord | undefined): GitHubPlugi
127
131
  });
128
132
  }
129
133
 
130
- function syncRepositoryGitHubConfig(repoRoot: string, config: GitHubPluginConfig): void {
134
+ function syncRepositoryGitHubConfig(repoRoot: string, config: GitHubPluginConfig): boolean {
131
135
  const record = findRepositoryRecord(repoRoot);
132
- if (!record) return;
136
+ if (!record) return false;
133
137
  const controllerHome = resolveRepoPreferredControllerHome(repoRoot);
134
138
  const current = record.github;
135
139
  const repository = config.repository?.trim();
136
140
  const effectiveRepository = repository
137
141
  || current?.repository
138
142
  || (current?.owner && current?.repo ? `${current.owner}/${current.repo}` : undefined);
139
- if (!effectiveRepository) return;
143
+ if (!effectiveRepository) return false;
140
144
  const [owner, repo] = effectiveRepository.includes("/") ? effectiveRepository.split("/", 2) : [current?.owner, current?.repo];
141
- if (!owner || !repo) return;
145
+ if (!owner || !repo) return false;
142
146
  updateRepository(record.repoId, {
143
147
  github: {
144
148
  owner,
@@ -156,6 +160,7 @@ function syncRepositoryGitHubConfig(repoRoot: string, config: GitHubPluginConfig
156
160
  authenticationCapability: current?.authenticationCapability ?? "unknown",
157
161
  },
158
162
  }, controllerHome);
163
+ return true;
159
164
  }
160
165
 
161
166
  export function loadGitHubPluginConfig(repoRoot: string): GitHubPluginConfig {
@@ -173,12 +178,12 @@ export function loadGitHubPluginConfig(repoRoot: string): GitHubPluginConfig {
173
178
  projectNumber: legacyConfig.projectNumber ?? registryConfig.projectNumber,
174
179
  statusField: legacyConfig.statusField ?? registryConfig.statusField,
175
180
  });
176
- syncRepositoryGitHubConfig(repoRoot, merged);
181
+ if (syncRepositoryGitHubConfig(repoRoot, merged)) retireLegacyGitHubPluginConfig(repoRoot);
177
182
  return merged;
178
183
  }
179
184
  if (registryConfig) return registryConfig;
180
185
  if (legacyConfig) {
181
- syncRepositoryGitHubConfig(repoRoot, legacyConfig);
186
+ if (syncRepositoryGitHubConfig(repoRoot, legacyConfig)) retireLegacyGitHubPluginConfig(repoRoot);
182
187
  return legacyConfig;
183
188
  }
184
189
  return defaultGitHubPluginConfig();
@@ -224,10 +229,10 @@ export function saveGitHubPluginConfig(
224
229
  projectNumber,
225
230
  statusField,
226
231
  };
227
- syncRepositoryGitHubConfig(repoRoot, config);
228
- const path = join(repoRoot, CONFIG_PATH);
229
- mkdirSync(dirname(path), { recursive: true });
230
- writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
232
+ if (!syncRepositoryGitHubConfig(repoRoot, config)) {
233
+ throw new Error("GITHUB_PLUGIN_REPOSITORY_REGISTRATION_REQUIRED: configure GitHub only after the repository is registered in Controller Home");
234
+ }
235
+ retireLegacyGitHubPluginConfig(repoRoot);
231
236
  statusCache.set(repoRoot, {
232
237
  at: Date.now() - STATUS_CACHE_TTL_MS + CONFIG_STATUS_CACHE_TTL_MS,
233
238
  fingerprint: JSON.stringify(config),
@@ -6,11 +6,9 @@
6
6
  * names are an internal implementation detail — Phase 2 sealed hooks will
7
7
  * replace them with bundled implementations without changing the tuple.
8
8
  *
9
- * Derived from `.codex/hooks.json` reality verified Phase 0 canary
10
- * 2026-05-28 (see docs/architecture/global-hook-runtime.md and Codex consult
11
- * session 019e6df7-e7c9-70e2-8872-db9869420bd0). The matcher dimension was
12
- * the missing piece in the X (event-only) design — see
13
- * tasks/notes/hook-global-runtime.notes.md § Phase 1B Design Pivot.
9
+ * Derived from `.codex/hooks.json` reality verified by the Phase 0 canary on
10
+ * 2026-05-28. Historical rationale and verification evidence are preserved in
11
+ * Git history; the matcher-aware registry and its tests are the current contract.
14
12
  *
15
13
  * Order matters: it is the stable adapter entry order. Codex hashes adapter
16
14
  * entries by `(absolute-path, event-snake, i, j)`, so any reordering re-prompts
@@ -1,10 +1,14 @@
1
1
  import * as fs from 'fs';
2
+ import * as os from 'os';
2
3
  import * as path from 'path';
3
4
  import { fileURLToPath } from 'url';
4
5
  import { execFileSync, spawnSync, type StdioOptions } from 'child_process';
6
+ import { repositoryControllerRoot, resolveControllerHome } from '../repositories/controller-home';
7
+ import { findRegisteredRepositoryByCheckoutRoot } from '../repositories/registry';
5
8
  import { getRoute, type HookEvent, type RouteId } from './route-registry';
6
9
 
7
- const OPT_IN_MARKER = '.ai/harness/workflow-contract.json';
10
+ const OPT_IN_MARKER = 'forge.config.json';
11
+ const LEGACY_OPT_IN_MARKER = '.ai/harness/workflow-contract.json';
8
12
  const POLICY_FILE = '.ai/harness/policy.json';
9
13
  const PACKAGE_ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
10
14
 
@@ -83,7 +87,7 @@ export function resolveRepoRoot(cwd: string): string | null {
83
87
  }
84
88
 
85
89
  export function isOptIn(repoRoot: string): boolean {
86
- return fs.existsSync(path.join(repoRoot, OPT_IN_MARKER));
90
+ return fs.existsSync(path.join(repoRoot, OPT_IN_MARKER)) || fs.existsSync(path.join(repoRoot, LEGACY_OPT_IN_MARKER));
87
91
  }
88
92
 
89
93
  /**
@@ -108,6 +112,36 @@ export interface ResolvedHooksDir {
108
112
  source: HookSource;
109
113
  }
110
114
 
115
+ export interface ResolvedHookStateRoot {
116
+ root: string;
117
+ source: 'env' | 'controller-home' | 'ephemeral';
118
+ repoId?: string;
119
+ }
120
+
121
+ export function resolveHookStateRoot(
122
+ repoRoot: string,
123
+ env: NodeJS.ProcessEnv = process.env,
124
+ ): ResolvedHookStateRoot {
125
+ const explicit = env.FORGE_HOOK_STATE_ROOT?.trim();
126
+ if (explicit && path.isAbsolute(explicit)) {
127
+ fs.mkdirSync(explicit, { recursive: true });
128
+ return { root: explicit, source: 'env' };
129
+ }
130
+
131
+ const controllerHome = resolveControllerHome(env.FORGE_CONTROLLER_HOME);
132
+ const repository = findRegisteredRepositoryByCheckoutRoot(repoRoot, controllerHome);
133
+ if (repository) {
134
+ const root = path.join(repositoryControllerRoot(controllerHome, repository.repoId), 'hook-state');
135
+ fs.mkdirSync(root, { recursive: true });
136
+ return { root, source: 'controller-home', repoId: repository.repoId };
137
+ }
138
+
139
+ return {
140
+ root: fs.mkdtempSync(path.join(os.tmpdir(), 'forge-hook-state-')),
141
+ source: 'ephemeral',
142
+ };
143
+ }
144
+
111
145
  function repoPinsHookSource(repoRoot: string): boolean {
112
146
  try {
113
147
  const raw = fs.readFileSync(path.join(repoRoot, POLICY_FILE), 'utf-8');
@@ -173,6 +207,7 @@ export function runHook(opts: RunHookOptions): RunHookResult {
173
207
  return { exitCode: 2, reason: 'unknown-route', repoRoot, scriptsRun, skippedScripts };
174
208
  }
175
209
 
210
+ const hookState = resolveHookStateRoot(repoRoot);
176
211
  const resolved: ResolvedHooksDir = opts.hooksDir
177
212
  ? { dir: opts.hooksDir, source: 'env' }
178
213
  : resolveHooksDir(repoRoot);
@@ -202,6 +237,7 @@ export function runHook(opts: RunHookOptions): RunHookResult {
202
237
  ? ['inherit', 'pipe', 'inherit']
203
238
  : (opts.stdio ?? 'inherit');
204
239
 
240
+ try {
205
241
  for (const script of route.scripts) {
206
242
  const scriptPath = path.join(hooksDir, script);
207
243
  if (!fs.existsSync(scriptPath)) {
@@ -230,7 +266,12 @@ export function runHook(opts: RunHookOptions): RunHookResult {
230
266
  const child = spawnSync('bash', [scriptPath, ...(opts.args ?? [])], {
231
267
  cwd: repoRoot,
232
268
  stdio,
233
- env: { ...process.env, HOOK_REPO_ROOT: repoRoot },
269
+ env: {
270
+ ...process.env,
271
+ HOOK_REPO_ROOT: repoRoot,
272
+ FORGE_HOOK_STATE_ROOT: hookState.root,
273
+ FORGE_REPO_ID: hookState.repoId ?? '',
274
+ },
234
275
  });
235
276
 
236
277
  if (child.error) {
@@ -300,4 +341,9 @@ export function runHook(opts: RunHookOptions): RunHookResult {
300
341
  }
301
342
 
302
343
  return { exitCode: 0, reason: 'ok', repoRoot, scriptsRun, skippedScripts };
344
+ } finally {
345
+ if (hookState.source === 'ephemeral') {
346
+ fs.rmSync(hookState.root, { recursive: true, force: true });
347
+ }
348
+ }
303
349
  }
package/src/cli/index.ts CHANGED
@@ -17,6 +17,7 @@ import { buildSetupCommand, formatInitHook, runInitHook } from './commands/init-
17
17
  import { formatMigratePlan, runMigrate } from './commands/migrate';
18
18
  import { buildToolsCommand } from './commands/tools';
19
19
  import { buildPluginCommand } from './commands/plugin';
20
+ import { buildComputerCommand } from './commands/computer';
20
21
  import { buildBrainCommand } from './commands/brain';
21
22
  import { buildCapabilityContextCommand } from './commands/capability-context';
22
23
  import { buildDocsCommand } from './commands/docs';
@@ -53,6 +54,7 @@ export const SUBCOMMANDS = [
53
54
  'setup',
54
55
  'tools',
55
56
  'plugin',
57
+ 'computer',
56
58
  'brain',
57
59
  'capability-context',
58
60
  'docs',
@@ -509,6 +511,7 @@ export function buildProgram(): Command {
509
511
 
510
512
  program.addCommand(buildToolsCommand());
511
513
  program.addCommand(buildPluginCommand());
514
+ program.addCommand(buildComputerCommand());
512
515
  program.addCommand(buildBrainCommand(), { hidden: true });
513
516
  program.addCommand(buildCapabilityContextCommand(), { hidden: true });
514
517
  program.addCommand(buildDocsCommand());
@@ -18,8 +18,8 @@ import {
18
18
  import {
19
19
  loadMcpLocalConfig,
20
20
  loadMcpServiceLocalConfig,
21
- } from '../mcp/auth';
22
- import { PREFERRED_FACADE_TOOL_NAMES, DEFAULT_CONTROLLER_TOOL_NAMES } from '../mcp/toolset-names';
21
+ } from '../../../adapters/mcp/auth';
22
+ import { PREFERRED_FACADE_TOOL_NAMES, DEFAULT_CONTROLLER_TOOL_NAMES } from '../../../adapters/mcp/toolset-names';
23
23
  import { resolveRepoPreferredControllerHome } from '../repositories/controller-home';
24
24
  import type { PlainStatusTone } from './console-view-models';
25
25