@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,1088 @@
1
+ import { createHash } from 'crypto';
2
+ import type { CallToolResult, McpToolDefinition } from '../../../cli/mcp/tools';
3
+ import {
4
+ buildMultiRepositoryToolDefinitions,
5
+ type MultiRepositoryMcpToolContext,
6
+ } from '../../../cli/mcp/multi-repository';
7
+ import { repositoryToolDefinitions } from '../../../cli/mcp/repository-tools';
8
+ import { runtimeToolDefinitions } from './runtime-tools';
9
+ import { executionToolDefinitions } from './execution-tools';
10
+ import { processToolDefinitions } from './process-tools';
11
+ import { resolveRepositorySelection } from '../../../cli/repositories/registry';
12
+ import { executionIdentityForRepository } from '../../control-plane/execution/execution-identity';
13
+ import { getEditSession, recordEditSessionProcessCheckReceipts } from '../../../cli/editing/edit-session';
14
+ import { controllerCheckExecutionIdentity, listControllerChecks } from '../../../cli/controller/check-runner';
15
+ import type {
16
+ ExecutionOperationMetadata,
17
+ ExecutionTimeoutPolicy,
18
+ } from '../../execution/jobs/types';
19
+ import { claimsForMcpOperation } from './resource-policy';
20
+ import { classifyRepositoryCommand, classifyRepositoryCommandReplay } from '../../../cli/repositories/command-classifier';
21
+ import {
22
+ isFastEligibleTool,
23
+ routeExecution,
24
+ type ExecutionDecision,
25
+ } from '../../execution/thin-harness';
26
+ import {
27
+ checkRequiresDurableWorkflow,
28
+ claimsForCheck,
29
+ classifyRepositoryCommandRoute,
30
+ getProcessRecord,
31
+ processCheckCompletionReceipt,
32
+ processCheckSemanticScopeKey,
33
+ } from '../../execution/process-runtime';
34
+ import { runPersistedCheckViaProcessRuntime } from './persisted-check-process';
35
+ import {
36
+ isProcessIsolatedReadDiagnostic,
37
+ runReadOnlyDiagnosticViaProcessRuntime,
38
+ } from '../../diagnostics/process-facade';
39
+ import { resourceClaimsConflict } from '../../resources/claims/conflicts';
40
+
41
+ const DIRECT_REPOSITORY_TOOLS = new Set(['repository_list', 'repository_get', 'repository_workbench', 'repository_command_preview']);
42
+ export const RETIRED_AGENT_OPERATIONS = new Set([
43
+ 'dispatch_task',
44
+ 'launch_issue',
45
+ 'dispatch_ready_tasks',
46
+ 'retry_task_run',
47
+ 'quick_agent_session',
48
+ 'submit_local_job',
49
+ ]);
50
+
51
+ // Explicitly authorized bounded control-plane writes whose handlers already own
52
+ // their mutation boundary. These must not be promoted to retired ExecutionJobs.
53
+ const DIRECT_CONTROL_WRITE_TOOLS = new Set(['runtime_maintenance_apply']);
54
+
55
+ // Historical ExecutionJobs remain readable migration evidence only.
56
+ function executionJobCreationRetired(): boolean {
57
+ return true;
58
+ }
59
+
60
+ /**
61
+ * Tools whose Fast/Durable boundary is owned by Thin Harness classification.
62
+ * Gateway must classify BEFORE creating an ExecutionJob so short readonly
63
+ * repository commands do not pay queue/worker overhead.
64
+ */
65
+ const THIN_ROUTED_TOOLS = new Set([
66
+ 'repository_command_execute',
67
+ 'repository_safe_patch_apply',
68
+ 'repository_safe_patch_plan',
69
+ 'repository_git_status',
70
+ 'repository_git_diff',
71
+ 'repository_git_commit',
72
+ 'git_stage_paths',
73
+ 'git_commit_paths',
74
+ 'git_diff_paths',
75
+ 'apply_patch',
76
+ 'apply_edit_operations',
77
+ 'search_repository',
78
+ 'read_file_range',
79
+ 'read_repository_file',
80
+ // Checks and edit verification use Process Runtime unless multi-phase/release requires Durable.
81
+ 'run_check',
82
+ 'verify_edit_session',
83
+ ]);
84
+
85
+ /** Blocking native host tools must never execute on the public MCP event loop. */
86
+ const GATEWAY_ISOLATED_TOOLS = new Set([
87
+ // Native Apple tooling uses synchronous xcodebuild/simctl subprocesses.
88
+ 'ios_review_packet', 'ios_xcode_status', 'ios_simulators_list', 'ios_project_discover',
89
+ 'ios_schemes_list', 'ios_simulator_boot', 'ios_app_build', 'ios_app_install',
90
+ 'ios_app_launch', 'ios_simulator_screenshot', 'ios_simulator_log_tail', 'ios_ui_smoke_test',
91
+ // Diagnostics and maintenance perform process-table and recursive filesystem scans.
92
+ 'workflow_watchdog_report', 'runtime_cleanup_preview', 'runtime_cleanup_apply',
93
+ 'runtime_maintenance_status', 'runtime_maintenance_apply',
94
+ // Release and recovery operations may spawn Git/process checks or restart managed children.
95
+ 'release_gate', 'runtime_recovery', 'capability_recovery',
96
+ ]);
97
+
98
+ export function isGatewayIsolatedTool(name: string): boolean {
99
+ return GATEWAY_ISOLATED_TOOLS.has(name);
100
+ }
101
+
102
+ /** Tools that already own their direct-read versus durable-write boundary. */
103
+ const SELF_MANAGED_DURABLE_TOOLS = new Set(['plugin_action_execute']);
104
+
105
+ export function isSelfManagedDurableTool(name: string): boolean {
106
+ return SELF_MANAGED_DURABLE_TOOLS.has(name);
107
+ }
108
+ /** High-frequency bounded reads execute in the current MCP request. */
109
+ const DIRECT_HOT_READ_TOOLS = new Set([
110
+ 'get_task_run', 'get_task_run_events', 'get_task_run_log',
111
+ 'get_job', 'list_jobs',
112
+ 'work_get', 'work_list', 'work_status_digest', 'work_result_summary',
113
+ 'controller_ready', 'repository_runtime_snapshot',
114
+ 'rh_status', 'rh_context', 'rh_inbox',
115
+ 'controller_context_pack',
116
+ 'repository_git_status', 'repository_git_diff', 'git_diff_paths',
117
+ ]);
118
+
119
+ export function isDirectHotReadTool(name: string): boolean {
120
+ return DIRECT_HOT_READ_TOOLS.has(name);
121
+ }
122
+ /** Small interactive development writes: run synchronously by default so ChatGPT/GUI get immediate results. */
123
+ const INTERACTIVE_SYNC_WRITE_TOOLS = new Set([
124
+ 'repository_safe_patch_apply',
125
+ 'repository_git_create_branch',
126
+ 'repository_git_switch_branch',
127
+ 'repository_git_merge_branch',
128
+ 'repository_git_delete_branch',
129
+ 'repository_git_commit',
130
+ 'repository_git_finish_workflow',
131
+ 'begin_edit_session',
132
+ 'apply_patch',
133
+ 'apply_edit_operations',
134
+ 'create_edit_savepoint',
135
+ 'git_stage_paths',
136
+ 'git_commit_paths',
137
+ // Recovery writes against an existing Run must remain available while legacy
138
+ // Runs are the very thing preventing runtime-storage relocation. These tools
139
+ // do not create new execution ownership or dispatch new work.
140
+ 'finish_task_run',
141
+ 'cancel_task_run',
142
+ ]);
143
+ const AGENT_DELEGATION_TOOLS = new Set([
144
+ 'dispatch_task',
145
+ 'launch_issue',
146
+ 'dispatch_ready_tasks',
147
+ 'retry_task_run',
148
+ 'quick_agent_session',
149
+ ]);
150
+ const EXPLICIT_EXTERNAL_CONTROLLER_TOOLS = new Set([
151
+ 'publish_issue_to_github',
152
+ 'close_github_issue',
153
+ 'request_release_gate',
154
+ 'promote_candidate_finding',
155
+ ]);
156
+
157
+ const GATEWAY_ROUTE_BEHAVIOR_PROBES: ReadonlyArray<{
158
+ id: string;
159
+ operation: string;
160
+ args: Record<string, unknown>;
161
+ }> = [
162
+ { id: 'hot-read', operation: 'controller_ready', args: {} },
163
+ { id: 'isolated-read-diagnostic', operation: 'workflow_watchdog_report', args: {} },
164
+ { id: 'readonly-command', operation: 'repository_command_execute', args: { command: ['git', 'status', '--short'] } },
165
+ { id: 'managed-local-command', operation: 'repository_command_execute', args: { command: ['bun', 'run', 'check:type'], timeout_ms: 120_000 } },
166
+ { id: 'focused-check', operation: 'run_check', args: { check_id: 'package:check:type' } },
167
+ { id: 'release-check', operation: 'run_check', args: { check_id: 'package:check:release' } },
168
+ { id: 'interactive-write', operation: 'repository_safe_patch_apply', args: { operations: [] } },
169
+ { id: 'external-controller', operation: 'request_release_gate', args: {} },
170
+ { id: 'unknown-tool', operation: '__route_behavior_probe_unknown__', args: {} },
171
+ ];
172
+
173
+ export interface GatewayRouteBehaviorSnapshot {
174
+ schemaVersion: 1;
175
+ fingerprint: string;
176
+ probeCount: number;
177
+ probes: Array<{
178
+ id: string;
179
+ operation: string;
180
+ path: 'direct' | 'fast' | 'durable' | 'reject';
181
+ reasons: string[];
182
+ decision?: {
183
+ mode: string;
184
+ risk: string;
185
+ estimatedClass: string;
186
+ requiresIsolation: boolean;
187
+ requiresRecovery: boolean;
188
+ effects: Record<string, boolean>;
189
+ };
190
+ }>;
191
+ }
192
+
193
+ /**
194
+ * Fingerprint the real Gateway classifier over a fixed, bounded behavior matrix.
195
+ * This is deliberately distinct from the MCP schema/tool-surface fingerprint.
196
+ */
197
+ export function gatewayRouteBehaviorSnapshot(): GatewayRouteBehaviorSnapshot {
198
+ const probes = GATEWAY_ROUTE_BEHAVIOR_PROBES.map((probe) => {
199
+ const classification = classifyGatewayExecutionPath(probe.operation, probe.args);
200
+ return {
201
+ id: probe.id,
202
+ operation: probe.operation,
203
+ path: classification.path,
204
+ reasons: [...classification.reasons],
205
+ ...(classification.decision ? {
206
+ decision: {
207
+ mode: classification.decision.mode,
208
+ risk: classification.decision.risk,
209
+ estimatedClass: classification.decision.estimatedClass,
210
+ requiresIsolation: classification.decision.requiresIsolation,
211
+ requiresRecovery: classification.decision.requiresRecovery,
212
+ effects: { ...classification.decision.effects },
213
+ },
214
+ } : {}),
215
+ };
216
+ });
217
+ return {
218
+ schemaVersion: 1,
219
+ fingerprint: createHash('sha256').update(JSON.stringify(probes)).digest('hex'),
220
+ probeCount: probes.length,
221
+ probes,
222
+ };
223
+ }
224
+ const MAX_DURABLE_TIMEOUT_MS = 24 * 60 * 60_000;
225
+
226
+ function durableTimeoutMs(value: unknown, fallback: number): number {
227
+ if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
228
+ return Math.max(1_000, Math.min(Math.trunc(value), MAX_DURABLE_TIMEOUT_MS));
229
+ }
230
+
231
+ function wantsAsyncExecution(args: Record<string, unknown>): boolean {
232
+ return args.apply_mode === 'async'
233
+ || args.mode === 'async'
234
+ || args.mode === 'durable'
235
+ || args.async === true
236
+ || args.background === true;
237
+ }
238
+
239
+ export function runsAsInteractiveSyncWrite(
240
+ name: string,
241
+ args: Record<string, unknown> = {},
242
+ ): boolean {
243
+ return INTERACTIVE_SYNC_WRITE_TOOLS.has(name) && !wantsAsyncExecution(args);
244
+ }
245
+
246
+ export function wantsWaitForResult(args: Record<string, unknown>): boolean {
247
+ return args.wait === true
248
+ || args.await_result === true
249
+ || args.wait_for_result === true;
250
+ }
251
+
252
+ export function waitTimeoutMs(args: Record<string, unknown>): number {
253
+ const explicitInteractiveWait = args.interactive_wait_ms ?? args.wait_ms;
254
+ if (typeof explicitInteractiveWait === 'number' && Number.isFinite(explicitInteractiveWait)) {
255
+ return Math.max(200, Math.min(Math.trunc(explicitInteractiveWait), 120_000));
256
+ }
257
+ if (typeof args.timeout_ms === 'number' && Number.isFinite(args.timeout_ms) && wantsWaitForResult(args)) {
258
+ return Math.max(200, Math.min(Math.trunc(args.timeout_ms), 120_000));
259
+ }
260
+ return 15_000;
261
+ }
262
+
263
+ export function operationExecutionTimeoutMsForMcpCall(
264
+ name: string,
265
+ args: Record<string, unknown>,
266
+ ): number {
267
+ const requested = args.execution_timeout_ms ?? args.timeout_ms;
268
+ return durableTimeoutMs(requested, AGENT_DELEGATION_TOOLS.has(name) ? 60 * 60_000 : 15 * 60_000);
269
+ }
270
+
271
+ /**
272
+ * Build independent budgets for the durable Parent Job. Agent delegation keeps
273
+ * the caller's operation execution budget on the Child Run; the Parent only
274
+ * receives enough execution time to create and durably associate that child.
275
+ */
276
+ export function executionTimeoutPolicyForMcpCall(
277
+ name: string,
278
+ args: Record<string, unknown>,
279
+ ): ExecutionTimeoutPolicy {
280
+ const operationExecutionMs = operationExecutionTimeoutMsForMcpCall(name, args);
281
+ const agentDelegation = AGENT_DELEGATION_TOOLS.has(name);
282
+ return {
283
+ admissionTimeoutMs: durableTimeoutMs(
284
+ args.admission_timeout_ms,
285
+ agentDelegation ? 5 * 60_000 : operationExecutionMs,
286
+ ),
287
+ queueTimeoutMs: durableTimeoutMs(
288
+ args.queue_timeout_ms,
289
+ agentDelegation ? MAX_DURABLE_TIMEOUT_MS : operationExecutionMs,
290
+ ),
291
+ executionTimeoutMs: agentDelegation ? 120_000 : operationExecutionMs,
292
+ interactiveWaitMs: waitTimeoutMs(args),
293
+ };
294
+ }
295
+
296
+ function result(value: Record<string, unknown>, isError = false): CallToolResult {
297
+ return {
298
+ content: [{ type: 'text', text: JSON.stringify(value, null, 2) }],
299
+ structuredContent: value,
300
+ ...(isError ? { isError: true } : {}),
301
+ };
302
+ }
303
+
304
+ export function getMcpToolDefinition(ctx: MultiRepositoryMcpToolContext, name: string): McpToolDefinition | undefined {
305
+ return [...runtimeToolDefinitions, ...executionToolDefinitions, ...processToolDefinitions, ...repositoryToolDefinitions, ...buildMultiRepositoryToolDefinitions(ctx)]
306
+ .find((tool) => tool.name === name);
307
+ }
308
+
309
+ /**
310
+ * Classify Gateway execution path before any ExecutionJob is created.
311
+ * Fast decisions short-circuit durable queueing so Thin Harness owns the request.
312
+ */
313
+ export function classifyGatewayExecutionPath(
314
+ name: string,
315
+ args: Record<string, unknown> = {},
316
+ opts: { allowReadOnly?: boolean; forceDurable?: boolean; definition?: McpToolDefinition } = {},
317
+ ): {
318
+ path: 'direct' | 'fast' | 'durable' | 'reject';
319
+ reasons: string[];
320
+ decision?: ExecutionDecision;
321
+ } {
322
+ // Heavy read-only diagnostics must leave the Gateway event loop before the
323
+ // generic read-only shortcut. Process Runtime preserves the same request and
324
+ // returns either the completed JSON or a queryable process handle.
325
+ if (isProcessIsolatedReadDiagnostic(name)) {
326
+ return { path: 'fast', reasons: ['isolated_read_diagnostic_process'] };
327
+ }
328
+ // Registered bounded reads execute through their real handler.
329
+ if (opts.definition?.annotations?.readOnlyHint === true) {
330
+ return { path: 'direct', reasons: ['registered_readonly_tool'] };
331
+ }
332
+ if (name.startsWith('repository_') && DIRECT_REPOSITORY_TOOLS.has(name)) {
333
+ return { path: 'direct', reasons: ['direct_repository_tool'] };
334
+ }
335
+ if (isDirectHotReadTool(name)) {
336
+ return { path: 'direct', reasons: ['direct_hot_read'] };
337
+ }
338
+ if (runsAsInteractiveSyncWrite(name, args)) {
339
+ return { path: 'direct', reasons: ['interactive_sync_write'] };
340
+ }
341
+ if (isSelfManagedDurableTool(name)) {
342
+ return { path: 'direct', reasons: ['self_managed_durable_boundary'] };
343
+ }
344
+ if (DIRECT_CONTROL_WRITE_TOOLS.has(name) && !wantsAsyncExecution(args)) {
345
+ return { path: 'direct', reasons: ['bounded_direct_control_write'] };
346
+ }
347
+ if (EXPLICIT_EXTERNAL_CONTROLLER_TOOLS.has(name)) {
348
+ return { path: 'durable', reasons: ['explicit_external_controller_boundary'] };
349
+ }
350
+ if (opts.forceDurable === true || isGatewayIsolatedTool(name)) {
351
+ return {
352
+ path: 'durable',
353
+ reasons: opts.forceDurable ? ['force_durable'] : ['gateway_isolated_tool'],
354
+ };
355
+ }
356
+ if (wantsAsyncExecution(args)) {
357
+ return {
358
+ path: 'durable',
359
+ reasons: ['caller_requested_async_or_durable'],
360
+ };
361
+ }
362
+ // run_check: Process Runtime for ordinary checks; Durable only for release/multi-phase.
363
+ if (name === 'run_check') {
364
+ const checkId = String(args.check_id ?? args.checkId ?? '').trim();
365
+ if (args.apply_mode === 'async' || args.mode === 'durable' || args.force_durable === true) {
366
+ return { path: 'durable', reasons: ['caller_requested_durable_check'] };
367
+ }
368
+ if (checkId && checkRequiresDurableWorkflow(checkId)) {
369
+ return { path: 'durable', reasons: ['multi_phase_or_release_check'] };
370
+ }
371
+ // Route as "fast" so shouldCreateDurableJob returns false; actual execution
372
+ // uses Process Runtime (direct or managed handle) in routeDurableMcpCall / legacy handler.
373
+ return {
374
+ path: 'fast',
375
+ reasons: ['run_check_process_runtime'],
376
+ decision: {
377
+ mode: 'fast',
378
+ reasons: ['run_check_process_runtime'],
379
+ risk: 'workspace_write',
380
+ estimatedClass: 'short',
381
+ requiresIsolation: false,
382
+ requiresRecovery: false,
383
+ effects: {
384
+ readsWorkspace: true,
385
+ mutatesWorkspace: true,
386
+ mutatesGitRefs: false,
387
+ remoteWrite: false,
388
+ },
389
+ },
390
+ };
391
+ }
392
+
393
+ // verify_edit_session is a Process Runtime orchestration surface. It may
394
+ // return a managed handle, but it must never be promoted to a retired
395
+ // ExecutionJob/LocalJob merely because the edit session has checks.
396
+ if (name === 'verify_edit_session') {
397
+ if (args.apply_mode === 'async' || args.mode === 'durable' || args.force_durable === true) {
398
+ return { path: 'durable', reasons: ['caller_requested_durable_edit_verification'] };
399
+ }
400
+ const checkIds = Array.isArray(args.check_ids)
401
+ ? args.check_ids.map(String).map((entry) => entry.trim()).filter(Boolean)
402
+ : [];
403
+ if (checkIds.some((checkId) => checkRequiresDurableWorkflow(checkId))) {
404
+ return { path: 'durable', reasons: ['multi_phase_or_release_edit_check'] };
405
+ }
406
+ return {
407
+ path: 'fast',
408
+ reasons: ['verify_edit_session_process_runtime'],
409
+ decision: {
410
+ mode: 'fast',
411
+ reasons: ['verify_edit_session_process_runtime'],
412
+ risk: 'workspace_write',
413
+ estimatedClass: 'short',
414
+ requiresIsolation: false,
415
+ requiresRecovery: false,
416
+ effects: {
417
+ readsWorkspace: true,
418
+ mutatesWorkspace: true,
419
+ mutatesGitRefs: false,
420
+ remoteWrite: false,
421
+ },
422
+ },
423
+ };
424
+ }
425
+
426
+ // repository_command_execute has one authoritative classifier. Process Runtime
427
+ // owns every local single-process command regardless of timeout; explicit
428
+ // async/durable requests were handled above and remain external-controller work.
429
+ if (name === 'repository_command_execute') {
430
+ const command = args.command;
431
+ if (!(typeof command === 'string' || Array.isArray(command))) {
432
+ return { path: 'reject', reasons: ['repository_command_missing'] };
433
+ }
434
+ const route = classifyRepositoryCommandRoute(command as string | string[], {
435
+ defaultBranch: typeof args.default_branch === 'string' ? args.default_branch : undefined,
436
+ timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
437
+ });
438
+ if (route.route === 'process_direct' || route.route === 'process_managed') {
439
+ const commandClassification = classifyRepositoryCommand(
440
+ command as string | string[],
441
+ typeof args.default_branch === 'string' ? args.default_branch : undefined,
442
+ );
443
+ const risk = commandClassification.risk === 'readonly'
444
+ ? 'readonly'
445
+ : commandClassification.risk === 'remote_write'
446
+ ? 'remote_write'
447
+ : commandClassification.risk === 'destructive'
448
+ ? 'destructive'
449
+ : 'workspace_write';
450
+ const reasons = ['repository_command_process_runtime', route.reason];
451
+ return {
452
+ path: 'fast',
453
+ reasons,
454
+ decision: {
455
+ mode: 'fast',
456
+ reasons,
457
+ risk,
458
+ estimatedClass: route.route === 'process_direct' ? 'short' : 'long',
459
+ requiresIsolation: false,
460
+ requiresRecovery: false,
461
+ effects: {
462
+ readsWorkspace: true,
463
+ mutatesWorkspace: risk !== 'readonly',
464
+ mutatesGitRefs: risk !== 'readonly' && /(?:^|\s)git\s+(?:commit|merge|branch|switch|checkout|reset|rebase|tag)\b/i.test(
465
+ Array.isArray(command) ? command.join(' ') : command,
466
+ ),
467
+ remoteWrite: risk === 'remote_write',
468
+ },
469
+ },
470
+ };
471
+ }
472
+ if (route.route === 'reject') return { path: 'reject', reasons: [route.reason] };
473
+ return { path: 'durable', reasons: [route.reason] };
474
+ }
475
+
476
+ if (THIN_ROUTED_TOOLS.has(name)) {
477
+ const decision = routeExecution({
478
+ operation: name,
479
+ mode: args.mode === 'fast' ? 'fast' : 'auto',
480
+ background: args.background === true || args.apply_mode === 'async' || args.async === true,
481
+ requiresRecovery: args.requires_recovery === true,
482
+ requiresIsolation: args.isolation === 'new_worktree' || args.requires_isolation === true,
483
+ requiresWorktree: args.isolation === 'new_worktree',
484
+ agentRun: name === 'quick_agent_session' || name === 'dispatch_task',
485
+ remoteWrite: name.includes('push') || name === 'publish_issue_to_github',
486
+ timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
487
+ command: args.command as string | string[] | undefined,
488
+ paths: Array.isArray(args.paths) ? args.paths.map(String) : undefined,
489
+ allowedPaths: Array.isArray(args.allowed_paths) ? args.allowed_paths.map(String) : undefined,
490
+ patchOperationCount: Array.isArray(args.operations) ? args.operations.length : undefined,
491
+ patchPaths: Array.isArray(args.operations)
492
+ ? args.operations
493
+ .filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null)
494
+ .map((entry) => String(entry.path ?? '').trim())
495
+ .filter(Boolean)
496
+ : undefined,
497
+ });
498
+ if (decision.mode === 'fast') {
499
+ return {
500
+ path: 'fast',
501
+ reasons: decision.reasons,
502
+ decision,
503
+ };
504
+ }
505
+ if (decision.mode === 'reject') {
506
+ return { path: 'reject', reasons: decision.reasons, decision };
507
+ }
508
+ // Keep isFastEligibleTool as a secondary guard for tools whose operation
509
+ // name maps to a Fast allowlist entry but routeExecution used a durable alias.
510
+ if (isFastEligibleTool(name, args)) {
511
+ return {
512
+ path: 'fast',
513
+ reasons: ['thin_router_fast_eligible'],
514
+ };
515
+ }
516
+ return {
517
+ path: 'durable',
518
+ reasons: decision.reasons.length > 0 ? decision.reasons : ['thin_router_requires_durable'],
519
+ decision,
520
+ };
521
+ }
522
+ if (opts.definition) {
523
+ return { path: 'direct', reasons: ['registered_tool_direct_handler'] };
524
+ }
525
+ return { path: 'reject', reasons: ['tool_not_found'] };
526
+ }
527
+
528
+ export function shouldCreateDurableJob(
529
+ ctx: MultiRepositoryMcpToolContext,
530
+ name: string,
531
+ args: Record<string, unknown> = {},
532
+ opts: { allowReadOnly?: boolean; forceDurable?: boolean } = {},
533
+ ): boolean {
534
+ if (executionJobCreationRetired()) return false;
535
+ const definition = getMcpToolDefinition(ctx, name);
536
+ if (!definition) return false;
537
+ // One authoritative decision: do not duplicate read/write/isolation policy here.
538
+ return classifyGatewayExecutionPath(name, args, { ...opts, definition }).path === 'durable';
539
+ }
540
+
541
+ function canonical(value: unknown): unknown {
542
+ if (Array.isArray(value)) return value.map(canonical);
543
+ if (value && typeof value === 'object') {
544
+ return Object.fromEntries(Object.entries(value as Record<string, unknown>)
545
+ .filter(([key]) => key !== 'request_id')
546
+ .sort(([left], [right]) => left.localeCompare(right))
547
+ .map(([key, entry]) => [key, canonical(entry)]));
548
+ }
549
+ return value;
550
+ }
551
+
552
+ export function hashMcpToolArguments(args: Record<string, unknown>): string {
553
+ return createHash('sha256').update(JSON.stringify(canonical(args))).digest('hex').slice(0, 20);
554
+ }
555
+
556
+ export function validateMcpToolArguments(name: string, definition: McpToolDefinition, args: Record<string, unknown>): void {
557
+ const schema = definition.inputSchema as { required?: unknown; properties?: Record<string, unknown>; additionalProperties?: unknown };
558
+ const required = Array.isArray(schema.required) ? schema.required.filter((value): value is string => typeof value === 'string') : [];
559
+ const missing = required.filter((key) => args[key] === undefined || args[key] === null || args[key] === '');
560
+ if (missing.length > 0) {
561
+ throw new Error(`INVALID_ARGUMENT: ${name} is missing required argument(s): ${missing.join(', ')}`);
562
+ }
563
+ if (schema.additionalProperties === false && schema.properties) {
564
+ const allowed = new Set(Object.keys(schema.properties));
565
+ const unexpected = Object.keys(args).filter((key) => !allowed.has(key));
566
+ if (unexpected.length > 0) {
567
+ throw new Error(`INVALID_ARGUMENT: ${name} received unsupported argument(s): ${unexpected.join(', ')}`);
568
+ }
569
+ }
570
+ }
571
+
572
+ export function operationMetadataForTool(
573
+ name: string,
574
+ definition: McpToolDefinition,
575
+ claims: ReturnType<typeof claimsForMcpOperation>,
576
+ timeoutMs: number,
577
+ args: Record<string, unknown> = {},
578
+ defaultBranch?: string,
579
+ timeoutPolicy?: ExecutionTimeoutPolicy,
580
+ ): ExecutionOperationMetadata {
581
+ if (name === 'repository_command_execute' && args.command !== undefined) {
582
+ const classification = classifyRepositoryCommand(args.command as string | string[], defaultBranch);
583
+ const replay = classifyRepositoryCommandReplay(args.command as string | string[], defaultBranch);
584
+ const mode = classification.risk === 'readonly'
585
+ ? 'readonly'
586
+ : classification.risk === 'remote_write'
587
+ ? 'remote_write'
588
+ : classification.risk === 'destructive'
589
+ ? 'destructive'
590
+ : 'mutating';
591
+ return {
592
+ mode,
593
+ idempotent: replay.idempotent,
594
+ replayable: replay.replayable,
595
+ timeoutMs,
596
+ admissionTimeoutMs: timeoutPolicy?.admissionTimeoutMs,
597
+ queueTimeoutMs: timeoutPolicy?.queueTimeoutMs,
598
+ executionTimeoutMs: timeoutPolicy?.executionTimeoutMs,
599
+ interactiveWaitMs: timeoutPolicy?.interactiveWaitMs,
600
+ retryPolicy: replay.retryPolicy,
601
+ approvalPolicy: classification.risk === 'readonly'
602
+ ? 'none'
603
+ : classification.risk === 'destructive' ? 'required' : 'request',
604
+ lockScope: claims.map((claim) => claim.resourceKey),
605
+ resourceClaims: claims,
606
+ };
607
+ }
608
+ const destructive = definition.annotations?.destructiveHint === true;
609
+ const remoteWrite = claims.some((claim) => claim.resourceKey.startsWith('remote:'));
610
+ const readOnly = definition.annotations?.readOnlyHint === true || claims.length === 0;
611
+ const mode = destructive
612
+ ? 'destructive'
613
+ : remoteWrite
614
+ ? 'remote_write'
615
+ : readOnly
616
+ ? 'readonly'
617
+ : 'mutating';
618
+ return {
619
+ mode,
620
+ idempotent: readOnly,
621
+ replayable: readOnly,
622
+ timeoutMs,
623
+ admissionTimeoutMs: timeoutPolicy?.admissionTimeoutMs,
624
+ queueTimeoutMs: timeoutPolicy?.queueTimeoutMs,
625
+ executionTimeoutMs: timeoutPolicy?.executionTimeoutMs,
626
+ interactiveWaitMs: timeoutPolicy?.interactiveWaitMs,
627
+ retryPolicy: readOnly ? 'safe_retry' : 'idempotent_request',
628
+ approvalPolicy: destructive ? 'required' : remoteWrite || !readOnly ? 'request' : 'none',
629
+ lockScope: claims.map((claim) => claim.resourceKey),
630
+ resourceClaims: claims,
631
+ };
632
+ }
633
+
634
+ export function injectDurableCommandFields(tool: McpToolDefinition): McpToolDefinition {
635
+ const schema = tool.inputSchema as { type?: unknown; properties?: Record<string, unknown>; [key: string]: unknown };
636
+ if (schema.type !== 'object') return tool;
637
+ return {
638
+ ...tool,
639
+ inputSchema: {
640
+ ...schema,
641
+ properties: {
642
+ ...(schema.properties ?? {}),
643
+ request_id: {
644
+ type: 'string',
645
+ description: 'Idempotency key. Process Runtime retries return the original Process; durable operations return the original Work or historical Job.',
646
+ },
647
+ apply_mode: {
648
+ type: 'string',
649
+ enum: ['sync', 'async'],
650
+ description: 'Interactive development tools default to sync. Set async to queue a durable Job instead.',
651
+ },
652
+ wait: {
653
+ type: 'boolean',
654
+ description: 'When true for durable operations, wait up to wait_ms for a terminal result digest.',
655
+ },
656
+ wait_ms: {
657
+ type: 'number',
658
+ description: 'Max wait for terminal job result. Only used when wait=true; never enables waiting by itself. Default 15000, max 120000.',
659
+ },
660
+ admission_timeout_ms: {
661
+ type: 'number',
662
+ description: 'Durable admission budget before the Scheduler first observes the Job.',
663
+ },
664
+ queue_timeout_ms: {
665
+ type: 'number',
666
+ description: 'Durable queue budget after Scheduler admission and before Worker start.',
667
+ },
668
+ execution_timeout_ms: {
669
+ type: 'number',
670
+ description: 'Operation execution budget. For Agent delegation this is the Child Run budget and is never silently reduced by the Parent Job.',
671
+ },
672
+ interactive_wait_ms: {
673
+ type: 'number',
674
+ description: 'Caller-side wait budget only. It never cancels or shortens the durable operation.',
675
+ },
676
+ },
677
+ },
678
+ };
679
+ }
680
+
681
+ export async function routeDurableMcpCall(
682
+ ctx: MultiRepositoryMcpToolContext,
683
+ name: string,
684
+ args: Record<string, unknown>,
685
+ opts: { allowReadOnly?: boolean; forceDurable?: boolean } = {},
686
+ ): Promise<CallToolResult | undefined> {
687
+ const definition = getMcpToolDefinition(ctx, name);
688
+ if (!definition) {
689
+ return result({
690
+ accepted: false,
691
+ mode: 'reject',
692
+ path: 'reject',
693
+ rejectCode: 'TOOL_NOT_FOUND',
694
+ error: {
695
+ code: 'TOOL_NOT_FOUND',
696
+ message: `${name} is not registered by this forge build.`,
697
+ },
698
+ }, true);
699
+ }
700
+
701
+ if (RETIRED_AGENT_OPERATIONS.has(name)) {
702
+ return result({
703
+ accepted: false,
704
+ mode: 'reject',
705
+ path: 'reject',
706
+ rejectCode: 'AGENT_RUN_DEPRECATED',
707
+ message: 'Kernel-managed Agent Runs are retired. Create or resume a WorkContract, claim it, then start the external Controller through rh_work.launcher_start.',
708
+ migration: ['rh_work.plan_create', 'rh_work.controller_claim', 'rh_work.launcher_start', 'rh_inbox.create'],
709
+ });
710
+ }
711
+
712
+ // Classify BEFORE creating any ExecutionJob / LocalJob / Worker.
713
+ const classification = classifyGatewayExecutionPath(name, args, { ...opts, definition });
714
+ if (classification.path === 'reject' && classification.reasons.includes('tool_not_found')) {
715
+ return result({
716
+ accepted: false,
717
+ mode: 'reject',
718
+ path: 'reject',
719
+ routing: {
720
+ path: 'reject',
721
+ reasons: classification.reasons,
722
+ },
723
+ rejectCode: 'TOOL_NOT_FOUND',
724
+ error: {
725
+ code: 'TOOL_NOT_FOUND',
726
+ message: `${name} is not registered by this forge build.`,
727
+ },
728
+ }, true);
729
+ }
730
+ if (classification.path === 'reject' && classification.decision) {
731
+ return result({
732
+ accepted: false,
733
+ mode: 'reject',
734
+ path: 'reject',
735
+ routing: {
736
+ path: 'reject',
737
+ reasons: classification.reasons,
738
+ decision: classification.decision,
739
+ },
740
+ rejectCode: classification.decision.rejectCode,
741
+ message: classification.reasons.join('; ') || 'operation rejected by Thin Harness routing',
742
+ suggestedOperation: classification.decision.suggestedOperation,
743
+ }, true);
744
+ }
745
+
746
+ if (classification.path === 'durable' && executionJobCreationRetired()) {
747
+ return result({
748
+ accepted: false,
749
+ mode: 'external_controller_required',
750
+ path: 'external_controller_required',
751
+ routing: {
752
+ path: 'external_controller_required',
753
+ reasons: [...classification.reasons, 'execution_job_creation_retired'],
754
+ ...(classification.decision ? { decision: classification.decision } : {}),
755
+ },
756
+ rejectCode: 'EXECUTION_JOB_RETIRED',
757
+ message: 'This operation requires an explicitly claimed external Controller; the Kernel no longer creates ExecutionJobs.',
758
+ suggestedOperation: 'Create or resume a WorkContract, claim it with controller_claim, then use Process Runtime commands or rh_work.launcher_start.',
759
+ });
760
+ }
761
+
762
+ if (isProcessIsolatedReadDiagnostic(name) && classification.path === 'fast') {
763
+ const repository = resolveRepositorySelection({
764
+ repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
765
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
766
+ explicitPath: ctx.explicitRepository?.canonicalRoot,
767
+ controllerHome: ctx.controllerHome,
768
+ allowSoleRepository: true,
769
+ });
770
+ if (!repository) {
771
+ return result({
772
+ accepted: false,
773
+ mode: 'reject',
774
+ path: 'reject',
775
+ message: `${name} requires a resolvable repository`,
776
+ }, true);
777
+ }
778
+ try {
779
+ const payload = await runReadOnlyDiagnosticViaProcessRuntime({
780
+ controllerHome: ctx.controllerHome,
781
+ repository,
782
+ tool: name,
783
+ args: {
784
+ ...args,
785
+ __diagnostic_toolset: ctx.toolset,
786
+ __diagnostic_profile: ctx.policy.profile,
787
+ },
788
+ });
789
+ return result(payload, payload.accepted === false);
790
+ } catch (error) {
791
+ const message = error instanceof Error ? error.message : String(error);
792
+ const code = message.includes(':') ? message.slice(0, message.indexOf(':')) : 'DIAGNOSTIC_PROCESS_FAILED';
793
+ return result({
794
+ accepted: false,
795
+ mode: 'process_direct',
796
+ path: 'process_direct',
797
+ error: { code, message },
798
+ durableSideEffects: {
799
+ executionJobCount: 0,
800
+ localJobCount: 0,
801
+ workerSpawnCount: 0,
802
+ projectionUpdateCount: 0,
803
+ },
804
+ }, true);
805
+ }
806
+ }
807
+
808
+ // Edit-session verification uses the same persisted Process Runtime checks as run_check.
809
+ // The deterministic per-revision request IDs make retries collect the original process
810
+ // instead of launching a duplicate command.
811
+ if (name === 'verify_edit_session' && classification.path === 'fast') {
812
+ const repository = resolveRepositorySelection({
813
+ repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
814
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
815
+ explicitPath: ctx.explicitRepository?.canonicalRoot,
816
+ controllerHome: ctx.controllerHome,
817
+ allowSoleRepository: true,
818
+ });
819
+ if (!repository) {
820
+ return result({ accepted: false, mode: 'reject', path: 'reject', message: 'verify_edit_session requires a resolvable repository' });
821
+ }
822
+ const editSessionId = String(args.session_id ?? '').trim();
823
+ if (!editSessionId) {
824
+ return result({ accepted: false, mode: 'reject', path: 'reject', message: 'verify_edit_session requires session_id' });
825
+ }
826
+ const editSession = getEditSession(repository.canonicalRoot, editSessionId);
827
+ const checkIds = Array.from(new Set(
828
+ (Array.isArray(args.check_ids) ? args.check_ids.map(String) : editSession.requestedChecks)
829
+ .map((entry) => entry.trim())
830
+ .filter(Boolean),
831
+ ));
832
+ const requestBase = typeof args.request_id === 'string' && args.request_id.trim()
833
+ ? args.request_id.trim()
834
+ : `verify-edit:${editSession.sessionId}:r${editSession.currentRevision}:${createHash('sha256').update(JSON.stringify(checkIds)).digest('hex').slice(0, 16)}`;
835
+ if (checkIds.length === 0) {
836
+ const checked = recordEditSessionProcessCheckReceipts(repository.canonicalRoot, editSession.sessionId, {
837
+ repoId: repository.repoId,
838
+ checkoutId: repository.activeCheckoutId,
839
+ receipts: [],
840
+ reviewer: typeof args.reviewer === 'string' ? args.reviewer : undefined,
841
+ note: typeof args.note === 'string' ? args.note : undefined,
842
+ });
843
+ return result({ accepted: true, mode: 'direct', path: 'process_direct', completed: true, ok: true, session: checked, receipts: [] });
844
+ }
845
+ // Parallel-first without a timeout-based correctness tradeoff. Build
846
+ // conflict-connected lanes from the same Resource Claim model used by the
847
+ // Lease store. Different lanes run concurrently; checks in one lane retain
848
+ // the historical managed-process behavior: once a check is still running,
849
+ // stop that lane and continue it on the caller's retry. This avoids turning
850
+ // a legitimate long serialization wait into PROCESS_LEASE_CONFLICT.
851
+ const availableChecks = new Map(listControllerChecks(repository.canonicalRoot).map((check) => [check.id, check] as const));
852
+ const claimSets = checkIds.map((checkId) => {
853
+ const check = availableChecks.get(checkId);
854
+ return claimsForCheck(
855
+ checkId,
856
+ check?.command,
857
+ repository.repoId,
858
+ repository.activeCheckoutId,
859
+ check?.effects,
860
+ );
861
+ });
862
+ const lanes: number[][] = [];
863
+ const assigned = new Set<number>();
864
+ for (let start = 0; start < checkIds.length; start += 1) {
865
+ if (assigned.has(start)) continue;
866
+ const lane: number[] = [];
867
+ const queue = [start];
868
+ assigned.add(start);
869
+ while (queue.length > 0) {
870
+ const current = queue.shift()!;
871
+ lane.push(current);
872
+ for (let candidate = 0; candidate < checkIds.length; candidate += 1) {
873
+ if (assigned.has(candidate)) continue;
874
+ const conflicts = claimSets[current]!.some((left) =>
875
+ claimSets[candidate]!.some((right) => resourceClaimsConflict(left, right)));
876
+ if (!conflicts) continue;
877
+ assigned.add(candidate);
878
+ queue.push(candidate);
879
+ }
880
+ }
881
+ lanes.push(lane.sort((left, right) => left - right));
882
+ }
883
+ const leaseWaitMs = typeof args.lease_wait_ms === 'number' && Number.isFinite(args.lease_wait_ms)
884
+ ? Math.max(0, Math.min(Math.trunc(args.lease_wait_ms), 15_000))
885
+ : 0;
886
+ const facadesByIndex: Array<Awaited<ReturnType<typeof runPersistedCheckViaProcessRuntime>> | undefined> = new Array(checkIds.length);
887
+ await Promise.all(lanes.map(async (lane) => {
888
+ for (const index of lane) {
889
+ const checkId = checkIds[index]!;
890
+ const checkRequestId = `${requestBase}:check:${index + 1}:${createHash('sha256').update(checkId).digest('hex').slice(0, 12)}`;
891
+ const facade = await runPersistedCheckViaProcessRuntime({
892
+ controllerHome: ctx.controllerHome,
893
+ repoId: repository.repoId,
894
+ checkoutId: repository.activeCheckoutId,
895
+ repoRoot: repository.canonicalRoot,
896
+ executionIdentity: executionIdentityForRepository(repository),
897
+ checkId,
898
+ timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
899
+ interactiveWaitMs: typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : undefined,
900
+ requestId: checkRequestId,
901
+ commandId: checkRequestId,
902
+ verificationBinding: {
903
+ editSessionId: editSession.sessionId,
904
+ editRevision: editSession.currentRevision,
905
+ issueId: editSession.issueId,
906
+ taskId: editSession.taskId,
907
+ },
908
+ leaseWaitMs,
909
+ });
910
+ facadesByIndex[index] = facade;
911
+ if (facade.mode === 'durable' || !facade.process || !facade.process.completed) break;
912
+ }
913
+ }));
914
+ const facades = facadesByIndex.filter((facade): facade is Awaited<ReturnType<typeof runPersistedCheckViaProcessRuntime>> => Boolean(facade));
915
+ const durableFailure = facades.find((facade) => facade.mode === 'durable' || !facade.process);
916
+ if (durableFailure) {
917
+ return result({
918
+ accepted: false,
919
+ mode: 'durable',
920
+ path: 'durable',
921
+ checkId: durableFailure.checkId,
922
+ message: durableFailure.durable?.reason ?? 'check requires durable workflow',
923
+ suggestedOperation: durableFailure.durable?.suggestedOperation,
924
+ });
925
+ }
926
+ const processes = facades.map((facade) => facade.process!);
927
+ const pending = processes.find((process) => !process.completed);
928
+ if (pending || processes.length !== checkIds.length) {
929
+ return result({
930
+ accepted: true,
931
+ mode: 'managed',
932
+ path: 'process_managed',
933
+ completed: false,
934
+ sessionId: editSession.sessionId,
935
+ editRevision: editSession.currentRevision,
936
+ requestId: requestBase,
937
+ processes,
938
+ next: `Re-run verify_edit_session with request_id=${requestBase}; Process Runtime will reuse the same process records.`,
939
+ durableSideEffects: { executionJobCount: 0, localJobCount: 0, workerSpawnCount: 0, projectionUpdateCount: 0 },
940
+ });
941
+ }
942
+ const receipts = processes.map((handle, index) => {
943
+ const record = getProcessRecord(ctx.controllerHome, repository.repoId, handle.processId);
944
+ if (!record) throw new Error(`PROCESS_CHECK_RECEIPT_MISSING: process record not found: ${handle.processId}`);
945
+ const checkId = checkIds[index]!;
946
+ const currentIdentity = record.checkExecution
947
+ ? controllerCheckExecutionIdentity(repository.canonicalRoot, checkId, record.checkExecution.timeoutMs)
948
+ : undefined;
949
+ return processCheckCompletionReceipt(record, {
950
+ repoId: repository.repoId,
951
+ checkoutId: repository.activeCheckoutId,
952
+ editSessionId: editSession.sessionId,
953
+ editRevision: editSession.currentRevision,
954
+ issueId: editSession.issueId,
955
+ taskId: editSession.taskId,
956
+ checkId,
957
+ processId: handle.processId,
958
+ ...(currentIdentity ? {
959
+ checkExecution: {
960
+ cacheKey: currentIdentity.cacheKey,
961
+ revision: currentIdentity.revision,
962
+ definitionDigest: currentIdentity.definitionDigest,
963
+ environmentFingerprint: currentIdentity.environmentFingerprint,
964
+ timeoutMs: currentIdentity.timeoutMs,
965
+ scopeKey: processCheckSemanticScopeKey({
966
+ checkoutId: repository.activeCheckoutId,
967
+ verificationBinding: {
968
+ editSessionId: editSession.sessionId,
969
+ editRevision: editSession.currentRevision,
970
+ issueId: editSession.issueId,
971
+ taskId: editSession.taskId,
972
+ },
973
+ }, currentIdentity.reuseScope),
974
+ },
975
+ } : {}),
976
+ });
977
+ });
978
+ const checked = recordEditSessionProcessCheckReceipts(repository.canonicalRoot, editSession.sessionId, {
979
+ repoId: repository.repoId,
980
+ checkoutId: repository.activeCheckoutId,
981
+ receipts,
982
+ reviewer: typeof args.reviewer === 'string' ? args.reviewer : undefined,
983
+ note: typeof args.note === 'string' ? args.note : undefined,
984
+ });
985
+ return result({
986
+ accepted: true,
987
+ mode: 'direct',
988
+ path: 'process_direct',
989
+ completed: true,
990
+ ok: receipts.every((receipt) => receipt.ok),
991
+ session: checked,
992
+ receipts,
993
+ durableSideEffects: { executionJobCount: 0, localJobCount: 0, workerSpawnCount: 0, projectionUpdateCount: 0 },
994
+ });
995
+ }
996
+
997
+ // run_check Process Runtime facade — execute here so legacy LocalBridgeJob path is skipped.
998
+ if (name === 'run_check' && classification.path === 'fast') {
999
+ const restoringDisabledRepository = false;
1000
+ void restoringDisabledRepository;
1001
+ const repository = resolveRepositorySelection({
1002
+ repoId: typeof args.repo_id === 'string' ? args.repo_id : undefined,
1003
+ checkoutId: typeof args.checkout_id === 'string' ? args.checkout_id : undefined,
1004
+ explicitPath: ctx.explicitRepository?.canonicalRoot,
1005
+ controllerHome: ctx.controllerHome,
1006
+ allowSoleRepository: true,
1007
+ });
1008
+ if (!repository) {
1009
+ return result({
1010
+ accepted: false,
1011
+ mode: 'reject',
1012
+ path: 'reject',
1013
+ message: 'run_check requires a resolvable repository',
1014
+ });
1015
+ }
1016
+ const checkId = String(args.check_id ?? '').trim();
1017
+ if (!checkId) {
1018
+ return result({
1019
+ accepted: false,
1020
+ mode: 'reject',
1021
+ path: 'reject',
1022
+ message: 'run_check requires check_id',
1023
+ });
1024
+ }
1025
+ const facade = await runPersistedCheckViaProcessRuntime({
1026
+ controllerHome: ctx.controllerHome,
1027
+ repoId: repository.repoId,
1028
+ checkoutId: repository.activeCheckoutId,
1029
+ repoRoot: repository.canonicalRoot,
1030
+ executionIdentity: executionIdentityForRepository(repository),
1031
+ checkId,
1032
+ timeoutMs: typeof args.timeout_ms === 'number' ? args.timeout_ms : undefined,
1033
+ interactiveWaitMs: typeof args.interactive_wait_ms === 'number' ? args.interactive_wait_ms : undefined,
1034
+ requestId: typeof args.request_id === 'string' ? args.request_id : undefined,
1035
+ forceDurable: args.force_durable === true,
1036
+ });
1037
+ if (facade.mode === 'durable') {
1038
+ // Multi-phase/release should already be classified durable. Remaining durable
1039
+ // reasons (missing check, explicit force) must not silently create empty jobs
1040
+ // without a clear signal — return structured escalation instead of LocalBridge.
1041
+ return result({
1042
+ accepted: false,
1043
+ mode: 'durable',
1044
+ path: 'durable',
1045
+ routing: {
1046
+ path: 'durable',
1047
+ reasons: [facade.durable?.reason ?? 'check_requires_durable'],
1048
+ },
1049
+ checkId: facade.checkId,
1050
+ message: facade.durable?.reason ?? 'check requires durable workflow',
1051
+ suggestedOperation: facade.durable?.suggestedOperation,
1052
+ durableSideEffects: facade.durableSideEffects,
1053
+ });
1054
+ }
1055
+ const handle = facade.process;
1056
+ return result({
1057
+ accepted: true,
1058
+ mode: facade.mode,
1059
+ path: facade.mode === 'direct' ? 'process_direct' : 'process_managed',
1060
+ routing: {
1061
+ path: facade.mode,
1062
+ reasons: classification.reasons,
1063
+ },
1064
+ checkId: facade.checkId,
1065
+ repoId: repository.repoId,
1066
+ checkoutId: repository.activeCheckoutId,
1067
+ processId: handle?.processId,
1068
+ status: handle?.status,
1069
+ completed: handle?.completed === true,
1070
+ deduplicated: handle?.deduplicated === true,
1071
+ semanticDeduplicated: handle?.semanticDeduplicated === true,
1072
+ ok: handle?.ok,
1073
+ exitCode: handle?.exitCode,
1074
+ timedOut: handle?.timedOut,
1075
+ stdout: handle?.stdout,
1076
+ stderr: handle?.stderr,
1077
+ durableSideEffects: facade.durableSideEffects,
1078
+ next: handle?.completed
1079
+ ? 'Check finished on Process Runtime without ExecutionJob / LocalBridgeJob / Worker.'
1080
+ : `Check still running as managed process ${handle?.processId}. Poll process_get or process_wait with process_id=${handle?.processId}; do not re-run the same check.`,
1081
+ });
1082
+ }
1083
+
1084
+ // Durable classifications have already returned the explicit external-controller
1085
+ // handoff above. All remaining tools are direct, fast, or self-managed and must
1086
+ // not retain a dormant ExecutionJob creation branch.
1087
+ return undefined;
1088
+ }