@moretea-labs/forge 1.7.2 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (900) hide show
  1. package/AGENTS.md +121 -62
  2. package/CHANGELOG.md +40 -0
  3. package/CLAUDE.md +57 -62
  4. package/CONTRIBUTING.md +3 -2
  5. package/README.md +2 -2
  6. package/SKILL.md +0 -1
  7. package/THIRD_PARTY_NOTICES.md +5 -2
  8. package/adapters/browser/index.ts +2 -0
  9. package/adapters/chatgpt/browser-delivery-host.ts +77 -0
  10. package/adapters/chatgpt/browser-delivery-runtime.ts +1256 -0
  11. package/adapters/chatgpt/controller-binding-store.ts +134 -0
  12. package/adapters/chatgpt/controller-round-host.ts +68 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +99 -0
  14. package/adapters/chatgpt/provider-delivery.ts +340 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +218 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  18. package/adapters/computer/chatgpt-target-router.ts +103 -0
  19. package/adapters/computer/chrome-extension/background.js +385 -0
  20. package/adapters/computer/chrome-extension/content.js +378 -0
  21. package/adapters/computer/chrome-extension/core.js +24 -0
  22. package/adapters/computer/chrome-extension/manifest.json +30 -0
  23. package/adapters/computer/desktop-operator-contract.ts +7 -0
  24. package/adapters/computer/desktop-operator-discovery.ts +181 -0
  25. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  26. package/adapters/computer/desktop-operator-provider.ts +312 -0
  27. package/adapters/computer/index.ts +1 -0
  28. package/adapters/computer/interaction-target-authority.ts +1068 -0
  29. package/adapters/controller-process/binding-store.ts +34 -0
  30. package/adapters/controller-process/controller-host.ts +26 -0
  31. package/adapters/mcp/access-mode.ts +132 -0
  32. package/adapters/mcp/audit.ts +32 -0
  33. package/adapters/mcp/auth.ts +406 -0
  34. package/adapters/mcp/instructions.ts +37 -0
  35. package/adapters/mcp/legacy-context.ts +18 -0
  36. package/adapters/mcp/multi-repository.ts +421 -0
  37. package/adapters/mcp/oauth.ts +464 -0
  38. package/adapters/mcp/paths.ts +143 -0
  39. package/adapters/mcp/policy.ts +232 -0
  40. package/adapters/mcp/proxy-env.ts +62 -0
  41. package/adapters/mcp/readiness-projection.ts +24 -0
  42. package/adapters/mcp/redaction.ts +21 -0
  43. package/adapters/mcp/repo.ts +24 -0
  44. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  45. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  46. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  47. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  48. package/adapters/mcp/runtime-gateway/context-adapter.ts +1167 -0
  49. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  50. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +206 -0
  51. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  52. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +130 -0
  53. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  54. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  55. package/adapters/mcp/runtime-gateway/execution-tools.ts +173 -0
  56. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  57. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +412 -0
  58. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  59. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  60. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  61. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  62. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +380 -0
  63. package/adapters/mcp/runtime-gateway/process-tools.ts +457 -0
  64. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +88 -0
  65. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +285 -0
  66. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  67. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  68. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +79 -0
  69. package/adapters/mcp/runtime-gateway/result-adapter.ts +114 -0
  70. package/adapters/mcp/runtime-gateway/router.ts +242 -0
  71. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  72. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1200 -0
  73. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  74. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +574 -0
  75. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  76. package/adapters/mcp/runtime-gateway/runtime-tools.ts +78 -0
  77. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +187 -0
  78. package/adapters/mcp/runtime-gateway/shared-adapter.ts +45 -0
  79. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +962 -0
  80. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  81. package/adapters/mcp/runtime-gateway/work-adapter.ts +325 -0
  82. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  83. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  84. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  85. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  86. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  87. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  88. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  89. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  90. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  91. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  92. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  93. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  94. package/adapters/mcp/server.ts +1092 -0
  95. package/adapters/mcp/setup.ts +789 -0
  96. package/adapters/mcp/tool-capability-cache.ts +87 -0
  97. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  98. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5139 -0
  99. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +145 -0
  100. package/adapters/mcp/tool-mapping/repository-tools.ts +1682 -0
  101. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  102. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  103. package/adapters/mcp/toolset-names.ts +79 -0
  104. package/adapters/mcp/toolset-selection.ts +41 -0
  105. package/adapters/mcp/toolset.ts +337 -0
  106. package/adapters/mcp/transports/http-observation.ts +365 -0
  107. package/adapters/mcp/transports/http.ts +933 -0
  108. package/adapters/mcp/transports/oauth-http.ts +322 -0
  109. package/adapters/mcp/transports/session-registry.ts +519 -0
  110. package/adapters/mcp/transports/stdio.ts +8 -0
  111. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +223 -0
  112. package/adapters/mcp/types.ts +41 -0
  113. package/assets/AGENTS.md +2 -16
  114. package/assets/CLAUDE.md +2 -16
  115. package/assets/hooks/AGENTS.md +3 -14
  116. package/assets/hooks/CLAUDE.md +3 -14
  117. package/assets/hooks/hook-input.sh +9 -2
  118. package/assets/hooks/lib/workflow-state.sh +28 -10
  119. package/assets/hooks/prompt-guard.sh +63 -37
  120. package/assets/hooks/security-sentinel.sh +2 -1
  121. package/assets/hooks/session-start-context.sh +7 -5
  122. package/assets/hooks/stop-orchestrator.sh +13 -3
  123. package/assets/initializer-question-pack.v4.json +11 -7
  124. package/assets/partials/05-workflow.partial.md +18 -73
  125. package/assets/partials/07-footer.partial.md +1 -1
  126. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  127. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  128. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  129. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  130. package/assets/plan-map.json +11 -11
  131. package/assets/plugin-registry.v1.json +11 -3
  132. package/assets/plugin-trust-policy.v1.json +6 -0
  133. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  134. package/assets/recovery/forge-wsl-rescue +271 -0
  135. package/assets/reference-configs/agentic-development-flow.md +25 -0
  136. package/assets/reference-configs/development-protocol.md +11 -15
  137. package/assets/reference-configs/document-generation.md +1 -1
  138. package/assets/reference-configs/global-working-rules.md +28 -1
  139. package/assets/reference-configs/harness-overview.md +22 -112
  140. package/assets/reference-configs/hook-operations.md +1 -1
  141. package/assets/reference-configs/sprint-contracts.md +2 -2
  142. package/assets/skill-version.json +2 -2
  143. package/assets/templates/helpers/architecture-event.ts +3 -34
  144. package/assets/templates/helpers/architecture-queue.sh +61 -10
  145. package/assets/templates/helpers/archive-workflow.sh +90 -180
  146. package/assets/templates/helpers/capability-config.ts +8 -11
  147. package/assets/templates/helpers/capability-resolver.ts +37 -19
  148. package/assets/templates/helpers/capture-plan.sh +2 -2
  149. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  150. package/assets/templates/helpers/check-task-sync.sh +82 -11
  151. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  152. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  153. package/assets/templates/helpers/contract-worktree.sh +26 -24
  154. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  155. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  156. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  157. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  158. package/assets/templates/helpers/new-plan.sh +2 -2
  159. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  160. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  161. package/assets/templates/helpers/switch-plan.sh +1 -1
  162. package/assets/templates/helpers/workflow-contract.ts +1 -0
  163. package/assets/workflow-contract.v1.json +63 -171
  164. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  165. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  166. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  167. package/docs/architecture/CURRENT.md +233 -28
  168. package/docs/architecture/EVOLUTION.md +13 -0
  169. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  170. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  171. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  172. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  173. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  174. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  175. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +37 -0
  176. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +311 -0
  177. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  178. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  179. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  180. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  181. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  182. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  183. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  184. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  185. package/docs/architecture/domains/verification.md +8 -0
  186. package/docs/architecture/domains/workflow-engine.md +7 -1
  187. package/docs/architecture/index.md +3 -3
  188. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  189. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  190. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  191. package/docs/forge-plugin-management.md +20 -4
  192. package/docs/forge-runtime-self-healing-loop.md +2 -0
  193. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  194. package/docs/operations/controller-browser-plugin.md +3 -1
  195. package/docs/operations/controller-performance-and-502.md +17 -0
  196. package/docs/operations/controller-reliability-runbook.md +2 -2
  197. package/docs/operations/features.md +1 -1
  198. package/docs/operations/features.zh-CN.md +1 -1
  199. package/docs/operations/homebrew.md +2 -2
  200. package/docs/operations/mcp-tool-exposure.md +2 -0
  201. package/docs/operations/platform-support.md +16 -8
  202. package/docs/operations/platform-support.zh-CN.md +2 -2
  203. package/docs/operations/releasing.md +2 -0
  204. package/docs/operations/standalone-disaster-recovery.md +38 -5
  205. package/docs/operations/uu-remote-rescue.md +41 -0
  206. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  207. package/docs/public-usage-guide.md +1 -1
  208. package/docs/public-usage-guide.zh-CN.md +1 -1
  209. package/docs/tutorials/01-install-and-start.md +1 -1
  210. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  211. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  212. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  213. package/docs/wiki/Implementation.md +1 -1
  214. package/package.json +46 -26
  215. package/packages/kernel/cognition/api/index.ts +6 -0
  216. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  217. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  218. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  219. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  220. package/packages/kernel/cognition/domain/learning.ts +106 -0
  221. package/packages/kernel/cognition/domain/memory.ts +254 -0
  222. package/packages/kernel/controller/api/index.ts +3 -0
  223. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  224. package/packages/kernel/controller/application/controller-round-service.ts +41 -0
  225. package/packages/kernel/controller/application/controller-service.ts +30 -0
  226. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +529 -0
  227. package/packages/kernel/controller/domain/controller-round.ts +110 -0
  228. package/packages/kernel/controller/domain/execution-quality.ts +135 -0
  229. package/packages/kernel/controller/domain/types.ts +56 -0
  230. package/packages/kernel/controller/index.ts +1 -0
  231. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  232. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1970 -0
  233. package/packages/kernel/controller/infrastructure/controller-session-store.ts +804 -0
  234. package/packages/kernel/controller/ports/controller-host.ts +18 -0
  235. package/packages/kernel/goal/api/index.ts +1 -0
  236. package/packages/kernel/goal/domain/types.ts +40 -0
  237. package/packages/kernel/goal/index.ts +1 -0
  238. package/packages/kernel/identity/api/index.ts +15 -0
  239. package/packages/kernel/identity/application/identity-service.ts +67 -0
  240. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  241. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  242. package/packages/kernel/identity/domain/grant.ts +72 -0
  243. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  244. package/packages/kernel/identity/domain/scope.ts +63 -0
  245. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  246. package/packages/kernel/identity/domain/types.ts +44 -0
  247. package/packages/kernel/identity/domain/user-request.ts +93 -0
  248. package/packages/kernel/identity/domain/workspace.ts +56 -0
  249. package/packages/kernel/identity/index.ts +1 -0
  250. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  251. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  252. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  253. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  254. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  255. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  256. package/packages/kernel/memory/api/index.ts +5 -0
  257. package/packages/kernel/memory/application/experience-service.ts +118 -0
  258. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  259. package/packages/kernel/memory/domain/experience.ts +103 -0
  260. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  261. package/packages/kernel/memory/index.ts +1 -0
  262. package/packages/kernel/scheduler/api/index.ts +4 -0
  263. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  264. package/packages/kernel/scheduler/application/schedule-service.ts +27 -0
  265. package/packages/kernel/scheduler/application/settlement.ts +182 -0
  266. package/packages/kernel/scheduler/domain/schedule.ts +236 -0
  267. package/packages/kernel/scheduler/index.ts +1 -0
  268. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +805 -0
  269. package/packages/kernel/work/api/index.ts +16 -0
  270. package/packages/kernel/work/application/work-service.ts +123 -0
  271. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  272. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  273. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  274. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  275. package/packages/kernel/work/domain/engineering-design.ts +286 -0
  276. package/packages/kernel/work/domain/engineering-profile.ts +238 -0
  277. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  278. package/packages/kernel/work/domain/execution-concurrency.ts +247 -0
  279. package/packages/kernel/work/domain/execution-snapshot.ts +2 -0
  280. package/packages/kernel/work/domain/implementation-review.ts +193 -0
  281. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  282. package/packages/kernel/work/domain/project-engineering-contract.ts +224 -0
  283. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  284. package/{src/runtime/control-plane/facade/work-state-machine.ts → packages/kernel/work/domain/state-machine.ts} +37 -66
  285. package/packages/kernel/work/domain/types.ts +534 -0
  286. package/packages/kernel/work/index.ts +1 -0
  287. package/packages/kernel/work/infrastructure/work-contract-store.ts +1967 -0
  288. package/packages/kernel/work/ports/work-contract-store.ts +21 -0
  289. package/packages/plugin-runtime/browser/index.ts +3 -0
  290. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  291. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  292. package/packages/plugin-runtime/browser/session-authority.ts +62 -0
  293. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  294. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  295. package/packages/plugin-runtime/computer/index.ts +8 -0
  296. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  297. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  298. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  299. package/packages/plugin-runtime/computer/provider.ts +19 -0
  300. package/packages/plugin-runtime/computer/target-authority.ts +215 -0
  301. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  302. package/packages/plugin-runtime/external/index.ts +1 -0
  303. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +581 -0
  304. package/packages/plugin-runtime/index.ts +3 -0
  305. package/packages/protocols/browser/index.ts +1 -0
  306. package/packages/protocols/browser/session.ts +98 -0
  307. package/packages/protocols/computer/contract.ts +225 -0
  308. package/packages/protocols/computer/index.ts +1 -0
  309. package/packages/protocols/failure/contract.ts +158 -0
  310. package/packages/protocols/failure/index.ts +1 -0
  311. package/packages/protocols/handoff/index.ts +1 -0
  312. package/packages/protocols/handoff/status.ts +22 -0
  313. package/packages/protocols/mcp/execution-context.ts +11 -0
  314. package/packages/protocols/mcp/index.ts +2 -0
  315. package/packages/protocols/mcp/tool-contract.ts +42 -0
  316. package/packages/workflow-runtime/api/index.ts +2 -0
  317. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  318. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  319. package/packages/workflow-runtime/index.ts +1 -0
  320. package/scripts/activate-source-baseline.ts +7 -9
  321. package/scripts/assemble-template.ts +1 -1
  322. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  323. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  324. package/scripts/canary-controller-semantic-wait.ts +183 -0
  325. package/scripts/canary-global-hook.sh +2 -2
  326. package/scripts/check-mcp-compatibility.ts +85 -7
  327. package/scripts/check-platform-support.mjs +28 -2
  328. package/scripts/check-public-docs.sh +1 -1
  329. package/scripts/check-repository-hygiene.mjs +92 -0
  330. package/scripts/check-runtime-architecture.mjs +1643 -127
  331. package/scripts/check-source-duplication.mjs +9 -1
  332. package/scripts/controller-ngrok-rotation.sh +5 -4
  333. package/scripts/create-project-dirs.sh +10 -74
  334. package/scripts/forge-local-recovery-helper.mjs +282 -0
  335. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  336. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  337. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  338. package/scripts/hook-shim.sh +2 -2
  339. package/scripts/init-project.sh +12 -70
  340. package/scripts/install-desktop-operator-registration.ts +4 -2
  341. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  342. package/scripts/install-standalone-recovery.ts +122 -10
  343. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  344. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  345. package/scripts/lib/controller-home-env.sh +6 -3
  346. package/scripts/lib/project-init-lib.sh +42 -582
  347. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  348. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  349. package/scripts/open-source-audit-allowlist.txt +11 -1
  350. package/scripts/portability-bindings.mjs +70 -0
  351. package/scripts/run-bounded-command.mjs +60 -0
  352. package/scripts/run-bun-test-file.ts +22 -6
  353. package/scripts/run-governed-gate.ts +4 -2
  354. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  355. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  356. package/scripts/smoke-mcp-http-runtime.ts +6 -1
  357. package/scripts/smoke-runtime-recovery.ts +13 -11
  358. package/scripts/smoke-schedule-engine.ts +24 -16
  359. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  360. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  361. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  362. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  363. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  364. package/scripts/smoke-workflow-supervisor.ts +103 -0
  365. package/scripts/test-governance.ts +51 -2
  366. package/scripts/verify-forge-runtime.sh +2 -1
  367. package/src/cli/agent-jobs/executor-health.ts +11 -34
  368. package/src/cli/agent-jobs/integration.ts +18 -49
  369. package/src/cli/agent-jobs/job-manager.ts +17 -4
  370. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  371. package/src/cli/chatgpt-browser/binding.ts +20 -10
  372. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  373. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  374. package/src/cli/chatgpt-browser/engine.ts +10 -11
  375. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  376. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  377. package/src/cli/chatgpt-browser/types.ts +1 -0
  378. package/src/cli/commands/bootstrap-control.ts +334 -0
  379. package/src/cli/commands/brain-assistant.ts +52 -0
  380. package/src/cli/commands/brain.ts +191 -40
  381. package/src/cli/commands/chatgpt.ts +32 -67
  382. package/src/cli/commands/computer.ts +437 -0
  383. package/src/cli/commands/doctor.ts +18 -1
  384. package/src/cli/commands/init-hook.ts +71 -61
  385. package/src/cli/commands/init.ts +3 -1
  386. package/src/cli/commands/mcp.ts +16 -10
  387. package/src/cli/commands/plugin.ts +38 -12
  388. package/src/cli/commands/recovery.ts +507 -80
  389. package/src/cli/commands/runtime.ts +12 -7
  390. package/src/cli/commands/setup-profile.ts +97 -39
  391. package/src/cli/commands/status.ts +2 -1
  392. package/src/cli/controller/check-runner.ts +500 -100
  393. package/src/cli/controller/completion-backlog.ts +3 -3
  394. package/src/cli/controller/completion-orchestrator.ts +4 -43
  395. package/src/cli/controller/completion-target.ts +3 -72
  396. package/src/cli/controller/context/source-materializer.ts +81 -100
  397. package/src/cli/controller/context/types.ts +7 -1
  398. package/src/cli/controller/context-pack.ts +28 -6
  399. package/src/cli/controller/execution-completion.ts +4 -7
  400. package/src/cli/controller/execution-policy.ts +36 -153
  401. package/src/cli/controller/governance.ts +2 -3
  402. package/src/cli/controller/issue-store.ts +4 -99
  403. package/src/cli/controller/launch-agents.ts +59 -18
  404. package/src/cli/controller/operational-plan.ts +24 -51
  405. package/src/cli/controller/runtime-config.ts +5 -1
  406. package/src/cli/controller/stuck-state-migration.ts +2 -3
  407. package/src/cli/controller/systemd-user.ts +148 -0
  408. package/src/cli/controller/types.ts +10 -70
  409. package/src/cli/controller/worklog.ts +67 -13
  410. package/src/cli/editing/edit-operation-contract.ts +92 -0
  411. package/src/cli/editing/edit-session.ts +290 -20
  412. package/src/cli/github/plugin.ts +17 -12
  413. package/src/cli/hook/route-registry.ts +3 -5
  414. package/src/cli/hook/runtime.ts +49 -3
  415. package/src/cli/index.ts +3 -0
  416. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  417. package/src/cli/local-bridge/console-automations.ts +20 -15
  418. package/src/cli/local-bridge/console-view-models.ts +3 -12
  419. package/src/cli/local-bridge/facade-api.ts +105 -205
  420. package/src/cli/local-bridge/job-store.ts +1 -1
  421. package/src/cli/local-bridge/server.ts +48 -174
  422. package/src/cli/local-bridge/types.ts +0 -1
  423. package/src/cli/mcp/access-mode.ts +2 -132
  424. package/src/cli/mcp/access-tools.ts +2 -387
  425. package/src/cli/mcp/audit.ts +2 -32
  426. package/src/cli/mcp/auth.ts +2 -404
  427. package/src/cli/mcp/instructions.ts +2 -34
  428. package/src/cli/mcp/legacy-context.ts +2 -16
  429. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  430. package/src/cli/mcp/multi-repository.ts +2 -436
  431. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  432. package/src/cli/mcp/oauth.ts +2 -375
  433. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  434. package/src/cli/mcp/paths.ts +2 -140
  435. package/src/cli/mcp/policy.ts +2 -232
  436. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  437. package/src/cli/mcp/proxy-env.ts +2 -62
  438. package/src/cli/mcp/readiness-projection.ts +2 -24
  439. package/src/cli/mcp/redaction.ts +2 -21
  440. package/src/cli/mcp/repo.ts +2 -24
  441. package/src/cli/mcp/repository-tools.ts +2 -1613
  442. package/src/cli/mcp/server.ts +2 -951
  443. package/src/cli/mcp/setup.ts +2 -737
  444. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  445. package/src/cli/mcp/tool-contract.ts +2 -14
  446. package/src/cli/mcp/tools.ts +2 -9
  447. package/src/cli/mcp/toolset-names.ts +2 -70
  448. package/src/cli/mcp/toolset-selection.ts +2 -41
  449. package/src/cli/mcp/toolset.ts +2 -336
  450. package/src/cli/mcp/transports/AGENTS.md +1 -10
  451. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  452. package/src/cli/mcp/transports/http.ts +2 -1414
  453. package/src/cli/mcp/transports/session-registry.ts +2 -490
  454. package/src/cli/mcp/transports/stdio.ts +2 -8
  455. package/src/cli/mcp/types.ts +2 -41
  456. package/src/cli/mcp/umbrella-tools.ts +2 -117
  457. package/src/cli/repositories/command-executor.ts +91 -39
  458. package/src/cli/repositories/command-scope.ts +139 -4
  459. package/src/cli/repositories/controller-home.ts +167 -1
  460. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  461. package/src/cli/repositories/git-command-executor.ts +2 -2
  462. package/src/cli/repositories/identity.ts +13 -0
  463. package/src/cli/repositories/registry.ts +145 -60
  464. package/src/cli/repositories/repository-snapshot.ts +53 -7
  465. package/src/cli/repositories/runtime-storage.ts +27 -2
  466. package/src/cli/repositories/safe-patch.ts +34 -38
  467. package/src/cli/repositories/selected-path-actions.ts +22 -2
  468. package/src/cli/repositories/structured-git.ts +167 -27
  469. package/src/cli/repository/session-cache.ts +92 -6
  470. package/src/cli/runtime/helper-runner.ts +7 -0
  471. package/src/cli/runtime-invocation.ts +8 -1
  472. package/src/cli/tools/codegraph.ts +44 -25
  473. package/src/core/adoption/manifest-templates.ts +1 -1
  474. package/src/core/adoption/plan.ts +3 -26
  475. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  476. package/src/effects/process-runner.ts +8 -14
  477. package/src/runtime/context/assistant-context.ts +167 -0
  478. package/src/runtime/context/assistant-work-context.ts +209 -0
  479. package/src/runtime/context/automatic-learning.ts +565 -0
  480. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  481. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  482. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  483. package/src/runtime/context/cognitive-attention.ts +173 -0
  484. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  485. package/src/runtime/context/context-closure.ts +305 -0
  486. package/src/runtime/context/context-pack-process.ts +103 -0
  487. package/src/runtime/context/context-plane.ts +203 -0
  488. package/src/runtime/context/direct-controller-learning.ts +298 -0
  489. package/src/runtime/context/project-engineering-contract.ts +60 -0
  490. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  491. package/src/runtime/context/semantic-navigation.ts +6 -34
  492. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  493. package/src/runtime/context/typescript-navigation.ts +89 -3
  494. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  495. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  496. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  497. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  498. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  499. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  500. package/src/runtime/control-plane/cleanup-artifact-retention.ts +531 -0
  501. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  502. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +282 -0
  503. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +380 -0
  504. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +113 -16
  505. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  506. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  507. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  508. package/src/runtime/control-plane/execution/retained-work-resume.ts +439 -102
  509. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  510. package/src/runtime/control-plane/execution/validation.ts +34 -11
  511. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +87 -0
  512. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  513. package/src/runtime/control-plane/execution/work-completion-authority.ts +31 -44
  514. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  515. package/src/runtime/control-plane/execution/work-evidence-policy.ts +46 -53
  516. package/src/runtime/control-plane/execution/work-execution-support.ts +85 -164
  517. package/src/runtime/control-plane/execution/work-handle-authority.ts +349 -73
  518. package/src/runtime/control-plane/execution/work-handle-store.ts +55 -2
  519. package/src/runtime/control-plane/execution/work-head-settlement.ts +108 -0
  520. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +173 -28
  521. package/src/runtime/control-plane/execution/work-operation-service.ts +92 -40
  522. package/src/runtime/control-plane/execution/work-preparation-service.ts +145 -269
  523. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  524. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  525. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +543 -225
  526. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +59 -45
  527. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  528. package/src/runtime/control-plane/execution/work-verification-service.ts +662 -52
  529. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +205 -16
  530. package/src/runtime/control-plane/facade/capability-registry.ts +380 -44
  531. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  532. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  533. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  534. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  535. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -22
  536. package/src/runtime/control-plane/facade/goal-workloop.ts +565 -1202
  537. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +145 -0
  538. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +266 -52
  539. package/src/runtime/control-plane/facade/index.ts +4 -3
  540. package/src/runtime/control-plane/facade/operation-digest.ts +34 -73
  541. package/src/runtime/control-plane/facade/plan-contract-store.ts +671 -245
  542. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  543. package/src/runtime/control-plane/facade/repository-work-admission.ts +31 -23
  544. package/src/runtime/control-plane/facade/requirement-authority.ts +121 -0
  545. package/src/runtime/control-plane/facade/requirement-board.ts +9 -4
  546. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +85 -0
  547. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  548. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  549. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -15
  550. package/src/runtime/control-plane/facade/types.ts +218 -620
  551. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  552. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  553. package/src/runtime/control-plane/generated-cache-retention.ts +336 -19
  554. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  555. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +13 -2
  556. package/src/runtime/control-plane/global-scheduler/maintenance.ts +274 -84
  557. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  558. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  559. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -2
  560. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  561. package/src/runtime/control-plane/global-scheduler/scheduler.ts +227 -109
  562. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  563. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  564. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  565. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  566. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +160 -0
  567. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  568. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +139 -670
  569. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  570. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +25 -6
  571. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -194
  572. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  573. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  574. package/src/runtime/control-plane/persistence/experience-store.ts +302 -0
  575. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  576. package/src/runtime/control-plane/persistence/requirement-store.ts +230 -80
  577. package/src/runtime/control-plane/persistence/sqlite-store.ts +654 -78
  578. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  579. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  580. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  581. package/src/runtime/control-plane/release-retention.ts +154 -26
  582. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  583. package/src/runtime/control-plane/runtime-cleanup.ts +844 -38
  584. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  585. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  586. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +479 -0
  587. package/src/runtime/control-plane/workspace/workspace-store.ts +249 -0
  588. package/src/runtime/diagnostics/incident-repair.ts +573 -0
  589. package/src/runtime/diagnostics/mcp-timing.ts +239 -6
  590. package/src/runtime/diagnostics/performance.ts +6 -14
  591. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  592. package/src/runtime/evidence/artifact-store.ts +216 -35
  593. package/src/runtime/evidence/evidence-store.ts +112 -8
  594. package/src/runtime/evidence/operational-shadow.ts +38 -0
  595. package/src/runtime/evidence/output-handle-index.ts +225 -0
  596. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  597. package/src/runtime/evidence/result-store.ts +158 -44
  598. package/src/runtime/evidence/sensitive-output.ts +4 -4
  599. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  600. package/src/runtime/execution/jobs/store.ts +124 -6
  601. package/src/runtime/execution/managed-workspace.ts +112 -5
  602. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  603. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  604. package/src/runtime/execution/process-runtime/check-facade.ts +24 -10
  605. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  606. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  607. package/src/runtime/execution/process-runtime/check-result.ts +177 -2
  608. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +58 -9
  609. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  610. package/src/runtime/execution/process-runtime/command-facade.ts +117 -114
  611. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  612. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  613. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  614. package/src/runtime/execution/process-runtime/index.ts +4 -0
  615. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  616. package/src/runtime/execution/process-runtime/lightweight-managed.ts +283 -73
  617. package/src/runtime/execution/process-runtime/persisted-check.ts +130 -23
  618. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  619. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  620. package/src/runtime/execution/process-runtime/resource-claims.ts +125 -64
  621. package/src/runtime/execution/process-runtime/runtime.ts +167 -17
  622. package/src/runtime/execution/process-runtime/store.ts +30 -2
  623. package/src/runtime/execution/process-runtime/types.ts +27 -0
  624. package/src/runtime/execution/workers/executor.ts +18 -19
  625. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  626. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  627. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  628. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  629. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  630. package/src/runtime/gateway/mcp/router.ts +2 -1125
  631. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  632. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  633. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  634. package/src/runtime/maintenance/cleanup.ts +38 -24
  635. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  636. package/src/runtime/platform/computer-platform.ts +14 -0
  637. package/src/runtime/platform/executable-discovery.ts +54 -0
  638. package/src/runtime/platform/fetch-http-server.ts +90 -0
  639. package/src/runtime/platform/service-inventory.ts +130 -0
  640. package/src/runtime/platform/service-manager.ts +146 -0
  641. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  642. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  643. package/src/runtime/plugins/action-application.ts +192 -0
  644. package/src/runtime/plugins/app-store-connect-adapter.ts +47 -35
  645. package/src/runtime/plugins/browser-adapter.ts +898 -135
  646. package/src/runtime/plugins/browser-automation-service.ts +33 -34
  647. package/src/runtime/plugins/browser-macos-bridge.ts +386 -46
  648. package/src/runtime/plugins/browser-manifest-surface.ts +75 -17
  649. package/src/runtime/plugins/browser-native-session-service.ts +64 -14
  650. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  651. package/src/runtime/plugins/browser-registration.ts +32 -0
  652. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  653. package/src/runtime/plugins/browser-runtime.ts +55 -10
  654. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  655. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  656. package/src/runtime/plugins/browser-session-store.ts +243 -80
  657. package/src/runtime/plugins/browser-session-types.ts +2 -98
  658. package/src/runtime/plugins/capability-authorization-grants.ts +272 -59
  659. package/src/runtime/plugins/catalog-trust.ts +82 -0
  660. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  661. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  662. package/src/runtime/plugins/computer-registration.ts +1050 -0
  663. package/src/runtime/plugins/config-store.ts +119 -0
  664. package/src/runtime/plugins/desktop-operator-external-policy.ts +964 -0
  665. package/src/runtime/plugins/desktop-operator-registration.ts +123 -12
  666. package/src/runtime/plugins/errors.ts +8 -1
  667. package/src/runtime/plugins/external-adapter.ts +82 -323
  668. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  669. package/src/runtime/plugins/external-registration.ts +30 -2
  670. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  671. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  672. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  673. package/src/runtime/plugins/first-party-registry.ts +3 -1
  674. package/src/runtime/plugins/github-adapter.ts +1 -2
  675. package/src/runtime/plugins/gmail-adapter.ts +29 -8
  676. package/src/runtime/plugins/google-calendar-adapter.ts +8 -8
  677. package/src/runtime/plugins/google-shared.ts +45 -53
  678. package/src/runtime/plugins/google-tasks-adapter.ts +8 -8
  679. package/src/runtime/plugins/ios-adapter.ts +2 -3
  680. package/src/runtime/plugins/lightweight-action.ts +208 -2
  681. package/src/runtime/plugins/local-system-adapter.ts +192 -2
  682. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  683. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  684. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  685. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  686. package/src/runtime/plugins/resend-adapter.ts +15 -24
  687. package/src/runtime/plugins/store.ts +1003 -387
  688. package/src/runtime/plugins/types.ts +28 -1
  689. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  690. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  691. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  692. package/src/runtime/plugins/xiaohongshu-publish.ts +102 -430
  693. package/src/runtime/projections/controller-context.ts +12 -6
  694. package/src/runtime/projections/git-status-sampler.ts +73 -22
  695. package/src/runtime/projections/invalidation.ts +7 -3
  696. package/src/runtime/projections/materialized-view.ts +93 -43
  697. package/src/runtime/recovery/actions.ts +3 -3
  698. package/src/runtime/recovery/capability-action-application.ts +229 -0
  699. package/src/runtime/recovery/index.ts +3 -0
  700. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  701. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  702. package/src/runtime/recovery/maintenance-executor.ts +701 -168
  703. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  704. package/src/runtime/recovery/store.ts +29 -11
  705. package/src/runtime/release/identity.ts +6 -0
  706. package/src/runtime/release/release-coordinator.ts +296 -0
  707. package/src/runtime/release/release-session.ts +716 -0
  708. package/src/runtime/release/release-state-migration.ts +25 -0
  709. package/src/runtime/resources/leases/store.ts +56 -25
  710. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  711. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  712. package/src/runtime/root/browser-session-composition.ts +59 -0
  713. package/src/runtime/root/computer-composition.ts +376 -0
  714. package/src/runtime/root/computer-target-composition.ts +16 -0
  715. package/src/runtime/root/computer-target-persistence.ts +39 -0
  716. package/src/runtime/root/controller-progression-composition.ts +192 -0
  717. package/src/runtime/root/controller-round-composition.ts +126 -0
  718. package/src/runtime/root/controller-services.ts +2 -0
  719. package/src/runtime/root/deployment-topology.ts +106 -0
  720. package/src/runtime/root/entry.ts +8 -6
  721. package/src/runtime/root/gateway-adapter.ts +3 -3
  722. package/src/runtime/root/known-good-recovery.ts +184 -0
  723. package/src/runtime/root/local-bridge.ts +5 -3
  724. package/src/runtime/root/mcp-transport.ts +116 -23
  725. package/src/runtime/root/ownership.ts +261 -9
  726. package/src/runtime/root/package-connector-service.ts +212 -74
  727. package/src/runtime/root/package-runtime-release.ts +199 -33
  728. package/src/runtime/root/package-runtime-service.ts +77 -108
  729. package/src/runtime/root/release-execution-canary.ts +103 -0
  730. package/src/runtime/root/release-loader.ts +150 -0
  731. package/src/runtime/root/release-manifest.ts +185 -7
  732. package/src/runtime/root/release-materialize.ts +474 -31
  733. package/src/runtime/root/release-store.ts +425 -37
  734. package/src/runtime/root/runtime-lane.ts +191 -0
  735. package/src/runtime/root/runtime.ts +379 -32
  736. package/src/runtime/root/scheduled-controller-composition.ts +76 -0
  737. package/src/runtime/root/scheduler.ts +12 -4
  738. package/src/runtime/root/service-runner.ts +3 -3
  739. package/src/runtime/root/service.ts +73 -45
  740. package/src/runtime/root/status.ts +49 -0
  741. package/src/runtime/root/types.ts +55 -3
  742. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  743. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  744. package/src/runtime/root/write-fence.ts +50 -2
  745. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  746. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  747. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  748. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  749. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  750. package/src/runtime/shared/process-environment.ts +36 -10
  751. package/src/runtime/shared/response-budget.ts +1 -3
  752. package/src/runtime/shared/storage-capacity.ts +68 -0
  753. package/src/runtime/standalone-recovery/controller-home-migration.ts +1108 -0
  754. package/src/runtime/standalone-recovery/core.ts +4609 -495
  755. package/src/runtime/standalone-recovery/entry.ts +642 -81
  756. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  757. package/src/runtime/standalone-recovery/installer.ts +399 -177
  758. package/src/runtime/standalone-recovery/mcp-server.ts +79 -0
  759. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  760. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  761. package/src/runtime/standalone-recovery/performance.ts +173 -0
  762. package/src/runtime/standalone-recovery/release.ts +58 -5
  763. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  764. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  765. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  766. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  767. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -4
  768. package/src/runtime/workflow/schedules/engine.ts +298 -484
  769. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  770. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  771. package/src/runtime/workflow/schedules/store.ts +2 -607
  772. package/src/runtime/workflow/schedules/types.ts +2 -127
  773. package/src/runtime/workflow/schedules/work-continuation.ts +220 -16
  774. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  775. package/src/runtime/workflows/runtime.ts +482 -0
  776. package/src/testing/test-governance.ts +95 -30
  777. package/supervisor/chatgpt-conversation.ts +23 -0
  778. package/supervisor/client.ts +201 -0
  779. package/supervisor/control-plane.ts +868 -0
  780. package/supervisor/entry.ts +15 -0
  781. package/supervisor/forge-validators.ts +80 -0
  782. package/supervisor/index.ts +5 -0
  783. package/supervisor/native-browser-adapter.ts +786 -0
  784. package/supervisor/native-messaging/host.ts +39 -0
  785. package/supervisor/native-messaging/manifest.ts +26 -0
  786. package/supervisor/native-messaging/protocol.ts +27 -0
  787. package/supervisor/paths.ts +18 -0
  788. package/supervisor/protocol.ts +202 -0
  789. package/supervisor/server.ts +404 -0
  790. package/supervisor/store.ts +1451 -0
  791. package/supervisor/tsconfig.json +8 -0
  792. package/supervisor/types.ts +255 -0
  793. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  794. package/docs/architecture/history/README.md +0 -7
  795. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  796. package/docs/architecture/history/global-hook-runtime.md +0 -166
  797. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  798. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  799. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  800. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  801. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  802. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  803. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  804. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  805. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  806. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  807. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  808. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  809. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  810. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  811. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  812. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  813. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  814. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  815. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  816. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  817. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  818. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  819. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  820. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  821. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  822. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  823. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  824. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  825. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  826. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  827. package/docs/architecture/requests/archive/2026/root.md +0 -68
  828. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  829. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  830. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  831. package/scripts/archive-architecture-request.sh +0 -4
  832. package/scripts/benchmark-background-check-overlap.ts +0 -228
  833. package/scripts/benchmark-controller-hotpath.ts +0 -212
  834. package/scripts/benchmark-controller-round2.ts +0 -139
  835. package/scripts/benchmark-ios-agent-device.ts +0 -514
  836. package/scripts/benchmark-mcp-host.sh +0 -117
  837. package/scripts/benchmark-mcp-transport.ts +0 -170
  838. package/scripts/benchmark-quality-harness.ts +0 -146
  839. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  840. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  841. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  842. package/scripts/benchmark-thin-harness.ts +0 -251
  843. package/scripts/benchmark-typescript-navigation.ts +0 -186
  844. package/scripts/benchmark-work-efficiency.ts +0 -334
  845. package/scripts/build-controller-ui.ts +0 -28
  846. package/scripts/check-npm-release.sh +0 -32
  847. package/scripts/check-public-release-surface.sh +0 -19
  848. package/scripts/check-release-published.sh +0 -57
  849. package/scripts/check-release-readiness.sh +0 -37
  850. package/scripts/check-release-version.mjs +0 -74
  851. package/scripts/check-tarball-install-smoke.sh +0 -67
  852. package/scripts/package-source-archive.sh +0 -147
  853. package/scripts/public-release-files.txt +0 -39
  854. package/scripts/public-release.ts +0 -174
  855. package/scripts/publish-release-tarball.sh +0 -27
  856. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  857. package/scripts/run-skill-evals.ts +0 -1022
  858. package/scripts/stage-runtime-release.ts +0 -39
  859. package/src/cli/controller/progress.ts +0 -656
  860. package/src/cli/controller/work-mode.ts +0 -181
  861. package/src/cli/local-bridge/console-assets.ts +0 -17
  862. package/src/cli/local-bridge/dashboard.ts +0 -17
  863. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  864. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  865. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  866. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  867. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  868. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  869. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  870. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  871. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  872. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  873. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  874. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  875. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  876. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  877. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  878. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  879. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  880. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  881. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  882. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  883. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  884. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  885. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  886. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  887. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  888. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  889. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  890. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  891. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -385
  892. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -1913
  893. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  894. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -449
  895. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -1118
  896. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -93
  897. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  898. package/src/runtime/control-plane/routing/index.ts +0 -1
  899. package/src/runtime/control-plane/routing/route-policy.ts +0 -382
  900. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -1,1613 +1,2 @@
