@moretea-labs/forge 1.5.0-rc.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 (903) hide show
  1. package/AGENTS.md +120 -0
  2. package/CHANGELOG.md +36 -0
  3. package/CLAUDE.md +120 -0
  4. package/CODE_OF_CONDUCT.md +23 -0
  5. package/CONTRIBUTING.md +77 -0
  6. package/LICENSE +22 -0
  7. package/NOTICE +9 -0
  8. package/README.en.md +5 -0
  9. package/README.es.md +12 -0
  10. package/README.fr.md +12 -0
  11. package/README.ja.md +12 -0
  12. package/README.md +132 -0
  13. package/README.zh-CN.md +84 -0
  14. package/SECURITY.md +50 -0
  15. package/SKILL.md +431 -0
  16. package/SUPPORT.md +31 -0
  17. package/THIRD_PARTY_NOTICES.md +18 -0
  18. package/agents/openai.yaml +4 -0
  19. package/assets/AGENTS.md +68 -0
  20. package/assets/CLAUDE.md +68 -0
  21. package/assets/branding/README.md +10 -0
  22. package/assets/branding/forge-controller-flow.mmd +8 -0
  23. package/assets/hooks/AGENTS.md +75 -0
  24. package/assets/hooks/CLAUDE.md +75 -0
  25. package/assets/hooks/anti-simplification.sh +12 -0
  26. package/assets/hooks/changelog-guard.sh +80 -0
  27. package/assets/hooks/codex.hooks.template.json +60 -0
  28. package/assets/hooks/first-principles-guard.sh +72 -0
  29. package/assets/hooks/hook-input.sh +618 -0
  30. package/assets/hooks/lib/session-state.sh +106 -0
  31. package/assets/hooks/lib/workflow-state.sh +1730 -0
  32. package/assets/hooks/post-bash.sh +215 -0
  33. package/assets/hooks/post-edit-guard.sh +256 -0
  34. package/assets/hooks/post-tool-observer.sh +99 -0
  35. package/assets/hooks/pre-edit-guard.sh +240 -0
  36. package/assets/hooks/prompt-guard.sh +1077 -0
  37. package/assets/hooks/run-hook.sh +67 -0
  38. package/assets/hooks/security-sentinel.sh +115 -0
  39. package/assets/hooks/session-start-context.sh +593 -0
  40. package/assets/hooks/settings.template.json +60 -0
  41. package/assets/hooks/stop-orchestrator.sh +171 -0
  42. package/assets/hooks/subagent-return-channel-guard.sh +107 -0
  43. package/assets/hooks/worktree-guard.sh +39 -0
  44. package/assets/initializer-question-pack.v1.json +132 -0
  45. package/assets/initializer-question-pack.v1.schema.json +46 -0
  46. package/assets/initializer-question-pack.v2.json +174 -0
  47. package/assets/initializer-question-pack.v3.json +206 -0
  48. package/assets/initializer-question-pack.v3.schema.json +92 -0
  49. package/assets/initializer-question-pack.v4.json +557 -0
  50. package/assets/initializer-question-pack.v4.schema.json +169 -0
  51. package/assets/partials/01-header.partial.md +10 -0
  52. package/assets/partials/02-iron-rules.partial.md +30 -0
  53. package/assets/partials/03-philosophy.partial.md +32 -0
  54. package/assets/partials/04-project-structure.partial.md +56 -0
  55. package/assets/partials/05-workflow.partial.md +79 -0
  56. package/assets/partials/06-cloudflare.partial.md +20 -0
  57. package/assets/partials/07-footer.partial.md +38 -0
  58. package/assets/partials/08-orchestration.partial.md +49 -0
  59. package/assets/partials/09-compact-instructions.partial.md +11 -0
  60. package/assets/partials/_assembly-order.md +40 -0
  61. package/assets/partials-agents/01-header.partial.md +8 -0
  62. package/assets/partials-agents/02-operating-mode.partial.md +44 -0
  63. package/assets/partials-agents/03-orchestration.partial.md +45 -0
  64. package/assets/partials-agents/04-task-protocol.partial.md +69 -0
  65. package/assets/partials-agents/05-coding-constraints.partial.md +20 -0
  66. package/assets/partials-agents/06-quality-safety.partial.md +23 -0
  67. package/assets/partials-agents/07-cloudflare.partial.md +9 -0
  68. package/assets/partials-agents/08-deep-docs.partial.md +32 -0
  69. package/assets/plan-map.json +301 -0
  70. package/assets/plugin-registry.v1.json +8 -0
  71. package/assets/project-structures/ai-native-collaborative-editor.txt +25 -0
  72. package/assets/project-structures/ai-native-product-copilot.txt +21 -0
  73. package/assets/project-structures/ai-native-runtime-console.txt +25 -0
  74. package/assets/project-structures/ai-native-sidecar-kernel.txt +19 -0
  75. package/assets/project-structures/astro-ssr.txt +25 -0
  76. package/assets/project-structures/expo-nativewind.txt +52 -0
  77. package/assets/project-structures/monorepo.txt +63 -0
  78. package/assets/project-structures/remix.txt +50 -0
  79. package/assets/project-structures/tanstack-start-workers.txt +51 -0
  80. package/assets/project-structures/vite-tanstack.txt +58 -0
  81. package/assets/reference-configs/AGENTS.md +13 -0
  82. package/assets/reference-configs/CLAUDE.md +13 -0
  83. package/assets/reference-configs/agentic-development-flow.md +94 -0
  84. package/assets/reference-configs/ai-workflows.md +14 -0
  85. package/assets/reference-configs/changelog-versioning.md +13 -0
  86. package/assets/reference-configs/coding-standards.md +14 -0
  87. package/assets/reference-configs/development-protocol.md +21 -0
  88. package/assets/reference-configs/document-generation.md +38 -0
  89. package/assets/reference-configs/evaluator-rubric.md +19 -0
  90. package/assets/reference-configs/external-tooling.md +374 -0
  91. package/assets/reference-configs/git-strategy.md +14 -0
  92. package/assets/reference-configs/global-working-rules.md +64 -0
  93. package/assets/reference-configs/handoff-protocol.md +38 -0
  94. package/assets/reference-configs/harness-overview.md +124 -0
  95. package/assets/reference-configs/heartbeat-triage.md +57 -0
  96. package/assets/reference-configs/hook-operations.md +96 -0
  97. package/assets/reference-configs/release-deploy.md +40 -0
  98. package/assets/reference-configs/spa-day-protocol.md +14 -0
  99. package/assets/reference-configs/sprint-contracts.md +89 -0
  100. package/assets/reference-configs/workflow-orchestration.md +14 -0
  101. package/assets/skill-hooks.json +41 -0
  102. package/assets/skill-version.json +189 -0
  103. package/assets/skills/claude-review/SKILL.md +231 -0
  104. package/assets/skills/codex-review/SKILL.md +103 -0
  105. package/assets/templates/AGENTS.md +13 -0
  106. package/assets/templates/CLAUDE.md +13 -0
  107. package/assets/templates/architecture.template.md +80 -0
  108. package/assets/templates/brief.template.md +38 -0
  109. package/assets/templates/contract.template.md +104 -0
  110. package/assets/templates/decisions.template.md +85 -0
  111. package/assets/templates/factor-factory/factor-backtest-report.template.md +36 -0
  112. package/assets/templates/factor-factory/factor-hypothesis.template.md +30 -0
  113. package/assets/templates/factor-factory/factor-registry.template.json +5 -0
  114. package/assets/templates/gitignore.template +53 -0
  115. package/assets/templates/guides/metro-esm-gotchas.template.md +46 -0
  116. package/assets/templates/helpers/architecture-event.ts +822 -0
  117. package/assets/templates/helpers/architecture-queue.sh +647 -0
  118. package/assets/templates/helpers/archive-architecture-request.sh +244 -0
  119. package/assets/templates/helpers/archive-workflow.sh +295 -0
  120. package/assets/templates/helpers/capability-config.ts +394 -0
  121. package/assets/templates/helpers/capability-resolver.ts +505 -0
  122. package/assets/templates/helpers/capture-plan.sh +335 -0
  123. package/assets/templates/helpers/check-agent-tooling.sh +1533 -0
  124. package/assets/templates/helpers/check-architecture-sync.sh +287 -0
  125. package/assets/templates/helpers/check-brain-manifest.sh +255 -0
  126. package/assets/templates/helpers/check-context-files.sh +49 -0
  127. package/assets/templates/helpers/check-deploy-sql-order.sh +117 -0
  128. package/assets/templates/helpers/check-skill-version.ts +193 -0
  129. package/assets/templates/helpers/check-task-sync.sh +65 -0
  130. package/assets/templates/helpers/check-task-workflow.sh +1002 -0
  131. package/assets/templates/helpers/codex-handoff-resume.sh +269 -0
  132. package/assets/templates/helpers/context-contract-sync.sh +516 -0
  133. package/assets/templates/helpers/contract-run.ts +465 -0
  134. package/assets/templates/helpers/contract-worktree.sh +725 -0
  135. package/assets/templates/helpers/ensure-task-workflow.sh +1218 -0
  136. package/assets/templates/helpers/harness-trace-grade.sh +150 -0
  137. package/assets/templates/helpers/heartbeat-triage.sh +361 -0
  138. package/assets/templates/helpers/inspect-project-state.ts +280 -0
  139. package/assets/templates/helpers/maintenance-triage.sh +167 -0
  140. package/assets/templates/helpers/migrate-project-template.sh +54 -0
  141. package/assets/templates/helpers/migrate-workflow-docs.ts +413 -0
  142. package/assets/templates/helpers/new-plan.sh +183 -0
  143. package/assets/templates/helpers/new-spec.sh +50 -0
  144. package/assets/templates/helpers/new-sprint.sh +49 -0
  145. package/assets/templates/helpers/plan-to-todo.sh +799 -0
  146. package/assets/templates/helpers/prepare-codex-handoff.sh +203 -0
  147. package/assets/templates/helpers/prepare-handoff.sh +81 -0
  148. package/assets/templates/helpers/refresh-current-status.sh +469 -0
  149. package/assets/templates/helpers/select-agent-context-blocks.sh +66 -0
  150. package/assets/templates/helpers/ship-worktrees.sh +561 -0
  151. package/assets/templates/helpers/sprint-backlog.sh +837 -0
  152. package/assets/templates/helpers/summarize-failures.sh +125 -0
  153. package/assets/templates/helpers/switch-plan.sh +153 -0
  154. package/assets/templates/helpers/sync-brain-docs.sh +381 -0
  155. package/assets/templates/helpers/verify-contract.sh +705 -0
  156. package/assets/templates/helpers/verify-sprint.sh +680 -0
  157. package/assets/templates/helpers/workflow-contract.ts +202 -0
  158. package/assets/templates/helpers/workstream-sync.sh +263 -0
  159. package/assets/templates/implementation-notes.template.md +37 -0
  160. package/assets/templates/packages.template.md +45 -0
  161. package/assets/templates/plan.template.md +77 -0
  162. package/assets/templates/prd.template.md +165 -0
  163. package/assets/templates/research.template.md +25 -0
  164. package/assets/templates/review.template.md +78 -0
  165. package/assets/templates/spec.template.md +31 -0
  166. package/assets/templates/sprint.template.md +69 -0
  167. package/assets/templates/tech-stack.template.md +57 -0
  168. package/assets/versions.json +77 -0
  169. package/assets/workflow-contract.v1.json +671 -0
  170. package/bin/forge-desktop-helper.mjs +204 -0
  171. package/bin/forge-hook.mjs +32 -0
  172. package/bin/forge-runtime-service.mjs +34 -0
  173. package/bin/forge-runtime.mjs +30 -0
  174. package/bin/forge.mjs +32 -0
  175. package/docs/CHANGELOG.md +978 -0
  176. package/docs/README.md +72 -0
  177. package/docs/README.zh-CN.md +58 -0
  178. package/docs/architecture/chatgpt-handoff-facade.md +393 -0
  179. package/docs/architecture/current/README.md +158 -0
  180. package/docs/architecture/current/approved-target-architecture.zh-CN.md +1501 -0
  181. package/docs/architecture/current/architecture-invariants.md +331 -0
  182. package/docs/architecture/current/automation-and-schedule-engine.md +453 -0
  183. package/docs/architecture/current/codegraph-context-provider.md +226 -0
  184. package/docs/architecture/current/control-plane-authority-inventory.md +82 -0
  185. package/docs/architecture/current/controller-repository-decoupling.md +148 -0
  186. package/docs/architecture/current/dispatch-and-agent-strategy.md +354 -0
  187. package/docs/architecture/current/entity-model.md +619 -0
  188. package/docs/architecture/current/external-plugin-governance.md +396 -0
  189. package/docs/architecture/current/failure-recovery.md +471 -0
  190. package/docs/architecture/current/governance.md +213 -0
  191. package/docs/architecture/current/human-interaction-plane.md +87 -0
  192. package/docs/architecture/current/implementation-status.md +128 -0
  193. package/docs/architecture/current/job-and-run-lifecycle.md +413 -0
  194. package/docs/architecture/current/local-workspace-target-grants.md +70 -0
  195. package/docs/architecture/current/migration-roadmap.md +105 -0
  196. package/docs/architecture/current/multi-repository-execution.md +371 -0
  197. package/docs/architecture/current/operations-runbook.md +45 -0
  198. package/docs/architecture/current/peer-supercontroller-runtime.md +32 -0
  199. package/docs/architecture/current/personal-assistant-plugin-baseline.md +207 -0
  200. package/docs/architecture/current/repository-access-modes.md +102 -0
  201. package/docs/architecture/current/route-policy.md +15 -0
  202. package/docs/architecture/current/route-session-concurrency.md +85 -0
  203. package/docs/architecture/current/runtime-architecture-simplification.md +214 -0
  204. package/docs/architecture/current/runtime-directory-map.md +49 -0
  205. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +85 -0
  206. package/docs/architecture/current/scheduler-and-resource-claims.md +432 -0
  207. package/docs/architecture/current/session-aware-execution-and-authorization.md +77 -0
  208. package/docs/architecture/current/system-overview.md +144 -0
  209. package/docs/architecture/current/target-requirements-traceability.md +202 -0
  210. package/docs/architecture/current/thin-harness-governance-policy.md +32 -0
  211. package/docs/architecture/current/thin-harness-v1.md +313 -0
  212. package/docs/architecture/current/verification-and-release-gates.md +391 -0
  213. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +100 -0
  214. package/docs/architecture/decisions/20260803-canonical-skill-surface.md +40 -0
  215. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +53 -0
  216. package/docs/architecture/diagrams/.gitkeep +1 -0
  217. package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +186 -0
  218. package/docs/architecture/domains/.gitkeep +0 -0
  219. package/docs/architecture/domains/public-surface.md +30 -0
  220. package/docs/architecture/domains/runtime-harness.md +33 -0
  221. package/docs/architecture/domains/verification.md +33 -0
  222. package/docs/architecture/domains/workflow-engine.md +30 -0
  223. package/docs/architecture/global-hook-runtime.md +162 -0
  224. package/docs/architecture/history.md +38 -0
  225. package/docs/architecture/index.md +114 -0
  226. package/docs/architecture/ios-semantic-automation-provider-v2.md +166 -0
  227. package/docs/architecture/modules/.gitkeep +0 -0
  228. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +24 -0
  229. package/docs/architecture/requests/.gitkeep +1 -0
  230. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
  231. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +59 -0
  232. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +59 -0
  233. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +59 -0
  234. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +59 -0
  235. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
  236. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
  237. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
  238. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
  239. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +59 -0
  240. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  241. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  242. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
  243. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  244. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
  245. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  246. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
  247. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
  248. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
  249. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +59 -0
  250. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +59 -0
  251. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +63 -0
  252. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
  253. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
  254. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
  255. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
  256. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +60 -0
  257. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +60 -0
  258. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +68 -0
  259. package/docs/architecture/requests/archive/2026/root.md +68 -0
  260. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +76 -0
  261. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +68 -0
  262. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +69 -0
  263. package/docs/architecture/reviews/2026-07-11-access-surface-review.md +99 -0
  264. package/docs/architecture/snapshots/.gitkeep +1 -0
  265. package/docs/forge-autonomous-goal-loop.md +7 -0
  266. package/docs/forge-chatgpt-browser-engine.md +11 -0
  267. package/docs/forge-chatgpt-mcp-setup.md +239 -0
  268. package/docs/forge-chatgpt-supervised-automation.md +11 -0
  269. package/docs/forge-github-issue-launcher.md +7 -0
  270. package/docs/forge-plugin-management.md +95 -0
  271. package/docs/forge-provider-configuration.md +7 -0
  272. package/docs/forge-runtime-self-healing-loop.md +7 -0
  273. package/docs/images/forge-banner-cn.svg +1 -0
  274. package/docs/images/forge-banner.svg +1 -0
  275. package/docs/images/forge-controller-flow.svg +1 -0
  276. package/docs/images/image.png +0 -0
  277. package/docs/images/repo-harness-gptpro-cn.png +0 -0
  278. package/docs/images/repo-harness-gptpro.png +0 -0
  279. package/docs/images/repo-harness-hook-carrot.png +0 -0
  280. package/docs/operations/chatgpt-personal-assistant-runtime.md +83 -0
  281. package/docs/operations/checkout-route-integrity.md +22 -0
  282. package/docs/operations/controller-browser-plugin.md +299 -0
  283. package/docs/operations/controller-desktop-plugin.md +112 -0
  284. package/docs/operations/controller-performance-and-502.md +126 -0
  285. package/docs/operations/controller-reliability-runbook.md +134 -0
  286. package/docs/operations/environment-hardening.md +50 -0
  287. package/docs/operations/features.md +45 -0
  288. package/docs/operations/features.zh-CN.md +45 -0
  289. package/docs/operations/github-repository.md +60 -0
  290. package/docs/operations/gmail-assistant-routines.md +186 -0
  291. package/docs/operations/homebrew.md +26 -0
  292. package/docs/operations/local-system-assistant.md +46 -0
  293. package/docs/operations/local-system-assistant.zh-CN.md +46 -0
  294. package/docs/operations/mcp-tool-exposure.md +58 -0
  295. package/docs/operations/mobile-intents-shortcuts.md +117 -0
  296. package/docs/operations/open-source-release-hygiene.md +31 -0
  297. package/docs/operations/personal-assistant-operator-guide.md +61 -0
  298. package/docs/operations/platform-support.md +62 -0
  299. package/docs/operations/platform-support.zh-CN.md +61 -0
  300. package/docs/operations/provider-configuration.md +31 -0
  301. package/docs/operations/releasing.md +86 -0
  302. package/docs/operations/releasing.zh-CN.md +86 -0
  303. package/docs/operations/route-session-concurrency-baseline.json +893 -0
  304. package/docs/operations/route-session-concurrency-baseline.md +94 -0
  305. package/docs/operations/runtime-performance-diagnostics.md +14 -0
  306. package/docs/operations/sqlite-control-plane-recovery.md +65 -0
  307. package/docs/operations/standalone-disaster-recovery.md +136 -0
  308. package/docs/operations/troubleshooting.md +72 -0
  309. package/docs/operations/troubleshooting.zh-CN.md +70 -0
  310. package/docs/public-usage-guide.md +33 -0
  311. package/docs/public-usage-guide.zh-CN.md +33 -0
  312. package/docs/tutorials/01-install-and-start.md +93 -0
  313. package/docs/tutorials/01-install-and-start.zh-CN.md +93 -0
  314. package/docs/tutorials/02-connect-chatgpt.md +82 -0
  315. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +80 -0
  316. package/docs/tutorials/03-first-repository-task.md +57 -0
  317. package/docs/tutorials/03-first-repository-task.zh-CN.md +57 -0
  318. package/docs/tutorials/README.md +13 -0
  319. package/docs/tutorials/README.zh-CN.md +13 -0
  320. package/docs/wiki/Architecture.md +85 -0
  321. package/docs/wiki/Core-Concepts.md +27 -0
  322. package/docs/wiki/Home.md +36 -0
  323. package/docs/wiki/Implementation.md +172 -0
  324. package/docs/wiki/Installation.md +50 -0
  325. package/docs/wiki/Integrations.md +29 -0
  326. package/docs/wiki/Operations.md +26 -0
  327. package/docs/wiki/Quick-Start.md +46 -0
  328. package/docs/wiki/Releases-and-Upgrades.md +34 -0
  329. package/docs/wiki/Runtime-Architecture.md +50 -0
  330. package/docs/wiki/Security-Model.md +31 -0
  331. package/docs/wiki/Troubleshooting.md +38 -0
  332. package/docs/wiki/Work-Lifecycle.md +31 -0
  333. package/docs/wiki/_Sidebar.md +21 -0
  334. package/install.ps1 +48 -0
  335. package/install.sh +66 -0
  336. package/package.json +156 -0
  337. package/scripts/activate-source-baseline.ts +335 -0
  338. package/scripts/architecture-event.ts +822 -0
  339. package/scripts/architecture-queue.sh +647 -0
  340. package/scripts/archive-architecture-request.sh +244 -0
  341. package/scripts/archive-workflow.sh +295 -0
  342. package/scripts/assemble-template.ts +1172 -0
  343. package/scripts/benchmark-controller-hotpath.ts +212 -0
  344. package/scripts/benchmark-controller-round2.ts +139 -0
  345. package/scripts/benchmark-ios-agent-device.ts +514 -0
  346. package/scripts/benchmark-route-session-concurrency.ts +714 -0
  347. package/scripts/benchmark-thin-harness-gateway-ab.ts +632 -0
  348. package/scripts/benchmark-thin-harness-mcp-e2e.ts +479 -0
  349. package/scripts/benchmark-thin-harness.ts +251 -0
  350. package/scripts/bootstrap-runtime-maintenance-recovery.sh +183 -0
  351. package/scripts/canary-global-hook.sh +263 -0
  352. package/scripts/capability-config.ts +394 -0
  353. package/scripts/capability-resolver.ts +505 -0
  354. package/scripts/capture-plan.sh +335 -0
  355. package/scripts/check-agent-tooling.sh +1549 -0
  356. package/scripts/check-architecture-sync.sh +373 -0
  357. package/scripts/check-brain-manifest.sh +255 -0
  358. package/scripts/check-ci.sh +16 -0
  359. package/scripts/check-context-files.sh +49 -0
  360. package/scripts/check-deploy-sql-order.sh +117 -0
  361. package/scripts/check-mcp-compatibility.ts +93 -0
  362. package/scripts/check-npm-release.sh +32 -0
  363. package/scripts/check-open-source-tracked-surface.sh +146 -0
  364. package/scripts/check-package-identity.mjs +117 -0
  365. package/scripts/check-platform-support.mjs +79 -0
  366. package/scripts/check-public-docs.sh +105 -0
  367. package/scripts/check-public-release-surface.sh +19 -0
  368. package/scripts/check-release-published.sh +57 -0
  369. package/scripts/check-release-readiness.sh +43 -0
  370. package/scripts/check-release-version.mjs +74 -0
  371. package/scripts/check-runtime-architecture.mjs +593 -0
  372. package/scripts/check-runtime-env.mjs +89 -0
  373. package/scripts/check-skill-version.ts +193 -0
  374. package/scripts/check-tarball-install-smoke.sh +66 -0
  375. package/scripts/check-task-sync.sh +65 -0
  376. package/scripts/check-task-workflow.sh +1002 -0
  377. package/scripts/check-third-party-notices.mjs +36 -0
  378. package/scripts/codex-handoff-resume.sh +269 -0
  379. package/scripts/complete-control-plane-cutover.ts +126 -0
  380. package/scripts/context-contract-sync.sh +516 -0
  381. package/scripts/contract-run.ts +465 -0
  382. package/scripts/contract-worktree.sh +725 -0
  383. package/scripts/controller-ngrok-rotation.sh +678 -0
  384. package/scripts/create-project-dirs.sh +282 -0
  385. package/scripts/ensure-codegraph.sh +16 -0
  386. package/scripts/ensure-task-workflow.sh +1218 -0
  387. package/scripts/export-requirement-portfolio.ts +28 -0
  388. package/scripts/factor-lab-check.sh +73 -0
  389. package/scripts/factor-lab-new.sh +96 -0
  390. package/scripts/factor-lab-promote.sh +86 -0
  391. package/scripts/factor-lab-reject.sh +68 -0
  392. package/scripts/harness-trace-grade.sh +150 -0
  393. package/scripts/heartbeat-triage.sh +361 -0
  394. package/scripts/hook-dispatch-diet-report.ts +234 -0
  395. package/scripts/hook-shim.sh +93 -0
  396. package/scripts/init-project.sh +505 -0
  397. package/scripts/initializer-question-pack.ts +200 -0
  398. package/scripts/inspect-project-state.ts +280 -0
  399. package/scripts/install-desktop-operator-registration.ts +45 -0
  400. package/scripts/install-standalone-recovery.ts +74 -0
  401. package/scripts/lib/AGENTS.md +13 -0
  402. package/scripts/lib/CLAUDE.md +13 -0
  403. package/scripts/lib/controller-home-env.sh +69 -0
  404. package/scripts/lib/project-init-lib.sh +2759 -0
  405. package/scripts/load-standalone-recovery.sh +17 -0
  406. package/scripts/loop-engine-cutover-gate.ts +324 -0
  407. package/scripts/maintenance-triage.sh +167 -0
  408. package/scripts/migrate-project-template.sh +1189 -0
  409. package/scripts/migrate-requirement-portfolio.ts +86 -0
  410. package/scripts/migrate-workflow-docs.ts +413 -0
  411. package/scripts/new-plan.sh +183 -0
  412. package/scripts/new-spec.sh +50 -0
  413. package/scripts/new-sprint.sh +49 -0
  414. package/scripts/open-source-audit-allowlist.txt +46 -0
  415. package/scripts/package-source-archive.sh +147 -0
  416. package/scripts/plan-to-todo.sh +799 -0
  417. package/scripts/prepare-codex-handoff.sh +203 -0
  418. package/scripts/prepare-handoff.sh +81 -0
  419. package/scripts/public-release-files.txt +39 -0
  420. package/scripts/public-release.ts +174 -0
  421. package/scripts/publish-release-tarball.sh +27 -0
  422. package/scripts/refresh-current-status.sh +469 -0
  423. package/scripts/refresh-ios-physical-runtime.ts +196 -0
  424. package/scripts/repair-executable-modes.ts +8 -0
  425. package/scripts/rollout-all-registered-repos.sh +7 -0
  426. package/scripts/route-nl-vs-ts-eval.ts +679 -0
  427. package/scripts/run-bun-test-file.ts +182 -0
  428. package/scripts/run-governed-gate.ts +140 -0
  429. package/scripts/run-mobile-monitor-bridge.ts +71 -0
  430. package/scripts/run-skill-evals.ts +1022 -0
  431. package/scripts/run-skill-hook.ts +244 -0
  432. package/scripts/run-supervised-command.ts +24 -0
  433. package/scripts/run-tests-portable.sh +20 -0
  434. package/scripts/select-agent-context-blocks.sh +66 -0
  435. package/scripts/setup-plugins.sh +43 -0
  436. package/scripts/ship-worktrees.sh +561 -0
  437. package/scripts/smoke-browser-cdp-bridge.ts +93 -0
  438. package/scripts/smoke-chatgpt-supervised-automation.ts +208 -0
  439. package/scripts/smoke-ios-physical-device.ts +114 -0
  440. package/scripts/smoke-mcp-http-runtime.ts +216 -0
  441. package/scripts/smoke-mcp-tool-surface.ts +117 -0
  442. package/scripts/smoke-runtime-recovery.ts +220 -0
  443. package/scripts/smoke-schedule-engine.ts +283 -0
  444. package/scripts/sprint-backlog.sh +837 -0
  445. package/scripts/stage-runtime-release.ts +38 -0
  446. package/scripts/summarize-failures.sh +125 -0
  447. package/scripts/switch-plan.sh +153 -0
  448. package/scripts/sync-brain-docs.sh +381 -0
  449. package/scripts/sync-codex-installed-copies.sh +183 -0
  450. package/scripts/test-governance.ts +75 -0
  451. package/scripts/verify-contract.sh +705 -0
  452. package/scripts/verify-forge-runtime.sh +31 -0
  453. package/scripts/verify-sprint.sh +680 -0
  454. package/scripts/windows-paths.d.mts +7 -0
  455. package/scripts/windows-paths.mjs +28 -0
  456. package/scripts/workflow-contract.ts +206 -0
  457. package/scripts/workstream-sync.sh +263 -0
  458. package/src/cli/agent-jobs/executable-resolver.ts +289 -0
  459. package/src/cli/agent-jobs/executor-health.ts +252 -0
  460. package/src/cli/agent-jobs/integration.ts +963 -0
  461. package/src/cli/agent-jobs/job-manager.ts +2030 -0
  462. package/src/cli/agent-jobs/types.ts +219 -0
  463. package/src/cli/agent-jobs/worker-lifecycle.ts +288 -0
  464. package/src/cli/chatgpt-browser/bind-server.ts +504 -0
  465. package/src/cli/chatgpt-browser/binding.ts +140 -0
  466. package/src/cli/chatgpt-browser/bridge-extension.ts +221 -0
  467. package/src/cli/chatgpt-browser/bridge-provider.ts +268 -0
  468. package/src/cli/chatgpt-browser/engine.ts +569 -0
  469. package/src/cli/chatgpt-browser/file-policy.ts +158 -0
  470. package/src/cli/chatgpt-browser/native-provider.ts +553 -0
  471. package/src/cli/chatgpt-browser/oracle-provider.ts +437 -0
  472. package/src/cli/chatgpt-browser/prompt-assembler.ts +29 -0
  473. package/src/cli/chatgpt-browser/session-store.ts +301 -0
  474. package/src/cli/chatgpt-browser/types.ts +172 -0
  475. package/src/cli/commands/adopt-plan.ts +186 -0
  476. package/src/cli/commands/brain-root.ts +132 -0
  477. package/src/cli/commands/brain.ts +609 -0
  478. package/src/cli/commands/capability-context.ts +613 -0
  479. package/src/cli/commands/chatgpt.ts +424 -0
  480. package/src/cli/commands/controller.ts +680 -0
  481. package/src/cli/commands/docs.ts +103 -0
  482. package/src/cli/commands/doctor.ts +476 -0
  483. package/src/cli/commands/global-runtime.ts +323 -0
  484. package/src/cli/commands/hook.ts +34 -0
  485. package/src/cli/commands/init-hook.ts +870 -0
  486. package/src/cli/commands/init.ts +829 -0
  487. package/src/cli/commands/install.ts +86 -0
  488. package/src/cli/commands/mcp.ts +315 -0
  489. package/src/cli/commands/migrate.ts +154 -0
  490. package/src/cli/commands/plugin.ts +74 -0
  491. package/src/cli/commands/prompt-guard-decision.ts +238 -0
  492. package/src/cli/commands/recovery.ts +667 -0
  493. package/src/cli/commands/repository.ts +224 -0
  494. package/src/cli/commands/run.ts +23 -0
  495. package/src/cli/commands/runtime.ts +191 -0
  496. package/src/cli/commands/security.ts +440 -0
  497. package/src/cli/commands/status.ts +137 -0
  498. package/src/cli/commands/tools.ts +167 -0
  499. package/src/cli/controller/check-runner.ts +1022 -0
  500. package/src/cli/controller/codex-continuation.ts +153 -0
  501. package/src/cli/controller/completion-backlog.ts +380 -0
  502. package/src/cli/controller/completion-orchestrator.ts +1807 -0
  503. package/src/cli/controller/completion-target.ts +96 -0
  504. package/src/cli/controller/composite-operations.ts +196 -0
  505. package/src/cli/controller/composite-result.ts +130 -0
  506. package/src/cli/controller/context-pack.ts +652 -0
  507. package/src/cli/controller/execution-completion.ts +175 -0
  508. package/src/cli/controller/execution-policy.ts +392 -0
  509. package/src/cli/controller/governance.ts +594 -0
  510. package/src/cli/controller/issue-store.ts +1421 -0
  511. package/src/cli/controller/launch-agents.ts +410 -0
  512. package/src/cli/controller/legacy-issue-cutover.ts +415 -0
  513. package/src/cli/controller/lifecycle-authority.ts +16 -0
  514. package/src/cli/controller/migrated-issue-decision.ts +237 -0
  515. package/src/cli/controller/operational-plan.ts +226 -0
  516. package/src/cli/controller/postcondition.ts +134 -0
  517. package/src/cli/controller/progress.ts +656 -0
  518. package/src/cli/controller/project-state.ts +147 -0
  519. package/src/cli/controller/requirement-portfolio-export.ts +146 -0
  520. package/src/cli/controller/requirement-portfolio-migration.ts +613 -0
  521. package/src/cli/controller/run-evidence.ts +43 -0
  522. package/src/cli/controller/runtime-config.ts +92 -0
  523. package/src/cli/controller/stuck-state-migration.ts +396 -0
  524. package/src/cli/controller/task-ledger.ts +632 -0
  525. package/src/cli/controller/task-status-resolver.ts +403 -0
  526. package/src/cli/controller/types.ts +273 -0
  527. package/src/cli/controller/work-mode.ts +186 -0
  528. package/src/cli/controller/worklog.ts +201 -0
  529. package/src/cli/diagnostic-entry.ts +39 -0
  530. package/src/cli/editing/edit-session.ts +1606 -0
  531. package/src/cli/editing/executable-modes.ts +70 -0
  532. package/src/cli/github/github.ts +274 -0
  533. package/src/cli/github/plugin.ts +345 -0
  534. package/src/cli/github/session.ts +104 -0
  535. package/src/cli/hook/prompt-guard-decision.ts +238 -0
  536. package/src/cli/hook/prompt-intents.ts +534 -0
  537. package/src/cli/hook/route-registry.ts +107 -0
  538. package/src/cli/hook/runtime.ts +303 -0
  539. package/src/cli/hook/state-snapshot.ts +388 -0
  540. package/src/cli/hook-entry.ts +51 -0
  541. package/src/cli/index.ts +574 -0
  542. package/src/cli/installer/managed-entries.ts +78 -0
  543. package/src/cli/installer/shared.ts +65 -0
  544. package/src/cli/installer/targets/claude.ts +136 -0
  545. package/src/cli/installer/targets/codex.ts +174 -0
  546. package/src/cli/installer/targets/registry.ts +28 -0
  547. package/src/cli/installer/types.ts +72 -0
  548. package/src/cli/local-bridge/connector-freshness.ts +529 -0
  549. package/src/cli/local-bridge/console-view-models.ts +324 -0
  550. package/src/cli/local-bridge/dashboard.ts +1312 -0
  551. package/src/cli/local-bridge/facade-api.ts +1877 -0
  552. package/src/cli/local-bridge/job-store.ts +1451 -0
  553. package/src/cli/local-bridge/mobile-intents.ts +344 -0
  554. package/src/cli/local-bridge/mobile-monitor.ts +209 -0
  555. package/src/cli/local-bridge/server.ts +3183 -0
  556. package/src/cli/local-bridge/types.ts +176 -0
  557. package/src/cli/mcp/access-mode.ts +132 -0
  558. package/src/cli/mcp/access-tools.ts +387 -0
  559. package/src/cli/mcp/audit.ts +32 -0
  560. package/src/cli/mcp/auth.ts +402 -0
  561. package/src/cli/mcp/instructions.ts +33 -0
  562. package/src/cli/mcp/legacy-context.ts +16 -0
  563. package/src/cli/mcp/legacy-tool-service.ts +5516 -0
  564. package/src/cli/mcp/multi-repository.ts +423 -0
  565. package/src/cli/mcp/oauth.ts +226 -0
  566. package/src/cli/mcp/paths.ts +134 -0
  567. package/src/cli/mcp/policy.ts +230 -0
  568. package/src/cli/mcp/proxy-env.ts +62 -0
  569. package/src/cli/mcp/readiness-projection.ts +24 -0
  570. package/src/cli/mcp/redaction.ts +21 -0
  571. package/src/cli/mcp/repo.ts +24 -0
  572. package/src/cli/mcp/repository-tools.ts +1295 -0
  573. package/src/cli/mcp/server.ts +341 -0
  574. package/src/cli/mcp/setup.ts +793 -0
  575. package/src/cli/mcp/tool-capability-cache.ts +87 -0
  576. package/src/cli/mcp/tools.ts +9 -0
  577. package/src/cli/mcp/toolset-names.ts +70 -0
  578. package/src/cli/mcp/toolset-selection.ts +41 -0
  579. package/src/cli/mcp/toolset.ts +300 -0
  580. package/src/cli/mcp/transports/AGENTS.md +39 -0
  581. package/src/cli/mcp/transports/CLAUDE.md +39 -0
  582. package/src/cli/mcp/transports/http.ts +1234 -0
  583. package/src/cli/mcp/transports/session-registry.ts +428 -0
  584. package/src/cli/mcp/transports/stdio.ts +8 -0
  585. package/src/cli/mcp/types.ts +41 -0
  586. package/src/cli/mcp/umbrella-tools.ts +117 -0
  587. package/src/cli/repo-adoption/reclaim-runtime.ts +681 -0
  588. package/src/cli/repositories/branch-name-policy.ts +57 -0
  589. package/src/cli/repositories/command-classifier.ts +600 -0
  590. package/src/cli/repositories/command-executor.ts +1066 -0
  591. package/src/cli/repositories/command-normalization.ts +53 -0
  592. package/src/cli/repositories/command-scope.ts +264 -0
  593. package/src/cli/repositories/controller-home.ts +88 -0
  594. package/src/cli/repositories/entity-migration.ts +199 -0
  595. package/src/cli/repositories/ephemeral-workspace.ts +62 -0
  596. package/src/cli/repositories/git-command-executor.ts +301 -0
  597. package/src/cli/repositories/goal-registry.ts +239 -0
  598. package/src/cli/repositories/identity.ts +64 -0
  599. package/src/cli/repositories/local-project-onboarding.ts +539 -0
  600. package/src/cli/repositories/locks.ts +262 -0
  601. package/src/cli/repositories/registry.ts +1057 -0
  602. package/src/cli/repositories/runtime-storage.ts +411 -0
  603. package/src/cli/repositories/safe-patch.ts +421 -0
  604. package/src/cli/repositories/selected-path-actions.ts +341 -0
  605. package/src/cli/repositories/structured-git.ts +257 -0
  606. package/src/cli/repositories/types.ts +155 -0
  607. package/src/cli/repositories/umbrella.ts +134 -0
  608. package/src/cli/repositories/workbench.ts +140 -0
  609. package/src/cli/repositories/worktree-storage.ts +137 -0
  610. package/src/cli/repository/inspector.ts +637 -0
  611. package/src/cli/repository/session-cache.ts +453 -0
  612. package/src/cli/runtime/helper-runner.ts +172 -0
  613. package/src/cli/runtime-invocation.ts +318 -0
  614. package/src/cli/tools/codegraph.ts +676 -0
  615. package/src/cli/v81-entry.ts +29 -0
  616. package/src/core/adoption/gitignore-plan.ts +127 -0
  617. package/src/core/adoption/helper-wrapper-plan.ts +159 -0
  618. package/src/core/adoption/manifest-templates.ts +60 -0
  619. package/src/core/adoption/modes.ts +7 -0
  620. package/src/core/adoption/operations.ts +126 -0
  621. package/src/core/adoption/plan.ts +149 -0
  622. package/src/core/adoption/render.ts +70 -0
  623. package/src/core/adoption/rollback.ts +62 -0
  624. package/src/core/adoption/summary.ts +43 -0
  625. package/src/core/adoption/workflow-contract-asset.ts +14 -0
  626. package/src/core/adoption/workflow-contract-plan.ts +31 -0
  627. package/src/effects/fs-transaction.ts +540 -0
  628. package/src/effects/git-executable.ts +59 -0
  629. package/src/effects/managed-block.ts +86 -0
  630. package/src/effects/path-safety.ts +47 -0
  631. package/src/effects/process-runner.ts +192 -0
  632. package/src/runtime/assistant/action-proposals.ts +279 -0
  633. package/src/runtime/assistant/intent.ts +395 -0
  634. package/src/runtime/assistant/model-provider.ts +460 -0
  635. package/src/runtime/assistant/openapi.ts +223 -0
  636. package/src/runtime/assistant/policy.ts +89 -0
  637. package/src/runtime/assistant/readiness.ts +258 -0
  638. package/src/runtime/assistant/routine-runtime.ts +477 -0
  639. package/src/runtime/assistant/schedule-binding.ts +171 -0
  640. package/src/runtime/assistant/standing-grants.ts +375 -0
  641. package/src/runtime/assistant/store.ts +243 -0
  642. package/src/runtime/assistant/types.ts +135 -0
  643. package/src/runtime/context/codegraph-read-provider.ts +347 -0
  644. package/src/runtime/context/codegraph-sidecar.cjs +207 -0
  645. package/src/runtime/control-plane/dispatch-priority.ts +67 -0
  646. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +151 -0
  647. package/src/runtime/control-plane/execution/execution-identity.ts +456 -0
  648. package/src/runtime/control-plane/execution/session-store.ts +175 -0
  649. package/src/runtime/control-plane/execution/validation.ts +117 -0
  650. package/src/runtime/control-plane/execution/verification-evidence.ts +191 -0
  651. package/src/runtime/control-plane/execution/work-handle-store.ts +225 -0
  652. package/src/runtime/control-plane/execution/work-prepare-request-store.ts +159 -0
  653. package/src/runtime/control-plane/execution/work-task-receipt.ts +445 -0
  654. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +821 -0
  655. package/src/runtime/control-plane/facade/capability-registry.ts +279 -0
  656. package/src/runtime/control-plane/facade/check-normalization.ts +233 -0
  657. package/src/runtime/control-plane/facade/codex-delegation.ts +196 -0
  658. package/src/runtime/control-plane/facade/controller-session-store.ts +199 -0
  659. package/src/runtime/control-plane/facade/facade-result.ts +41 -0
  660. package/src/runtime/control-plane/facade/goal-workloop-access.ts +177 -0
  661. package/src/runtime/control-plane/facade/goal-workloop.ts +1216 -0
  662. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +221 -0
  663. package/src/runtime/control-plane/facade/index.ts +16 -0
  664. package/src/runtime/control-plane/facade/operation-digest.ts +528 -0
  665. package/src/runtime/control-plane/facade/plan-contract-store.ts +403 -0
  666. package/src/runtime/control-plane/facade/policy-gate.ts +149 -0
  667. package/src/runtime/control-plane/facade/requirement-board.ts +280 -0
  668. package/src/runtime/control-plane/facade/self-healing-loop.ts +555 -0
  669. package/src/runtime/control-plane/facade/suggested-actions.ts +108 -0
  670. package/src/runtime/control-plane/facade/types.ts +729 -0
  671. package/src/runtime/control-plane/facade/work-admission-policy.ts +93 -0
  672. package/src/runtime/control-plane/facade/work-continuation.ts +104 -0
  673. package/src/runtime/control-plane/facade/work-contract-store.ts +1118 -0
  674. package/src/runtime/control-plane/facade/work-task-projection.ts +66 -0
  675. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +365 -0
  676. package/src/runtime/control-plane/global-scheduler/scheduler.ts +920 -0
  677. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +89 -0
  678. package/src/runtime/control-plane/goal-loop/config-facade.ts +700 -0
  679. package/src/runtime/control-plane/goal-loop/config-store.ts +570 -0
  680. package/src/runtime/control-plane/goal-loop/config-types.ts +213 -0
  681. package/src/runtime/control-plane/goal-loop/executor-router.ts +109 -0
  682. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +149 -0
  683. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +304 -0
  684. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +1001 -0
  685. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +160 -0
  686. package/src/runtime/control-plane/goal-loop/index.ts +13 -0
  687. package/src/runtime/control-plane/goal-loop/local-tools.ts +290 -0
  688. package/src/runtime/control-plane/goal-loop/policy-gates.ts +203 -0
  689. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +93 -0
  690. package/src/runtime/control-plane/goal-loop/provider-registry.ts +545 -0
  691. package/src/runtime/control-plane/goal-loop/types.ts +378 -0
  692. package/src/runtime/control-plane/governance/access-policy.ts +147 -0
  693. package/src/runtime/control-plane/governance/authorization.ts +195 -0
  694. package/src/runtime/control-plane/governance/external-effects.ts +43 -0
  695. package/src/runtime/control-plane/launcher/thin-launcher.ts +97 -0
  696. package/src/runtime/control-plane/persistence/metadata-payload-policy.ts +53 -0
  697. package/src/runtime/control-plane/persistence/requirement-store.ts +241 -0
  698. package/src/runtime/control-plane/persistence/sqlite-store.ts +539 -0
  699. package/src/runtime/control-plane/release-retention.ts +447 -0
  700. package/src/runtime/control-plane/repo-actor/actor.ts +181 -0
  701. package/src/runtime/control-plane/repo-actor/registry.ts +20 -0
  702. package/src/runtime/control-plane/routing/index.ts +1 -0
  703. package/src/runtime/control-plane/routing/route-policy.ts +379 -0
  704. package/src/runtime/control-plane/runtime-cleanup.ts +727 -0
  705. package/src/runtime/control-plane/runtime-generation.ts +509 -0
  706. package/src/runtime/control-plane/runtime-pid-ownership.ts +11 -0
  707. package/src/runtime/control-plane/runtime-status-client.ts +90 -0
  708. package/src/runtime/control-plane/startup-recovery.ts +198 -0
  709. package/src/runtime/diagnostics/connectivity-observability.ts +475 -0
  710. package/src/runtime/diagnostics/mcp-timing.ts +64 -0
  711. package/src/runtime/diagnostics/performance.ts +379 -0
  712. package/src/runtime/diagnostics/process-facade.ts +350 -0
  713. package/src/runtime/diagnostics/read-only-tool.ts +226 -0
  714. package/src/runtime/evidence/artifact-store.ts +154 -0
  715. package/src/runtime/evidence/event-ledger.ts +80 -0
  716. package/src/runtime/evidence/evidence-store.ts +68 -0
  717. package/src/runtime/evidence/process-check-receipt.ts +43 -0
  718. package/src/runtime/evidence/result-store.ts +209 -0
  719. package/src/runtime/evidence/sensitive-output.ts +353 -0
  720. package/src/runtime/execution/jobs/child-reference.ts +124 -0
  721. package/src/runtime/execution/jobs/legacy-adapter.ts +22 -0
  722. package/src/runtime/execution/jobs/receipt-recovery.ts +119 -0
  723. package/src/runtime/execution/jobs/receipt-store.ts +243 -0
  724. package/src/runtime/execution/jobs/store.ts +737 -0
  725. package/src/runtime/execution/jobs/timeouts.ts +109 -0
  726. package/src/runtime/execution/jobs/types.ts +230 -0
  727. package/src/runtime/execution/jobs/wait.ts +45 -0
  728. package/src/runtime/execution/process-runtime/canary.ts +26 -0
  729. package/src/runtime/execution/process-runtime/check-facade.ts +272 -0
  730. package/src/runtime/execution/process-runtime/check-receipt.ts +185 -0
  731. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +60 -0
  732. package/src/runtime/execution/process-runtime/command-facade.ts +321 -0
  733. package/src/runtime/execution/process-runtime/gc.ts +171 -0
  734. package/src/runtime/execution/process-runtime/index.ts +9 -0
  735. package/src/runtime/execution/process-runtime/interactive-admission.ts +23 -0
  736. package/src/runtime/execution/process-runtime/process-runner-entry.ts +466 -0
  737. package/src/runtime/execution/process-runtime/resource-claims.ts +440 -0
  738. package/src/runtime/execution/process-runtime/runtime.ts +1816 -0
  739. package/src/runtime/execution/process-runtime/store.ts +687 -0
  740. package/src/runtime/execution/process-runtime/types.ts +352 -0
  741. package/src/runtime/execution/thin-harness/async-process.ts +181 -0
  742. package/src/runtime/execution/thin-harness/batch-executor.ts +671 -0
  743. package/src/runtime/execution/thin-harness/execution-router.ts +700 -0
  744. package/src/runtime/execution/thin-harness/fast-executor.ts +1263 -0
  745. package/src/runtime/execution/thin-harness/fast-receipt.ts +235 -0
  746. package/src/runtime/execution/thin-harness/fingerprint-worker.ts +191 -0
  747. package/src/runtime/execution/thin-harness/index.ts +13 -0
  748. package/src/runtime/execution/thin-harness/latency-trace.ts +107 -0
  749. package/src/runtime/execution/thin-harness/lightweight-lanes.ts +745 -0
  750. package/src/runtime/execution/thin-harness/mutation-gate.ts +578 -0
  751. package/src/runtime/execution/thin-harness/proposal-store.ts +409 -0
  752. package/src/runtime/execution/thin-harness/request-ledger.ts +595 -0
  753. package/src/runtime/execution/thin-harness/search-worker.ts +114 -0
  754. package/src/runtime/execution/thin-harness/types.ts +313 -0
  755. package/src/runtime/execution/thin-harness/workspace-savepoint.ts +333 -0
  756. package/src/runtime/execution/workers/executor.ts +687 -0
  757. package/src/runtime/execution/workers/ownership.ts +94 -0
  758. package/src/runtime/execution/workers/worker-entry.ts +277 -0
  759. package/src/runtime/gateway/mcp/execution-tools.ts +2009 -0
  760. package/src/runtime/gateway/mcp/persisted-check-process.ts +255 -0
  761. package/src/runtime/gateway/mcp/process-tools.ts +230 -0
  762. package/src/runtime/gateway/mcp/resource-policy.ts +195 -0
  763. package/src/runtime/gateway/mcp/router.ts +1088 -0
  764. package/src/runtime/gateway/mcp/runtime-tools.ts +5994 -0
  765. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +219 -0
  766. package/src/runtime/health/evaluator.ts +474 -0
  767. package/src/runtime/health/index.ts +2 -0
  768. package/src/runtime/health/operational-view.ts +198 -0
  769. package/src/runtime/maintenance/cleanup.ts +419 -0
  770. package/src/runtime/model-clients/deepseek-adapter.ts +312 -0
  771. package/src/runtime/model-clients/index.ts +2 -0
  772. package/src/runtime/model-clients/types.ts +101 -0
  773. package/src/runtime/observability/gateway-contention-metrics.ts +129 -0
  774. package/src/runtime/observability/route-session-benchmark.ts +110 -0
  775. package/src/runtime/personal-assistant/gmail-triage-manager.ts +231 -0
  776. package/src/runtime/personal-assistant/reporting-runtime.ts +344 -0
  777. package/src/runtime/personal-assistant/triage-runtime.ts +748 -0
  778. package/src/runtime/plugins/app-store-connect-adapter.ts +868 -0
  779. package/src/runtime/plugins/browser-adapter.ts +2812 -0
  780. package/src/runtime/plugins/browser-automation-service.ts +46 -0
  781. package/src/runtime/plugins/browser-handoff-host.ts +304 -0
  782. package/src/runtime/plugins/browser-handoff.ts +371 -0
  783. package/src/runtime/plugins/browser-macos-bridge.ts +865 -0
  784. package/src/runtime/plugins/browser-node-bridge-host.ts +64 -0
  785. package/src/runtime/plugins/browser-node-bridge.ts +249 -0
  786. package/src/runtime/plugins/desktop-adapter.ts +374 -0
  787. package/src/runtime/plugins/desktop-operator-registration.ts +418 -0
  788. package/src/runtime/plugins/errors.ts +39 -0
  789. package/src/runtime/plugins/execution-origin.ts +26 -0
  790. package/src/runtime/plugins/external-adapter.ts +322 -0
  791. package/src/runtime/plugins/external-registration.ts +308 -0
  792. package/src/runtime/plugins/external-unix-socket-probe.cjs +79 -0
  793. package/src/runtime/plugins/external-unix-socket.ts +238 -0
  794. package/src/runtime/plugins/first-party-registry.ts +37 -0
  795. package/src/runtime/plugins/github-adapter.ts +266 -0
  796. package/src/runtime/plugins/gmail-adapter.ts +729 -0
  797. package/src/runtime/plugins/google-calendar-adapter.ts +468 -0
  798. package/src/runtime/plugins/google-shared.ts +578 -0
  799. package/src/runtime/plugins/google-tasks-adapter.ts +535 -0
  800. package/src/runtime/plugins/interaction-session.ts +252 -0
  801. package/src/runtime/plugins/ios/agent-device-capabilities.ts +258 -0
  802. package/src/runtime/plugins/ios/agent-device-failures.ts +95 -0
  803. package/src/runtime/plugins/ios/agent-device-provider.ts +63 -0
  804. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +268 -0
  805. package/src/runtime/plugins/ios/app-adapters.ts +122 -0
  806. package/src/runtime/plugins/ios-adapter.ts +509 -0
  807. package/src/runtime/plugins/ios-agent-device.ts +2311 -0
  808. package/src/runtime/plugins/ios-physical-device.ts +955 -0
  809. package/src/runtime/plugins/local-system-adapter.ts +1016 -0
  810. package/src/runtime/plugins/macos-capability-broker.ts +73 -0
  811. package/src/runtime/plugins/managed-process-adapter.ts +366 -0
  812. package/src/runtime/plugins/resend-adapter.ts +506 -0
  813. package/src/runtime/plugins/store.ts +1025 -0
  814. package/src/runtime/plugins/types.ts +138 -0
  815. package/src/runtime/projections/controller-context.ts +596 -0
  816. package/src/runtime/projections/git-status-sampler.ts +84 -0
  817. package/src/runtime/projections/invalidation.ts +250 -0
  818. package/src/runtime/projections/materialized-view.ts +694 -0
  819. package/src/runtime/recovery/actions.ts +158 -0
  820. package/src/runtime/recovery/audit.ts +38 -0
  821. package/src/runtime/recovery/classifier.ts +163 -0
  822. package/src/runtime/recovery/index.ts +9 -0
  823. package/src/runtime/recovery/local-jobs-repair.ts +393 -0
  824. package/src/runtime/recovery/maintenance-executor.ts +822 -0
  825. package/src/runtime/recovery/patch-handoff.ts +50 -0
  826. package/src/runtime/recovery/probe.ts +308 -0
  827. package/src/runtime/recovery/store.ts +35 -0
  828. package/src/runtime/recovery/types.ts +175 -0
  829. package/src/runtime/release/identity.ts +101 -0
  830. package/src/runtime/release/release-gate.ts +137 -0
  831. package/src/runtime/resources/claims/conflicts.ts +205 -0
  832. package/src/runtime/resources/index.ts +1 -0
  833. package/src/runtime/resources/leases/store.ts +539 -0
  834. package/src/runtime/resources/leases/types.ts +50 -0
  835. package/src/runtime/resources/ownership.ts +72 -0
  836. package/src/runtime/root/controller-services.ts +42 -0
  837. package/src/runtime/root/entry.ts +70 -0
  838. package/src/runtime/root/gateway-adapter.ts +46 -0
  839. package/src/runtime/root/local-bridge.ts +72 -0
  840. package/src/runtime/root/mcp-transport.ts +198 -0
  841. package/src/runtime/root/ownership.ts +94 -0
  842. package/src/runtime/root/readiness.ts +69 -0
  843. package/src/runtime/root/release-manifest.ts +147 -0
  844. package/src/runtime/root/release-materialize.ts +509 -0
  845. package/src/runtime/root/release-store.ts +236 -0
  846. package/src/runtime/root/runtime.ts +318 -0
  847. package/src/runtime/root/scheduler.ts +58 -0
  848. package/src/runtime/root/service-runner-entry.ts +20 -0
  849. package/src/runtime/root/service-runner.ts +69 -0
  850. package/src/runtime/root/service.ts +291 -0
  851. package/src/runtime/root/status.ts +127 -0
  852. package/src/runtime/root/types.ts +112 -0
  853. package/src/runtime/root/write-fence.ts +309 -0
  854. package/src/runtime/safe-tooling/browser-safe.ts +133 -0
  855. package/src/runtime/safe-tooling/external-filesystem.ts +304 -0
  856. package/src/runtime/safe-tooling/google-credential-store.ts +95 -0
  857. package/src/runtime/safe-tooling/google-oauth-broker.ts +286 -0
  858. package/src/runtime/safe-tooling/index.ts +11 -0
  859. package/src/runtime/safe-tooling/ios-development.ts +1039 -0
  860. package/src/runtime/safe-tooling/job-summary.ts +361 -0
  861. package/src/runtime/safe-tooling/plugin-summary.ts +53 -0
  862. package/src/runtime/safe-tooling/resend-oauth.ts +387 -0
  863. package/src/runtime/safe-tooling/review-artifacts.ts +133 -0
  864. package/src/runtime/safe-tooling/types.ts +103 -0
  865. package/src/runtime/safe-tooling/workspace-auth.ts +116 -0
  866. package/src/runtime/shared/bounded-child-supervisor.ts +235 -0
  867. package/src/runtime/shared/idempotent-retry.ts +128 -0
  868. package/src/runtime/shared/json-files.ts +43 -0
  869. package/src/runtime/shared/local-bridge-surface.ts +231 -0
  870. package/src/runtime/shared/managed-env.ts +154 -0
  871. package/src/runtime/shared/node-ts-loader.mjs +50 -0
  872. package/src/runtime/shared/process-environment.ts +97 -0
  873. package/src/runtime/shared/process-identity.ts +72 -0
  874. package/src/runtime/shared/process-tree.ts +227 -0
  875. package/src/runtime/shared/response-budget.ts +246 -0
  876. package/src/runtime/standalone-recovery/core.ts +2275 -0
  877. package/src/runtime/standalone-recovery/entry.ts +686 -0
  878. package/src/runtime/standalone-recovery/http-transport.ts +317 -0
  879. package/src/runtime/standalone-recovery/installer.ts +747 -0
  880. package/src/runtime/standalone-recovery/release.ts +241 -0
  881. package/src/runtime/watchdog/workflow-watchdog.ts +118 -0
  882. package/src/runtime/workflow/campaigns/cleanup.ts +263 -0
  883. package/src/runtime/workflow/campaigns/engine.ts +112 -0
  884. package/src/runtime/workflow/campaigns/normalize.ts +100 -0
  885. package/src/runtime/workflow/campaigns/review.ts +315 -0
  886. package/src/runtime/workflow/campaigns/store.ts +526 -0
  887. package/src/runtime/workflow/campaigns/supervisor.ts +112 -0
  888. package/src/runtime/workflow/campaigns/types.ts +290 -0
  889. package/src/runtime/workflow/campaigns/workspace-agent.ts +155 -0
  890. package/src/runtime/workflow/campaigns/workspace.ts +200 -0
  891. package/src/runtime/workflow/findings/store.ts +165 -0
  892. package/src/runtime/workflow/findings/types.ts +36 -0
  893. package/src/runtime/workflow/portfolio/engine.ts +20 -0
  894. package/src/runtime/workflow/portfolio/store.ts +185 -0
  895. package/src/runtime/workflow/portfolio/types.ts +29 -0
  896. package/src/runtime/workflow/schedules/engine.ts +620 -0
  897. package/src/runtime/workflow/schedules/settlement.ts +144 -0
  898. package/src/runtime/workflow/schedules/store.ts +417 -0
  899. package/src/runtime/workflow/schedules/types.ts +124 -0
  900. package/src/runtime/workspace-targets/index.ts +24 -0
  901. package/src/runtime/workspace-targets/target-grant.ts +721 -0
  902. package/src/testing/test-governance.ts +626 -0
  903. package/src/version.ts +21 -0
