@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
@@ -135,9 +135,115 @@ export function rollbackStoppedRepoLocalControllerHomeStorage(migration: Control
135
135
  renameSync(physicalHome, logicalHome);
136
136
  }
137
137
 
138
+
139
+ export interface StoppedControllerHomeAuthorityRelocation {
140
+ migrated: boolean;
141
+ sourceHome: string;
142
+ destinationHome: string;
143
+ archivedDestinationHome?: string;
144
+ }
145
+
146
+ function directoryEntryExists(path: string): boolean {
147
+ try { lstatSync(path); return true; } catch (error) {
148
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false;
149
+ throw error;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Atomically relocate one fully stopped Controller Home to a new durable path.
155
+ * The caller owns liveness fencing and must prove Runtime, Connector, Recovery
156
+ * Gateway, Recovery Watchdog, and any other writers are stopped before calling.
157
+ *
158
+ * Existing destination contents are never merged. A caller that has already
159
+ * proven the destination is an authority-free shell may request archival; the
160
+ * entire shell is renamed aside so rollback can restore it byte-for-byte.
161
+ */
162
+ export function relocateStoppedControllerHomeAuthority(input: {
163
+ sourceHome: string;
164
+ destinationHome: string;
165
+ archiveExistingDestination?: boolean;
166
+ archiveSuffix?: string;
167
+ }): StoppedControllerHomeAuthorityRelocation {
168
+ const sourceHome = resolve(input.sourceHome);
169
+ const destinationHome = resolve(input.destinationHome);
170
+ if (sourceHome === destinationHome) throw new Error('CONTROLLER_HOME_RELOCATION_SAME_HOME');
171
+ if (!directoryEntryExists(sourceHome)) throw new Error(`CONTROLLER_HOME_RELOCATION_SOURCE_MISSING: ${sourceHome}`);
172
+ const sourceStat = lstatSync(sourceHome);
173
+ if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink()) {
174
+ throw new Error(`CONTROLLER_HOME_RELOCATION_SOURCE_UNSUPPORTED: ${sourceHome}`);
175
+ }
176
+ mkdirSync(dirname(destinationHome), { recursive: true });
177
+
178
+ let archivedDestinationHome: string | undefined;
179
+ if (directoryEntryExists(destinationHome)) {
180
+ const destinationStat = lstatSync(destinationHome);
181
+ if (!destinationStat.isDirectory() || destinationStat.isSymbolicLink()) {
182
+ throw new Error(`CONTROLLER_HOME_RELOCATION_DESTINATION_UNSUPPORTED: ${destinationHome}`);
183
+ }
184
+ if (!input.archiveExistingDestination) {
185
+ throw new Error(`CONTROLLER_HOME_RELOCATION_DESTINATION_EXISTS: ${destinationHome}`);
186
+ }
187
+ const suffix = input.archiveSuffix?.trim() || `${Date.now()}-${process.pid}`;
188
+ if (!/^[A-Za-z0-9._-]{1,120}$/.test(suffix)) throw new Error('CONTROLLER_HOME_RELOCATION_ARCHIVE_SUFFIX_INVALID');
189
+ archivedDestinationHome = `${destinationHome}.pre-migration-${suffix}`;
190
+ if (directoryEntryExists(archivedDestinationHome)) {
191
+ throw new Error(`CONTROLLER_HOME_RELOCATION_ARCHIVE_EXISTS: ${archivedDestinationHome}`);
192
+ }
193
+ renameSync(destinationHome, archivedDestinationHome);
194
+ }
195
+
196
+ try {
197
+ renameSync(sourceHome, destinationHome);
198
+ if (directoryEntryExists(sourceHome) || !lstatSync(destinationHome).isDirectory()) {
199
+ throw new Error('CONTROLLER_HOME_RELOCATION_POSTCHECK_FAILED');
200
+ }
201
+ return {
202
+ migrated: true,
203
+ sourceHome,
204
+ destinationHome,
205
+ ...(archivedDestinationHome ? { archivedDestinationHome } : {}),
206
+ };
207
+ } catch (error) {
208
+ try {
209
+ if (!directoryEntryExists(sourceHome) && directoryEntryExists(destinationHome)) renameSync(destinationHome, sourceHome);
210
+ if (archivedDestinationHome && !directoryEntryExists(destinationHome) && directoryEntryExists(archivedDestinationHome)) {
211
+ renameSync(archivedDestinationHome, destinationHome);
212
+ }
213
+ } catch {
214
+ throw new Error(`CONTROLLER_HOME_RELOCATION_ROLLBACK_FAILED: ${error instanceof Error ? error.message : String(error)}`);
215
+ }
216
+ throw error;
217
+ }
218
+ }
219
+
220
+ /** Caller must keep all Controller Home writers stopped until rollback completes. */
221
+ export function rollbackStoppedControllerHomeAuthorityRelocation(
222
+ relocation: StoppedControllerHomeAuthorityRelocation,
223
+ ): void {
224
+ if (!relocation.migrated) return;
225
+ const sourceHome = resolve(relocation.sourceHome);
226
+ const destinationHome = resolve(relocation.destinationHome);
227
+ const archivedDestinationHome = relocation.archivedDestinationHome ? resolve(relocation.archivedDestinationHome) : undefined;
228
+ if (directoryEntryExists(sourceHome)) throw new Error(`CONTROLLER_HOME_RELOCATION_ROLLBACK_SOURCE_EXISTS: ${sourceHome}`);
229
+ if (!directoryEntryExists(destinationHome) || !lstatSync(destinationHome).isDirectory()) {
230
+ throw new Error(`CONTROLLER_HOME_RELOCATION_ROLLBACK_DESTINATION_MISSING: ${destinationHome}`);
231
+ }
232
+ if (archivedDestinationHome && !directoryEntryExists(archivedDestinationHome)) {
233
+ throw new Error(`CONTROLLER_HOME_RELOCATION_ROLLBACK_ARCHIVE_MISSING: ${archivedDestinationHome}`);
234
+ }
235
+ renameSync(destinationHome, sourceHome);
236
+ try {
237
+ if (archivedDestinationHome) renameSync(archivedDestinationHome, destinationHome);
238
+ } catch (error) {
239
+ try { if (!directoryEntryExists(destinationHome) && directoryEntryExists(sourceHome)) renameSync(sourceHome, destinationHome); } catch { /* best effort */ }
240
+ throw new Error(`CONTROLLER_HOME_RELOCATION_ROLLBACK_RESTORE_FAILED: ${error instanceof Error ? error.message : String(error)}`);
241
+ }
242
+ }
243
+
138
244
  export function ensureControllerHome(explicit?: string): string {
139
245
  const home = ensureControllerHomeStorage(resolveControllerHome(explicit));
140
- for (const child of ['', 'repositories', 'system', 'locks', 'indexes', 'audit', 'mcp', 'sessions', 'work-handles']) {
246
+ for (const child of ['', 'repositories', 'system', 'locks', 'indexes', 'audit', 'mcp', 'sessions', 'work-handles', 'workflows']) {
141
247
  mkdirSync(join(home, child), { recursive: true });
142
248
  }
143
249
  return home;
@@ -147,7 +253,21 @@ export function ensureRepoPreferredControllerHome(repoRoot?: string, explicit?:
147
253
  return ensureControllerHome(resolveRepoPreferredControllerHome(repoRoot, explicit));
148
254
  }
149
255
 
256
+ /** Legacy adapter-only sentinel. Never use this as a canonical storage or resource scope. */
150
257
  export const CONTROLLER_SCOPE_REPO_ID = '__controller__';
258
+ /** Canonical mechanical scope for state owned by the serving ForgeInstance itself. */
259
+ export const FORGE_INSTANCE_SCOPE_KEY = 'forge-instance';
260
+
261
+ /** Human-editable user Workflow Asset content. Machine workflow state stays in control-plane persistence. */
262
+ export function controllerWorkflowContentRoot(controllerHome: string): string {
263
+ return join(resolveControllerHome(controllerHome), 'workflows');
264
+ }
265
+
266
+ export function ensureControllerWorkflowContentRoot(controllerHome: string): string {
267
+ const root = controllerWorkflowContentRoot(ensureControllerHome(controllerHome));
268
+ mkdirSync(root, { recursive: true });
269
+ return root;
270
+ }
151
271
 
152
272
  export function controllerSystemRoot(controllerHome: string): string {
153
273
  return join(resolveControllerHome(controllerHome), 'system');
@@ -166,6 +286,51 @@ export function repositoryControllerRoot(controllerHome: string, repoId: string)
166
286
  : join(resolveControllerHome(durableHome), 'repositories', repoId);
167
287
  }
168
288
 
289
+ /** Reserved prefix for arbitrary workspace scopes; registered repository ids are `repo_*`. */
290
+ export const WORKSPACE_SCOPE_PREFIX = 'workspace_';
291
+
292
+ /**
293
+ * Reserved scope key for portable semantic facts (Requirement/Plan/Work) that
294
+ * belong to the ForgeInstance rather than to one repository. Repository and
295
+ * project placement stays optional provenance on those records.
296
+ */
297
+ export const SEMANTIC_SCOPE_KEY = 'semantic';
298
+
299
+ export function isWorkspaceScopeKey(scopeKey: string): boolean {
300
+ return scopeKey.trim().startsWith(WORKSPACE_SCOPE_PREFIX);
301
+ }
302
+
303
+ export function isSemanticScopeKey(scopeKey: string): boolean {
304
+ return scopeKey.trim() === SEMANTIC_SCOPE_KEY;
305
+ }
306
+
307
+ /**
308
+ * Controller-Home root for an arbitrary workspace scope. A workspace has no
309
+ * repository semantics, so its operation facts own a sibling partition instead
310
+ * of a repository partition.
311
+ */
312
+ export function workspaceScopeRoot(controllerHome: string, scopeKey: string): string {
313
+ const key = scopeKey.trim();
314
+ if (!isWorkspaceScopeKey(key)) throw new Error(`WORKSPACE_SCOPE_KEY_REQUIRED: ${scopeKey}`);
315
+ return join(resolveControllerHome(durableControllerHome(controllerHome)), 'workspaces', key);
316
+ }
317
+
318
+ /**
319
+ * Controller-Home root for one operation scope key. Repository scopes (including
320
+ * the controller-system sentinel) keep their established root; workspace scopes
321
+ * own the workspace partition.
322
+ */
323
+ export function scopedOperationRoot(controllerHome: string, scopeKey: string): string {
324
+ const key = scopeKey.trim();
325
+ return key === FORGE_INSTANCE_SCOPE_KEY
326
+ ? controllerSystemRoot(controllerHome)
327
+ : isWorkspaceScopeKey(key)
328
+ ? workspaceScopeRoot(controllerHome, key)
329
+ : isSemanticScopeKey(key)
330
+ ? join(resolveControllerHome(durableControllerHome(controllerHome)), SEMANTIC_SCOPE_KEY)
331
+ : repositoryControllerRoot(controllerHome, key);
332
+ }
333
+
169
334
  export function ensureRepositoryControllerLayout(controllerHome: string, repoId: string): string {
170
335
  const root = repositoryControllerRoot(controllerHome, repoId);
171
336
  for (const child of [
@@ -178,6 +343,7 @@ export function ensureRepositoryControllerLayout(controllerHome: string, repoId:
178
343
  'indexes',
179
344
  'edit-sessions',
180
345
  'controller',
346
+ 'hook-state',
181
347
  'local-bridge',
182
348
  'ephemeral-issues',
183
349
  'work-handles',
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'crypto';
2
2
  import { existsSync, realpathSync, statSync } from 'fs';
3
- import { isAbsolute, join } from 'path';
4
- import type { RepositoryRecord } from './types';
3
+ import { isAbsolute } from 'path';
4
+ import type { RepositoryCommandScopeTarget } from './command-scope';
5
5
 
6
6
  export interface EphemeralWorkspaceCoordinates {
7
7
  workspaceId: string;
@@ -10,7 +10,11 @@ export interface EphemeralWorkspaceCoordinates {
10
10
  }
11
11
 
12
12
  export interface EphemeralWorkspaceTarget extends EphemeralWorkspaceCoordinates {
13
- repository: RepositoryRecord;
13
+ /**
14
+ * Typed command target for an arbitrary workspace: it carries the workspace
15
+ * scope key and root, and no repository identity at all.
16
+ */
17
+ commandTarget: RepositoryCommandScopeTarget;
14
18
  }
15
19
 
16
20
  export function ephemeralWorkspaceCoordinates(rootInput: string): EphemeralWorkspaceCoordinates {
@@ -29,34 +33,20 @@ export function ephemeralWorkspaceCoordinates(rootInput: string): EphemeralWorks
29
33
  };
30
34
  }
31
35
 
32
- export function resolveEphemeralWorkspaceTarget(rootInput: string, controllerHome: string): EphemeralWorkspaceTarget {
36
+ /**
37
+ * `controllerHome` is retained for call-site compatibility; an arbitrary
38
+ * workspace owns no controller-scoped repository record.
39
+ */
40
+ export function resolveEphemeralWorkspaceTarget(rootInput: string, _controllerHome?: string): EphemeralWorkspaceTarget {
33
41
  const coordinates = ephemeralWorkspaceCoordinates(rootInput);
34
- const now = new Date().toISOString();
35
- const repository: RepositoryRecord = {
36
- schemaVersion: 1,
37
- repoId: coordinates.workspaceId,
38
- displayName: `Ephemeral Workspace (${coordinates.canonicalRoot.split(/[\\/]/).at(-1) || 'root'})`,
39
- localRoot: coordinates.canonicalRoot,
40
- canonicalRoot: coordinates.canonicalRoot,
41
- activeCheckoutId: coordinates.checkoutId,
42
- checkouts: [{
43
- checkoutId: coordinates.checkoutId,
44
- localRoot: coordinates.canonicalRoot,
42
+ return {
43
+ ...coordinates,
44
+ commandTarget: {
45
45
  canonicalRoot: coordinates.canonicalRoot,
46
- worktree: false,
47
- branch: null,
48
- createdAt: now,
49
- updatedAt: now,
50
- lastSeenAt: now,
51
- lifecycle: 'active',
52
- }],
53
- repositoryType: 'unknown',
54
- enabled: true,
55
- createdAt: now,
56
- updatedAt: now,
57
- lastSeenAt: now,
58
- configurationPath: join(controllerHome, 'ephemeral-workspaces', `${coordinates.workspaceId}.json`),
59
- stateStorageStrategy: 'controller-home',
46
+ workspaceScopeKey: coordinates.workspaceId,
47
+ // The workspace's own checkout coordinate, never a repository checkout id.
48
+ activeCheckoutId: coordinates.checkoutId,
49
+ enabled: true,
50
+ },
60
51
  };
61
- return { ...coordinates, repository };
62
52
  }
@@ -3,7 +3,7 @@ import { spawnSync } from 'child_process';
3
3
  import { appendFileSync, mkdirSync, realpathSync } from 'fs';
4
4
  import { dirname, join, relative } from 'path';
5
5
  import { capProcessOutput, redactProcessOutput } from '../../effects/process-runner';
6
- import { repositoryControllerRoot } from './controller-home';
6
+ import { scopedOperationRoot } from './controller-home';
7
7
  import { classifyRepositoryCommand, type RepositoryCommandAuthorization, type RepositoryCommandClassification } from './command-classifier';
8
8
  import { resolveRepositoryCommandCwd } from './command-scope';
9
9
  import type { RepositoryRecord } from './types';
@@ -209,7 +209,7 @@ function snapshotChanged(before: RepositoryGitSnapshot, after: RepositoryGitSnap
209
209
  }
210
210
 
211
211
  function auditExecution(controllerHome: string, repository: RepositoryRecord, execution: RepositoryGitExecution): void {
212
- const path = join(repositoryControllerRoot(controllerHome, repository.repoId), 'audit', 'git-commands.jsonl');
212
+ const path = join(scopedOperationRoot(controllerHome, repository.repoId), 'audit', 'git-commands.jsonl');
213
213
  mkdirSync(dirname(path), { recursive: true });
214
214
  appendFileSync(path, `${JSON.stringify({
215
215
  timestamp: new Date().toISOString(),
@@ -39,6 +39,19 @@ export function stableRemoteRepoId(canonicalRemote: string): string {
39
39
  return `repo_${digest(`remote\0${canonicalRemote}`).slice(0, 24)}`;
40
40
  }
41
41
 
42
+ /** Portable Project identity: stable across ForgeInstance/repository registrations for the same canonical remote. */
43
+ export function stablePortableProjectId(canonicalRemote: string): string {
44
+ const normalized = normalizeRemoteUrl(canonicalRemote);
45
+ if (!normalized) throw new Error('PROJECT_REMOTE_IDENTITY_REQUIRED');
46
+ return `project_${digest(`project\0${normalized}`).slice(0, 24)}`;
47
+ }
48
+
49
+ export function portableProjectSourceFingerprint(canonicalRemote: string): string {
50
+ const normalized = normalizeRemoteUrl(canonicalRemote);
51
+ if (!normalized) throw new Error('PROJECT_REMOTE_IDENTITY_REQUIRED');
52
+ return digest(`project-source\0${normalized}`);
53
+ }
54
+
42
55
  export function newLocalRepoId(): string {
43
56
  return `repo_local_${randomUUID().replace(/-/g, '')}`;
44
57
  }
@@ -1,12 +1,12 @@
1
1
  import { spawnSync } from 'child_process';
2
2
  import {
3
- appendFileSync,
4
3
  existsSync,
5
4
  mkdirSync,
6
5
  readFileSync,
7
6
  realpathSync,
8
7
  renameSync,
9
8
  rmSync,
9
+ statSync,
10
10
  writeFileSync,
11
11
  } from 'fs';
12
12
  import { dirname, join, relative, resolve } from 'path';
@@ -17,6 +17,7 @@ import {
17
17
  ensureControllerHome,
18
18
  ensureRepositoryControllerLayout,
19
19
  } from './controller-home';
20
+ import { withControllerLock } from './locks';
20
21
  import {
21
22
  inferDisplayName,
22
23
  newLocalRepoId,
@@ -38,7 +39,7 @@ import type {
38
39
 
39
40
  const REGISTRY_FILE = 'repositories.json';
40
41
  const FOCUS_FILE = 'focus.json';
41
- const LOCAL_CONFIG = '.ai/harness/repository.json';
42
+ const LEGACY_LOCAL_CONFIG = '.ai/harness/repository.json';
42
43
  const LEGACY_GITHUB_PLUGIN_CONFIG = '.forge/plugins/github.json';
43
44
 
44
45
  interface RegisterRepositoryInput {
@@ -218,6 +219,25 @@ function repositoryByGitCommonDirectory(records: RepositoryRecord[], root: strin
218
219
  return linkedWorktreeFallback ?? historicalCheckoutFallback;
219
220
  }
220
221
 
222
+ /**
223
+ * Resolve an already-registered repository from one concrete checkout root
224
+ * without mutating Repository Registry state. Exact canonical/active-checkout
225
+ * matches stay filesystem-only; Git common-directory probing is a bounded
226
+ * compatibility fallback for linked worktrees that predate checkout tracking.
227
+ */
228
+ export function findRegisteredRepositoryByCheckoutRoot(
229
+ root: string,
230
+ controllerHome?: string,
231
+ ): RepositoryRecord | undefined {
232
+ const candidateRoot = resolve(root);
233
+ const records = listRepositories(controllerHome).filter((record) => record.enabled !== false && !record.removedAt);
234
+ const exact = records.find((record) => (
235
+ comparablePath(record.canonicalRoot) === comparablePath(candidateRoot)
236
+ || activeCheckouts(record).some((checkout) => comparablePath(checkout.canonicalRoot) === comparablePath(candidateRoot))
237
+ ));
238
+ return exact ?? repositoryByGitCommonDirectory(records, candidateRoot);
239
+ }
240
+
221
241
  function managedCheckoutMatchesRepository(record: RepositoryRecord, checkout: RepositoryCheckout): boolean {
222
242
  return repositoryCheckoutRootMatches(record, checkout.canonicalRoot);
223
243
  }
@@ -272,6 +292,51 @@ function readRegistryFile(path: string, strict: boolean): RepositoryRegistry | u
272
292
  }
273
293
  }
274
294
 
295
+ interface RepositoryRegistryReadSnapshot {
296
+ fileIdentity: string;
297
+ registry: RepositoryRegistry;
298
+ }
299
+
300
+ const repositoryRegistryReadSnapshots = new Map<string, RepositoryRegistryReadSnapshot>();
301
+
302
+ function registryFileIdentity(path: string): string | undefined {
303
+ try {
304
+ const stat = statSync(path, { bigint: true });
305
+ return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
306
+ } catch {
307
+ return undefined;
308
+ }
309
+ }
310
+
311
+ function cloneRepositoryRecord(record: RepositoryRecord): RepositoryRecord {
312
+ return {
313
+ ...record,
314
+ checkouts: record.checkouts.map((checkout) => ({ ...checkout })),
315
+ github: record.github
316
+ ? { ...record.github, labels: record.github.labels ? [...record.github.labels] : undefined }
317
+ : undefined,
318
+ };
319
+ }
320
+
321
+ function loadRepositoryRegistryReadSnapshot(controllerHome?: string): RepositoryRegistry {
322
+ const path = registryPath(controllerHome);
323
+ const beforeIdentity = registryFileIdentity(path);
324
+ const cached = beforeIdentity ? repositoryRegistryReadSnapshots.get(path) : undefined;
325
+ if (cached && cached.fileIdentity === beforeIdentity) return cached.registry;
326
+
327
+ let registry = readRegistryFile(path, true) ?? defaultRegistry();
328
+ let afterIdentity = registryFileIdentity(path);
329
+ if (beforeIdentity && afterIdentity && beforeIdentity !== afterIdentity) {
330
+ // A cross-process atomic replacement raced this read. Re-read once from the
331
+ // new physical authority instead of caching a mixed-generation snapshot.
332
+ registry = readRegistryFile(path, true) ?? defaultRegistry();
333
+ afterIdentity = registryFileIdentity(path);
334
+ }
335
+ if (afterIdentity) repositoryRegistryReadSnapshots.set(path, { fileIdentity: afterIdentity, registry });
336
+ else repositoryRegistryReadSnapshots.delete(path);
337
+ return registry;
338
+ }
339
+
275
340
  function timestampValue(value: string | undefined): number {
276
341
  const parsed = value ? Date.parse(value) : Number.NaN;
277
342
  return Number.isFinite(parsed) ? parsed : 0;
@@ -336,9 +401,27 @@ export function loadRepositoryRegistry(controllerHome?: string): RepositoryRegis
336
401
 
337
402
  export function saveRepositoryRegistry(registry: RepositoryRegistry, controllerHome?: string): RepositoryRegistry {
338
403
  const home = ensureControllerHome(registryHome(controllerHome));
339
- const next = { ...registry, schemaVersion: 1 as const, updatedAt: now() };
340
- atomicJson(join(home, REGISTRY_FILE), next);
341
- return next;
404
+ return withControllerLock(
405
+ home,
406
+ { scope: 'global', resource: 'repository-registry' },
407
+ 'repository-registry:save',
408
+ () => {
409
+ const path = join(home, REGISTRY_FILE);
410
+ const current = readRegistryFile(path, true);
411
+ if (current && current.updatedAt !== registry.updatedAt) {
412
+ throw new Error(
413
+ `REPOSITORY_REGISTRY_STALE: expected=${registry.updatedAt}; current=${current.updatedAt}; reload canonical Repository Registry and retry`,
414
+ );
415
+ }
416
+ const previousRevision = timestampValue(registry.updatedAt);
417
+ const updatedAt = new Date(Math.max(Date.now(), previousRevision + 1)).toISOString();
418
+ const next = { ...registry, schemaVersion: 1 as const, updatedAt };
419
+ atomicJson(path, next);
420
+ return next;
421
+ },
422
+ 30_000,
423
+ 5_000,
424
+ );
342
425
  }
343
426
 
344
427
  export function consolidateRepositoryRegistry(controllerHome?: string): RepositoryRegistry {
@@ -354,7 +437,7 @@ function resolveGitRoot(inputPath: string): string {
354
437
  }
355
438
 
356
439
  function readLocalIdentity(canonicalRoot: string): { repoId?: string } {
357
- const path = join(canonicalRoot, LOCAL_CONFIG);
440
+ const path = join(canonicalRoot, LEGACY_LOCAL_CONFIG);
358
441
  if (!existsSync(path)) return {};
359
442
  try {
360
443
  const parsed = JSON.parse(readFileSync(path, 'utf-8')) as { repoId?: unknown };
@@ -395,28 +478,6 @@ function readLegacyGitHubPluginConfig(canonicalRoot: string): Partial<Repository
395
478
  }
396
479
  }
397
480
 
398
- function ensureHarnessRuntimeIgnored(canonicalRoot: string): void {
399
- const gitExclude = git(canonicalRoot, ['rev-parse', '--git-path', 'info/exclude']);
400
- if (!gitExclude) return;
401
- const path = resolve(canonicalRoot, gitExclude);
402
- const existing = existsSync(path) ? readFileSync(path, 'utf-8') : '';
403
- if (existing.split(/\r?\n/).some((line) => line.trim() === '.ai/harness/')) return;
404
- mkdirSync(dirname(path), { recursive: true });
405
- const prefix = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
406
- appendFileSync(path, `${prefix}# forge runtime metadata (controller-owned, never source)\n.ai/harness/\n`, 'utf-8');
407
- }
408
-
409
- function writeLocalIdentity(record: RepositoryRecord): void {
410
- ensureHarnessRuntimeIgnored(record.canonicalRoot);
411
- const path = join(record.canonicalRoot, LOCAL_CONFIG);
412
- atomicJson(path, {
413
- schemaVersion: 1,
414
- repoId: record.repoId,
415
- checkoutId: record.activeCheckoutId,
416
- stateStorageStrategy: record.stateStorageStrategy,
417
- });
418
- }
419
-
420
481
  function repositoryType(root: string, remoteUrl: string | undefined): RepositoryType {
421
482
  const bare = git(root, ['rev-parse', '--is-bare-repository']);
422
483
  if (bare === 'true') return 'bare';
@@ -540,17 +601,39 @@ export function repositorySummary(record: RepositoryRecord): RepositorySummary {
540
601
  }
541
602
 
542
603
  export function listRepositories(controllerHome?: string, options: { includeRemoved?: boolean } = {}): RepositoryRecord[] {
543
- return loadRepositoryRegistry(controllerHome).repositories
604
+ return loadRepositoryRegistryReadSnapshot(controllerHome).repositories
544
605
  .filter((record) => options.includeRemoved === true || !record.removedAt)
545
- .sort((a, b) => a.displayName.localeCompare(b.displayName) || a.repoId.localeCompare(b.repoId));
606
+ .sort((a, b) => a.displayName.localeCompare(b.displayName) || a.repoId.localeCompare(b.repoId))
607
+ .map(cloneRepositoryRecord);
546
608
  }
547
609
 
548
610
  export function getRepository(repoId: string, controllerHome?: string, options: { includeRemoved?: boolean } = {}): RepositoryRecord {
549
- const record = loadRepositoryRegistry(controllerHome).repositories.find((candidate) => candidate.repoId === repoId);
611
+ const record = loadRepositoryRegistryReadSnapshot(controllerHome).repositories.find((candidate) => candidate.repoId === repoId);
550
612
  if (!record || (record.removedAt && options.includeRemoved !== true)) {
551
613
  throw new Error(`repository not found: ${repoId}`);
552
614
  }
553
- return record;
615
+ return cloneRepositoryRecord(record);
616
+ }
617
+
618
+ export type RepositoryCheckoutSelectionErrorCode = 'CHECKOUT_NOT_FOUND' | 'CHECKOUT_NOT_ACTIVE';
619
+
620
+ export class RepositoryCheckoutSelectionError extends Error {
621
+ readonly code: RepositoryCheckoutSelectionErrorCode;
622
+ readonly repoId: string;
623
+ readonly checkoutId: string;
624
+ readonly lifecycle?: RepositoryCheckoutLifecycle;
625
+
626
+ constructor(input: { code: RepositoryCheckoutSelectionErrorCode; repoId: string; checkoutId: string; lifecycle?: RepositoryCheckoutLifecycle }) {
627
+ const message = input.code === 'CHECKOUT_NOT_FOUND'
628
+ ? `checkout not found for ${input.repoId}: ${input.checkoutId}`
629
+ : `CHECKOUT_NOT_ACTIVE: ${input.repoId}/${input.checkoutId} is ${input.lifecycle ?? 'unknown'}`;
630
+ super(message);
631
+ this.name = 'RepositoryCheckoutSelectionError';
632
+ this.code = input.code;
633
+ this.repoId = input.repoId;
634
+ this.checkoutId = input.checkoutId;
635
+ this.lifecycle = input.lifecycle;
636
+ }
554
637
  }
555
638
 
556
639
  export function selectRepositoryCheckout(
@@ -560,10 +643,10 @@ export function selectRepositoryCheckout(
560
643
  ): RepositoryRecord {
561
644
  if (!checkoutId?.trim()) return record;
562
645
  const checkout = record.checkouts.find((candidate) => candidate.checkoutId === checkoutId.trim());
563
- if (!checkout) throw new Error(`checkout not found for ${record.repoId}: ${checkoutId}`);
646
+ if (!checkout) throw new RepositoryCheckoutSelectionError({ code: 'CHECKOUT_NOT_FOUND', repoId: record.repoId, checkoutId: checkoutId.trim() });
564
647
  const lifecycle = repositoryCheckoutLifecycle(checkout);
565
648
  if (lifecycle !== 'active' && !(options.allowArchived === true && lifecycle === 'archived')) {
566
- throw new Error(`CHECKOUT_NOT_ACTIVE: ${record.repoId}/${checkout.checkoutId} is ${lifecycle}`);
649
+ throw new RepositoryCheckoutSelectionError({ code: 'CHECKOUT_NOT_ACTIVE', repoId: record.repoId, checkoutId: checkout.checkoutId, lifecycle });
567
650
  }
568
651
  return {
569
652
  ...record,
@@ -599,13 +682,29 @@ export function registerRepository(input: RegisterRepositoryInput): RepositoryRe
599
682
  ? repositoryByGitCommonDirectory(registry.repositories, canonicalRoot)
600
683
  : undefined;
601
684
  const existingIdentity = existingByRoot ?? existingByCommonDirectory;
602
- const derivedRepoId = input.repoIdOverride?.trim()
685
+ const explicitRepoId = input.repoIdOverride?.trim();
686
+ const derivedRepoId = explicitRepoId
603
687
  || existingIdentity?.repoId
604
688
  || localIdentity.repoId
605
689
  || (canonicalRemote ? stableRemoteRepoId(canonicalRemote) : newLocalRepoId());
606
- const repoId = existingIdentity?.repoId ?? derivedRepoId;
690
+ const existingByDerivedId = registry.repositories.find((record) => record.repoId === derivedRepoId);
691
+ // Repository identity is rooted in one Git checkout family, not merely one
692
+ // remote URL. Two independent clones of the same remote have different Git
693
+ // common directories and must remain separate Repository records. The one
694
+ // intentional exception is an explicit registration replacement; legacy
695
+ // repo-local identity may also restore a record whose old canonical root no
696
+ // longer exists after a filesystem move.
697
+ const explicitReplacement = Boolean(explicitRepoId && existingByDerivedId);
698
+ const legacyMovedRoot = Boolean(
699
+ !explicitRepoId
700
+ && localIdentity.repoId
701
+ && existingByDerivedId
702
+ && !existsSync(existingByDerivedId.canonicalRoot),
703
+ );
704
+ const existing = existingIdentity ?? (explicitReplacement || legacyMovedRoot ? existingByDerivedId : undefined);
705
+ const repoId = existing?.repoId
706
+ ?? (existingByDerivedId && !existingIdentity ? newLocalRepoId() : derivedRepoId);
607
707
  const checkoutId = stableCheckoutId(repoId, canonicalRoot);
608
- const existing = existingIdentity ?? registry.repositories.find((record) => record.repoId === repoId);
609
708
  const checkout: RepositoryCheckout = {
610
709
  checkoutId,
611
710
  localRoot: canonicalRoot,
@@ -623,8 +722,8 @@ export function registerRepository(input: RegisterRepositoryInput): RepositoryRe
623
722
  // A repository-scoped command may start from a managed checkout (for example
624
723
  // immutable release construction). Registering that path must add/update the
625
724
  // checkout only; it must never promote the ephemeral worktree to repository
626
- // canonical authority. Explicit activation remains available through
627
- // addRepositoryCheckout({ activate: true }).
725
+ // canonical authority. Active checkout selection is separate authority held
726
+ // by activeCheckoutId; canonicalRoot remains the repository registration root.
628
727
  if (existing && worktree && existing.canonicalRemote && canonicalRemote !== existing.canonicalRemote) {
629
728
  throw new Error(`CHECKOUT_REPOSITORY_MISMATCH: ${canonicalRoot}`);
630
729
  }
@@ -645,13 +744,6 @@ export function registerRepository(input: RegisterRepositoryInput): RepositoryRe
645
744
  registry.repositories[index] = next;
646
745
  saveRepositoryRegistry(registry, home);
647
746
  ensureRepositoryControllerLayout(home, next.repoId);
648
- ensureHarnessRuntimeIgnored(canonicalRoot);
649
- atomicJson(join(canonicalRoot, LOCAL_CONFIG), {
650
- schemaVersion: 1,
651
- repoId: next.repoId,
652
- checkoutId,
653
- stateStorageStrategy: next.stateStorageStrategy,
654
- });
655
747
  return selectRepositoryCheckout(next, checkoutId);
656
748
  }
657
749
 
@@ -675,7 +767,7 @@ export function registerRepository(input: RegisterRepositoryInput): RepositoryRe
675
767
  createdAt: existing?.createdAt ?? timestamp,
676
768
  updatedAt: timestamp,
677
769
  lastSeenAt: timestamp,
678
- configurationPath: join(canonicalRoot, LOCAL_CONFIG),
770
+ configurationPath: registryPath(home),
679
771
  stateStorageStrategy: input.stateStorageStrategy ?? existing?.stateStorageStrategy ?? 'hybrid',
680
772
  disabledAt: enabled ? undefined : existing?.disabledAt,
681
773
  removedAt: enabled ? undefined : existing?.removedAt,
@@ -687,7 +779,6 @@ export function registerRepository(input: RegisterRepositoryInput): RepositoryRe
687
779
  ];
688
780
  saveRepositoryRegistry(registry, home);
689
781
  ensureRepositoryControllerLayout(home, repoId);
690
- writeLocalIdentity(record);
691
782
  return record;
692
783
  }
693
784
 
@@ -748,6 +839,9 @@ export function addRepositoryCheckout(input: AddRepositoryCheckoutInput): Reposi
748
839
  if (current.canonicalRemote && canonicalRemote !== current.canonicalRemote) {
749
840
  throw new Error(`CHECKOUT_REPOSITORY_MISMATCH: ${canonicalRoot}`);
750
841
  }
842
+ if (!repositoryCheckoutRootMatches(current, canonicalRoot)) {
843
+ throw new Error(`CHECKOUT_REPOSITORY_MISMATCH: ${canonicalRoot}`);
844
+ }
751
845
  const timestamp = now();
752
846
  const checkoutId = stableCheckoutId(current.repoId, canonicalRoot);
753
847
  const checkout: RepositoryCheckout = {
@@ -764,21 +858,14 @@ export function addRepositoryCheckout(input: AddRepositoryCheckoutInput): Reposi
764
858
  const activate = input.activate === true;
765
859
  const next: RepositoryRecord = {
766
860
  ...current,
767
- ...(activate ? { localRoot: canonicalRoot, canonicalRoot, activeCheckoutId: checkoutId } : {}),
861
+ ...(activate ? { activeCheckoutId: checkoutId } : {}),
768
862
  checkouts: [...current.checkouts.filter((value) => value.checkoutId !== checkoutId), checkout],
769
863
  updatedAt: timestamp,
770
864
  lastSeenAt: timestamp,
771
865
  };
772
866
  registry.repositories[index] = next;
773
867
  saveRepositoryRegistry(registry, home);
774
- ensureHarnessRuntimeIgnored(canonicalRoot);
775
- atomicJson(join(canonicalRoot, LOCAL_CONFIG), {
776
- schemaVersion: 1,
777
- repoId: next.repoId,
778
- checkoutId,
779
- stateStorageStrategy: next.stateStorageStrategy,
780
- });
781
- return next;
868
+ return activate ? selectRepositoryCheckout(next, checkoutId) : next;
782
869
  }
783
870
 
784
871
  export function setRepositoryCheckoutLifecycle(input: SetRepositoryCheckoutLifecycleInput): RepositoryRecord {
@@ -868,7 +955,6 @@ export function updateRepository(repoId: string, patch: UpdateRepositoryInput, c
868
955
  };
869
956
  registry.repositories[index] = next;
870
957
  saveRepositoryRegistry(registry, controllerHome);
871
- writeLocalIdentity(next);
872
958
  return next;
873
959
  }
874
960
 
@@ -993,13 +1079,12 @@ export function refreshRepository(repoId: string, controllerHome?: string): Repo
993
1079
  repositoryType: repositoryType(canonicalRoot, rawRemote),
994
1080
  updatedAt: timestamp,
995
1081
  lastSeenAt: timestamp,
996
- configurationPath: join(canonicalRoot, LOCAL_CONFIG),
1082
+ configurationPath: registryPath(home),
997
1083
  };
998
1084
  registry.repositories[index] = refreshed;
999
1085
  registry.repositories = retireCanonicalDuplicates(registry.repositories, canonicalRoot, repoId, timestamp);
1000
1086
  saveRepositoryRegistry(registry, home);
1001
1087
  ensureRepositoryControllerLayout(home, repoId);
1002
- writeLocalIdentity(refreshed);
1003
1088
  return refreshed;
1004
1089
  }
1005
1090