@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,57 @@
1
+ export const MAX_SAFE_BRANCH_NAME_LENGTH = 180;
2
+
3
+ export interface BranchNamePolicyOptions {
4
+ readonly maxLength?: number;
5
+ readonly purpose?: string;
6
+ }
7
+
8
+ const UNSAFE_BRANCH_CHARS = /[\s~^:?*[\\\]\0]/;
9
+
10
+ function reason(message: string, purpose?: string): Error {
11
+ return new Error(`${purpose ?? 'GIT_BRANCH'}_INVALID: ${message}`);
12
+ }
13
+
14
+ export function branchSlugSegment(value: string, maxLength = 48): string {
15
+ const slug = value
16
+ .toLowerCase()
17
+ .replace(/[^a-z0-9._-]+/g, '-')
18
+ .replace(/^[.-]+|[.-]+$/g, '')
19
+ .replace(/\.{2,}/g, '.')
20
+ .replace(/-{2,}/g, '-')
21
+ .slice(0, maxLength)
22
+ .replace(/[.-]+$/g, '');
23
+ return slug || 'automation';
24
+ }
25
+
26
+ export function validateBranchName(raw: unknown, options: BranchNamePolicyOptions = {}): string {
27
+ const branch = String(raw ?? '').trim();
28
+ const maxLength = options.maxLength ?? MAX_SAFE_BRANCH_NAME_LENGTH;
29
+ const purpose = options.purpose ?? 'GIT_BRANCH';
30
+ if (!branch) throw reason('branch name is required', purpose);
31
+ if (branch.length > maxLength) throw reason(`branch name exceeds ${maxLength} characters: ${branch}`, purpose);
32
+ if (branch.startsWith('-')) throw reason(`branch name must not start with '-': ${branch}`, purpose);
33
+ if (branch.startsWith('/') || branch.endsWith('/')) throw reason(`branch name must not start or end with '/': ${branch}`, purpose);
34
+ if (branch.startsWith('refs/')) throw reason(`branch name must be relative, not a full ref: ${branch}`, purpose);
35
+ if (branch === '@' || branch.includes('@{')) throw reason(`branch name contains forbidden @ syntax: ${branch}`, purpose);
36
+ if (branch.includes('..')) throw reason(`branch name contains '..': ${branch}`, purpose);
37
+ if (branch.endsWith('.')) throw reason(`branch name must not end with '.': ${branch}`, purpose);
38
+ if (branch.endsWith('.lock')) throw reason(`branch name must not end with '.lock': ${branch}`, purpose);
39
+ if (UNSAFE_BRANCH_CHARS.test(branch)) throw reason(`branch name contains unsafe characters: ${branch}`, purpose);
40
+ for (const segment of branch.split('/')) {
41
+ if (!segment) throw reason(`branch name contains an empty path segment: ${branch}`, purpose);
42
+ if (segment.startsWith('.')) throw reason(`branch segment must not start with '.': ${branch}`, purpose);
43
+ if (segment.endsWith('.lock')) throw reason(`branch segment must not end with '.lock': ${branch}`, purpose);
44
+ }
45
+ return branch;
46
+ }
47
+
48
+ export function branchRef(branch: unknown, options: BranchNamePolicyOptions = {}): string {
49
+ return `refs/heads/${validateBranchName(branch, options)}`;
50
+ }
51
+
52
+ export function campaignBranchName(input: { readonly title: string; readonly identity: string }): string {
53
+ return validateBranchName(
54
+ `campaign/${branchSlugSegment(input.title)}-${input.identity}`,
55
+ { purpose: 'CAMPAIGN_WORKSPACE_BRANCH' },
56
+ );
57
+ }
@@ -0,0 +1,600 @@
1
+ import { normalizeRepositoryCommand, type CanonicalRepositoryCommand } from './command-normalization';
2
+
3
+ export type RepositoryCommandRisk = 'readonly' | 'workspace_write' | 'remote_write' | 'destructive';
4
+ export type RepositoryCommandAuthorization = 'explicit_user_request' | 'confirmed_plan' | 'policy' | 'full_access' | 'goal_delegation' | 'gpt_risk_delegate' | 'user_confirmation';
5
+ export type RepositoryCommandConfirmation = 'none' | 'authorization' | 'strong_confirmation';
6
+
7
+ export interface RepositoryCommandClassification {
8
+ risk: RepositoryCommandRisk;
9
+ confirmation: RepositoryCommandConfirmation;
10
+ reasons: string[];
11
+ }
12
+
13
+ export type RepositoryCommandReplayPolicy = 'none' | 'safe_retry' | 'idempotent_request';
14
+
15
+ export interface RepositoryCommandReplayClassification {
16
+ replayable: boolean;
17
+ idempotent: boolean;
18
+ retryPolicy: RepositoryCommandReplayPolicy;
19
+ reasons: string[];
20
+ }
21
+
22
+ const READ_ONLY_PROGRAMS = new Set([
23
+ 'pwd', 'ls', 'rg', 'grep', 'egrep', 'fgrep', 'cat', 'head', 'tail', 'wc',
24
+ 'sort', 'uniq', 'cut', 'tr', 'stat', 'file', 'which', 'whereis', 'basename',
25
+ 'dirname', 'printf', 'echo', 'true', 'false', 'ps', 'pgrep', 'date', 'uname',
26
+ 'id', 'whoami', 'du', 'df', 'realpath', 'readlink', 'jq', 'shasum', 'sha256sum',
27
+ // Pure delay/wait utilities do not mutate the repository; used by Fast Path concurrency tests.
28
+ 'sleep',
29
+ ]);
30
+
31
+ const READ_ONLY_GIT_SUBCOMMANDS = new Set([
32
+ 'status', 'log', 'show', 'diff', 'blame', 'grep', 'merge-base', 'rev-list',
33
+ 'rev-parse', 'for-each-ref', 'show-ref', 'ls-files', 'ls-tree', 'cat-file',
34
+ 'name-rev', 'describe', 'shortlog', 'reflog', 'fsck', 'ls-remote',
35
+ 'count-objects', 'verify-pack', 'check-ignore',
36
+ ]);
37
+
38
+ function shellSegments(command: string): string[] {
39
+ const segments: string[] = [];
40
+ let current = '';
41
+ let quote: "'" | '"' | undefined;
42
+ let escaped = false;
43
+
44
+ const flush = () => {
45
+ const segment = current.trim();
46
+ if (segment) segments.push(segment);
47
+ current = '';
48
+ };
49
+
50
+ for (let index = 0; index < command.length; index += 1) {
51
+ const character = command[index]!;
52
+ if (escaped) {
53
+ current += character;
54
+ escaped = false;
55
+ continue;
56
+ }
57
+ if (character === '\\' && quote !== "'") {
58
+ current += character;
59
+ escaped = true;
60
+ continue;
61
+ }
62
+ if (quote) {
63
+ current += character;
64
+ if (character === quote) quote = undefined;
65
+ continue;
66
+ }
67
+ if (character === "'" || character === '"') {
68
+ quote = character;
69
+ current += character;
70
+ continue;
71
+ }
72
+ if (character === ';' || character === '|' || character === '&') {
73
+ flush();
74
+ if (command[index + 1] === character) index += 1;
75
+ continue;
76
+ }
77
+ current += character;
78
+ }
79
+ flush();
80
+ return segments;
81
+ }
82
+
83
+ function isSedInPlaceSegment(segment: string): boolean {
84
+ const words = firstWords(segment);
85
+ if (words[0]?.toLowerCase() !== 'sed') return false;
86
+ return words.slice(1).some((word) => word === '--in-place'
87
+ || word.startsWith('--in-place=')
88
+ || /^-[^-]*i/.test(word));
89
+ }
90
+
91
+ function hasRepositoryOutputRedirection(command: string): boolean {
92
+ let quote: "'" | '"' | undefined;
93
+ let escaped = false;
94
+ for (let index = 0; index < command.length; index += 1) {
95
+ const character = command[index]!;
96
+ if (escaped) {
97
+ escaped = false;
98
+ continue;
99
+ }
100
+ if (character === '\\' && quote !== "'") {
101
+ escaped = true;
102
+ continue;
103
+ }
104
+ if (quote) {
105
+ if (character === quote) quote = undefined;
106
+ continue;
107
+ }
108
+ if (character === "'" || character === '"') {
109
+ quote = character;
110
+ continue;
111
+ }
112
+ if (character !== '>' || command[index - 1] === '=') continue;
113
+
114
+ let targetIndex = index + 1;
115
+ if (command[targetIndex] === '>') targetIndex += 1;
116
+ while (/\s/.test(command[targetIndex] ?? '')) targetIndex += 1;
117
+ if (command[targetIndex] === '&' && /\d/.test(command[targetIndex + 1] ?? '')) continue;
118
+ if (command.slice(targetIndex).startsWith('/dev/null')) continue;
119
+ return true;
120
+ }
121
+ return false;
122
+ }
123
+
124
+ function firstWords(segment: string): string[] {
125
+ return segment
126
+ .replace(/^\s*(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*/, '')
127
+ .split(/\s+/)
128
+ .map((word) => word.replace(/^['"]|['"]$/g, ''));
129
+ }
130
+
131
+ function hasGitFlag(words: string[], ...flags: string[]): boolean {
132
+ return words.some((word) => flags.includes(word));
133
+ }
134
+
135
+ /**
136
+ * Shared Git readonly subcommand gate for shell segments and typed argv.
137
+ * Mutating branch/tag/remote/config/worktree flags stay non-readonly.
138
+ */
139
+ function isReadOnlyGitCommand(words: string[]): boolean {
140
+ const subcommand = words[1]?.toLowerCase();
141
+ if (!subcommand) return false;
142
+ if (READ_ONLY_GIT_SUBCOMMANDS.has(subcommand)) return true;
143
+ if (subcommand === 'branch') {
144
+ if (hasGitFlag(words, '-d', '-D', '-m', '-M', '--delete', '--move', '--copy', '--set-upstream-to', '--unset-upstream')
145
+ || words.some((word) => word.startsWith('--set-upstream-to='))) {
146
+ return false;
147
+ }
148
+ return words.length === 2
149
+ || hasGitFlag(
150
+ words,
151
+ '-a', '--all', '-r', '--remotes', '-l', '--list', '-v', '-vv',
152
+ '--merged', '--no-merged', '--contains', '--no-contains', '--points-at', '--show-current',
153
+ )
154
+ || words.some((word) => word.startsWith('--contains=') || word.startsWith('--points-at='));
155
+ }
156
+ if (subcommand === 'tag') {
157
+ return words.length === 2
158
+ || hasGitFlag(words, '-l', '--list', '--points-at', '--contains', '--no-contains')
159
+ || words.some((word) => word.startsWith('--contains=') || word.startsWith('--points-at='));
160
+ }
161
+ if (subcommand === 'remote') {
162
+ return words.length === 2
163
+ || hasGitFlag(words, '-v', '--verbose')
164
+ || words[2]?.toLowerCase() === 'show'
165
+ || words[2]?.toLowerCase() === 'get-url';
166
+ }
167
+ if (subcommand === 'config') {
168
+ return hasGitFlag(words, '--get', '--get-all', '--get-regexp', '--list', '-l');
169
+ }
170
+ if (subcommand === 'worktree') {
171
+ return words[2]?.toLowerCase() === 'list';
172
+ }
173
+ return false;
174
+ }
175
+
176
+ function readOnlyGitSegment(words: string[], _segment: string): boolean {
177
+ return isReadOnlyGitCommand(words);
178
+ }
179
+
180
+ function isReadOnlySegment(segment: string): boolean {
181
+ const words = firstWords(segment);
182
+ const program = words[0]?.toLowerCase();
183
+ if (!program) return false;
184
+ if (program === 'git') return readOnlyGitSegment(words, segment);
185
+ if (program === 'find') return !/(?:-delete|-exec|-execdir|-ok|-okdir)\b/.test(segment);
186
+ if (program === 'sed') return !isSedInPlaceSegment(segment);
187
+ if (program === 'gh') {
188
+ return /\bgh\s+(?:repo\s+view|pr\s+(?:list|view|status|checks|diff)|issue\s+(?:list|view)|run\s+(?:list|view|watch)|release\s+(?:list|view|download))(?:\s|$)/.test(segment);
189
+ }
190
+ return READ_ONLY_PROGRAMS.has(program);
191
+ }
192
+
193
+ /** Package scripts that are local validation (not install/publish/mutate deps). */
194
+ const SAFE_PACKAGE_SCRIPT = /^(?:test|check|lint|typecheck|format:check|tsc)(?::|$)/i;
195
+
196
+ function isSafePackageRunner(program: string, words: string[]): boolean {
197
+ if (!['bun', 'npm', 'pnpm', 'yarn', 'node'].includes(program)) return false;
198
+ // bun test <path>, npm test, etc.
199
+ if (words[1]?.toLowerCase() === 'test') return true;
200
+ // bun run check:type / npm run lint / pnpm run typecheck
201
+ if (words[1]?.toLowerCase() === 'run' && words[2] && SAFE_PACKAGE_SCRIPT.test(words[2])) return true;
202
+ // bunx tsc --noEmit / npx eslint
203
+ if ((program === 'bun' && words[1]?.toLowerCase() === 'x') || program === 'node') {
204
+ const tool = words[program === 'node' ? 1 : 2]?.toLowerCase();
205
+ if (tool === 'tsc' || tool === 'eslint' || tool === 'biome') return true;
206
+ }
207
+ return false;
208
+ }
209
+
210
+ function isReplaySafeValidationWords(words: string[]): boolean {
211
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
212
+ const subcommand = words[1]?.toLowerCase();
213
+ if (!program) return false;
214
+ if (isSafePackageRunner(program, words)) return true;
215
+ if (program === 'bun') return subcommand === 'test';
216
+ if (program === 'node') return words.slice(1).some((word) => word === '--test' || word.startsWith('--test='));
217
+ if (program === 'go') return subcommand === 'test';
218
+ if (program === 'cargo') return subcommand === 'test' || subcommand === 'check';
219
+ if (program === 'swift') return subcommand === 'test';
220
+ if (program === 'tsc') return true;
221
+ if (program === 'eslint' || program === 'biome') return true;
222
+ if (program === 'pytest' || program === 'py.test') return true;
223
+ if ((program === 'python' || program === 'python3') && subcommand === '-m') return words[2]?.toLowerCase() === 'pytest';
224
+ if (program === 'mvn' || program === 'mvnw') return words.slice(1).some((word) => word === 'test' || word === 'verify');
225
+ if (program === 'gradle' || program === 'gradlew') return words.slice(1).some((word) => word === 'test' || word === 'check');
226
+ if (program === 'xcodebuild') {
227
+ return words.slice(1).some((word) => ['build', 'test', 'build-for-testing', 'test-without-building'].includes(word.toLowerCase()));
228
+ }
229
+ return false;
230
+ }
231
+
232
+ function isReplaySafeValidationSegment(segment: string): boolean {
233
+ return isReplaySafeValidationWords(firstWords(segment));
234
+ }
235
+
236
+ /** Mask shell-literal text that cannot activate operators/substitution.
237
+ * Single-quoted content and backslash-escaped characters are data, while
238
+ * double-quoted content remains active for $()/backtick expansion.
239
+ */
240
+ function shellOperatorView(command: string): string {
241
+ let output = '';
242
+ let singleQuoted = false;
243
+ for (let index = 0; index < command.length; index += 1) {
244
+ const char = command[index] ?? '';
245
+ if (singleQuoted) {
246
+ if (char === "'") singleQuoted = false;
247
+ output += ' ';
248
+ continue;
249
+ }
250
+ if (char === "'") {
251
+ singleQuoted = true;
252
+ output += ' ';
253
+ continue;
254
+ }
255
+ if (char === '\\' && index + 1 < command.length) {
256
+ output += ' ';
257
+ index += 1;
258
+ continue;
259
+ }
260
+ output += char;
261
+ }
262
+ return output;
263
+ }
264
+
265
+ /**
266
+ * Dangerous shell constructs that must never ride the Process Runtime / Fast Path
267
+ * even when individual segments look like tests or readonly tools.
268
+ */
269
+ export function shellCommandHasUnsafeConstructs(command: string): { unsafe: boolean; reasons: string[] } {
270
+ const reasons: string[] = [];
271
+ const normalized = command.trim();
272
+ const operators = shellOperatorView(normalized);
273
+ // Background jobs
274
+ if (/(?:^|[^&])&(?:[^&]|$)/.test(operators.replace(/&&/g, ' '))) {
275
+ reasons.push('background execution (&) is not allowed on the direct process path');
276
+ }
277
+ // Dynamic substitution / eval
278
+ if (/(?:^|[\s;|&])eval(?:\s|$)/i.test(operators)) reasons.push('eval is not allowed');
279
+ if (/\$\([^)]*\)/.test(operators) || /`[^`]+`/.test(operators)) {
280
+ reasons.push('command substitution is not allowed');
281
+ }
282
+ if (/\$\{[^}]+\}/.test(operators) && !/\$\{\w+\}/.test(operators.replace(/\$\{\w+\}/g, ''))) {
283
+ // keep simple ${VAR} allowed later; complex nested expansions flagged below
284
+ }
285
+ // Download-and-execute
286
+ if (/\b(?:curl|wget)\b[\s\S]*\|\s*(?:sh|bash|zsh|fish)\b/i.test(operators)) {
287
+ reasons.push('download-and-execute pipelines are not allowed');
288
+ }
289
+ if (/\b(?:curl|wget)\b[\s\S]*\b(?:-o|--output)\b[\s\S]*&&\s*(?:sh|bash|\.\/)/i.test(operators)) {
290
+ reasons.push('download then execute is not allowed');
291
+ }
292
+ // Path escape hints
293
+ if (/(?:^|[\s"'])\.\.\/(?:\.\.\/)*/.test(normalized)) {
294
+ reasons.push('parent-directory path traversal requires durable review');
295
+ }
296
+ return { unsafe: reasons.length > 0, reasons };
297
+ }
298
+
299
+ /**
300
+ * Safe fixed shell combinations: every segment is readonly or a known local
301
+ * validation command, joined only by && or ; (not pipes that mix side effects).
302
+ * Example: `bun test tests/a.test.ts && bun run check:type`
303
+ */
304
+ export function isSafeFixedShellCombination(command: string): boolean {
305
+ const normalized = command.trim();
306
+ if (!normalized) return false;
307
+ if (shellCommandHasUnsafeConstructs(normalized).unsafe) return false;
308
+ if (hasRepositoryOutputRedirection(normalized)) return false;
309
+ // Reject bare pipes that feed dynamic interpreters
310
+ if (/\|\s*(?:sh|bash|zsh|python|node|perl|ruby)\b/i.test(normalized)) return false;
311
+ const segments = shellSegments(normalized);
312
+ if (segments.length === 0) return false;
313
+ return segments.every((segment) => isReadOnlySegment(segment) || isReplaySafeValidationSegment(segment));
314
+ }
315
+
316
+ /**
317
+ * When a shell string is a safe fixed combination, classify at the highest risk
318
+ * among segments (readonly if all readonly, else workspace_write for validation).
319
+ */
320
+ export function classifySafeShellCombination(command: string): RepositoryCommandClassification | undefined {
321
+ if (!isSafeFixedShellCombination(command)) return undefined;
322
+ const segments = shellSegments(command);
323
+ const allReadonly = segments.every(isReadOnlySegment);
324
+ if (allReadonly) {
325
+ return {
326
+ risk: 'readonly',
327
+ confirmation: 'none',
328
+ reasons: ['safe fixed shell combination of repository-local read operations'],
329
+ };
330
+ }
331
+ return {
332
+ risk: 'workspace_write',
333
+ confirmation: 'none',
334
+ reasons: ['safe fixed shell combination of local validation commands'],
335
+ };
336
+ }
337
+
338
+ function escapeRegex(value: string): string {
339
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
340
+ }
341
+
342
+ export function classifyRepositoryCommand(
343
+ input: string | readonly string[] | CanonicalRepositoryCommand,
344
+ defaultBranch?: string,
345
+ ): RepositoryCommandClassification {
346
+ const canonical = 'kind' in Object(input) && (input as CanonicalRepositoryCommand).kind
347
+ ? input as CanonicalRepositoryCommand
348
+ : normalizeRepositoryCommand(input);
349
+ if (canonical.kind === 'argv') return classifyArgvCommand(canonical, defaultBranch);
350
+ return classifyShellCommand(canonical.shellCommand!, defaultBranch);
351
+ }
352
+
353
+ export function classifyRepositoryCommandReplay(
354
+ input: string | readonly string[] | CanonicalRepositoryCommand,
355
+ defaultBranch?: string,
356
+ ): RepositoryCommandReplayClassification {
357
+ const canonical = 'kind' in Object(input) && (input as CanonicalRepositoryCommand).kind
358
+ ? input as CanonicalRepositoryCommand
359
+ : normalizeRepositoryCommand(input);
360
+ const classification = classifyRepositoryCommand(canonical, defaultBranch);
361
+ if (classification.risk === 'readonly') {
362
+ return {
363
+ replayable: true,
364
+ idempotent: true,
365
+ retryPolicy: 'safe_retry',
366
+ reasons: ['recognized read-only repository command'],
367
+ };
368
+ }
369
+ if (classification.risk === 'remote_write' || classification.risk === 'destructive') {
370
+ return {
371
+ replayable: false,
372
+ idempotent: false,
373
+ retryPolicy: 'none',
374
+ reasons: ['remote or destructive commands require outcome review after execution starts'],
375
+ };
376
+ }
377
+ const shellParts = canonical.kind === 'shell' ? shellSegments(canonical.shellCommand!) : [];
378
+ const validationOnly = canonical.kind === 'argv'
379
+ ? isReplaySafeValidationWords([canonical.executable!, ...(canonical.args ?? [])])
380
+ : !hasRepositoryOutputRedirection(canonical.shellCommand!)
381
+ && !shellParts.some(isSedInPlaceSegment)
382
+ && shellParts.length > 0
383
+ && shellParts.every((segment) => isReadOnlySegment(segment) || isReplaySafeValidationSegment(segment));
384
+ if (validationOnly) {
385
+ return {
386
+ replayable: true,
387
+ idempotent: true,
388
+ retryPolicy: 'idempotent_request',
389
+ reasons: ['recognized local validation command with repeatable repository effects'],
390
+ };
391
+ }
392
+ return {
393
+ replayable: false,
394
+ idempotent: false,
395
+ retryPolicy: 'none',
396
+ reasons: ['command outcome must be reviewed before replay'],
397
+ };
398
+ }
399
+
400
+ export function fixedShellWrapperCommand(argv: readonly string[]): string | undefined {
401
+ const program = argv[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
402
+ if (!program || !['sh', 'bash', 'zsh'].includes(program)) return undefined;
403
+ for (let index = 1; index < argv.length; index += 1) {
404
+ const option = argv[index] ?? '';
405
+ if (option === '--') return undefined;
406
+ if (option === '-c' || /^-[^-]*c[^-]*$/.test(option)) {
407
+ const script = argv[index + 1];
408
+ return typeof script === 'string' && script.trim() ? script : undefined;
409
+ }
410
+ }
411
+ return undefined;
412
+ }
413
+
414
+ function classifyArgvCommand(
415
+ command: CanonicalRepositoryCommand,
416
+ defaultBranch?: string,
417
+ ): RepositoryCommandClassification {
418
+ const argv = [command.executable!, ...(command.args ?? [])];
419
+ const program = argv[0]!.split(/[\\/]/).at(-1)!.toLowerCase();
420
+ const subcommand = argv[1]?.toLowerCase();
421
+ const reasons: string[] = [];
422
+ const has = (value: string) => argv.includes(value);
423
+ const forcePush = program === 'git' && subcommand === 'push' && (has('--force') || has('--force-with-lease') || has('-f') || argv.some((arg) => arg.startsWith('+')));
424
+ const hardReset = program === 'git' && subcommand === 'reset' && has('--hard');
425
+ const cleanAll = program === 'git' && subcommand === 'clean' && (has('-fdx') || argv.some((arg) => arg.startsWith('-') && arg.includes('x') && arg.includes('f')));
426
+ const deleteRemote = program === 'git' && subcommand === 'push' && (has('--delete') || argv.some((arg) => arg.startsWith(':')));
427
+ const deletesDefault = Boolean(defaultBranch && deleteRemote && argv.includes(defaultBranch));
428
+ if (forcePush) reasons.push('force push rewrites shared remote history');
429
+ if (hardReset) reasons.push('hard reset can discard local changes and commits');
430
+ if (cleanAll) reasons.push('git clean can permanently remove untracked or ignored files');
431
+ if (deletesDefault) reasons.push(`remote deletion targets the default branch ${defaultBranch}`);
432
+ if (reasons.length > 0) return { risk: 'destructive', confirmation: 'strong_confirmation', reasons };
433
+ if (program === 'git' && ((subcommand === 'push' && deleteRemote) || (['branch', 'tag'].includes(subcommand ?? '') && (has('--delete') || has('-d') || has('-D'))))) {
434
+ return { risk: 'destructive', confirmation: 'authorization', reasons: ['deletes a remote branch or tag'] };
435
+ }
436
+ if (program === 'rm' || program === 'rmdir' || program === 'unlink' || (program === 'find' && has('-delete'))) {
437
+ return { risk: 'destructive', confirmation: 'authorization', reasons: ['deletes repository files'] };
438
+ }
439
+ if (program === 'git' && subcommand === 'push') return { risk: 'remote_write', confirmation: 'authorization', reasons: ['writes Git refs to a remote'] };
440
+ if (program === 'git' && isReadOnlyGitCommand(argv)) {
441
+ return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command is a recognized repository-local read operation'] };
442
+ }
443
+ // Explicit shell wrappers are common in generated diagnostics. Re-classify
444
+ // the fixed inner command instead of treating `sh -c` / `bash -lc` wrappers
445
+ // as workspace mutations. Unsafe shell constructs are still rejected by the
446
+ // normal shell classifier.
447
+ const wrappedShellCommand = fixedShellWrapperCommand(argv);
448
+ if (wrappedShellCommand !== undefined) {
449
+ return classifyShellCommand(wrappedShellCommand, defaultBranch);
450
+ }
451
+ if (program === 'find' && !argv.some((word) => ['-delete', '-exec', '-execdir', '-ok', '-okdir'].includes(word))) {
452
+ return { risk: 'readonly', confirmation: 'none', reasons: ['find is read-only without mutation or exec actions'] };
453
+ }
454
+ if (program === 'sed' && !argv.slice(1).some((word) => word === '--in-place' || word.startsWith('--in-place=') || /^-[^-]*i/.test(word))) {
455
+ return { risk: 'readonly', confirmation: 'none', reasons: ['sed is read-only without in-place editing'] };
456
+ }
457
+ if (program === 'launchctl' && ['print', 'print-disabled', 'list', 'managerpid', 'manageruid'].includes(subcommand ?? '')) {
458
+ return { risk: 'readonly', confirmation: 'none', reasons: ['launchctl observation does not mutate repository or host service state'] };
459
+ }
460
+ if (program === 'plutil' && argv.slice(1).some((word) => word === '-p' || word === '-lint')) {
461
+ return { risk: 'readonly', confirmation: 'none', reasons: ['plutil print/lint is read-only'] };
462
+ }
463
+ if (program === 'log' && ['show', 'stream', 'stats', 'config'].includes(subcommand ?? '') && subcommand !== 'config') {
464
+ return { risk: 'readonly', confirmation: 'none', reasons: ['system log observation is read-only'] };
465
+ }
466
+ // Explicit readonly GitHub CLI observations (must not be treated as workspace write).
467
+ if (program === 'gh') {
468
+ const group = subcommand ?? '';
469
+ const action = (argv[2] ?? '').toLowerCase();
470
+ const readonlyGh =
471
+ (group === 'repo' && action === 'view')
472
+ || (group === 'pr' && ['list', 'view', 'status', 'checks', 'diff'].includes(action))
473
+ || (group === 'issue' && ['list', 'view'].includes(action))
474
+ || (group === 'run' && ['list', 'view', 'watch'].includes(action))
475
+ || (group === 'release' && ['list', 'view', 'download'].includes(action));
476
+ if (readonlyGh) {
477
+ return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command is a recognized GitHub read operation'] };
478
+ }
479
+ }
480
+ if (program === 'git' && ['add', 'commit', 'pull', 'fetch', 'merge', 'rebase', 'checkout', 'switch', 'cherry-pick', 'revert', 'stash', 'mv', 'restore', 'apply', 'am', 'bisect'].includes(subcommand ?? '')) {
481
+ return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['changes the checkout, local refs, index, or working tree'] };
482
+ }
483
+ if (['touch', 'mkdir', 'cp', 'mv', 'install', 'tee', 'truncate', 'patch'].includes(program)
484
+ || (['npm', 'bun', 'pnpm', 'yarn'].includes(program) && ['install', 'add', 'remove', 'update', 'run'].includes(subcommand ?? ''))) {
485
+ return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['writes repository files'] };
486
+ }
487
+ // Lightweight project script info queries stay readonly when they only request help/version.
488
+ if (['bun', 'node', 'npm', 'pnpm', 'yarn', 'python', 'python3', 'cargo', 'go', 'swift'].includes(program)
489
+ && argv.slice(1).some((word) => word === '--help' || word === '-h' || word === '--version' || word === '-V' || word === 'version' || word === 'help')) {
490
+ const mutating = argv.slice(1).some((word) => ['install', 'add', 'remove', 'update', 'publish', 'run', 'test', 'build'].includes(word.toLowerCase()));
491
+ if (!mutating) {
492
+ return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command only requests help or version information'] };
493
+ }
494
+ }
495
+ if (program === 'git' && READ_ONLY_GIT_SUBCOMMANDS.has(subcommand ?? '')) {
496
+ return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command is a recognized repository-local read operation'] };
497
+ }
498
+ if (READ_ONLY_PROGRAMS.has(program)) return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command is a recognized repository-local read operation'] };
499
+ return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['unrecognized argv behavior is conservatively treated as a workspace write'] };
500
+ }
501
+
502
+ function classifyShellCommand(
503
+ command: string,
504
+ defaultBranch?: string,
505
+ ): RepositoryCommandClassification {
506
+ const normalized = command.trim();
507
+ const reasons: string[] = [];
508
+
509
+ // Reject unsafe constructs early (background, eval, download|sh, substitution).
510
+ const unsafe = shellCommandHasUnsafeConstructs(normalized);
511
+ if (unsafe.unsafe) {
512
+ return {
513
+ risk: 'destructive',
514
+ confirmation: 'strong_confirmation',
515
+ reasons: unsafe.reasons,
516
+ };
517
+ }
518
+
519
+ // Allow safe fixed combinations (e.g. bun test path && bun run check:type)
520
+ // without forcing Durable merely because the command is a shell string with &&.
521
+ const safeCombo = classifySafeShellCombination(normalized);
522
+ if (safeCombo) return safeCombo;
523
+
524
+ const forcePush = /\bgit\s+push\b[^\n]*(?:--force(?:-with-lease)?\b|-f(?:\s|$)|\+[^\s:]+:[^\s]+)/i.test(normalized);
525
+ const hardReset = /\bgit\s+reset\b[^\n]*--hard\b/i.test(normalized);
526
+ const cleanAll = /\bgit\s+clean\b[^\n]*(?:-[a-z]*x|--force)/i.test(normalized);
527
+ const deleteRemote = /\bgit\s+push\b[^\n]*(?:--delete\b|\s:[^\s]+)/i.test(normalized);
528
+ const deletesDefault = Boolean(defaultBranch && deleteRemote
529
+ && new RegExp(`(?:^|[\\s/:])${escapeRegex(defaultBranch)}(?:\\s|$)`, 'i').test(normalized));
530
+ const broadDelete = /(?:^|[;&|]\s*)rm\s+(?:-[^\s]*r[^\s]*f|-[^\s]*f[^\s]*r)\s+(?:\.|\*|[^\s]*\/\*)(?:\s|$)/i.test(normalized);
531
+
532
+ if (forcePush) reasons.push('force push rewrites shared remote history');
533
+ if (hardReset) reasons.push('hard reset can discard local changes and commits');
534
+ if (cleanAll) reasons.push('git clean can permanently remove untracked or ignored files');
535
+ if (deletesDefault) reasons.push(`remote deletion targets the default branch ${defaultBranch}`);
536
+ if (broadDelete) reasons.push('broad recursive file deletion was requested');
537
+ if (reasons.length > 0) return { risk: 'destructive', confirmation: 'strong_confirmation', reasons };
538
+
539
+ const destructivePatterns: Array<[RegExp, string]> = [
540
+ [/\bgit\s+push\b[^\n]*(?:--delete\b|\s:[^\s]+)/i, 'deletes a remote branch or tag'],
541
+ [/\bgit\s+(?:branch|tag)\b[^\n]*(?:\s-[dD]\b|\s--delete\b)/i, 'deletes a local branch or tag'],
542
+ [/\bgit\s+(?:checkout|restore)\b[^\n]*(?:--force\b|-f\b|--worktree\b|--source\b)/i, 'may overwrite working-tree content'],
543
+ [/(?:^|[;&|]\s*)(?:rm|rmdir|unlink)(?:\s|$)/i, 'deletes repository files'],
544
+ [/\bfind\b[^\n]*-delete\b/i, 'deletes repository files through find'],
545
+ ];
546
+ for (const [pattern, reason] of destructivePatterns) if (pattern.test(normalized)) reasons.push(reason);
547
+ if (reasons.length > 0) return { risk: 'destructive', confirmation: 'authorization', reasons };
548
+
549
+ const remoteWritePatterns: Array<[RegExp, string]> = [
550
+ [/\bgit\s+push\b/i, 'writes Git refs to a remote'],
551
+ [/\bgh\s+(?:pr\s+(?:create|edit|close|reopen|merge|comment|review)|issue\s+(?:create|edit|close|reopen|comment)|release\s+(?:create|edit|delete|upload)|repo\s+(?:create|edit|archive|delete))\b/i, 'writes GitHub remote state'],
552
+ [/\b(?:npm|bun)\s+publish\b/i, 'publishes a package'],
553
+ ];
554
+ for (const [pattern, reason] of remoteWritePatterns) if (pattern.test(normalized)) reasons.push(reason);
555
+ if (reasons.length > 0) return { risk: 'remote_write', confirmation: 'authorization', reasons };
556
+
557
+ if (hasRepositoryOutputRedirection(normalized)) reasons.push('redirects output into a repository file');
558
+ if (shellSegments(normalized).some(isSedInPlaceSegment)) reasons.push('edits repository files in place');
559
+ if (reasons.length > 0) return { risk: 'workspace_write', confirmation: 'authorization', reasons };
560
+
561
+ // Safe fixed validation combinations are already handled above. Remaining shell
562
+ // package runners that are validation-only (test/check/lint/typecheck) are
563
+ // workspace_write with no confirmation — they may write caches/snapshots but
564
+ // do not require Durable solely because they use `bun run` / `npm run`.
565
+ const segmentsRaw = shellSegments(normalized);
566
+ if (segmentsRaw.length > 0 && segmentsRaw.every((segment) => isReadOnlySegment(segment) || isReplaySafeValidationSegment(segment))) {
567
+ const allReadonly = segmentsRaw.every(isReadOnlySegment);
568
+ return {
569
+ risk: allReadonly ? 'readonly' : 'workspace_write',
570
+ confirmation: allReadonly ? 'none' : 'none',
571
+ reasons: allReadonly
572
+ ? ['all command segments are recognized as repository-local read operations']
573
+ : ['shell segments are recognized local validation commands'],
574
+ };
575
+ }
576
+
577
+ const workspaceWritePatterns: Array<[RegExp, string]> = [
578
+ [/\bgit\s+(?:add|commit|pull|fetch|merge|rebase|checkout|switch|cherry-pick|revert|stash|mv|rm|restore|apply|am|bisect)(?:\s|$)/i, 'changes the checkout, local refs, index, or working tree'],
579
+ [/(?:^|[;&|]\s*)(?:touch|mkdir|cp|mv|install|tee|truncate|patch)(?:\s|$)/i, 'writes repository files'],
580
+ // install/add/remove/update mutate deps; bare `run` of unknown scripts stays conservative below.
581
+ [/(?:^|[;&|]\s*)(?:npm|bun|pnpm|yarn)\s+(?:install|add|remove|update)(?:\s|$)/i, 'may modify dependencies, generated files, or the working tree'],
582
+ [/(?:^|[;&|]\s*)(?:npm|bun|pnpm|yarn)\s+run\s+(?!test|check|lint|typecheck|format:check|tsc)[a-z0-9:_-]+/i, 'may modify dependencies, generated files, or the working tree'],
583
+ ];
584
+ for (const [pattern, reason] of workspaceWritePatterns) if (pattern.test(normalized)) reasons.push(reason);
585
+ if (reasons.length > 0) return { risk: 'workspace_write', confirmation: 'authorization', reasons };
586
+
587
+ const segments = shellSegments(normalized.toLowerCase());
588
+ if (segments.length > 0 && segments.every(isReadOnlySegment)) {
589
+ return {
590
+ risk: 'readonly',
591
+ confirmation: 'none',
592
+ reasons: ['all command segments are recognized as repository-local read operations'],
593
+ };
594
+ }
595
+ return {
596
+ risk: 'workspace_write',
597
+ confirmation: 'authorization',
598
+ reasons: ['unrecognized shell behavior is conservatively treated as a workspace write'],
599
+ };
600
+ }