@@ -0,0 +1,1295 @@
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 { executeRepositoryCommand, previewRepositoryCommandExecution } from '../repositories/command-executor';
6
+ import { withControllerLock } from '../repositories/locks';
7
+ import {
8
+ disableRepository,
9
+ findIdenticalRepositoryRegistration,
10
+ getRepository,
11
+ listRepositories,
12
+ refreshRepository,
13
+ registerRepository,
14
+ removeRepository,
15
+ repositorySummary,
16
+ resolveRepositorySelection,
17
+ updateRepository,
18
+ validateRepository,
19
+ } from '../repositories/registry';
20
+ import { buildControllerWorkbench } from '../repositories/workbench';
21
+ import { applySafePatch, buildSafePatchPlan } from '../repositories/safe-patch';
22
+ import { buildSyncOperationDigest, classifyUserFacingError } from '../../runtime/control-plane/facade/operation-digest';
23
+ import { diagnoseRepositoryStuckState, listRepositoryGoalRuns, readRepositoryGoalRegistry, runRepositoryGoal, upsertRepositoryGoal } from '../repositories/goal-registry';
24
+ import {
25
+ repositoryGitCommit,
26
+ repositoryGitCreateBranch,
27
+ repositoryGitDeleteBranch,
28
+ repositoryGitDiff,
29
+ repositoryGitFinishWorkflow,
30
+ repositoryGitMergeBranch,
31
+ repositoryGitStatus,
32
+ repositoryGitSwitchBranch,
33
+ } from '../repositories/structured-git';
34
+ import {
35
+ readRepositoryGitStatusSample,
36
+ writeRepositoryGitStatusSample,
37
+ } from '../../runtime/projections/git-status-sampler';
38
+ import {
39
+ executeLightweightLanes,
40
+ executeRepositoryBatch,
41
+ integratePatchProposals,
42
+ listFastReceipts,
43
+ readFastReceipt,
44
+ routeExecution,
45
+ } from '../../runtime/execution/thin-harness';
46
+ import {
47
+ classifyRepositoryCommandRoute,
48
+ executeRepositoryCommandViaProcessRuntime,
49
+ } from '../../runtime/execution/process-runtime/command-facade';
50
+ import { assessWorkMode, parseExplicitTaskMode } from '../controller/work-mode';
51
+ import type { CallToolResult, McpToolDefinition } from './tools';
52
+ import {
53
+ compactCommandOutput,
54
+ compactErrorMessage,
55
+ compactRoutingSummary,
56
+ RESPONSE_BUDGET,
57
+ } from '../../runtime/shared/response-budget';
58
+
59
+ export type RepositoryToolResult = CallToolResult;
60
+
61
+ function definition(
62
+ name: string,
63
+ description: string,
64
+ properties: Record<string, unknown>,
65
+ required: string[] = [],
66
+ readOnlyHint = false,
67
+ destructiveHint = false,
68
+ ): McpToolDefinition {
69
+ return {
70
+ name,
71
+ description,
72
+ inputSchema: {
73
+ type: 'object',
74
+ properties,
75
+ ...(required.length > 0 ? { required } : {}),
76
+ additionalProperties: false,
77
+ },
78
+ annotations: { readOnlyHint, openWorldHint: false, destructiveHint },
79
+ };
80
+ }
81
+
82
+ const repoId = { type: 'string', description: 'Stable Repository Registry repoId.' };
83
+
84
+ export const repositoryToolDefinitions: McpToolDefinition[] = [
85
+ definition('repository_register', 'Register a Git repository with the Controller.', {
86
+ path: { type: 'string' },
87
+ display_name: { type: 'string' },
88
+ remote_url: { type: 'string' },
89
+ default_branch: { type: 'string' },
90
+ detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full checkout and migration evidence.' },
91
+ }, ['path']),
92
+ definition('repository_latest_source_diagnose', 'Read-only diagnosis that compares sibling project directories and recommends the latest usable source tree.', {
93
+ path: { type: 'string', description: 'Absolute local project path.' },
94
+ repo_id: repoId,
95
+ }, [], true),
96
+ definition('repository_bootstrap_local_project', 'Safely initialize and optionally register a trusted non-Git local project directory.', {
97
+ path: { type: 'string', description: 'Absolute local project path.' },
98
+ display_name: { type: 'string' },
99
+ default_branch: { type: 'string' },
100
+ mode: { type: 'string', enum: ['init_git_only', 'init_git_and_register', 'replace_registration'] },
101
+ replace_registered_repo_id: repoId,
102
+ confirm_authorization: { type: 'boolean', description: 'Must be true to authorize Git initialization and registration.' },
103
+ }, ['path', 'confirm_authorization'], false, true),
104
+ definition('repository_list', 'List registered repositories.', {
105
+ include_removed: { type: 'boolean' },
106
+ }, [], true),
107
+ definition('repository_get', 'Inspect one registered repository.', {
108
+ repo_id: repoId,
109
+ include_removed: { type: 'boolean' },
110
+ detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns the complete checkout history.' },
111
+ }, ['repo_id'], true),
112
+ definition('repository_validate', 'Validate repository identity and migrate legacy ownership.', {
113
+ repo_id: repoId,
114
+ detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full migration evidence.' },
115
+ }, ['repo_id']),
116
+ definition('repository_refresh', 'Refresh repository Git and checkout metadata.', {
117
+ repo_id: repoId,
118
+ detail_level: { type: 'string', enum: ['summary', 'detail'], description: 'Defaults to summary; detail returns full checkout and migration evidence.' },
119
+ }, ['repo_id']),
120
+ definition('repository_update', 'Update mutable repository metadata.', {
121
+ repo_id: repoId,
122
+ display_name: { type: 'string' },
123
+ default_branch: { type: 'string' },
124
+ enabled: { type: 'boolean' },
125
+ }, ['repo_id']),
126
+ definition('repository_disable', 'Disable new execution while retaining audit history.', {
127
+ repo_id: repoId,
128
+ }, ['repo_id']),
129
+ definition('repository_remove', 'Soft-remove a repository while retaining audit history.', {
130
+ repo_id: repoId,
131
+ }, ['repo_id'], true),
132
+ 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.', {
133
+ repo_id: repoId,
134
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repository-scoped operations.' },
135
+ include_removed: { type: 'boolean' },
136
+ operation: {
137
+ type: 'string',
138
+ enum: ['summary', 'batch_execute', 'lanes_execute', 'lanes_integrate', 'fast_receipt_get', 'fast_receipt_list', 'execution_route', 'assess_work_mode'],
139
+ 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/Campaign routing advice.',
140
+ },
141
+ payload: {
142
+ type: 'object',
143
+ 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.',
144
+ additionalProperties: true,
145
+ },
146
+ }),
147
+
148
+
149
+
150
+ definition('repository_goal_list', 'List durable repository goals stored inside the checkout.', {
151
+ repo_id: repoId,
152
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
153
+ }, [], true),
154
+ definition('repository_goal_upsert', 'Create or update one durable repository goal for repeated assistant workflows.', {
155
+ repo_id: repoId,
156
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
157
+ id: { type: 'string' },
158
+ title: { type: 'string' },
159
+ status: { type: 'string', enum: ['active', 'paused', 'done'] },
160
+ checks: { type: 'array', items: { type: 'string' } },
161
+ notes: { type: 'string' },
162
+ }, []),
163
+ definition('repository_stuck_diagnose', 'Diagnose likely repository workflow blockers from Git state and registered goals.', {
164
+ repo_id: repoId,
165
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
166
+ }, [], true),
167
+ definition('repository_goal_run', 'Run one durable repository goal iteration, optionally executing its configured checks and recording a goal-run artifact.', {
168
+ repo_id: repoId,
169
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
170
+ goal_id: { type: 'string', description: 'Goal id. Defaults to the first active goal.' },
171
+ run_checks: { type: 'boolean', description: 'When true, execute configured checks. Defaults to diagnosis-only.' },
172
+ }, []),
173
+ definition('repository_goal_runs', 'List recent repository goal-run artifacts.', {
174
+ repo_id: repoId,
175
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
176
+ limit: { type: 'number' },
177
+ }, [], true),
178
+
179
+ definition('repository_git_status', 'Return a structured Git status snapshot for the selected repository checkout.', {
180
+ repo_id: repoId,
181
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
182
+ refresh: { type: 'boolean', description: 'When true, explicitly refresh the Git status sample. The default public hot path only reads the latest daemon sample.' },
183
+ }, [], true),
184
+
185
+ definition('repository_git_diff', 'Return a bounded structured git diff for the selected repository, optionally staged and path-scoped.', {
186
+ repo_id: repoId,
187
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
188
+ staged: { type: 'boolean' },
189
+ paths: { type: 'array', items: { type: 'string' } },
190
+ max_bytes: { type: 'number' },
191
+ }, [], true),
192
+ definition('repository_git_create_branch', 'Create a safe local Git branch, optionally switching to it.', {
193
+ repo_id: repoId,
194
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
195
+ branch: { type: 'string' },
196
+ start_point: { type: 'string' },
197
+ switch_to: { type: 'boolean', description: 'Defaults to true. False creates the branch without switching.' },
198
+ }, ['branch']),
199
+ definition('repository_git_switch_branch', 'Switch to a safe local Git branch name.', {
200
+ repo_id: repoId,
201
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
202
+ branch: { type: 'string' },
203
+ }, ['branch']),
204
+ definition('repository_git_merge_branch', 'Merge a branch into the current branch using --ff-only by default.', {
205
+ repo_id: repoId,
206
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
207
+ branch: { type: 'string' },
208
+ no_ff: { type: 'boolean', description: 'Use --no-ff instead of the default --ff-only.' },
209
+ }, ['branch']),
210
+ definition('repository_git_delete_branch', 'Delete a safe local Git branch after it has been merged or intentionally discarded.', {
211
+ repo_id: repoId,
212
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
213
+ branch: { type: 'string' },
214
+ force: { type: 'boolean' },
215
+ }, ['branch']),
216
+
217
+ definition('repository_git_commit', 'Stage optional explicit paths and commit through a structured Git action.', {
218
+ repo_id: repoId,
219
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
220
+ message: { type: 'string' },
221
+ paths: { type: 'array', items: { type: 'string' } },
222
+ allow_empty: { type: 'boolean' },
223
+ }, ['message']),
224
+ definition('repository_git_finish_workflow', 'Finish the current feature workflow: require clean tree, switch to target, merge feature branch, and delete it by default.', {
225
+ repo_id: repoId,
226
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
227
+ feature_branch: { type: 'string', description: 'Defaults to the current branch.' },
228
+ target_branch: { type: 'string', description: 'Defaults to repository defaultBranch or main.' },
229
+ delete_branch: { type: 'boolean', description: 'Defaults to true.' },
230
+ no_ff: { type: 'boolean', description: 'Use --no-ff instead of the default --ff-only.' },
231
+ }, []),
232
+ definition('repository_safe_patch_plan', 'Plan a deterministic chunked repository patch with fresh file fingerprints before applying.', {
233
+ repo_id: repoId,
234
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
235
+ operations: { type: 'array', items: { type: 'object' }, description: 'Edit operations using the same shape as apply_patch.' },
236
+ chunk_size: { type: 'number', description: 'Maximum operations per deterministic chunk. Capped at 100.' },
237
+ }, ['operations'], true),
238
+ definition('repository_safe_patch_apply', 'Apply a deterministic chunked repository patch through edit sessions, refreshing missing file fingerprints before each chunk. Defaults to synchronous interactive apply.', {
239
+ repo_id: repoId,
240
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
241
+ session_id: { type: 'string', description: 'Existing edit session id. Omit to create one.' },
242
+ purpose: { type: 'string', description: 'Purpose for a newly created edit session.' },
243
+ operations: { type: 'array', items: { type: 'object' }, description: 'Edit operations using the same shape as apply_patch. create/write create parent dirs as needed.' },
244
+ chunk_size: { type: 'number', description: 'Maximum operations per deterministic chunk. Capped at 100.' },
245
+ expected_revision: { type: 'number', description: 'Expected starting edit-session revision.' },
246
+ allowed_paths: { type: 'array', items: { type: 'string' }, description: 'Optional allowed path globs for a newly created session.' },
247
+ continue_on_error: { type: 'boolean', description: 'Continue applying later independent chunks after a failed chunk. Defaults to false.' },
248
+ refresh_fingerprints: { type: 'boolean', description: 'Refresh file fingerprints before every chunk. Defaults to true.' },
249
+ recover_stale_session: { type: 'boolean', description: 'For new sessions, recover stale edit-session fingerprints into a fresh session. Defaults to true.' },
250
+ apply_mode: { type: 'string', enum: ['sync', 'async'], description: 'Defaults to sync for interactive development. Set async to queue a durable Job.' },
251
+ }, ['operations']),
252
+ definition('repository_command_preview', 'Preview one repository-scoped local command with classification, approval token, and Git snapshots.', {
253
+ repo_id: repoId,
254
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
255
+ 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.' },
256
+ cwd: { type: 'string', description: 'Optional root-relative working directory.' },
257
+ 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.' },
258
+ }, ['command'], true),
259
+ definition('repository_command_execute', 'Execute one repository-scoped local command through Full Access, Goal delegation, or a resumable approval request. Legacy preview-token callers remain compatible.', {
260
+ repo_id: repoId,
261
+ checkout_id: { type: 'string', description: 'Optional checkout identity for repositories with multiple local clones.' },
262
+ 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.' },
263
+ cwd: { type: 'string', description: 'Optional root-relative working directory.' },
264
+ 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.' },
265
+ approval_token: { type: 'string', description: 'Exact approval token returned by repository_command_preview.' },
266
+ approval_request_id: { type: 'string', description: 'Resolved approvalRequestId returned by approval_resolve.' },
267
+ timeout_ms: { type: 'number', description: 'Optional execution timeout in milliseconds.' },
268
+ max_output_bytes: { type: 'number', description: 'Optional cap for captured stdout/stderr.' },
269
+ }, ['command']),
270
+
271
+ // Thin Harness V1 is exposed through repository_workbench operations to keep the stable tool surface bounded.
272
+ ];
273
+
274
+ export const repositoryToolNames = repositoryToolDefinitions.map((tool) => tool.name);
275
+
276
+ function result(value: Record<string, unknown>): RepositoryToolResult {
277
+ // Compact text channel by default; structuredContent remains the machine view.
278
+ return {
279
+ content: [{ type: 'text', text: JSON.stringify(value) }],
280
+ structuredContent: value,
281
+ };
282
+ }
283
+
284
+ const DEFAULT_MIGRATION_SAMPLE_LIMIT = 3;
285
+
286
+ function withResponseMeta(payload: Record<string, unknown>, startedAt: number): Record<string, unknown> {
287
+ const response = {
288
+ ...payload,
289
+ responseMeta: {
290
+ serverDurationMs: Math.round((performance.now() - startedAt) * 100) / 100,
291
+ structuredPayloadBytes: 0,
292
+ },
293
+ };
294
+ response.responseMeta.structuredPayloadBytes = Buffer.byteLength(JSON.stringify(response), 'utf8');
295
+ return response;
296
+ }
297
+
298
+ function resolveRepositoryCommandTarget(
299
+ controllerHome: string,
300
+ args: Record<string, unknown>,
301
+ repoIdValue: string,
302
+ ): {
303
+ repository: ReturnType<typeof resolveRepositorySelection>;
304
+ executionIdentity: ResolvedExecutionIdentity;
305
+ workspace?: { workspaceId: string; root: string; registered: false };
306
+ } {
307
+ const workspaceRoot = typeof args.workspace_root === 'string' ? args.workspace_root.trim() : '';
308
+ const checkoutId = typeof args.checkout_id === 'string' ? args.checkout_id.trim() : '';
309
+ if (workspaceRoot) {
310
+ if (repoIdValue || checkoutId) {
311
+ throw new Error('EPHEMERAL_WORKSPACE_TARGET_CONFLICT: workspace_root cannot be combined with repo_id or checkout_id');
312
+ }
313
+ const target = resolveEphemeralWorkspaceTarget(workspaceRoot, controllerHome);
314
+ return {
315
+ repository: target.repository,
316
+ executionIdentity: {
317
+ schemaVersion: 1,
318
+ authority: 'ephemeral_workspace',
319
+ repositoryId: target.workspaceId,
320
+ checkoutId: target.checkoutId,
321
+ canonicalRoot: target.canonicalRoot,
322
+ },
323
+ workspace: { workspaceId: target.workspaceId, root: target.canonicalRoot, registered: false },
324
+ };
325
+ }
326
+ const repository = resolveRepositorySelection({
327
+ repoId: repoIdValue || undefined,
328
+ checkoutId: checkoutId || undefined,
329
+ controllerHome,
330
+ allowSoleRepository: true,
331
+ });
332
+ return {
333
+ repository,
334
+ executionIdentity: {
335
+ schemaVersion: 1,
336
+ authority: 'repository',
337
+ repositoryId: repository.repoId,
338
+ checkoutId: repository.activeCheckoutId,
339
+ canonicalRoot: repository.canonicalRoot,
340
+ },
341
+ };
342
+ }
343
+
344
+ export function summarizeEntityMigrationReport(
345
+ report: ReturnType<typeof bindRepositoryEntities>,
346
+ detail = false,
347
+ ): ReturnType<typeof bindRepositoryEntities> | Record<string, unknown> {
348
+ if (detail) return report;
349
+ const files = report.files.slice(0, DEFAULT_MIGRATION_SAMPLE_LIMIT);
350
+ const errors = report.errors.slice(0, DEFAULT_MIGRATION_SAMPLE_LIMIT);
351
+ return {
352
+ repoId: report.repoId,
353
+ checkoutId: report.checkoutId,
354
+ scanned: report.scanned,
355
+ updated: report.updated,
356
+ unresolved: report.unresolved,
357
+ fileCount: report.files.length,
358
+ errorCount: report.errors.length,
359
+ files,
360
+ errors,
361
+ truncated: report.files.length > files.length || report.errors.length > errors.length,
362
+ omittedFileCount: Math.max(0, report.files.length - files.length),
363
+ omittedErrorCount: Math.max(0, report.errors.length - errors.length),
364
+ };
365
+ }
366
+
367
+ export function summarizeRepositoryRegistration(
368
+ repository: ReturnType<typeof registerRepository>,
369
+ migration: ReturnType<typeof bindRepositoryEntities>,
370
+ detail = false,
371
+ fastPath = false,
372
+ ): Record<string, unknown> {
373
+ if (detail) {
374
+ return { detailLevel: 'detail', repository, migration, fastPath };
375
+ }
376
+ const checkoutCounts = repository.checkouts.reduce<Record<string, number>>((counts, checkout) => {
377
+ const lifecycle = checkout.lifecycle ?? 'active';
378
+ counts[lifecycle] = (counts[lifecycle] ?? 0) + 1;
379
+ return counts;
380
+ }, {});
381
+ return {
382
+ detailLevel: 'summary',
383
+ repository: {
384
+ ...repositorySummary(repository),
385
+ activeCheckoutId: repository.activeCheckoutId,
386
+ checkoutCount: repository.checkouts.length,
387
+ checkoutCounts,
388
+ },
389
+ migration: summarizeEntityMigrationReport(migration),
390
+ fastPath,
391
+ next: 'Re-call with detail_level=detail only when full checkout or migration evidence is required.',
392
+ };
393
+ }
394
+
395
+ export function summarizeRepositoryInspection(
396
+ repository: ReturnType<typeof getRepository>,
397
+ detail = false,
398
+ ): Record<string, unknown> {
399
+ if (detail) return { detailLevel: 'detail', repository };
400
+ const checkoutCounts = repository.checkouts.reduce<Record<string, number>>((counts, checkout) => {
401
+ const lifecycle = checkout.lifecycle ?? 'active';
402
+ counts[lifecycle] = (counts[lifecycle] ?? 0) + 1;
403
+ return counts;
404
+ }, {});
405
+ const activeCheckout = repository.checkouts.find((checkout) => checkout.checkoutId === repository.activeCheckoutId);
406
+ return {
407
+ detailLevel: 'summary',
408
+ repository: {
409
+ ...repositorySummary(repository),
410
+ activeCheckoutId: repository.activeCheckoutId,
411
+ ...(activeCheckout ? { activeCheckout } : {}),
412
+ checkoutCount: repository.checkouts.length,
413
+ checkoutCounts,
414
+ },
415
+ omittedCheckoutCount: Math.max(0, repository.checkouts.length - (activeCheckout ? 1 : 0)),
416
+ next: 'Re-call with detail_level=detail only when complete checkout history is required.',
417
+ };
418
+ }
419
+
420
+ function failure(error: unknown): RepositoryToolResult {
421
+ const message = compactErrorMessage(error);
422
+ const code = message.includes(':') ? message.slice(0, message.indexOf(':')) : 'REPOSITORY_TOOL_FAILED';
423
+ const details = typeof error === 'object' && error !== null && 'details' in error ? (error as { details?: unknown }).details : undefined;
424
+ const compactDetails = details !== undefined && Buffer.byteLength(JSON.stringify(details) ?? '', 'utf8') > RESPONSE_BUDGET.previewBytes
425
+ ? { omitted: true, message: 'Error details exceeded budget; inspect job/artifact/result refs.' }
426
+ : details;
427
+ return { ...result({ error: { code, message, ...(compactDetails !== undefined ? { details: compactDetails } : {}) } }), isError: true };
428
+ }
429
+
430
+ function compactProcessCommandPayload(input: {
431
+ accepted?: boolean;
432
+ mode: string;
433
+ path: string;
434
+ route?: string;
435
+ reasons: string[];
436
+ decision?: unknown;
437
+ repoId: string;
438
+ checkoutId?: string;
439
+ workspace?: { workspaceId: string; root: string; registered: false };
440
+ processId?: string;
441
+ process?: unknown;
442
+ completed?: boolean;
443
+ ok?: boolean;
444
+ exitCode?: number | null;
445
+ stdout?: string;
446
+ stderr?: string;
447
+ durableSideEffects?: Record<string, number>;
448
+ next: string;
449
+ /** summary (default) omits nested process / routing dumps; detail restores diagnostics. */
450
+ detailLevel?: 'summary' | 'detail';
451
+ includeFullProcess?: boolean;
452
+ }): Record<string, unknown> {
453
+ const output = compactCommandOutput(input.stdout, input.stderr, { ok: input.ok === true });
454
+ const detail = input.detailLevel === 'detail' || input.includeFullProcess === true;
455
+ const effects = input.durableSideEffects ?? {
456
+ executionJobCount: 0,
457
+ localJobCount: 0,
458
+ workerSpawnCount: 0,
459
+ projectionUpdateCount: 0,
460
+ };
461
+ const reason = input.reasons[0] ?? 'readonly_fast_path';
462
+
463
+ // Default success/failure: one authoritative stdout/stderr pair, no nested process dump.
464
+ if (!detail) {
465
+ const completed = input.completed !== false;
466
+ const ok = input.ok === true;
467
+ const payload: Record<string, unknown> = {
468
+ ...(completed ? { ok } : {}),
469
+ accepted: input.accepted ?? true,
470
+ mode: input.mode,
471
+ path: input.path,
472
+ route: input.route ?? input.path,
473
+ reason,
474
+ repoId: input.repoId,
475
+ ...(input.checkoutId ? { checkoutId: input.checkoutId } : {}),
476
+ ...(input.workspace ? { workspace: input.workspace } : {}),
477
+ ...(input.processId ? { processId: input.processId } : {}),
478
+ ...(completed ? { exitCode: input.exitCode ?? (ok ? 0 : 1) } : {}),
479
+ stdout: output.stdout ?? '',
480
+ stderr: output.stderr ?? '',
481
+ ...(output.stdoutTruncated ? { stdoutTruncated: true, stdoutBytes: output.stdoutBytes } : {}),
482
+ ...(output.stderrTruncated ? { stderrTruncated: true, stderrBytes: output.stderrBytes } : {}),
483
+ };
484
+ if (completed && !ok) {
485
+ payload.error = {
486
+ code: 'PROCESS_COMMAND_FAILED',
487
+ message: (output.stderr || 'process_direct command failed').slice(0, 800),
488
+ retryable: false,
489
+ exitCode: input.exitCode ?? 1,
490
+ };
491
+ }
492
+ // Zero side-effects are implicit for process_direct summary; only surface non-zero.
493
+ const nonZeroEffects = Object.fromEntries(
494
+ Object.entries(effects).filter(([, value]) => typeof value === 'number' && value > 0),
495
+ );
496
+ if (Object.keys(nonZeroEffects).length > 0) payload.durableSideEffects = nonZeroEffects;
497
+ return payload;
498
+ }
499
+
500
+ return {
501
+ accepted: input.accepted ?? true,
502
+ mode: input.mode,
503
+ path: input.path,
504
+ route: input.route ?? input.path,
505
+ routing: {
506
+ ...compactRoutingSummary({ path: input.path, mode: input.mode, reasons: input.reasons }),
507
+ ...(input.decision ? { decision: input.decision } : {}),
508
+ },
509
+ reason,
510
+ repoId: input.repoId,
511
+ ...(input.checkoutId ? { checkoutId: input.checkoutId } : {}),
512
+ ...(input.workspace ? { workspace: input.workspace } : {}),
513
+ ...(input.processId ? { processId: input.processId } : {}),
514
+ ok: input.ok,
515
+ exitCode: input.exitCode,
516
+ ...output,
517
+ // Nested process only in detail mode; never duplicate stdout/stderr there.
518
+ ...(input.process && typeof input.process === 'object'
519
+ ? {
520
+ process: (() => {
521
+ const record = { ...(input.process as Record<string, unknown>) };
522
+ delete record.stdout;
523
+ delete record.stderr;
524
+ delete record.durableSideEffects;
525
+ return record;
526
+ })(),
527
+ }
528
+ : {}),
529
+ durableSideEffects: effects,
530
+ next: input.next,
531
+ detailLevel: 'detail',
532
+ };
533
+ }
534
+
535
+ function emptyRepositoryMigration(repository: ReturnType<typeof registerRepository>) {
536
+ return {
537
+ repoId: repository.repoId,
538
+ checkoutId: repository.activeCheckoutId,
539
+ scanned: 0,
540
+ updated: 0,
541
+ unresolved: 0,
542
+ files: [] as string[],
543
+ errors: [] as Array<{ path: string; error: string }>,
544
+ };
545
+ }
546
+
547
+ function registrationOnlyAttachedExistingWorktree(repository: ReturnType<typeof registerRepository>): boolean {
548
+ const selected = repository.checkouts.find((checkout) => checkout.checkoutId === repository.activeCheckoutId);
549
+ return selected?.worktree === true
550
+ && repository.checkouts.some((checkout) => checkout.checkoutId !== selected.checkoutId);
551
+ }
552
+
553
+ export async function callRepositoryTool(
554
+ controllerHome: string,
555
+ name: string,
556
+ args: Record<string, unknown>,
557
+ ): Promise<RepositoryToolResult | undefined> {
558
+ if (!name.startsWith('repository_')) return undefined;
559
+ try {
560
+ const repoIdValue = typeof args.repo_id === 'string' ? args.repo_id.trim() : '';
561
+ switch (name) {
562
+ case 'repository_register': {
563
+ const startedAt = performance.now();
564
+ const registerInput = {
565
+ path: String(args.path ?? ''),
566
+ controllerHome,
567
+ displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
568
+ remoteUrl: typeof args.remote_url === 'string' ? args.remote_url : undefined,
569
+ defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
570
+ };
571
+ const identical = findIdenticalRepositoryRegistration(registerInput);
572
+ if (identical?.identical) {
573
+ const repository = identical.repository;
574
+ // Repeat registration with identical identity returns immediately.
575
+ // No legacy migration / edit-session migration / historical issue
576
+ // scan / old issue rebinding runs on this hot path.
577
+ const migration = emptyRepositoryMigration(repository);
578
+ return result(withResponseMeta(
579
+ summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail', true),
580
+ startedAt,
581
+ ));
582
+ }
583
+ const repository = registerRepository(registerInput);
584
+ // Adding a worktree checkout to an already registered repository changes
585
+ // checkout inventory only. Existing Issue/Task entities are already
586
+ // bound to this repoId, so re-running historical migration is wasted work
587
+ // and can produce misleading cross-repository rebinding diagnostics.
588
+ const migration = registrationOnlyAttachedExistingWorktree(repository)
589
+ ? emptyRepositoryMigration(repository)
590
+ : bindRepositoryEntities(repository);
591
+ return result(withResponseMeta(
592
+ summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail'),
593
+ startedAt,
594
+ ));
595
+ }
596
+ case 'repository_latest_source_diagnose':
597
+ return result({
598
+ diagnosis: diagnoseLatestLocalProjectSource({
599
+ path: typeof args.path === 'string' ? args.path : undefined,
600
+ repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
601
+ controllerHome,
602
+ }),
603
+ });
604
+ case 'repository_bootstrap_local_project':
605
+ return result({
606
+ bootstrap: bootstrapLocalProject({
607
+ path: String(args.path ?? ''),
608
+ controllerHome,
609
+ displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
610
+ defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
611
+ mode: typeof args.mode === 'string' ? args.mode as 'init_git_only' | 'init_git_and_register' | 'replace_registration' : undefined,
612
+ replaceRegisteredRepoId: typeof args.replace_registered_repo_id === 'string' ? args.replace_registered_repo_id : undefined,
613
+ confirmAuthorization: args.confirm_authorization === true,
614
+ }),
615
+ });
616
+ case 'repository_list':
617
+ return result({ repositories: listRepositories(controllerHome, { includeRemoved: args.include_removed === true }).map(repositorySummary) });
618
+ case 'repository_get': {
619
+ const repository = getRepository(repoIdValue, controllerHome, { includeRemoved: args.include_removed === true });
620
+ return result(summarizeRepositoryInspection(repository, args.detail_level === 'detail'));
621
+ }
622
+ case 'repository_validate': {
623
+ const startedAt = performance.now();
624
+ const repository = getRepository(repoIdValue, controllerHome, { includeRemoved: true });
625
+ const payload = {
626
+ detailLevel: args.detail_level === 'detail' ? 'detail' : 'summary',
627
+ validation: validateRepository(repoIdValue, controllerHome),
628
+ migration: summarizeEntityMigrationReport(bindRepositoryEntities(repository), args.detail_level === 'detail'),
629
+ };
630
+ return result(withResponseMeta(payload, startedAt));
631
+ }
632
+ case 'repository_refresh': {
633
+ const startedAt = performance.now();
634
+ const repository = refreshRepository(repoIdValue, controllerHome);
635
+ const migration = bindRepositoryEntities(repository);
636
+ return result(withResponseMeta(
637
+ summarizeRepositoryRegistration(repository, migration, args.detail_level === 'detail'),
638
+ startedAt,
639
+ ));
640
+ }
641
+ case 'repository_update':
642
+ return result({ repository: updateRepository(repoIdValue, {
643
+ displayName: typeof args.display_name === 'string' ? args.display_name : undefined,
644
+ defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
645
+ enabled: typeof args.enabled === 'boolean' ? args.enabled : undefined,
646
+ }, controllerHome) });
647
+ case 'repository_disable':
648
+ return result({ repository: disableRepository(repoIdValue, controllerHome) });
649
+ case 'repository_remove':
650
+ return result({ repository: removeRepository(repoIdValue, controllerHome) });
651
+ case 'repository_workbench': {
652
+ const operation = typeof args.operation === 'string' ? args.operation : 'summary';
653
+ if (operation === 'summary') {
654
+ return result({ workbench: buildControllerWorkbench(controllerHome, {
655
+ repoId: repoIdValue || undefined,
656
+ includeRemoved: args.include_removed === true,
657
+ }) });
658
+ }
659
+ const payload = typeof args.payload === 'object' && args.payload !== null
660
+ ? args.payload as Record<string, unknown>
661
+ : {};
662
+ if (operation === 'assess_work_mode') {
663
+ const description = typeof payload.description === 'string'
664
+ ? payload.description
665
+ : typeof args.description === 'string' ? args.description : '';
666
+ const assessment = assessWorkMode({
667
+ description,
668
+ knownPaths: Array.isArray(payload.known_paths) ? payload.known_paths.map(String) : undefined,
669
+ expectedFiles: typeof payload.expected_files === 'number' ? payload.expected_files : undefined,
670
+ expectedChangedLines: typeof payload.expected_changed_lines === 'number' ? payload.expected_changed_lines : undefined,
671
+ requiresInvestigation: payload.requires_investigation === true,
672
+ requiresParallelism: payload.requires_parallelism === true,
673
+ requiresLongRunningChecks: payload.requires_long_running_checks === true,
674
+ needsDependencies: payload.needs_dependencies === true,
675
+ requiresIndependentDeliverables: payload.requires_independent_deliverables === true,
676
+ independentTaskCount: typeof payload.independent_task_count === 'number' ? payload.independent_task_count : undefined,
677
+ requiresRemoteWrite: payload.requires_remote_write === true || payload.remote_write === true,
678
+ requiresRecovery: payload.requires_recovery === true,
679
+ agentRequested: payload.agent_requested === true || payload.requires_worker === true,
680
+ requiresWorkerIsolation: payload.requires_worker_isolation === true,
681
+ risk: typeof payload.risk === 'string' ? payload.risk as 'low' | 'medium' | 'high' | 'destructive' : undefined,
682
+ explicitMode: parseExplicitTaskMode(payload.mode),
683
+ });
684
+ return result({
685
+ assessment,
686
+ routing: {
687
+ path: assessment.executionPath,
688
+ reasons: assessment.reasons,
689
+ recommendedMode: assessment.recommendedMode,
690
+ issueRequired: assessment.issueRequired,
691
+ campaignRequired: assessment.campaignRequired,
692
+ },
693
+ nextTools: assessment.nextTools,
694
+ });
695
+ }
696
+ const internalTool = {
697
+ batch_execute: 'repository_batch_execute',
698
+ lanes_execute: 'repository_lanes_execute',
699
+ lanes_integrate: 'repository_lanes_integrate',
700
+ fast_receipt_get: 'repository_fast_receipt_get',
701
+ fast_receipt_list: 'repository_fast_receipt_list',
702
+ execution_route: 'repository_execution_route',
703
+ }[operation];
704
+ if (!internalTool) {
705
+ return failure(new Error(`REPOSITORY_WORKBENCH_OPERATION_INVALID: ${operation}`));
706
+ }
707
+ return callRepositoryTool(controllerHome, internalTool, {
708
+ ...payload,
709
+ repo_id: repoIdValue || payload.repo_id,
710
+ checkout_id: typeof args.checkout_id === 'string' ? args.checkout_id : payload.checkout_id,
711
+ });
712
+ }
713
+
714
+
715
+
716
+ case 'repository_goal_list': {
717
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
718
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, registry: readRepositoryGoalRegistry(repository) });
719
+ }
720
+ case 'repository_goal_upsert': {
721
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
722
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...upsertRepositoryGoal(repository, { id: args.id, title: args.title, status: args.status, checks: args.checks, notes: args.notes }) as unknown as Record<string, unknown> });
723
+ }
724
+ case 'repository_stuck_diagnose': {
725
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
726
+ return result({ diagnosis: diagnoseRepositoryStuckState(repository) });
727
+ }
728
+
729
+ case 'repository_goal_run': {
730
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
731
+ const ran = withControllerLock(
732
+ controllerHome,
733
+ { scope: 'repository', repoId: repository.repoId },
734
+ 'mcp:repository_goal_run',
735
+ () => runRepositoryGoal(repository, { goalId: args.goal_id, runChecks: args.run_checks }),
736
+ 60_000,
737
+ );
738
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...ran as unknown as Record<string, unknown> });
739
+ }
740
+ case 'repository_goal_runs': {
741
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
742
+ const limit = typeof args.limit === 'number' ? args.limit : typeof args.limit === 'string' ? Number(args.limit) : undefined;
743
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, runs: listRepositoryGoalRuns(repository, limit) });
744
+ }
745
+ case 'repository_git_status': {
746
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
747
+ const status = args.refresh === true
748
+ ? writeRepositoryGitStatusSample(controllerHome, repository)
749
+ : readRepositoryGitStatusSample(controllerHome, repository.repoId, repository.activeCheckoutId);
750
+ return result({
751
+ status: status ?? {
752
+ repoId: repository.repoId,
753
+ checkoutId: repository.activeCheckoutId,
754
+ sampleSource: 'daemon-sample',
755
+ sampled: false,
756
+ observedAt: null,
757
+ staleAgeMs: null,
758
+ 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.',
759
+ },
760
+ });
761
+ }
762
+
763
+ case 'repository_git_diff': {
764
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
765
+ return result({ diff: repositoryGitDiff(repository, { staged: args.staged, paths: args.paths, maxBytes: args.max_bytes }) });
766
+ }
767
+ case 'repository_git_create_branch': {
768
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
769
+ 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> });
770
+ }
771
+ case 'repository_git_switch_branch': {
772
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
773
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitSwitchBranch(controllerHome, repository, { branch: args.branch }) as unknown as Record<string, unknown> });
774
+ }
775
+ case 'repository_git_merge_branch': {
776
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
777
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitMergeBranch(controllerHome, repository, { branch: args.branch, noFf: args.no_ff }) as unknown as Record<string, unknown> });
778
+ }
779
+ case 'repository_git_delete_branch': {
780
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
781
+ return result({ repoId: repository.repoId, checkoutId: repository.activeCheckoutId, ...repositoryGitDeleteBranch(controllerHome, repository, { branch: args.branch, force: args.force }) as unknown as Record<string, unknown> });
782
+ }
783
+
784
+ case 'repository_git_commit': {
785
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
786
+ return result({ commit: repositoryGitCommit(controllerHome, repository, { message: args.message, paths: args.paths, allowEmpty: args.allow_empty }) });
787
+ }
788
+ case 'repository_git_finish_workflow': {
789
+ const repository = resolveRepositorySelection({ repoId: repoIdValue || undefined, checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined, controllerHome, allowSoleRepository: true });
790
+ return result({ finish: repositoryGitFinishWorkflow(controllerHome, repository, { featureBranch: args.feature_branch, targetBranch: args.target_branch, deleteBranch: args.delete_branch, noFf: args.no_ff }) });
791
+ }
792
+ case 'repository_safe_patch_plan': {
793
+ const repository = resolveRepositorySelection({
794
+ repoId: repoIdValue || undefined,
795
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
796
+ controllerHome,
797
+ allowSoleRepository: true,
798
+ });
799
+ return result({
800
+ repoId: repository.repoId,
801
+ checkoutId: repository.activeCheckoutId,
802
+ plan: buildSafePatchPlan(repository, { operations: args.operations, chunkSize: args.chunk_size }),
803
+ });
804
+ }
805
+ case 'repository_safe_patch_apply': {
806
+ const repository = resolveRepositorySelection({
807
+ repoId: repoIdValue || undefined,
808
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
809
+ controllerHome,
810
+ allowSoleRepository: true,
811
+ });
812
+ const applied = withControllerLock(
813
+ controllerHome,
814
+ { scope: 'repository', repoId: repository.repoId },
815
+ 'mcp:repository_safe_patch_apply',
816
+ () => applySafePatch(repository, {
817
+ sessionId: args.session_id,
818
+ purpose: args.purpose,
819
+ operations: args.operations,
820
+ chunkSize: args.chunk_size,
821
+ expectedRevision: args.expected_revision,
822
+ allowedPaths: args.allowed_paths,
823
+ continueOnError: args.continue_on_error,
824
+ refreshFingerprints: args.refresh_fingerprints,
825
+ recoverStaleSession: args.recover_stale_session,
826
+ }),
827
+ 60_000,
828
+ );
829
+ const changedFiles = [
830
+ ...new Set(
831
+ (applied.appliedChunks ?? []).flatMap((chunk) => chunk.paths ?? []),
832
+ ),
833
+ ];
834
+ const ok = applied.status === 'applied';
835
+ const firstFailure = applied.failures?.[0];
836
+ const digest = buildSyncOperationDigest({
837
+ ok,
838
+ operation: 'repository_safe_patch_apply',
839
+ summary: ok
840
+ ? `补丁已同步应用,涉及 ${changedFiles.length} 个文件。`
841
+ : applied.status === 'partial'
842
+ ? `补丁部分应用:${changedFiles.length} 个文件成功,存在失败 chunk。`
843
+ : `补丁应用失败:${firstFailure?.message || '请检查 failures 摘要'}`,
844
+ changedFiles,
845
+ errorClass: ok ? undefined : classifyUserFacingError({
846
+ code: firstFailure?.code,
847
+ message: firstFailure?.message,
848
+ infrastructure: firstFailure?.code === 'APPLY_FAILED',
849
+ }),
850
+ errorMessage: firstFailure?.message,
851
+ });
852
+ const payload = {
853
+ repoId: repository.repoId,
854
+ checkoutId: repository.activeCheckoutId,
855
+ ...applied as unknown as Record<string, unknown>,
856
+ phase: digest.phase,
857
+ statusLabel: digest.statusLabel,
858
+ summary: digest.summary,
859
+ terminal: true,
860
+ applyMode: 'sync',
861
+ digest,
862
+ suggestedNextActions: digest.suggestedNextActions,
863
+ };
864
+ return ok ? result(payload) : { ...result(payload), isError: true };
865
+ }
866
+ case 'repository_command_preview': {
867
+ const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue);
868
+ const { repository } = target;
869
+ const execution = withControllerLock(
870
+ controllerHome,
871
+ { scope: 'repository', repoId: repository.repoId },
872
+ 'mcp:repository_command_preview',
873
+ () => executeRepositoryCommand(controllerHome, repository, {
874
+ command: args.command as string | string[],
875
+ cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
876
+ dryRun: true,
877
+ allowNonGitWorkspace: target.workspace !== undefined,
878
+ }),
879
+ 60_000,
880
+ );
881
+ return result({
882
+ ...execution as unknown as Record<string, unknown>,
883
+ ...(target.workspace ? { workspace: target.workspace } : {}),
884
+ });
885
+ }
886
+ case 'repository_command_execute': {
887
+ const target = resolveRepositoryCommandTarget(controllerHome, args, repoIdValue);
888
+ const { repository, executionIdentity } = target;
889
+ const timeoutMs = typeof args.timeout_ms === 'number'
890
+ ? args.timeout_ms
891
+ : typeof args.timeout_ms === 'string'
892
+ ? Number(args.timeout_ms)
893
+ : undefined;
894
+ const maxOutputBytes = typeof args.max_output_bytes === 'number'
895
+ ? args.max_output_bytes
896
+ : typeof args.max_output_bytes === 'string'
897
+ ? Number(args.max_output_bytes)
898
+ : undefined;
899
+ // Worker-owned durable executions must not re-enter Fast Path or create a
900
+ // nested ExecutionJob. Local Job remains the worker settlement surface.
901
+ const fromDurableWorker = args.__from_durable_worker === true
902
+ || typeof args.__execution_job_id === 'string';
903
+ // Thin Harness: short readonly / focused-check commands skip Local Job when eligible.
904
+ const forceDurable = fromDurableWorker
905
+ || args.apply_mode === 'async'
906
+ || args.mode === 'durable'
907
+ || args.async === true
908
+ || args.background === true;
909
+ const routingDecision = routeExecution({
910
+ operation: 'repository_command_execute',
911
+ mode: forceDurable ? 'durable' : args.mode === 'fast' ? 'fast' : 'auto',
912
+ command: args.command as string | string[] | undefined,
913
+ timeoutMs,
914
+ background: args.background === true || args.async === true,
915
+ defaultBranch: repository.defaultBranch,
916
+ approvalContinuation: typeof args.approval_request_id === 'string'
917
+ || typeof args.approval_token === 'string',
918
+ });
919
+ // Unified Process Runtime for local commands (Direct/Managed) when not forced durable.
920
+ if (!forceDurable && !fromDurableWorker) {
921
+ try {
922
+ const routeClass = classifyRepositoryCommandRoute(args.command as string | string[], {
923
+ forceDurable: false,
924
+ defaultBranch: repository.defaultBranch,
925
+ timeoutMs,
926
+ });
927
+ if (routeClass.route === 'process_direct' || routeClass.route === 'process_managed') {
928
+ const processResult = await executeRepositoryCommandViaProcessRuntime({
929
+ controllerHome,
930
+ repository,
931
+ command: args.command as string | string[],
932
+ cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
933
+ timeoutMs,
934
+ maxOutputBytes,
935
+ requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
936
+ executionIdentity,
937
+ allowNonGitWorkspace: target.workspace !== undefined,
938
+ });
939
+ if (processResult.route === 'process_direct' || processResult.route === 'process_managed') {
940
+ const handle = processResult.process;
941
+ const detailLevel = args.detail_level === 'detail' || args.detail === true
942
+ ? 'detail'
943
+ : 'summary';
944
+ const directWithoutHandle = processResult.route === 'process_direct' && !handle;
945
+ const directNotExecuted = directWithoutHandle
946
+ && processResult.executionStatus !== undefined
947
+ && processResult.executionStatus !== 'executed';
948
+ if (directNotExecuted) {
949
+ const authorization = processResult.authorizationDecision ?? {
950
+ decision: 'deny' as const,
951
+ reason: 'Command was not executed because the required authorization was not satisfied.',
952
+ };
953
+ return result({
954
+ accepted: false,
955
+ mode: processResult.route,
956
+ path: processResult.reason ?? routeClass.reason,
957
+ route: processResult.route,
958
+ repoId: repository.repoId,
959
+ checkoutId: repository.activeCheckoutId,
960
+ workspace: target.workspace,
961
+ status: processResult.executionStatus,
962
+ policyDecision: processResult.policyDecision ?? 'approval_required',
963
+ authorization,
964
+ ...(processResult.approvalRequestId ? { approvalRequestId: processResult.approvalRequestId } : {}),
965
+ message: authorization.decision === 'user_confirmation_required'
966
+ ? authorization.humanSummary
967
+ : authorization.reason,
968
+ suggestedOperation: 'repository_command_preview',
969
+ });
970
+ }
971
+ const completed = directWithoutHandle || handle?.completed === true;
972
+ const status = directWithoutHandle
973
+ ? (processResult.ok === true ? 'succeeded' : 'failed')
974
+ : !handle
975
+ ? 'rejected'
976
+ : completed
977
+ ? (handle.cancelled ? 'cancelled' : handle.timedOut ? 'timed_out' : processResult.ok === true ? 'succeeded' : 'failed')
978
+ : 'running';
979
+ const payload = compactProcessCommandPayload({
980
+ accepted: true,
981
+ mode: processResult.route,
982
+ path: processResult.route,
983
+ route: processResult.route,
984
+ reasons: [processResult.reason ?? routeClass.reason, ...routingDecision.reasons],
985
+ decision: detailLevel === 'detail' ? routingDecision : undefined,
986
+ repoId: repository.repoId,
987
+ checkoutId: repository.activeCheckoutId,
988
+ workspace: target.workspace,
989
+ processId: handle?.processId,
990
+ process: detailLevel === 'detail' ? handle : undefined,
991
+ completed,
992
+ ok: completed ? processResult.ok : undefined,
993
+ exitCode: completed ? processResult.exitCode : undefined,
994
+ stdout: processResult.stdout,
995
+ stderr: processResult.stderr,
996
+ durableSideEffects: processResult.durableSideEffects,
997
+ next: directWithoutHandle
998
+ ? processResult.reason === 'readonly_fast_path'
999
+ ? 'Bounded readonly execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
1000
+ : 'Bounded ephemeral workspace execution completed without Process record / Lease / Local Job / ExecutionJob / Worker.'
1001
+ : processResult.route === 'process_direct' || completed
1002
+ ? 'Process Runtime completed without Local Job / ExecutionJob / Worker.'
1003
+ : `Process Runtime is managing ${handle?.processId}; poll process_get/process_wait instead of creating a Local Job.`,
1004
+ detailLevel,
1005
+ });
1006
+ payload.status = status;
1007
+ payload.processId = handle?.processId;
1008
+ payload.authorization = {
1009
+ decision: 'allow',
1010
+ source: directWithoutHandle ? 'bounded_read_direct' : 'process_runtime',
1011
+ reason: directWithoutHandle
1012
+ ? 'Readonly repository command executed through the bounded non-persistent direct path.'
1013
+ : 'Repository command executed through Unified Process Runtime.',
1014
+ };
1015
+ if (directWithoutHandle && processResult.reason !== 'readonly_fast_path') {
1016
+ payload.authorization = processResult.authorizationDecision?.decision === 'allow'
1017
+ ? processResult.authorizationDecision
1018
+ : {
1019
+ decision: 'allow',
1020
+ source: 'ephemeral_workspace_direct',
1021
+ reason: 'Bounded ephemeral workspace command executed through the non-persistent direct path.',
1022
+ };
1023
+ }
1024
+ if (handle?.processId) {
1025
+ payload.resultRef = { kind: 'process_logs', processId: handle.processId };
1026
+ }
1027
+ // Keep accepted true once the command was admitted to Process Runtime.
1028
+ payload.accepted = true;
1029
+ return processResult.ok === true || !completed
1030
+ ? result(payload)
1031
+ : { ...result(payload), isError: true };
1032
+ }
1033
+ }
1034
+ } catch (error) {
1035
+ // Process Runtime is authoritative. Falling through could spawn the
1036
+ // same command again through the legacy Fast/Local Job path.
1037
+ if (process.env.FORGE_DEBUG_PROCESS_RUNTIME === '1') {
1038
+ console.error('[repository_command_execute] process runtime error', error);
1039
+ }
1040
+ return failure(error);
1041
+ }
1042
+ }
1043
+ if (target.workspace && forceDurable) {
1044
+ return result({
1045
+ accepted: false,
1046
+ mode: 'durable',
1047
+ path: 'ephemeral_workspace_promotion_required',
1048
+ repoId: repository.repoId,
1049
+ checkoutId: repository.activeCheckoutId,
1050
+ workspace: target.workspace,
1051
+ message: 'Ephemeral workspaces support bounded local Direct/Managed execution only. Register the directory before durable, remote, release, or resumable Work.',
1052
+ suggestedOperation: 'repository_register',
1053
+ });
1054
+ }
1055
+ // Durable Worker calls skip Process/Fast above, then use the Local Bridge
1056
+ // compatibility projection below for writes/long commands so the worker
1057
+ // can settle the legacy child without creating a nested ExecutionJob.
1058
+ // Short readonly commands keep the zero-Local-Job direct path.
1059
+ if (fromDurableWorker) {
1060
+ try {
1061
+ const routeClass = classifyRepositoryCommandRoute(args.command as string | string[], {
1062
+ forceDurable: false,
1063
+ defaultBranch: repository.defaultBranch,
1064
+ timeoutMs,
1065
+ });
1066
+ if (routeClass.route === 'process_direct') {
1067
+ const processResult = await executeRepositoryCommandViaProcessRuntime({
1068
+ controllerHome,
1069
+ repository,
1070
+ command: args.command as string | string[],
1071
+ cwd: typeof args.cwd === 'string' ? args.cwd : undefined,
1072
+ timeoutMs,
1073
+ maxOutputBytes,
1074
+ requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
1075
+ executionIdentity,
1076
+ });
1077
+ if (processResult.route === 'process_direct') {
1078
+ const execRecord = processResult.process as unknown as Record<string, unknown> | undefined;
1079
+ const ok = processResult.ok === true;
1080
+ const inlinePayload = {
1081
+ accepted: ok,
1082
+ mode: 'durable',
1083
+ path: 'durable_worker_inline',
1084
+ routing: compactRoutingSummary({
1085
+ path: 'durable',
1086
+ mode: 'durable',
1087
+ reasons: ['durable_worker_inline_process_direct', routeClass.reason, ...routingDecision.reasons],
1088
+ }),
1089
+ repoId: repository.repoId,
1090
+ checkoutId: repository.activeCheckoutId,
1091
+ ok,
1092
+ processId: typeof execRecord?.processId === 'string' ? execRecord.processId : undefined,
1093
+ status: typeof execRecord?.status === 'string' ? execRecord.status : undefined,
1094
+ exitCode: typeof processResult.exitCode === 'number' ? processResult.exitCode : undefined,
1095
+ ...compactCommandOutput(
1096
+ typeof processResult.stdout === 'string' ? processResult.stdout : undefined,
1097
+ typeof processResult.stderr === 'string' ? processResult.stderr : undefined,
1098
+ { ok },
1099
+ ),
1100
+ durableSideEffects: processResult.durableSideEffects,
1101
+ next: 'Durable Worker executed a short readonly repository command inline without a Local Job.',
1102
+ };
1103
+ return ok ? result(inlinePayload) : { ...result(inlinePayload), isError: true };
1104
+ }
1105
+ }
1106
+ } catch (error) {
1107
+ if (process.env.FORGE_DEBUG_PROCESS_RUNTIME === '1') {
1108
+ console.error('[repository_command_execute] durable worker inline process runtime error', error);
1109
+ }
1110
+ }
1111
+ }
1112
+ return result({
1113
+ accepted: false,
1114
+ mode: 'durable',
1115
+ path: 'external_controller_required',
1116
+ routing: compactRoutingSummary({ path: 'durable', mode: 'durable', reasons: [routingDecision.reasons.join(','), 'local_bridge_execution_retired'] }),
1117
+ message: 'This command requires explicit external Controller handling; Local Bridge Jobs are retired for repository commands.',
1118
+ suggestedOperation: 'Create or claim WorkContract, then use rh_work.launcher_start or a Process Runtime-compatible command.',
1119
+ });
1120
+ }
1121
+ case 'repository_batch_execute': {
1122
+ const repository = resolveRepositorySelection({
1123
+ repoId: repoIdValue || undefined,
1124
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1125
+ controllerHome,
1126
+ allowSoleRepository: true,
1127
+ });
1128
+ const steps = Array.isArray(args.steps)
1129
+ ? args.steps
1130
+ .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1131
+ .map((entry) => ({
1132
+ id: typeof entry.id === 'string' ? entry.id : undefined,
1133
+ kind: String(entry.kind ?? '') as
1134
+ | 'read_file'
1135
+ | 'search'
1136
+ | 'git_status'
1137
+ | 'git_diff'
1138
+ | 'apply_patch'
1139
+ | 'run_short_command'
1140
+ | 'run_focused_check'
1141
+ | 'stage_paths'
1142
+ | 'commit_paths',
1143
+ input: (typeof entry.input === 'object' && entry.input !== null
1144
+ ? entry.input
1145
+ : {}) as Record<string, unknown>,
1146
+ }))
1147
+ : [];
1148
+ const batch = await executeRepositoryBatch(
1149
+ { controllerHome, repository },
1150
+ {
1151
+ repoId: repository.repoId,
1152
+ checkoutId: repository.activeCheckoutId,
1153
+ mode: args.mode === 'fast' || args.mode === 'durable' || args.mode === 'auto' ? args.mode : 'auto',
1154
+ steps,
1155
+ stopOnError: args.stop_on_error !== false,
1156
+ allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
1157
+ timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
1158
+ includeLatencyBreakdown: args.include_latency_breakdown === true,
1159
+ purpose: typeof args.purpose === 'string' ? args.purpose : undefined,
1160
+ requestId: typeof args.request_id === 'string' ? args.request_id.trim() || undefined : undefined,
1161
+ },
1162
+ );
1163
+ const payload = batch as unknown as Record<string, unknown>;
1164
+ return batch.ok ? result(payload) : { ...result(payload), isError: true };
1165
+ }
1166
+ case 'repository_lanes_execute': {
1167
+ const repository = resolveRepositorySelection({
1168
+ repoId: repoIdValue || undefined,
1169
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1170
+ controllerHome,
1171
+ allowSoleRepository: true,
1172
+ });
1173
+ const lanes = await executeLightweightLanes(
1174
+ { controllerHome, repository },
1175
+ {
1176
+ repoId: repository.repoId,
1177
+ checkoutId: repository.activeCheckoutId,
1178
+ readLanes: Array.isArray(args.read_lanes)
1179
+ ? args.read_lanes
1180
+ .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1181
+ .map((entry) => ({
1182
+ id: typeof entry.id === 'string' ? entry.id : undefined,
1183
+ kind: String(entry.kind ?? 'search') as 'search' | 'read_file' | 'git_status' | 'git_diff' | 'run_short_command',
1184
+ input: (typeof entry.input === 'object' && entry.input !== null
1185
+ ? entry.input
1186
+ : {}) as Record<string, unknown>,
1187
+ }))
1188
+ : undefined,
1189
+ patchProposalLanes: Array.isArray(args.patch_proposal_lanes)
1190
+ ? args.patch_proposal_lanes
1191
+ .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1192
+ .map((entry) => ({
1193
+ id: typeof entry.id === 'string' ? entry.id : undefined,
1194
+ readPaths: Array.isArray(entry.read_paths) ? entry.read_paths.map(String) : [],
1195
+ writePaths: Array.isArray(entry.write_paths) ? entry.write_paths.map(String) : [],
1196
+ proposedOperations: Array.isArray(entry.proposed_operations) ? entry.proposed_operations : [],
1197
+ assumptions: Array.isArray(entry.assumptions) ? entry.assumptions.map(String) : undefined,
1198
+ riskNotes: Array.isArray(entry.risk_notes) ? entry.risk_notes.map(String) : undefined,
1199
+ suggestedFocusedCheck: entry.suggested_focused_check as string | string[] | undefined,
1200
+ }))
1201
+ : undefined,
1202
+ failFast: args.fail_fast === true,
1203
+ maxConcurrency: typeof args.max_concurrency === 'number' ? args.max_concurrency : undefined,
1204
+ includeLatencyBreakdown: args.include_latency_breakdown === true,
1205
+ },
1206
+ );
1207
+ const payload = lanes as unknown as Record<string, unknown>;
1208
+ return lanes.ok ? result(payload) : { ...result(payload), isError: true };
1209
+ }
1210
+ case 'repository_lanes_integrate': {
1211
+ const repository = resolveRepositorySelection({
1212
+ repoId: repoIdValue || undefined,
1213
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1214
+ controllerHome,
1215
+ allowSoleRepository: true,
1216
+ });
1217
+ const proposals = Array.isArray(args.proposals)
1218
+ ? args.proposals
1219
+ .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
1220
+ .map((entry) => ({
1221
+ id: String(entry.id ?? 'proposal'),
1222
+ ok: entry.ok !== false,
1223
+ durationMs: 0,
1224
+ readPaths: Array.isArray(entry.read_paths) ? entry.read_paths.map(String) : [],
1225
+ writePaths: Array.isArray(entry.write_paths) ? entry.write_paths.map(String) : [],
1226
+ proposedOperations: Array.isArray(entry.proposed_operations) ? entry.proposed_operations : [],
1227
+ analysisOnly: entry.analysis_only === true,
1228
+ proposalId: typeof entry.proposal_id === 'string'
1229
+ ? entry.proposal_id
1230
+ : typeof entry.proposalId === 'string'
1231
+ ? entry.proposalId
1232
+ : undefined,
1233
+ }))
1234
+ : [];
1235
+ const integrated = await integratePatchProposals(
1236
+ { controllerHome, repository },
1237
+ proposals,
1238
+ {
1239
+ sessionId: typeof args.session_id === 'string' ? args.session_id : undefined,
1240
+ allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
1241
+ purpose: typeof args.purpose === 'string' ? args.purpose : undefined,
1242
+ requestId: typeof args.request_id === 'string' ? args.request_id.trim() || undefined : undefined,
1243
+ continueOnError: args.continue_on_error === true,
1244
+ },
1245
+ );
1246
+ const payload = integrated as unknown as Record<string, unknown>;
1247
+ return integrated.ok ? result(payload) : { ...result(payload), isError: true };
1248
+ }
1249
+ case 'repository_fast_receipt_get': {
1250
+ const repository = resolveRepositorySelection({
1251
+ repoId: repoIdValue || undefined,
1252
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1253
+ controllerHome,
1254
+ allowSoleRepository: true,
1255
+ });
1256
+ const receipt = readFastReceipt(controllerHome, repository.repoId, String(args.execution_id ?? ''));
1257
+ if (!receipt) return failure(new Error(`FAST_RECEIPT_NOT_FOUND: ${String(args.execution_id ?? '')}`));
1258
+ return result({ receipt });
1259
+ }
1260
+ case 'repository_fast_receipt_list': {
1261
+ const repository = resolveRepositorySelection({
1262
+ repoId: repoIdValue || undefined,
1263
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1264
+ controllerHome,
1265
+ allowSoleRepository: true,
1266
+ });
1267
+ const limit = typeof args.limit === 'number' ? args.limit : undefined;
1268
+ return result({ receipts: listFastReceipts(controllerHome, repository.repoId, limit) });
1269
+ }
1270
+ case 'repository_execution_route': {
1271
+ const repository = resolveRepositorySelection({
1272
+ repoId: repoIdValue || undefined,
1273
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1274
+ controllerHome,
1275
+ allowSoleRepository: true,
1276
+ });
1277
+ const decision = routeExecution({
1278
+ operation: String(args.operation ?? ''),
1279
+ mode: args.mode === 'fast' || args.mode === 'durable' || args.mode === 'auto' ? args.mode : 'auto',
1280
+ command: args.command as string | string[] | undefined,
1281
+ timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
1282
+ background: args.background === true,
1283
+ paths: Array.isArray(args.paths) ? args.paths.map(String) : undefined,
1284
+ allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
1285
+ defaultBranch: repository.defaultBranch,
1286
+ });
1287
+ return result({ decision, repoId: repository.repoId, checkoutId: repository.activeCheckoutId });
1288
+ }
1289
+ default:
1290
+ return failure(new Error(`UNKNOWN_REPOSITORY_TOOL: ${name}`));
1291
+ }
1292
+ } catch (error) {
1293
+ return failure(error);
1294
+ }
1295
+ }