1
- import { bindRepositoryEntities } from '../repositories/entity-migration';
2
- import { bootstrapLocalProject, diagnoseLatestLocalProjectSource } from '../repositories/local-project-onboarding';
3
- import { resolveEphemeralWorkspaceTarget } from '../repositories/ephemeral-workspace';
4
- import type { ResolvedExecutionIdentity } from '../../runtime/control-plane/execution/execution-identity';
5
- import { assertNoBoundExecutionSessionMutation, resolveClaimedRepositoryWorkId, resolveExplicitClaimedRepositoryWork, type RepositoryWorkAttributionCaller } from '../../runtime/control-plane/execution/repository-work-attribution';
6
- import { getWorkContract } from '../../runtime/control-plane/facade/work-contract-store';
7
- import { assertWorkPathsWithinScope } from '../../runtime/control-plane/execution/work-path-scope';
8
- import { ensureRepositoryMutationWorkHandle } from '../../runtime/control-plane/execution/work-handle-authority';
9
- import { isTerminalWorkContractStatus } from '../../runtime/control-plane/facade/types';
10
- import { executeRepositoryCommand, previewRepositoryCommandExecution } from '../repositories/command-executor';
11
- import { withControllerLock } from '../repositories/locks';
12
- import {
13
- disableRepository,
14
- findIdenticalRepositoryRegistration,
15
- getRepository,
16
- listRepositories,
17
- reconcileRepositoryCheckouts,
18
- refreshRepository,
19
- registerRepository,
20
- removeRepository,
21
- repositorySummary,
22
- resolveRepositorySelection,
23
- updateRepository,
24
- validateRepository,
25
- } from '../repositories/registry';
26
- import { buildControllerWorkbench } from '../repositories/workbench';
27
- import { applySafePatch, buildSafePatchPlan } from '../repositories/safe-patch';
28
- import { getEditSession, getEditSessionDiff, type EditSessionBinding } from '../editing/edit-session';
29
- import { buildSyncOperationDigest, classifyUserFacingError } from '../../runtime/control-plane/facade/operation-digest';
30
- import {
31
- repositoryGitCommit,
32
- repositoryGitCreateBranch,
33
- repositoryGitDeleteBranch,
34
- repositoryGitDiff,
35
- repositoryGitFinishWorkflow,
36
- repositoryGitMergeBranch,
37
- repositoryGitStatus,
38
- repositoryGitSwitchBranch,
39
- } from '../repositories/structured-git';
40
- import {
41
- readRepositoryGitStatusSample,
42
- writeRepositoryGitStatusSample,
43
- } from '../../runtime/projections/git-status-sampler';
44
- import {
45
- executeLightweightLanes,
46
- executeRepositoryBatch,
47
- integratePatchProposals,
48
- listFastReceipts,
49
- readFastReceipt,
50
- routeExecution,
51
- } from '../../runtime/execution/thin-harness';
52
- import {
53
- classifyRepositoryCommandRoute,
54
- executeRepositoryCommandViaProcessRuntime,
55
- } from '../../runtime/execution/process-runtime/command-facade';
56
- import { assessWorkMode, parseExplicitTaskMode } from '../controller/work-mode';
57
- import { classifyRepositoryCommand } from '../repositories/command-classifier';
58
- import { normalizeRepositoryCommand } from '../repositories/command-normalization';
59
- import { readRepositoryRange } from '../repository/inspector';
60
- import { getMcpPolicy } from './policy';
61
- import { redactMcpText } from './redaction';
62
- import type { CallToolResult, McpToolDefinition } from './tool-contract';
63
- import {
64
- boundUtf8,
65
- compactCommandOutput,
66
- compactErrorMessage,
67
- compactRoutingSummary,
68
- RESPONSE_BUDGET,
69
- } from '../../runtime/shared/response-budget';
70
-
71
- export type RepositoryToolResult = CallToolResult;
72
-
73
- function definition(
74
- name: string,
75
- description: string,
76
- properties: Record<string, unknown>,
77
- required: string[] = [],
78
- readOnlyHint = false,
79
- destructiveHint = false,
80
- ): McpToolDefinition {
81
- return {
82
- name,
83
- description,
84
- inputSchema: {
85
- type: 'object',
86
- properties,
87
- ...(required.length > 0 ? { required } : {}),
88
- additionalProperties: false,
89
- },
90
- annotations: { readOnlyHint, openWorldHint: false, destructiveHint },
91
- };
92
- }
93
-
94
- const repoId = { type: 'string', description: 'Stable Repository Registry repoId.' };
95
-
96
- export const repositoryToolDefinitions: McpToolDefinition[] = [
97
- definition('repository_register', 'Register a Git repository with the Controller.', {
98
- path: { type: 'string' },
99
- display_name: { type: 'string' },
100
- remote_url: { type: 'string' },
101
- default_branch: { type: 'string' },
102
- detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full checkout and migration evidence.' },
103
- }, ['path']),
104
- definition('repository_latest_source_diagnose', 'Read-only diagnosis that compares sibling project directories and recommends the latest usable source tree.', {
105
- path: { type: 'string', description: 'Absolute local project path.' },
106
- repo_id: repoId,
107
- }, [], true),
108
- definition('repository_bootstrap_local_project', 'Safely initialize and optionally register a trusted non-Git local project directory.', {
109
- path: { type: 'string', description: 'Absolute local project path.' },
110
- display_name: { type: 'string' },
111
- default_branch: { type: 'string' },
112
- mode: { type: 'string', enum: ['init_git_only', 'init_git_and_register', 'replace_registration'] },
113
- replace_registered_repo_id: repoId,
114
- confirm_authorization: { type: 'boolean', description: 'Must be true to authorize Git initialization and registration.' },
115
- }, ['path', 'confirm_authorization'], false, true),
116
- definition('repository_list', 'List registered repositories.', {
117
- include_removed: { type: 'boolean' },
118
- }, [], true),
119
- definition('repository_get', 'Inspect one registered repository.', {
120
- repo_id: repoId,
121
- include_removed: { type: 'boolean' },
122
- detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns the complete checkout history.' },
123
- }, ['repo_id'], true),
124
- definition('read_repository_file', 'Read a line range from one policy-readable repository file.', {
125
- repo_id: repoId,
126
- checkout_id: { type: 'string' },
127
- path: { type: 'string' },
128
- start_line: { type: 'number' },
129
- end_line: { type: 'number' },
130
- }, ['path'], true),
131
- definition('repository_validate', 'Validate repository identity and migrate legacy ownership.', {
132
- repo_id: repoId,
133
- detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full migration evidence.' },
134
- }, ['repo_id']),
135
- definition('repository_refresh', 'Refresh repository Git and checkout metadata.', {
136
- repo_id: repoId,
137
- detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full checkout and migration evidence.' },
138
- }, ['repo_id']),
139
- definition('repository_update', 'Update mutable repository metadata.', {
140
- repo_id: repoId,
141
- display_name: { type: 'string' },
142
- default_branch: { type: 'string' },
143
- enabled: { type: 'boolean' },
144
- }, ['repo_id']),
145
- definition('repository_disable', 'Disable new execution while retaining audit history.', {
146
- repo_id: repoId,
147
- }, ['repo_id']),
148
- definition('repository_remove', 'Soft-remove a repository while retaining audit history.', {
149
- repo_id: repoId,
150
- }, ['repo_id']),
151
- definition('repository_workbench', 'Return Workbench state or invoke one bounded Thin Harness operation without adding top-level MCP tools. Prefer batch_execute for multi-step status→search→read→diff or read→patch→check flows so ChatGPT pays one routing/receipt ownership cycle.', {
152
- repo_id: repoId,
153
- checkout_id: { type: 'string', description: 'Optional checkout identity for repository-scoped operations.' },
154
- include_removed: { type: 'boolean' },
155
- operation: {
156
- type: 'string',
157
- enum: ['summary', 'batch_execute', 'lanes_execute', 'lanes_integrate', 'fast_receipt_get', 'fast_receipt_list', 'execution_route', 'assess_work_mode'],
158
- description: 'Defaults to summary. Use batch_execute for multi-step Fast Path (one parent receipt). Use lanes_execute for limited parallel reads. Use assess_work_mode for Fast/Durable routing advice.',
159
- },
160
- payload: {
161
- type: 'object',
162
- description: 'Operation-specific bounded arguments. Batch write operations should include request_id. For batch_execute: { steps:[{id?, kind, input}], stop_on_error?, allowed_paths?, timeout_ms?, request_id?, purpose? }. For assess_work_mode: { description, known_paths?, expected_files?, requires_parallelism?, independent_task_count?, agent_requested? }. Agent routing is opt-in only.',
163
- additionalProperties: true,
164
- },
165
- }),
166
- definition('repository_git_status', 'Return a structured Git status snapshot for the selected repository checkout.', {
167
- repo_id: repoId,
168
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
169
- refresh: { type: 'boolean', description: 'When true, explicitly refresh the Git status sample. The default public hot path only reads the latest daemon sample.' },
170
- }, [], true),
171
-
172
- definition('repository_git_diff', 'Return a bounded structured git diff for the selected repository, optionally staged and path-scoped.', {
173
- repo_id: repoId,
174
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
175
- staged: { type: 'boolean' },
176
- paths: { type: 'array', items: { type: 'string' } },
177
- max_bytes: { type: 'number' },
178
- }, [], true),
179
- definition('repository_git_create_branch', 'Create a safe local Git branch, optionally switching to it.', {
180
- repo_id: repoId,
181
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
182
- branch: { type: 'string' },
183
- start_point: { type: 'string' },
184
- switch_to: { type: 'boolean', description: 'Defaults to true. False creates the branch without switching.' },
185
- }, ['branch']),
186
- definition('repository_git_switch_branch', 'Switch to a safe local Git branch name.', {
187
- repo_id: repoId,
188
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
189
- branch: { type: 'string' },
190
- }, ['branch']),
191
- definition('repository_git_merge_branch', 'Merge a branch into the current branch using --ff-only by default.', {
192
- repo_id: repoId,
193
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
194
- branch: { type: 'string' },
195
- no_ff: { type: 'boolean', description: 'Use --no-ff instead of the default --ff-only.' },
196
- }, ['branch']),
197
- definition('repository_git_delete_branch', 'Delete a safe local Git branch after it has been merged or intentionally discarded.', {
198
- repo_id: repoId,
199
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
200
- branch: { type: 'string' },
201
- force: { type: 'boolean' },
202
- }, ['branch']),
203
-
204
- definition('repository_git_commit', 'Stage optional explicit paths and commit through a structured Git action.', {
205
- repo_id: repoId,
206
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
207
- message: { type: 'string' },
208
- paths: { type: 'array', items: { type: 'string' } },
209
- allow_empty: { type: 'boolean' },
210
- }, ['message']),
211
- definition('repository_git_finish_workflow', 'Finish the current feature workflow: require clean tree, switch to target, merge feature branch, and delete it by default.', {
212
- repo_id: repoId,
213
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
214
- feature_branch: { type: 'string', description: 'Defaults to the current branch.' },
215
- target_branch: { type: 'string', description: 'Defaults to repository defaultBranch or main.' },
216
- delete_branch: { type: 'boolean', description: 'Defaults to true.' },
217
- no_ff: { type: 'boolean', description: 'Use --no-ff instead of the default --ff-only.' },
218
- }, []),
219
- definition('repository_safe_patch_plan', 'Plan a deterministic chunked repository patch with fresh file fingerprints before applying.', {
220
- repo_id: repoId,
221
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
222
- operations: { type: 'array', items: { type: 'object' }, description: 'Edit operations using the same shape as apply_patch.' },
223
- chunk_size: { type: 'number', description: 'Maximum operations per deterministic chunk. Capped at 100.' },
224
- }, ['operations'], true),
225
- definition('repository_safe_patch_apply', 'Apply one coherent deterministic edit batch and return bounded review evidence. Checks are opt-in: pass check_ids only when the batch is stable. Long checks return managed Process handles instead of blocking the MCP call; use validation_only with the returned session/request ids to join later without replaying the patch.', {
226
- repo_id: repoId,
227
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
228
- work_id: { type: 'string', description: 'Optional durable Work identity. Workflow controllers should pass the exact claimed Work id so attribution survives transient MCP transport sessions.' },
229
- session_id: { type: 'string', description: 'Existing edit session id. Required for validation_only; otherwise omit to create one.' },
230
- purpose: { type: 'string', description: 'Purpose for a newly created edit session.' },
231
- operations: { type: 'array', items: { type: 'object' }, description: 'Edit operations using the same shape as apply_patch. Required unless validation_only=true.' },
232
- chunk_size: { type: 'number', description: 'Maximum operations per deterministic chunk. Capped at 100.' },
233
- expected_revision: { type: 'number', description: 'Expected starting edit-session revision.' },
234
- allowed_paths: { type: 'array', items: { type: 'string' }, description: 'Optional allowed path globs for a newly created session.' },
235
- continue_on_error: { type: 'boolean', description: 'Continue applying later independent chunks after a failed chunk. Defaults to false.' },
236
- refresh_fingerprints: { type: 'boolean', description: 'Refresh file fingerprints before every chunk. Defaults to true.' },
237
- recover_stale_session: { type: 'boolean', description: 'For new sessions, recover stale edit-session fingerprints into a fresh session. Defaults to true.' },
238
- check_ids: { type: 'array', items: { type: 'string' }, description: 'Optional focused validation for this stable coherent edit batch. Omit to edit without running tests.' },
239
- check_timeout_ms: { type: 'number', description: 'Per-check execution budget. Long checks still return managed handles immediately.' },
240
- lease_wait_ms: { type: 'number', description: 'Bounded resource-lease wait for conflicting validation lanes.' },
241
- validation_request_id: { type: 'string', description: 'Stable validation identity returned by a prior edit+validation call; reuse with validation_only to join without replaying edits.' },
242
- validation_only: { type: 'boolean', description: 'When true, do not edit. Reconcile/reuse the existing session validation Processes identified by session_id/check_ids/validation_request_id.' },
243
- apply_mode: { type: 'string', enum: ['sync', 'async'], description: 'Defaults to sync for interactive development. Set async only for a separately durable operation.' },
244
- }),
245
- definition('repository_command_preview', 'Preview one repository-scoped local command with classification, approval token, and Git snapshots.', {
246
- repo_id: repoId,
247
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
248
- command: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }], description: 'Legacy shell string or typed argv array. Typed argv executes without a shell.' },
249
- cwd: { type: 'string', description: 'Optional root-relative working directory.' },
250
- workspace_root: { type: 'string', description: 'Absolute existing local directory used as an ephemeral execution root. Mutually exclusive with repo_id/checkout_id; does not register or initialize the directory.' },
251
- }, ['command'], true),
252
- definition('repository_command_execute', 'Execute one repository-scoped command through the thinnest eligible lane: ephemeral for ordinary local work, an in-memory lightweight handle when it outlives the interaction budget, or explicit Durable handling for Work/external/release effects. Lightweight handles have no SQLite, Lease, recovery, or replay membership. Use rh_context for routine code discovery/reading; shell exploration is fallback-only.', {
253
- repo_id: repoId,
254
- checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
255
- work_id: { type: 'string', description: 'Optional durable Work identity. Workflow controllers should pass the exact claimed Work id so attribution survives transient MCP transport sessions.' },
256
- command: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }], description: 'Legacy shell string or typed argv array. Typed argv executes without a shell.' },
257
- cwd: { type: 'string', description: 'Optional root-relative working directory.' },
258
- workspace_root: { type: 'string', description: 'Absolute existing local directory used as an ephemeral execution root. Mutually exclusive with repo_id/checkout_id; does not register or initialize the directory.' },
259
- approval_token: { type: 'string', description: 'Exact approval token returned by repository_command_preview.' },
260
- approval_request_id: { type: 'string', description: 'Resolved approvalRequestId returned by approval_resolve.' },
261
- timeout_ms: { type: 'number', description: 'Optional execution timeout in milliseconds.' },
262
- max_output_bytes: { type: 'number', description: 'Optional cap for captured stdout/stderr.' },
263
- }, ['command']),
264
-
265
- // Thin Harness V1 is exposed through repository_workbench operations to keep the stable tool surface bounded.
266
- ];
267
-
268
- export const repositoryToolNames = repositoryToolDefinitions.map((tool) => tool.name);
269
-
270
- function result(value: Record<string, unknown>): RepositoryToolResult {
271
- // Compact text channel by default; structuredContent remains the machine view.
272
- return {
273
- content: [{ type: 'text', text: JSON.stringify(value) }],
274
- structuredContent: value,
275
- };
276
- }
277
-
278
- const DEFAULT_MIGRATION_SAMPLE_LIMIT = 3;
279
-
280
- function withResponseMeta(payload: Record<string, unknown>, startedAt: number): Record<string, unknown> {
281
- const response = {
282
- ...payload,
283
- responseMeta: {
284
- serverDurationMs: Math.round((performance.now() - startedAt) * 100) / 100,
285
- structuredPayloadBytes: 0,
286
- },
287
- };
288
- response.responseMeta.structuredPayloadBytes = Buffer.byteLength(JSON.stringify(response), 'utf8');
289
- return response;
290
- }
291
-
292
- export type RepositoryToolCallerContext = RepositoryWorkAttributionCaller;
293
-
294
- export function claimedSessionEditBinding(
295
- controllerHome: string,
296
- repository: ReturnType<typeof resolveRepositorySelection>,
297
- caller?: RepositoryToolCallerContext,
298
- explicitWorkId?: unknown,
299
- ): EditSessionBinding | undefined {
300
- const workId = resolveClaimedRepositoryWorkId(controllerHome, repository, caller, explicitWorkId);
301
- if (!workId || !caller?.principalId?.trim()) return undefined;
302
- const work = getWorkContract({ controllerHome, repoId: repository.repoId }, workId);
303
- if (!work) return undefined;
304
- return {
305
- workId,
306
- repoId: repository.repoId,
307
- checkoutId: repository.activeCheckoutId,
308
- principalId: caller.principalId.trim(),
309
- controllerInstanceId: caller.controllerInstanceId,
310
- routeDecisionFingerprint: work.routeDecisionFingerprint,
311
- };
312
- }
313
-
314
- function safePatchEditBinding(
315
- controllerHome: string,
316
- repository: ReturnType<typeof resolveRepositorySelection>,
317
- caller: RepositoryToolCallerContext | undefined,
318
- args: Record<string, unknown>,
319
- ): EditSessionBinding | undefined {
320
- const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
321
- if (explicitWorkId) return claimedSessionEditBinding(controllerHome, repository, caller, explicitWorkId);
322
- const sessionId = typeof args.session_id === 'string' ? args.session_id.trim() : '';
323
- if (sessionId) {
324
- const existingWorkId = getEditSession(repository.canonicalRoot, sessionId).workId?.trim();
325
- return existingWorkId
326
- ? claimedSessionEditBinding(controllerHome, repository, caller, existingWorkId)
327
- : undefined;
328
- }
329
- assertNoBoundExecutionSessionMutation(controllerHome, repository, caller);
330
- return undefined;
331
- }
332
-
333
- function resolveRepositorySelectionForClaimedWork(
334
- controllerHome: string,
335
- args: Record<string, unknown>,
336
- repoIdValue: string,
337
- caller?: RepositoryToolCallerContext,
338
- ): ReturnType<typeof resolveRepositorySelection> {
339
- const checkoutId = typeof args.checkout_id === 'string' ? args.checkout_id.trim() : '';
340
- const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
341
- const repository = resolveRepositorySelection({
342
- repoId: repoIdValue || undefined,
343
- checkoutId: checkoutId || undefined,
344
- controllerHome,
345
- allowSoleRepository: true,
346
- });
347
- if (!explicitWorkId || checkoutId) return repository;
348
- const work = resolveExplicitClaimedRepositoryWork(controllerHome, repository, caller, explicitWorkId);
349
- if (!work?.checkoutId || work.checkoutId === repository.activeCheckoutId) return repository;
350
- return resolveRepositorySelection({
351
- repoId: repository.repoId,
352
- checkoutId: work.checkoutId,
353
- controllerHome,
354
- allowSoleRepository: true,
355
- });
356
- }
357
-
358
- function rawDefaultBranchMergeCommand(repository: ReturnType<typeof resolveRepositorySelection>, command: unknown): boolean {
359
- if (!repository.defaultBranch) return false;
360
- const checkout = repository.checkouts.find((entry) => entry.checkoutId === repository.activeCheckoutId);
361
- if (checkout?.branch !== repository.defaultBranch) return false;
362
- const normalized = normalizeRepositoryCommand(command);
363
- if (normalized.kind === 'argv') {
364
- const executable = normalized.executable?.split('/').pop();
365
- return executable === 'git' && normalized.args?.[0] === 'merge';
366
- }
367
- return /(?:^|[;&|]\s*)git\s+merge\b/.test(normalized.shellCommand ?? '');
368
- }
369
-
370
- interface HistoricalReadOnlyWorkContext {
371
- workId: string;
372
- status: string;
373
- mode: 'historical_read_only_observation';
374
- attribution: 'not_active_work';
375
- }
376
-
377
- function historicalReadOnlyWorkContext(
378
- controllerHome: string,
379
- repository: ReturnType<typeof resolveRepositorySelection>,
380
- args: Record<string, unknown>,
381
- ): HistoricalReadOnlyWorkContext | undefined {
382
- const requestedWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
383
- if (!requestedWorkId) return undefined;
384
- const work = getWorkContract({ controllerHome, repoId: repository.repoId }, requestedWorkId);
385
- if (!work || !isTerminalWorkContractStatus(work.status)) return undefined;
386
- const classification = classifyRepositoryCommand(args.command as string | string[], repository.defaultBranch);
387
- if (classification.risk !== 'readonly') return undefined;
388
- return {
389
- workId: work.workId,
390
- status: work.status,
391
- mode: 'historical_read_only_observation',
392
- attribution: 'not_active_work',
393
- };
394
- }
395
-
396
- function resolveRepositoryCommandTarget(
397
- controllerHome: string,
398
- args: Record<string, unknown>,
399
- repoIdValue: string,
400
- caller?: RepositoryToolCallerContext,
401
- ): {
402
- repository: ReturnType<typeof resolveRepositorySelection>;
403
- executionIdentity: ResolvedExecutionIdentity;
404
- workspace?: { workspaceId: string; root: string; registered: false };
405
- historicalWorkContext?: HistoricalReadOnlyWorkContext;
406
- } {
407
- const workspaceRoot = typeof args.workspace_root === 'string' ? args.workspace_root.trim() : '';
408
- const checkoutId = typeof args.checkout_id === 'string' ? args.checkout_id.trim() : '';
409
- if (workspaceRoot) {
410
- if (repoIdValue || checkoutId) {
411
- throw new Error('EPHEMERAL_WORKSPACE_TARGET_CONFLICT: workspace_root cannot be combined with repo_id or checkout_id');
412
- }
413
- const target = resolveEphemeralWorkspaceTarget(workspaceRoot, controllerHome);
414
- return {
415
- repository: target.repository,
416
- executionIdentity: {
417
- schemaVersion: 1,
418
- authority: 'ephemeral_workspace',
419
- repositoryId: target.workspaceId,
420
- checkoutId: target.checkoutId,
421
- canonicalRoot: target.canonicalRoot,
422
- },
423
- workspace: { workspaceId: target.workspaceId, root: target.canonicalRoot, registered: false },
424
- };
425
- }
426
- // A terminal Work no longer owns mutation or checkout authority. An exact
427
- // terminal work_id may still accompany a read-only observation immediately
428
- // after finalize, so preserve it as explicit historical context while
429
- // executing against the caller-selected/current repository checkout. Any
430
- // non-read-only command continues through claimed Work resolution and fails
431
- // closed for terminal attribution.
432
- const selectedRepository = resolveRepositorySelection({
433
- repoId: repoIdValue || undefined,
434
- checkoutId: checkoutId || undefined,
435
- controllerHome,
436
- allowSoleRepository: true,
437
- });
438
- const historicalWorkContext = historicalReadOnlyWorkContext(controllerHome, selectedRepository, args);
439
- if (historicalWorkContext) {
440
- return {
441
- repository: selectedRepository,
442
- executionIdentity: {
443
- schemaVersion: 1,
444
- authority: 'repository',
445
- repositoryId: selectedRepository.repoId,
446
- checkoutId: selectedRepository.activeCheckoutId,
447
- canonicalRoot: selectedRepository.canonicalRoot,
448
- },
449
- historicalWorkContext,
450
- };
451
- }
452
-
453
- const repository = resolveRepositorySelectionForClaimedWork(controllerHome, args, repoIdValue, caller);
454
- const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
455
- const workId = explicitWorkId
456
- ? resolveClaimedRepositoryWorkId(controllerHome, repository, caller, explicitWorkId)
457
- : undefined;
458
- return {
459
- repository,
460
- executionIdentity: {
461
- schemaVersion: 1,
462
- authority: 'repository',
463
- repositoryId: repository.repoId,
464
- checkoutId: repository.activeCheckoutId,
465
- canonicalRoot: repository.canonicalRoot,
466
- ...(workId ? { workId } : {}),
467
- },
468
- };
469
- }
470
-
471
- export function summarizeEntityMigrationReport(
472
- report: ReturnType<typeof bindRepositoryEntities>,
473
- detail = false,
474
- ): ReturnType<typeof bindRepositoryEntities> | Record<string, unknown> {
475
- if (detail) return report;
476
- const files = report.files.slice(0, DEFAULT_MIGRATION_SAMPLE_LIMIT);
477
- const errors = report.errors.slice(0, DEFAULT_MIGRATION_SAMPLE_LIMIT);
478
- return {
479
- repoId: report.repoId,
480
- checkoutId: report.checkoutId,
481
- scanned: report.scanned,
482
- updated: report.updated,
483
- unresolved: report.unresolved,
484
- fileCount: report.files.length,
485
- errorCount: report.errors.length,
486
- files,
487
- errors,
488
- truncated: report.files.length > files.length || report.errors.length > errors.length,
489
- omittedFileCount: Math.max(0, report.files.length - files.length),
490
- omittedErrorCount: Math.max(0, report.errors.length - errors.length),
491
- };
492
- }
493
-
494
- export function summarizeRepositoryRegistration(
495
- repository: ReturnType<typeof registerRepository>,
496
- migration: ReturnType<typeof bindRepositoryEntities>,
497
- detail = false,
498
- fastPath = false,
499
- ): Record<string, unknown> {
500
- if (detail) {
501
- return { detailLevel: 'detail', repository, migration, fastPath };
502
- }
503
- const checkoutCounts = repository.checkouts.reduce<Record<string, number>>((counts, checkout) => {
504
- const lifecycle = checkout.lifecycle ?? 'active';
505
- counts[lifecycle] = (counts[lifecycle] ?? 0) + 1;
506
- return counts;
507
- }, {});
508
- return {
509
- detailLevel: 'summary',
510
- repository: {
511
- ...repositorySummary(repository),
512
- activeCheckoutId: repository.activeCheckoutId,
513
- checkoutCount: repository.checkouts.length,
514
- checkoutCounts,
515
- },
516
- migration: summarizeEntityMigrationReport(migration),
517
- fastPath,
518
- next: 'Re-call with detail_level=detail only when full checkout or migration evidence is required.',
519
- };
520
- }
521
-
522
- export function summarizeRepositoryInspection(
523
- repository: ReturnType<typeof getRepository>,
524
- detail = false,
525
- ): Record<string, unknown> {
526
- if (detail) return { detailLevel: 'detail', repository };
527
- const checkoutCounts = repository.checkouts.reduce<Record<string, number>>((counts, checkout) => {
528
- const lifecycle = checkout.lifecycle ?? 'active';
529
- counts[lifecycle] = (counts[lifecycle] ?? 0) + 1;
530
- return counts;
531
- }, {});
532
- const activeCheckout = repository.checkouts.find((checkout) => checkout.checkoutId === repository.activeCheckoutId);
533
- return {
534
- detailLevel: 'summary',
535
- repository: {
536
- ...repositorySummary(repository),
537
- activeCheckoutId: repository.activeCheckoutId,
538
- ...(activeCheckout ? { activeCheckout } : {}),
539
- checkoutCount: repository.checkouts.length,
540
- checkoutCounts,
541
- },
542
- omittedCheckoutCount: Math.max(0, repository.checkouts.length - (activeCheckout ? 1 : 0)),
543
- next: 'Re-call with detail_level=detail only when complete checkout history is required.',
544
- };
545
- }
546
-
547
- function failure(error: unknown): RepositoryToolResult {
548
- const message = compactErrorMessage(error);
549
- const code = message.includes(':') ? message.slice(0, message.indexOf(':')) : 'REPOSITORY_TOOL_FAILED';
550
- const details = typeof error === 'object' && error !== null && 'details' in error ? (error as { details?: unknown }).details : undefined;
551
- const compactDetails = details !== undefined && Buffer.byteLength(JSON.stringify(details) ?? '', 'utf8') > RESPONSE_BUDGET.previewBytes
552
- ? { omitted: true, message: 'Error details exceeded budget; inspect job/artifact/result refs.' }
553
- : details;
554
- return { ...result({ error: { code, message, ...(compactDetails !== undefined ? { details: compactDetails } : {}) } }), isError: true };
555
- }
556
-
557
- interface RepositoryExplorationGuidance {
558
- code: 'FRAGMENTED_REPOSITORY_EXPLORATION';
559
- recommendedTool: 'rh_context';
560
- recommendedOperation: 'search';
561
- message: string;
562
- }
563
-
564
- function fragmentedRepositoryExplorationGuidance(command: unknown): RepositoryExplorationGuidance | undefined {
565
- if (typeof command !== 'string') return undefined;
566
- const segments = command.split(/(?:&&|\|\||[;|])/g);
567
- const readPrograms = new Set<string>();
568
- let readStepCount = 0;
569
- for (const segment of segments) {
570
- const match = segment.trim().match(/^(?:(?:command|env)\s+)?(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*(rg|grep|sed|cat|head|tail)\b/i);
571
- if (!match) continue;
572
- readStepCount += 1;
573
- readPrograms.add(match[1]!.toLowerCase());
574
- }
575
- if (readStepCount < 2) return undefined;
576
- return {
577
- code: 'FRAGMENTED_REPOSITORY_EXPLORATION',
578
- recommendedTool: 'rh_context',
579
- recommendedOperation: 'search',
580
- message: `Detected ${readStepCount} chained repository read steps (${[...readPrograms].join(', ')}). Prefer a broad rh_context request first, then repeat rh_context with selected paths or relationships when more evidence can improve correctness; keep shell search as fallback when the Context Plane cannot supply the needed evidence.`,
581
- };
582
- }
583
-
584
- function compactProcessCommandPayload(input: {
585
- accepted?: boolean;
586
- mode: string;
587
- path: string;
588
- route?: string;
589
- reasons: string[];
590
- decision?: unknown;
591
- repoId: string;
592
- checkoutId?: string;
593
- workspace?: { workspaceId: string; root: string; registered: false };
594
- historicalWorkContext?: HistoricalReadOnlyWorkContext;
595
- processId?: string;
596
- process?: unknown;
597
- completed?: boolean;
598
- ok?: boolean;
599
- exitCode?: number | null;
600
- stdout?: string;
601
- stderr?: string;
602
- durableSideEffects?: Record<string, number>;
603
- next: string;
604
- /** summary (default) omits nested process / routing dumps; detail restores diagnostics. */
605
- detailLevel?: 'summary' | 'detail';
606
- includeFullProcess?: boolean;
607
- guidance?: RepositoryExplorationGuidance;
608
- }): Record<string, unknown> {
609
- const output = compactCommandOutput(input.stdout, input.stderr, { ok: input.ok === true });
610
- const detail = input.detailLevel === 'detail' || input.includeFullProcess === true;
611
- const effects = input.durableSideEffects ?? {
612
- executionJobCount: 0,
613
- localJobCount: 0,
614
- workerSpawnCount: 0,
615
- projectionUpdateCount: 0,
616
- };
617
- const reason = input.reasons[0] ?? 'readonly_fast_path';
618
-
619
- // Default success/failure: one authoritative stdout/stderr pair, no nested process dump.
620
- if (!detail) {
621
- const completed = input.completed !== false;
622
- const ok = input.ok === true;
623
- const payload: Record<string, unknown> = {
624
- ...(completed ? { ok } : {}),
625
- accepted: input.accepted ?? true,
626
- mode: input.mode,
627
- path: input.path,
628
- route: input.route ?? input.path,
629
- reason,
630
- repoId: input.repoId,
631
- ...(input.checkoutId ? { checkoutId: input.checkoutId } : {}),
632
- ...(input.workspace ? { workspace: input.workspace } : {}),
633
- ...(input.historicalWorkContext ? { historicalWorkContext: input.historicalWorkContext } : {}),
634
- ...(input.processId ? { processId: input.processId } : {}),
635
- ...(completed ? { exitCode: input.exitCode ?? (ok ? 0 : 1) } : {}),
636
- // A running default response otherwise loses its only dependency-bound
637
- // continuation advice when the detailed Process record is omitted.
638
- ...(!completed ? { next: input.next } : {}),
639
- stdout: output.stdout ?? '',
640
- stderr: output.stderr ?? '',
641
- ...(output.stdoutTruncated ? { stdoutTruncated: true, stdoutBytes: output.stdoutBytes } : {}),
642
- ...(output.stderrTruncated ? { stderrTruncated: true, stderrBytes: output.stderrBytes } : {}),
643
- ...(input.guidance ? { guidance: input.guidance, suggestedOperation: 'rh_context' } : {}),
644
- };
645
- if (completed && !ok) {
646
- payload.error = {
647
- code: 'PROCESS_COMMAND_FAILED',
648
- message: (output.stderr || 'process_direct command failed').slice(0, 800),
649
- retryable: false,
650
- exitCode: input.exitCode ?? 1,
651
- };
652
- }
653
- // Zero side-effects are implicit for process_direct summary; only surface non-zero.
654
- const nonZeroEffects = Object.fromEntries(
655
- Object.entries(effects).filter(([, value]) => typeof value === 'number' && value > 0),
656
- );
657
- if (Object.keys(nonZeroEffects).length > 0) payload.durableSideEffects = nonZeroEffects;
658
- return payload;
659
- }
660
-
661
- return {
662
- accepted: input.accepted ?? true,
663
- mode: input.mode,
664
- path: input.path,
665
- route: input.route ?? input.path,
666
- routing: {
667
- ...compactRoutingSummary({ path: input.path, mode: input.mode, reasons: input.reasons }),
668
- ...(input.decision ? { decision: input.decision } : {}),
669
- },
670
- reason,
671
- repoId: input.repoId,
672
- ...(input.checkoutId ? { checkoutId: input.checkoutId } : {}),
673
- ...(input.workspace ? { workspace: input.workspace } : {}),
674
- ...(input.historicalWorkContext ? { historicalWorkContext: input.historicalWorkContext } : {}),
675
- ...(input.processId ? { processId: input.processId } : {}),
676
- ok: input.ok,
677
- exitCode: input.exitCode,
678
- ...output,
679
- // Nested process only in detail mode; never duplicate stdout/stderr there.
680
- ...(input.process && typeof input.process === 'object'
681
- ? {
682
- process: (() => {
683
- const record = { ...(input.process as Record<string, unknown>) };
684
- delete record.stdout;
685
- delete record.stderr;
686
- delete record.durableSideEffects;
687
- return record;
688
- })(),
689
- }
690
- : {}),
691
- durableSideEffects: effects,
692
- ...(input.guidance ? { guidance: input.guidance, suggestedOperation: 'rh_context' } : {}),
693
- next: input.next,
694
- detailLevel: 'detail',
695
- };
696
- }
697
-
698
- function emptyRepositoryMigration(repository: ReturnType<typeof registerRepository>) {
699
- return {
700
- repoId: repository.repoId,
701
- checkoutId: repository.activeCheckoutId,
702
- scanned: 0,
703
- updated: 0,
704
- unresolved: 0,
705
- files: [] as string[],
706
- errors: [] as Array<{ path: string; error: string }>,
707
- };
708
- }
709
-
710
- function registrationOnlyMetadataRefresh(
711
- match: ReturnType<typeof findIdenticalRepositoryRegistration>,
712
- ): boolean {
713
- if (!match || match.identical || match.reasons.length === 0) return false;
714
- const metadataReasons = new Set([
715
- 'remote_identity_changed',
716
- 'default_branch_changed',
717
- 'display_name_changed',
718
- ]);
719
- return match.reasons.every((reason) => metadataReasons.has(reason));
720
- }
721
-
722
- function registrationOnlyAttachedExistingWorktree(repository: ReturnType<typeof registerRepository>): boolean {
723
- const selected = repository.checkouts.find((checkout) => checkout.checkoutId === repository.activeCheckoutId);
724
- return selected?.worktree === true
725
- && repository.checkouts.some((checkout) => checkout.checkoutId !== selected.checkoutId);
726
- }
727
-
728
- export async function callRepositoryTool(
729
- controllerHome: string,
730
- name: string,
731
- args: Record<string, unknown>,
732
- caller?: RepositoryToolCallerContext,
733
- ): Promise<RepositoryToolResult | undefined> {
734
- if (!name.startsWith('repository_') && name !== 'read_repository_file') return undefined;
735
- try {
736
- const repoIdValue = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
737
- switch (name) {
738
- case 'read_repository_file': {
739
- const repository = resolveRepositorySelection({
740
- repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
741
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
742
- controllerHome,
743
- allowSoleRepository: true,
744
- });
745
- const path = String(args.path ?? '').trim();
746
- if (!path) throw new Error('REPOSITORY_PATH_REQUIRED: path is required');
747
- const session = caller?.sessionId
748
- ? { sessionId: caller.sessionId, repoId: repository.repoId, checkoutId: repository.activeCheckoutId }
749
- : undefined;
750
- const range = readRepositoryRange(
751
- repository.canonicalRoot,
752
- getMcpPolicy('controller', { repoRoot: repository.canonicalRoot }),
753
- path,
754
- typeof args.start_line === 'number' ? args.start_line : 1,
755
- typeof args.end_line === 'number' ? args.end_line : 200,
756
- session,
757
- );
758
- const redacted = redactMcpText(range.content);
759
- return result({ ...range, content: redacted.text, redactions: redacted.redactions });
760
- }
761
- case 'repository_register': {
762
- const startedAt = performance.now();
763
- const registerInput = {
764
- path: String(args.path ?? ''),
765
- controllerHome,
766
- displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
767
- remoteUrl: typeof args.remote_url === 'string' ? args.remote_url : undefined,
768
- defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
769
- };
770
- const identical = findIdenticalRepositoryRegistration(registerInput);
771
- if (identical?.identical) {
772
- const repository = identical.repository;
773
- // Repeat registration with identical identity returns immediately.
774
- // No legacy migration / edit-session migration / historical issue
775
- // scan / old issue rebinding runs on this hot path.
776
- const migration = emptyRepositoryMigration(repository);
777
- return result(withResponseMeta(
778
- summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail', true),
779
- startedAt,
780
- ));
781
- }
782
- const metadataRefresh = registrationOnlyMetadataRefresh(identical);
783
- const repository = registerRepository(registerInput);
784
- // Adding a worktree checkout or changing only display/remote/default-branch
785
- // metadata preserves repository + checkout authority. Existing entities
786
- // are already bound to the stable repoId, so a historical migration scan
787
- // would only add latency and stale unresolved diagnostics.
788
- const migration = registrationOnlyAttachedExistingWorktree(repository) || metadataRefresh
789
- ? emptyRepositoryMigration(repository)
790
- : bindRepositoryEntities(repository);
791
- return result(withResponseMeta(
792
- summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail', metadataRefresh),
793
- startedAt,
794
- ));
795
- }
796
- case 'repository_latest_source_diagnose':
797
- return result({
798
- diagnosis: diagnoseLatestLocalProjectSource({
799
- path: typeof args.path === 'string' ? args.path : undefined,
800
- repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
801
- controllerHome,
802
- }),
803
- });
804
- case 'repository_bootstrap_local_project':
805
- return result({
806
- bootstrap: bootstrapLocalProject({
807
- path: String(args.path ?? ''),
808
- controllerHome,
809
- displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
810
- defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
811
- mode: typeof args.mode === 'string' ? args.mode as 'init_git_only' | 'init_git_and_register' | 'replace_registration' : undefined,
812
- replaceRegisteredRepoId: typeof args.replace_registered_repo_id === 'string' ? args.replace_registered_repo_id : undefined,
813
- confirmAuthorization: args.confirm_authorization === true,
814
- }),
815
- });
816
- case 'repository_list':
817
- return result({ repositories: listRepositories(controllerHome, { includeRemoved: args.include_removed === true }).map(repositorySummary) });
818
- case 'repository_get': {
819
- // Repository inspection is also the bounded reconciliation point for
820
- // checkout lifecycle drift caused by worktrees being removed outside
821
- // Forge. Reuse the existing registry reconciler so stale worktrees are
822
- // not exposed as lifecycle=active to automation callers.
823
- reconcileRepositoryCheckouts(repoIdValue, controllerHome);
824
- const repository = getRepository(repoIdValue, controllerHome, { includeRemoved: args.include_removed === true });
825
- return result(summarizeRepositoryInspection(repository, args.detail_level === 'detail'));
826
- }
827
- case 'repository_validate': {
828
- const startedAt = performance.now();
829
- const repository = getRepository(repoIdValue, controllerHome, { includeRemoved: true });
830
- const payload = {
831
- detailLevel: args.detail_level === 'detail' ? 'detail' : 'summary',
832
- validation: validateRepository(repoIdValue, controllerHome),
833
- migration: summarizeEntityMigrationReport(bindRepositoryEntities(repository), args.detail_level === 'detail'),
834
- };
835
- return result(withResponseMeta(payload, startedAt));
836
- }
837
- case 'repository_refresh': {
838
- const startedAt = performance.now();
839
- const repository = refreshRepository(repoIdValue, controllerHome);
840
- const migration = bindRepositoryEntities(repository);
841
- return result(withResponseMeta(
842
- summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail'),
843
- startedAt,
844
- ));
845
- }
846
- case 'repository_update':
847
- return result({ repository: updateRepository(repoIdValue, {
848
- displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
849
- defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
850
- enabled: typeof args.enabled === 'boolean' ? args.enabled : undefined,
851
- }, controllerHome) });
852
- case 'repository_disable':
853
- return result({ repository: disableRepository(repoIdValue, controllerHome) });
854
- case 'repository_remove':
855
- return result({ repository: removeRepository(repoIdValue, controllerHome) });
856
- case 'repository_workbench': {
857
- const operation = typeof args.operation === 'string' ? args.operation : 'summary';
858
- if (operation === 'summary') {
859
- return result({ workbench: buildControllerWorkbench(controllerHome, {
860
- repoId: repoIdValue || undefined,
861
- includeRemoved: args.include_removed === true,
862
- }) });
863
- }
864
- const payload = typeof args.payload === 'object' && args.payload !== null
865
- ? args.payload as Record<string, unknown>
866
- : {};
867
- if (operation === 'assess_work_mode') {
868
- const description = typeof payload.description === 'string'
869
- ? payload.description
870
- : typeof args.description === 'string' ? args.description : '';
871
- const assessment = assessWorkMode({
872
- description,
873
- knownPaths: Array.isArray(payload.known_paths) ? payload.known_paths.map(String) : undefined,
874
- expectedFiles: typeof payload.expected_files === 'number' ? payload.expected_files : undefined,
875
- expectedChangedLines: typeof payload.expected_changed_lines === 'number' ? payload.expected_changed_lines : undefined,
876
- requiresInvestigation: payload.requires_investigation === true,
877
- requiresParallelism: payload.requires_parallelism === true,
878
- requiresLongRunningChecks: payload.requires_long_running_checks === true,
879
- needsDependencies: payload.needs_dependencies === true,
880
- requiresIndependentDeliverables: payload.requires_independent_deliverables === true,
881
- independentTaskCount: typeof payload.independent_task_count === 'number' ? payload.independent_task_count : undefined,
882
- requiresRemoteWrite: payload.requires_remote_write === true || payload.remote_write === true,
883
- requiresRecovery: payload.requires_recovery === true,
884
- agentRequested: payload.agent_requested === true || payload.requires_worker === true,
885
- requiresWorkerIsolation: payload.requires_worker_isolation === true,
886
- risk: typeof payload.risk === 'string' ? payload.risk as 'low' | 'medium' | 'high' | 'destructive' : undefined,
887
- explicitMode: parseExplicitTaskMode(payload.mode),
888
- });
889
- return result({
890
- assessment,
891
- routing: {
892
- path: assessment.executionPath,
893
- reasons: assessment.reasons,
894
- recommendedMode: assessment.recommendedMode,
895
- issueRequired: assessment.issueRequired,
896
- },
897
- nextTools: assessment.nextTools,
898
- });
899
- }
900
- const internalTool = {
901
- batch_execute: 'repository_batch_execute',
902
- lanes_execute: 'repository_lanes_execute',
903
- lanes_integrate: 'repository_lanes_integrate',
904
- fast_receipt_get: 'repository_fast_receipt_get',
905
- fast_receipt_list: 'repository_fast_receipt_list',
906
- execution_route: 'repository_execution_route',
907
- }[operation];
908
- if (!internalTool) {
909
- return failure(new Error(`REPOSITORY_WORKBENCH_OPERATION_INVALID: ${operation}`));
910
- }
911
- return callRepositoryTool(controllerHome, internalTool, {
912
- ...payload,
913
- repo_id: repoIdValue || payload.repo_id,
914
- checkout_id: typeof args.checkout_id === 'string' ? args.checkout_id : payload.checkout_id,
915
- });
916
- }
917
- case 'repository_git_status': {
918
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
919
- const status = args.refresh === true
920
- ? writeRepositoryGitStatusSample(controllerHome, repository)
921
- : readRepositoryGitStatusSample(controllerHome, repository.repoId, repository.activeCheckoutId);
922
- return result({
923
- status: status ?? {
924
- repoId: repository.repoId,
925
- checkoutId: repository.activeCheckoutId,
926
- sampleSource: 'daemon-sample',
927
- sampled: false,
928
- observedAt: null,
929
- staleAgeMs: null,
930
- message: 'Git status has not been sampled by the Forge Runtime yet. Retry after scheduler heartbeat or call with refresh=true for an explicit live refresh.',
931
- },
932
- });
933
- }
934
-
935
- case 'repository_git_diff': {
936
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
937
- return result({ diff: repositoryGitDiff(repository, { staged: args.staged, paths: args.paths, maxBytes: args.max_bytes }) });
938
- }
939
- case 'repository_git_create_branch': {
940
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
941
- return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitCreateBranch(controllerHome, repository, { branch: args.branch, startPoint: args.start_point, switchTo: args.switch_to }) as unknown as Record<string, unknown> });
942
- }
943
- case 'repository_git_switch_branch': {
944
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
945
- return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitSwitchBranch(controllerHome, repository, { branch: args.branch }) as unknown as Record<string, unknown> });
946
- }
947
- case 'repository_git_merge_branch': {
948
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
949
- return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitMergeBranch(controllerHome, repository, { branch: args.branch, noFf: args.no_ff }) as unknown as Record<string, unknown> });
950
- }
951
- case 'repository_git_delete_branch': {
952
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
953
- return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitDeleteBranch(controllerHome, repository, { branch: args.branch, force: args.force }) as unknown as Record<string, unknown> });
954
- }
955
-
956
- case 'repository_git_commit': {
957
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
958
- return result({ commit: repositoryGitCommit(controllerHome, repository, { message: args.message, paths: args.paths, allowEmpty: args.allow_empty }) });
959
- }
960
- case 'repository_git_finish_workflow': {
961
- const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
962
- return result({ finish: repositoryGitFinishWorkflow(controllerHome, repository, { featureBranch: args.feature_branch, targetBranch: args.target_branch, deleteBranch: args.delete_branch, noFf: args.no_ff }) });
963
- }
964
- case 'repository_safe_patch_plan': {
965
- const repository = resolveRepositorySelection({
966
- repoId: repoIdValue || undefined,
967
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
968
- controllerHome,
969
- allowSoleRepository: true,
970
- });
971
- return result({
972
- repoId: repository.repoId,
973
- checkoutId: repository.activeCheckoutId,
974
- plan: buildSafePatchPlan(repository, { operations: args.operations, chunkSize: args.chunk_size }),
975
- });
976
- }
977
- case 'repository_safe_patch_apply': {
978
- const repository = resolveRepositorySelectionForClaimedWork(controllerHome, args, repoIdValue, caller);
979
- const binding = safePatchEditBinding(controllerHome, repository, caller, args);
980
- if (binding?.workId) {
981
- const work = getWorkContract({ controllerHome, repoId: repository.repoId }, binding.workId);
982
- if (!work) throw new Error(`WORK_NOT_FOUND: ${binding.workId}`);
983
- const requestedPaths = buildSafePatchPlan(repository, { operations: args.operations, chunkSize: args.chunk_size })
984
- .chunks.flatMap((chunk) => chunk.paths);
985
- assertWorkPathsWithinScope(work, requestedPaths, {
986
- forbidden: 'WORK_MUTATION_FORBIDDEN_PATH',
987
- outOfScope: 'WORK_MUTATION_PATH_OUT_OF_SCOPE',
988
- });
989
- }
990
- const applied = withControllerLock(
991
- controllerHome,
992
- { scope: 'repository', repoId: repository.repoId },
993
- 'mcp:repository_safe_patch_apply',
994
- () => {
995
- if (binding?.workId) {
996
- ensureRepositoryMutationWorkHandle({
997
- controllerHome,
998
- repository,
999
- workId: binding.workId,
1000
- principalId: binding.principalId ?? caller?.principalId ?? '',
1001
- });
1002
- }
1003
- return applySafePatch(repository, {
1004
- sessionId: args.session_id,
1005
- purpose: args.purpose,
1006
- operations: args.operations,
1007
- chunkSize: args.chunk_size,
1008
- expectedRevision: args.expected_revision,
1009
- allowedPaths: args.allowed_paths,
1010
- continueOnError: args.continue_on_error,
1011
- refreshFingerprints: args.refresh_fingerprints,
1012
- recoverStaleSession: args.recover_stale_session,
1013
- binding,
1014
- });
1015
- },
1016
- 60_000,
1017
- );
1018
- const changedFiles = [
1019
- ...new Set(
1020
- (applied.appliedChunks ?? []).flatMap((chunk) => chunk.paths ?? []),
1021
- ),
1022
- ];
1023
- const ok = applied.status === 'applied';
1024
- const firstFailure = applied.failures?.[0];
1025
- const editDiff = applied.appliedChunks.length > 0
1026
- ? getEditSessionDiff(repository.canonicalRoot, applied.session.sessionId)
1027
- : undefined;
1028
- const boundedEditDiff = editDiff
1029
- ? boundUtf8(editDiff.patch, RESPONSE_BUDGET.inlineOutputBytes)
1030
- : undefined;
1031
- const reviewEvidence = editDiff && boundedEditDiff
1032
- ? {
1033
- source: 'edit_session' as const,
1034
- sessionId: editDiff.sessionId,
1035
- revision: editDiff.revision,
1036
- sha256: editDiff.sha256,
1037
- patchPreview: boundedEditDiff.text,
1038
- truncated: boundedEditDiff.truncated,
1039
- byteLength: boundedEditDiff.byteLength,
1040
- semanticReviewAuthority: 'chatgpt' as const,
1041
- next: boundedEditDiff.truncated
1042
- ? 'The edit diff exceeds the inline budget. Expand only the affected ranges or diff needed for semantic review.'
1043
- : 'Review this exact edit-session diff before deciding whether more edits or focused validation are needed.',
1044
- }
1045
- : undefined;
1046
- const digest = buildSyncOperationDigest({
1047
- ok,
1048
- operation: 'repository_safe_patch_apply',
1049
- summary: ok
1050
- ? `补丁已同步应用,涉及 ${changedFiles.length} 个文件。`
1051
- : applied.status === 'partial'
1052
- ? `补丁部分应用:${changedFiles.length} 个文件成功,存在失败 chunk。`
1053
- : `补丁应用失败:${firstFailure?.message || '请检查 failures 摘要'}`,
1054
- changedFiles,
1055
- errorClass: ok ? undefined : classifyUserFacingError({
1056
- code: firstFailure?.code,
1057
- message: firstFailure?.message,
1058
- infrastructure: firstFailure?.code === 'APPLY_FAILED',
1059
- }),
1060
- errorMessage: firstFailure?.message,
1061
- });
1062
- const payload = {
1063
- repoId: repository.repoId,
1064
- checkoutId: repository.activeCheckoutId,
1065
- ...applied as unknown as Record<string, unknown>,
1066
- phase: digest.phase,
1067
- statusLabel: digest.statusLabel,
1068
- summary: digest.summary,
1069
- terminal: true,
1070
- applyMode: 'sync',
1071
- digest,
1072
- ...(reviewEvidence ? { reviewEvidence } : {}),
1073
- suggestedNextActions: digest.suggestedNextActions,
1074
- };
1075
- return ok ? result(payload) : { ...result(payload), isError: true };
1076
- }
1077
- case 'repository_command_preview': {
1078
- const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue, caller);
1079
- const { repository } = target;
1080
- const execution = withControllerLock(
1081
- controllerHome,
1082
- { scope: 'repository', repoId: repository.repoId },
1083
- 'mcp:repository_command_preview',
1084
- () => executeRepositoryCommand(controllerHome, repository, {
1085
- command: args.command as string | string[],
1086
- cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
1087
- dryRun: true,
1088
- allowNonGitWorkspace: target.workspace !== undefined,
1089
- }),
1090
- 60_000,
1091
- );
1092
- return result({
1093
- ...execution as unknown as Record<string, unknown>,
1094
- ...(target.workspace ? { workspace: target.workspace } : {}),
1095
- });
1096
- }
1097
- case 'repository_command_execute': {
1098
- const explorationGuidance = fragmentedRepositoryExplorationGuidance(args.command);
1099
- const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue, caller);
1100
- const { repository, executionIdentity, historicalWorkContext } = target;
1101
- const explicitWorkId = typeof args.work_id === 'string' ? args.work_id.trim() : '';
1102
- if (!explicitWorkId) assertNoBoundExecutionSessionMutation(controllerHome, repository, caller);
1103
- const deliveryWorkId = rawDefaultBranchMergeCommand(repository, args.command)
1104
- ? executionIdentity.workId
1105
- : undefined;
1106
- if (deliveryWorkId) {
1107
- throw new Error(`WORK_DELIVERY_REQUIRES_FINALIZE: ${deliveryWorkId} must pass Work verification and use rh_work finalize before default-branch integration`);
1108
- }
1109
- if (executionIdentity.workId) {
1110
- const mutationClassification = classifyRepositoryCommand(args.command as string | string[], repository.defaultBranch);
1111
- if (mutationClassification.risk === 'workspace_write' || mutationClassification.risk === 'destructive') {
1112
- withControllerLock(
1113
- controllerHome,
1114
- { scope: 'repository', repoId: repository.repoId },
1115
- 'mcp:repository_command_execute:mutation-authority',
1116
- () => ensureRepositoryMutationWorkHandle({
1117
- controllerHome,
1118
- repository,
1119
- workId: executionIdentity.workId!,
1120
- principalId: caller?.principalId ?? '',
1121
- }),
1122
- 60_000,
1123
- );
1124
- }
1125
- }
1126
- const timeoutMs = typeof args.timeout_ms === 'number'
1127
- ? args.timeout_ms
1128
- : typeof args.timeout_ms === 'string'
1129
- ? Number(args.timeout_ms)
1130
- : undefined;
1131
- const maxOutputBytes = typeof args.max_output_bytes === 'number'
1132
- ? args.max_output_bytes
1133
- : typeof args.max_output_bytes === 'string'
1134
- ? Number(args.max_output_bytes)
1135
- : undefined;
1136
- // Worker-owned durable executions must not re-enter Fast Path or create a
1137
- // nested ExecutionJob. Local Job remains the worker settlement surface.
1138
- const fromDurableWorker = args.__from_durable_worker === true
1139
- || typeof args.__execution_job_id === 'string';
1140
- // Process Runtime owns local async execution. apply_mode=async means
1141
- // return its Process handle immediately; it must not promote a local
1142
- // command into the retired ExecutionJob path. Explicit mode=durable
1143
- // remains a separate external-Controller boundary.
1144
- const returnHandleImmediately = args.apply_mode === 'async'
1145
- || args.mode === 'async'
1146
- || args.async === true
1147
- || args.background === true;
1148
- const forceDurable = fromDurableWorker
1149
- || args.mode === 'durable'
1150
- || args.force_durable === true;
1151
- // repository_command_execute owns its command execution architecture.
1152
- // Do not send ordinary command text through Thin Harness semantic risk
1153
- // routing: that creates duplicate regex/classifier policy and turns
1154
- // unknown CLI shapes into false durable/reject decisions. Only an
1155
- // explicitly requested durable mode uses the generic durable router.
1156
- const routingDecision = forceDurable
1157
- ? routeExecution({
1158
- operation: 'repository_command_execute',
1159
- mode: 'durable',
1160
- timeoutMs,
1161
- background: args.background === true || args.async === true,
1162
- })
1163
- : {
1164
- mode: 'fast' as const,
1165
- reasons: ['repository_command_process_runtime_authoritative'],
1166
- risk: 'unknown' as const,
1167
- estimatedClass: 'unknown' as const,
1168
- requiresIsolation: false,
1169
- requiresRecovery: false,
1170
- suggestedOperation: undefined,
1171
- effects: {
1172
- readsWorkspace: true,
1173
- mutatesWorkspace: true,
1174
- mutatesGitRefs: false,
1175
- remoteWrite: false,
1176
- },
1177
- };
1178
- // Unified Process Runtime for local commands (Direct/Managed) when not forced durable.
1179
- // Ephemeral workspaces cannot persist a recoverable async Process handle,
1180
- // so their async requests remain promotion-required below.
1181
- if (!forceDurable && !fromDurableWorker && !(target.workspace && returnHandleImmediately)) {
1182
- try {
1183
- const routeClass = classifyRepositoryCommandRoute(args.command as string | string[], {
1184
- forceDurable: false,
1185
- defaultBranch: repository.defaultBranch,
1186
- timeoutMs,
1187
- });
1188
- if (routeClass.route === 'reject') {
1189
- return result({
1190
- accepted: false,
1191
- mode: 'reject',
1192
- path: routeClass.reason,
1193
- route: 'reject',
1194
- status: 'rejected',
1195
- repoId: repository.repoId,
1196
- checkoutId: repository.activeCheckoutId,
1197
- workspace: target.workspace,
1198
- message: routeClass.reason === 'standalone_recovery_lifecycle_required'
1199
- ? 'Canonical Runtime and connector lifecycle operations must be submitted to the standalone Forge Recovery owner, not executed as a child of repository Process Runtime.'
1200
- : 'Repository command execution was rejected by Process Runtime routing policy.',
1201
- suggestedOperation: routeClass.reason === 'standalone_recovery_lifecycle_required'
1202
- ? 'Use the standalone Forge Recovery connector.'
1203
- : routingDecision.suggestedOperation,
1204
- durableSideEffects: {
1205
- executionJobCount: 0,
1206
- localJobCount: 0,
1207
- workerSpawnCount: 0,
1208
- projectionUpdateCount: 0,
1209
- },
1210
- });
1211
- }
1212
- if (routeClass.route === 'durable' && target.workspace) {
1213
- return result({
1214
- accepted: false,
1215
- mode: 'durable',
1216
- path: 'ephemeral_workspace_promotion_required',
1217
- repoId: repository.repoId,
1218
- checkoutId: repository.activeCheckoutId,
1219
- workspace: target.workspace,
1220
- message: 'Ephemeral workspaces must be registered before durable remote effects so Process identity and reconciliation have a stable repository authority.',
1221
- suggestedOperation: 'repository_register',
1222
- });
1223
- }
1224
- if (routeClass.route === 'process_direct' || routeClass.route === 'process_managed' || routeClass.route === 'durable') {
1225
- const processRequestId = typeof args.request_id === 'string' ? args.request_id.trim() : '';
1226
- if (executionIdentity.workId && !processRequestId) {
1227
- throw new Error(
1228
- `WORK_PROCESS_REQUEST_ID_REQUIRED: ${executionIdentity.workId}; `
1229
- + 'Work-attributed Process Runtime commands require a stable request_id so reconnect/retry can resume the original Process without duplicate execution.',
1230
- );
1231
- }
1232
- const processResult = await executeRepositoryCommandViaProcessRuntime({
1233
- controllerHome,
1234
- repository,
1235
- command: args.command as string | string[],
1236
- cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
1237
- timeoutMs,
1238
- interactiveWaitMs: returnHandleImmediately
1239
- ? 0
1240
- : typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : undefined,
1241
- maxOutputBytes,
1242
- returnHandleImmediately,
1243
- requestId: processRequestId || undefined,
1244
- workId: executionIdentity.workId,
1245
- executionIdentity,
1246
- allowNonGitWorkspace: target.workspace !== undefined,
1247
- });
1248
- if (processResult.route === 'process_direct' || processResult.route === 'process_managed') {
1249
- const handle = processResult.process;
1250
- const detailLevel = args.detail_level === 'detail' || args.detail === true
1251
- ? 'detail'
1252
- : 'summary';
1253
- const directWithoutHandle = processResult.route === 'process_direct' && !handle;
1254
- const directNotExecuted = directWithoutHandle
1255
- && processResult.executionStatus !== undefined
1256
- && processResult.executionStatus !== 'executed';
1257
- if (directNotExecuted) {
1258
- const authorization = processResult.authorizationDecision ?? {
1259
- decision: 'deny' as const,
1260
- reason: 'Command was not executed because the required authorization was not satisfied.',
1261
- };
1262
- return result({
1263
- accepted: false,
1264
- mode: processResult.route,
1265
- path: processResult.reason ?? routeClass.reason,
1266
- route: processResult.route,
1267
- repoId: repository.repoId,
1268
- checkoutId: repository.activeCheckoutId,
1269
- workspace: target.workspace,
1270
- status: processResult.executionStatus,
1271
- policyDecision: processResult.policyDecision ?? 'approval_required',
1272
- authorization,
1273
- ...(processResult.approvalRequestId ? { approvalRequestId: processResult.approvalRequestId } : {}),
1274
- message: authorization.decision === 'user_confirmation_required'
1275
- ? authorization.humanSummary
1276
- : authorization.reason,
1277
- suggestedOperation: 'repository_command_preview',
1278
- });
1279
- }
1280
- const completed = directWithoutHandle || handle?.completed === true;
1281
- const status = directWithoutHandle
1282
- ? (processResult.ok === true ? 'succeeded' : 'failed')
1283
- : !handle
1284
- ? 'rejected'
1285
- : completed
1286
- ? (handle.cancelled ? 'cancelled' : handle.timedOut ? 'timed_out' : processResult.ok === true ? 'succeeded' : 'failed')
1287
- : 'running';
1288
- const payload = compactProcessCommandPayload({
1289
- accepted: true,
1290
- mode: processResult.route,
1291
- path: processResult.route,
1292
- route: processResult.route,
1293
- reasons: [processResult.reason ?? routeClass.reason, ...routingDecision.reasons],
1294
- decision: detailLevel === 'detail' ? routingDecision : undefined,
1295
- repoId: repository.repoId,
1296
- checkoutId: repository.activeCheckoutId,
1297
- workspace: target.workspace,
1298
- historicalWorkContext,
1299
- processId: handle?.processId,
1300
- process: detailLevel === 'detail' ? handle : undefined,
1301
- completed,
1302
- ok: completed ? processResult.ok : undefined,
1303
- exitCode: completed ? processResult.exitCode : undefined,
1304
- stdout: processResult.stdout,
1305
- stderr: processResult.stderr,
1306
- durableSideEffects: processResult.durableSideEffects,
1307
- guidance: explorationGuidance,
1308
- next: directWithoutHandle
1309
- ? processResult.reason === 'readonly_fast_path'
1310
- ? 'Bounded readonly execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
1311
- : 'Bounded ephemeral workspace execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
1312
- : processResult.route === 'process_direct' || completed
1313
- ? 'Process Runtime completed without Local Job / ExecutionJob / Worker.'
1314
- : `Process Runtime is managing ${handle?.processId}. Continue independent work; use process_get only if an observation can change the next decision, then join with process_wait when this result becomes a dependency. Do not re-run or periodically poll.`,
1315
- detailLevel,
1316
- });
1317
- payload.status = status;
1318
- payload.processId = handle?.processId;
1319
- payload.authorization = {
1320
- decision: 'allow',
1321
- source: directWithoutHandle ? 'bounded_read_direct' : 'process_runtime',
1322
- reason: directWithoutHandle
1323
- ? 'Readonly repository command executed through the bounded non-persistent direct path.'
1324
- : 'Repository command executed through Unified Process Runtime.',
1325
- };
1326
- if (directWithoutHandle && processResult.reason !== 'readonly_fast_path') {
1327
- payload.authorization = processResult.authorizationDecision?.decision === 'allow'
1328
- ? processResult.authorizationDecision
1329
- : {
1330
- decision: 'allow',
1331
- source: 'ephemeral_workspace_direct',
1332
- reason: 'Bounded ephemeral workspace command executed through the non-persistent direct path.',
1333
- };
1334
- }
1335
- if (handle?.processId) {
1336
- payload.resultRef = { kind: 'process_logs', processId: handle.processId };
1337
- }
1338
- // Keep accepted true once the command was admitted to Process Runtime.
1339
- payload.accepted = true;
1340
- return processResult.ok === true || !completed
1341
- ? result(payload)
1342
- : { ...result(payload), isError: true };
1343
- }
1344
- }
1345
- } catch (error) {
1346
- // Process Runtime is authoritative. Falling through could spawn the
1347
- // same command again through the legacy Fast/Local Job path.
1348
- if (process.env.FORGE_DEBUG_PROCESS_RUNTIME === '1') {
1349
- console.error('[repository_command_execute] process runtime error', error);
1350
- }
1351
- return failure(error);
1352
- }
1353
- }
1354
- if (target.workspace && (forceDurable || returnHandleImmediately)) {
1355
- return result({
1356
- accepted: false,
1357
- mode: 'durable',
1358
- path: 'ephemeral_workspace_promotion_required',
1359
- repoId: repository.repoId,
1360
- checkoutId: repository.activeCheckoutId,
1361
- workspace: target.workspace,
1362
- message: 'Ephemeral workspaces support bounded local Direct/Managed execution only. Register the directory before durable, remote, release, or resumable Work.',
1363
- suggestedOperation: 'repository_register',
1364
- });
1365
- }
1366
- // Durable Worker calls skip Process/Fast above, then use the Local Bridge
1367
- // compatibility projection below for writes/long commands so the worker
1368
- // can settle the legacy child without creating a nested ExecutionJob.
1369
- // Short readonly commands keep the zero-Local-Job direct path.
1370
- if (fromDurableWorker) {
1371
- try {
1372
- const routeClass = classifyRepositoryCommandRoute(args.command as string | string[], {
1373
- forceDurable: false,
1374
- defaultBranch: repository.defaultBranch,
1375
- timeoutMs,
1376
- });
1377
- if (routeClass.route === 'process_direct') {
1378
- const processResult = await executeRepositoryCommandViaProcessRuntime({
1379
- controllerHome,
1380
- repository,
1381
- command: args.command as string | string[],
1382
- cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
1383
- timeoutMs,
1384
- maxOutputBytes,
1385
- requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
1386
- workId: executionIdentity.workId,
1387
- executionIdentity,
1388
- });
1389
- if (processResult.route === 'process_direct') {
1390
- const execRecord = processResult.process as unknown as Record<string, unknown> | undefined;
1391
- const ok = processResult.ok === true;
1392
- const inlinePayload = {
1393
- accepted: ok,
1394
- mode: 'durable',
1395
- path: 'durable_worker_inline',
1396
- routing: compactRoutingSummary({
1397
- path: 'durable',
1398
- mode: 'durable',
1399
- reasons: ['durable_worker_inline_process_direct', routeClass.reason, ...routingDecision.reasons],
1400
- }),
1401
- repoId: repository.repoId,
1402
- checkoutId: repository.activeCheckoutId,
1403
- ok,
1404
- processId: typeof execRecord?.processId === 'string' ? execRecord.processId : undefined,
1405
- status: typeof execRecord?.status === 'string' ? execRecord.status : undefined,
1406
- exitCode: typeof processResult.exitCode === 'number' ? processResult.exitCode : undefined,
1407
- ...compactCommandOutput(
1408
- typeof processResult.stdout === 'string' ? processResult.stdout : undefined,
1409
- typeof processResult.stderr === 'string' ? processResult.stderr : undefined,
1410
- { ok },
1411
- ),
1412
- durableSideEffects: processResult.durableSideEffects,
1413
- next: 'Durable Worker executed a short readonly repository command inline without a Local Job.',
1414
- };
1415
- return ok ? result(inlinePayload) : { ...result(inlinePayload), isError: true };
1416
- }
1417
- }
1418
- } catch (error) {
1419
- if (process.env.FORGE_DEBUG_PROCESS_RUNTIME === '1') {
1420
- console.error('[repository_command_execute] durable worker inline process runtime error', error);
1421
- }
1422
- }
1423
- }
1424
- return result({
1425
- accepted: false,
1426
- mode: 'durable',
1427
- path: 'external_controller_required',
1428
- routing: compactRoutingSummary({ path: 'durable', mode: 'durable', reasons: [routingDecision.reasons.join(','), 'local_bridge_execution_retired'] }),
1429
- message: 'This command requires explicit external Controller handling; Local Bridge Jobs are retired for repository commands.',
1430
- suggestedOperation: 'Create or claim WorkContract, then use rh_work.launcher_start or a Process Runtime-compatible command.',
1431
- externalEffect: {
1432
- outcome: 'not_started',
1433
- ambiguousFailureOutcome: 'outcome_unknown',
1434
- replayPolicy: 'never_auto_retry',
1435
- reconciliation: 'After an ambiguous dispatch failure, inspect the remote ref/registry/release state before deciding whether to retry.',
1436
- },
1437
- });
1438
- }
1439
- case 'repository_batch_execute': {
1440
- const repository = resolveRepositorySelection({
1441
- repoId: repoIdValue || undefined,
1442
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1443
- controllerHome,
1444
- allowSoleRepository: true,
1445
- });
1446
- const steps = Array.isArray(args.steps)
1447
- ? args.steps
1448
- .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1449
- .map((entry) => ({
1450
- id: typeof entry.id === 'string' ? entry.id : undefined,
1451
- kind: String(entry.kind ?? '') as
1452
- | 'read_file'
1453
- | 'search'
1454
- | 'git_status'
1455
- | 'git_diff'
1456
- | 'apply_patch'
1457
- | 'run_short_command'
1458
- | 'run_focused_check'
1459
- | 'stage_paths'
1460
- | 'commit_paths',
1461
- input: (typeof entry.input === 'object' && entry.input !== null
1462
- ? entry.input
1463
- : {}) as Record<string, unknown>,
1464
- }))
1465
- : [];
1466
- const batch = await executeRepositoryBatch(
1467
- { controllerHome, repository },
1468
- {
1469
- repoId: repository.repoId,
1470
- checkoutId: repository.activeCheckoutId,
1471
- mode: args.mode === 'fast' || args.mode === 'durable' || args.mode === 'auto' ? args.mode : 'auto',
1472
- steps,
1473
- stopOnError: args.stop_on_error !== false,
1474
- allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
1475
- timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
1476
- includeLatencyBreakdown: args.include_latency_breakdown === true,
1477
- purpose: typeof args.purpose === 'string' ? args.purpose : undefined,
1478
- requestId: typeof args.request_id === 'string' ? args.request_id.trim() || undefined : undefined,
1479
- },
1480
- );
1481
- const payload = batch as unknown as Record<string, unknown>;
1482
- return batch.ok ? result(payload) : { ...result(payload), isError: true };
1483
- }
1484
- case 'repository_lanes_execute': {
1485
- const repository = resolveRepositorySelection({
1486
- repoId: repoIdValue || undefined,
1487
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1488
- controllerHome,
1489
- allowSoleRepository: true,
1490
- });
1491
- const lanes = await executeLightweightLanes(
1492
- { controllerHome, repository },
1493
- {
1494
- repoId: repository.repoId,
1495
- checkoutId: repository.activeCheckoutId,
1496
- readLanes: Array.isArray(args.read_lanes)
1497
- ? args.read_lanes
1498
- .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1499
- .map((entry) => ({
1500
- id: typeof entry.id === 'string' ? entry.id : undefined,
1501
- kind: String(entry.kind ?? 'search') as 'search' | 'read_file' | 'git_status' | 'git_diff' | 'run_short_command',
1502
- input: (typeof entry.input === 'object' && entry.input !== null
1503
- ? entry.input
1504
- : {}) as Record<string, unknown>,
1505
- }))
1506
- : undefined,
1507
- patchProposalLanes: Array.isArray(args.patch_proposal_lanes)
1508
- ? args.patch_proposal_lanes
1509
- .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1510
- .map((entry) => ({
1511
- id: typeof entry.id === 'string' ? entry.id : undefined,
1512
- readPaths: Array.isArray(entry.read_paths) ? entry.read_paths.map(String) : [],
1513
- writePaths: Array.isArray(entry.write_paths) ? entry.write_paths.map(String) : [],
1514
- proposedOperations: Array.isArray(entry.proposed_operations) ? entry.proposed_operations : [],
1515
- assumptions: Array.isArray(entry.assumptions) ? entry.assumptions.map(String) : undefined,
1516
- riskNotes: Array.isArray(entry.risk_notes) ? entry.risk_notes.map(String) : undefined,
1517
- suggestedFocusedCheck: entry.suggested_focused_check as string | string[] | undefined,
1518
- }))
1519
- : undefined,
1520
- failFast: args.fail_fast === true,
1521
- maxConcurrency: typeof args.max_concurrency === 'number' ? args.max_concurrency : undefined,
1522
- includeLatencyBreakdown: args.include_latency_breakdown === true,
1523
- },
1524
- );
1525
- const payload = lanes as unknown as Record<string, unknown>;
1526
- return lanes.ok ? result(payload) : { ...result(payload), isError: true };
1527
- }
1528
- case 'repository_lanes_integrate': {
1529
- const repository = resolveRepositorySelection({
1530
- repoId: repoIdValue || undefined,
1531
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1532
- controllerHome,
1533
- allowSoleRepository: true,
1534
- });
1535
- const proposals = Array.isArray(args.proposals)
1536
- ? args.proposals
1537
- .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1538
- .map((entry) => ({
1539
- id: String(entry.id ?? 'proposal'),
1540
- ok: entry.ok !== false,
1541
- durationMs: 0,
1542
- readPaths: Array.isArray(entry.read_paths) ? entry.read_paths.map(String) : [],
1543
- writePaths: Array.isArray(entry.write_paths) ? entry.write_paths.map(String) : [],
1544
- proposedOperations: Array.isArray(entry.proposed_operations) ? entry.proposed_operations : [],
1545
- analysisOnly: entry.analysis_only === true,
1546
- proposalId: typeof entry.proposal_id === 'string'
1547
- ? entry.proposal_id
1548
- : typeof entry.proposalId === 'string'
1549
- ? entry.proposalId
1550
- : undefined,
1551
- }))
1552
- : [];
1553
- const integrated = await integratePatchProposals(
1554
- { controllerHome, repository },
1555
- proposals,
1556
- {
1557
- sessionId: typeof args.session_id === 'string' ? args.session_id : undefined,
1558
- allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
1559
- purpose: typeof args.purpose === 'string' ? args.purpose : undefined,
1560
- requestId: typeof args.request_id === 'string' ? args.request_id.trim() || undefined : undefined,
1561
- continueOnError: args.continue_on_error === true,
1562
- },
1563
- );
1564
- const payload = integrated as unknown as Record<string, unknown>;
1565
- return integrated.ok ? result(payload) : { ...result(payload), isError: true };
1566
- }
1567
- case 'repository_fast_receipt_get': {
1568
- const repository = resolveRepositorySelection({
1569
- repoId: repoIdValue || undefined,
1570
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1571
- controllerHome,
1572
- allowSoleRepository: true,
1573
- });
1574
- const receipt = readFastReceipt(controllerHome, repository.repoId, String(args.execution_id ?? ''));
1575
- if (!receipt) return failure(new Error(`FAST_RECEIPT_NOT_FOUND: ${String(args.execution_id ?? '')}`));
1576
- return result({ receipt });
1577
- }
1578
- case 'repository_fast_receipt_list': {
1579
- const repository = resolveRepositorySelection({
1580
- repoId: repoIdValue || undefined,
1581
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1582
- controllerHome,
1583
- allowSoleRepository: true,
1584
- });
1585
- const limit = typeof args.limit === 'number' ? args.limit : undefined;
1586
- return result({ receipts: listFastReceipts(controllerHome, repository.repoId, limit) });
1587
- }
1588
- case 'repository_execution_route': {
1589
- const repository = resolveRepositorySelection({
1590
- repoId: repoIdValue || undefined,
1591
- checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1592
- controllerHome,
1593
- allowSoleRepository: true,
1594
- });
1595
- const decision = routeExecution({
1596
- operation: String(args.operation ?? ''),
1597
- mode: args.mode === 'fast' || args.mode === 'durable' || args.mode === 'auto' ? args.mode : 'auto',
1598
- command: args.command as string | string[] | undefined,
1599
- timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
1600
- background: args.background === true,
1601
- paths: Array.isArray(args.paths) ? args.paths.map(String) : undefined,
1602
- allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
1603
- defaultBranch: repository.defaultBranch,
1604
- });
1605
- return result({ decision, repoId: repository.repoId, checkoutId: repository.activeCheckoutId });
1606
- }
1607
- default:
1608
- return failure(new Error(`UNKNOWN_REPOSITORY_TOOL: ${name}`));
1609
- }
1610
- } catch (error) {
1611
- return failure(error);
1612
- }
1613
- }
1
+ /** @deprecated Kernel V2 compatibility shim. MCP adapter owns this surface. */
2
+ export * from '../../../adapters/mcp/tool-mapping/repository-tools';