@moretea-labs/forge 1.5.1 → 1.7.0

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 (434) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +46 -0
  3. package/CLAUDE.md +2 -0
  4. package/DESIGN.md +7 -2
  5. package/README.md +4 -4
  6. package/README.zh-CN.md +2 -2
  7. package/SKILL.md +2 -2
  8. package/THIRD_PARTY_NOTICES.md +1 -1
  9. package/agents/openai.yaml +1 -1
  10. package/assets/hooks/hook-input.sh +11 -8
  11. package/assets/hooks/lib/session-state.sh +10 -7
  12. package/assets/hooks/lib/workflow-state.sh +13 -177
  13. package/assets/hooks/post-tool-observer.sh +8 -2
  14. package/assets/hooks/pre-edit-guard.sh +8 -39
  15. package/assets/hooks/prompt-guard.sh +7 -83
  16. package/assets/hooks/session-start-context.sh +56 -1
  17. package/assets/partials/05-workflow.partial.md +1 -1
  18. package/assets/partials-agents/03-orchestration.partial.md +1 -1
  19. package/assets/plugin-registry.v1.json +54 -3
  20. package/assets/reference-configs/document-generation.md +1 -1
  21. package/assets/reference-configs/harness-overview.md +1 -1
  22. package/assets/reference-configs/hook-operations.md +1 -1
  23. package/assets/reference-configs/sprint-contracts.md +3 -3
  24. package/assets/skill-version.json +2 -2
  25. package/assets/templates/contract.template.md +2 -7
  26. package/assets/templates/helpers/capture-plan.sh +2 -2
  27. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  28. package/assets/templates/helpers/contract-worktree.sh +1 -21
  29. package/assets/templates/helpers/ensure-task-workflow.sh +13 -38
  30. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  31. package/assets/templates/helpers/new-plan.sh +1 -1
  32. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  33. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  34. package/assets/templates/helpers/sprint-backlog.sh +6 -6
  35. package/assets/templates/helpers/verify-contract.sh +1 -111
  36. package/assets/templates/helpers/verify-sprint.sh +3 -180
  37. package/assets/templates/plan.template.md +1 -1
  38. package/assets/templates/review.template.md +9 -34
  39. package/assets/workflow-contract.v1.json +10 -19
  40. package/docs/README.md +10 -10
  41. package/docs/architecture/CURRENT.md +170 -0
  42. package/docs/architecture/EVOLUTION.md +42 -0
  43. package/docs/architecture/current/README.md +4 -156
  44. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  45. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  46. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  47. package/docs/architecture/history/README.md +7 -0
  48. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  49. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  50. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  51. package/docs/architecture/history.md +3 -34
  52. package/docs/architecture/index.md +15 -98
  53. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  54. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  55. package/docs/architecture/versions/1.6.md +38 -0
  56. package/docs/architecture/versions/1.7.md +41 -0
  57. package/docs/forge-chatgpt-browser-engine.md +2 -2
  58. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  59. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  60. package/docs/forge-github-issue-launcher.md +1 -1
  61. package/docs/forge-runtime-self-healing-loop.md +1 -1
  62. package/docs/operations/controller-browser-plugin.md +38 -22
  63. package/docs/operations/controller-performance-and-502.md +124 -0
  64. package/docs/operations/controller-reliability-runbook.md +1 -1
  65. package/docs/operations/features.md +3 -3
  66. package/docs/operations/github-repository.md +1 -1
  67. package/docs/operations/homebrew.md +2 -2
  68. package/docs/operations/mcp-tool-exposure.md +5 -3
  69. package/docs/tutorials/01-install-and-start.md +1 -1
  70. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  71. package/docs/wiki/Architecture.md +6 -6
  72. package/docs/wiki/Implementation.md +2 -2
  73. package/docs/wiki/Installation.md +1 -1
  74. package/docs/wiki/Integrations.md +2 -2
  75. package/docs/wiki/Quick-Start.md +1 -1
  76. package/docs/wiki/Work-Lifecycle.md +1 -1
  77. package/package.json +29 -10
  78. package/scripts/activate-source-baseline.ts +17 -13
  79. package/scripts/benchmark-background-check-overlap.ts +228 -0
  80. package/scripts/benchmark-mcp-host.sh +117 -0
  81. package/scripts/benchmark-mcp-transport.ts +170 -0
  82. package/scripts/benchmark-quality-harness.ts +146 -0
  83. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  84. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  85. package/scripts/benchmark-typescript-navigation.ts +186 -0
  86. package/scripts/benchmark-work-efficiency.ts +334 -0
  87. package/scripts/capture-plan.sh +3 -3
  88. package/scripts/check-agent-tooling.sh +8 -35
  89. package/scripts/check-architecture-sync.sh +17 -86
  90. package/scripts/check-mcp-compatibility.ts +14 -0
  91. package/scripts/check-public-docs.sh +14 -1
  92. package/scripts/check-runtime-architecture.mjs +107 -64
  93. package/scripts/check-stable-baseline.ts +92 -0
  94. package/scripts/check-task-workflow.sh +4 -4
  95. package/scripts/contract-worktree.sh +1 -21
  96. package/scripts/ensure-task-workflow.sh +22 -55
  97. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  98. package/scripts/install-standalone-recovery.ts +24 -0
  99. package/scripts/lib/project-init-lib.sh +15 -44
  100. package/scripts/migrate-chatgpt-automation-schedules.ts +64 -0
  101. package/scripts/migrate-project-template.sh +23 -1179
  102. package/scripts/new-plan.sh +1 -1
  103. package/scripts/plan-to-todo.sh +11 -36
  104. package/scripts/run-governed-gate.ts +2 -1
  105. package/scripts/ship-worktrees.sh +2 -29
  106. package/scripts/smoke-ios-physical-device.ts +4 -2
  107. package/scripts/smoke-runtime-recovery.ts +1 -35
  108. package/scripts/smoke-schedule-engine.ts +1 -20
  109. package/scripts/sprint-backlog.sh +1 -1
  110. package/scripts/verify-contract.sh +1 -111
  111. package/scripts/verify-forge-runtime.sh +0 -1
  112. package/scripts/verify-sprint.sh +3 -180
  113. package/scripts/workflow-contract.ts +1 -5
  114. package/src/cli/commands/chatgpt.ts +31 -2
  115. package/src/cli/commands/init-hook.ts +3 -3
  116. package/src/cli/commands/mcp.ts +9 -5
  117. package/src/cli/commands/plugin.ts +37 -10
  118. package/src/cli/commands/recovery.ts +25 -3
  119. package/src/cli/commands/runtime.ts +55 -3
  120. package/src/cli/commands/security.ts +12 -1
  121. package/src/cli/commands/setup-profile.ts +31 -21
  122. package/src/cli/controller/check-runner.ts +106 -3
  123. package/src/cli/controller/composite-result.ts +1 -1
  124. package/src/cli/controller/context/focus.ts +51 -0
  125. package/src/cli/controller/context/instruction-context.ts +114 -0
  126. package/src/cli/controller/context/known-paths.ts +76 -0
  127. package/src/cli/controller/context/query-planning.ts +110 -0
  128. package/src/cli/controller/context/rule-resolution.ts +532 -0
  129. package/src/cli/controller/context/source-materializer.ts +278 -0
  130. package/src/cli/controller/context/structural.ts +16 -0
  131. package/src/cli/controller/context/types.ts +286 -0
  132. package/src/cli/controller/context-pack.ts +898 -430
  133. package/src/cli/controller/launch-agents.ts +77 -2
  134. package/src/cli/controller/operational-plan.ts +2 -2
  135. package/src/cli/controller/work-mode.ts +6 -4
  136. package/src/cli/editing/edit-session.ts +60 -7
  137. package/src/cli/github/github.ts +133 -0
  138. package/src/cli/hook/prompt-guard-decision.ts +17 -18
  139. package/src/cli/hook/prompt-intents.ts +1 -1
  140. package/src/cli/installer/managed-entries.ts +15 -1
  141. package/src/cli/local-bridge/console-automations.ts +225 -67
  142. package/src/cli/local-bridge/console-view-models.ts +3 -35
  143. package/src/cli/local-bridge/facade-api.ts +2 -217
  144. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  145. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +153 -3
  146. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  147. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +183 -3
  148. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +1 -1
  149. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +4 -3
  150. package/src/cli/local-bridge/frontend/src/lib/api.ts +18 -11
  151. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  152. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +1 -1
  153. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +4 -3
  154. package/src/cli/local-bridge/frontend/src/styles.css +27 -11
  155. package/src/cli/local-bridge/frontend/src/types.ts +8 -7
  156. package/src/cli/local-bridge/job-store.ts +1 -490
  157. package/src/cli/local-bridge/server.ts +29 -532
  158. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  159. package/src/cli/local-bridge/ui-dist/app.js +5101 -4967
  160. package/src/cli/mcp/auth.ts +5 -5
  161. package/src/cli/mcp/instructions.ts +3 -2
  162. package/src/cli/mcp/legacy-tool-service.ts +0 -189
  163. package/src/cli/mcp/multi-repository.ts +16 -5
  164. package/src/cli/mcp/oauth.ts +175 -26
  165. package/src/cli/mcp/paths.ts +8 -2
  166. package/src/cli/mcp/repository-tools.ts +356 -101
  167. package/src/cli/mcp/server.ts +625 -54
  168. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  169. package/src/cli/mcp/toolset-selection.ts +1 -1
  170. package/src/cli/mcp/toolset.ts +42 -5
  171. package/src/cli/mcp/transports/http.ts +125 -15
  172. package/src/cli/mcp/transports/session-registry.ts +67 -5
  173. package/src/cli/mcp/types.ts +3 -3
  174. package/src/cli/repositories/command-classifier.ts +209 -14
  175. package/src/cli/repositories/command-executor.ts +55 -521
  176. package/src/cli/repositories/command-process.ts +108 -0
  177. package/src/cli/repositories/command-scope.ts +99 -41
  178. package/src/cli/repositories/controller-home.ts +7 -8
  179. package/src/cli/repositories/git-command-executor.ts +2 -0
  180. package/src/cli/repositories/locks.ts +53 -16
  181. package/src/cli/repositories/repository-snapshot.ts +121 -0
  182. package/src/cli/repositories/safe-patch.ts +6 -4
  183. package/src/cli/repositories/selected-path-actions.ts +17 -9
  184. package/src/cli/repositories/structured-git.ts +110 -10
  185. package/src/cli/repository/inspector.ts +565 -62
  186. package/src/cli/repository/session-cache.ts +58 -17
  187. package/src/cli/v81-entry.ts +1 -4
  188. package/src/effects/fs-transaction.ts +85 -17
  189. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  190. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  191. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  192. package/src/runtime/context/lsp-client.ts +283 -0
  193. package/src/runtime/context/semantic-navigation.ts +275 -0
  194. package/src/runtime/context/swift-navigation.ts +565 -0
  195. package/src/runtime/context/typescript-navigation.ts +226 -0
  196. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  197. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +196 -2
  198. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  199. package/src/runtime/control-plane/execution/execution-identity.ts +65 -14
  200. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  201. package/src/runtime/control-plane/execution/validation.ts +15 -2
  202. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  203. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  204. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  205. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  206. package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
  207. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +175 -8
  208. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -21
  209. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +87 -9
  210. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  211. package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
  212. package/src/runtime/control-plane/facade/controller-session-store.ts +144 -14
  213. package/src/runtime/control-plane/facade/goal-workloop-access.ts +9 -2
  214. package/src/runtime/control-plane/facade/goal-workloop.ts +885 -105
  215. package/src/runtime/control-plane/facade/index.ts +1 -0
  216. package/src/runtime/control-plane/facade/plan-contract-store.ts +211 -26
  217. package/src/runtime/control-plane/facade/requirement-board.ts +24 -8
  218. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  219. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  220. package/src/runtime/control-plane/facade/types.ts +55 -11
  221. package/src/runtime/control-plane/facade/work-contract-store.ts +204 -73
  222. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  223. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  224. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  225. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  226. package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
  227. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  228. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  229. package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
  230. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  231. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  232. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  233. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  234. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  235. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  236. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  237. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  238. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  239. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  240. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
  241. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +642 -51
  242. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
  243. package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
  244. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  245. package/src/runtime/control-plane/persistence/requirement-store.ts +15 -11
  246. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  247. package/src/runtime/control-plane/release-retention.ts +62 -2
  248. package/src/runtime/control-plane/routing/route-policy.ts +7 -16
  249. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  250. package/src/runtime/diagnostics/mcp-timing.ts +19 -0
  251. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  252. package/src/runtime/diagnostics/performance.ts +24 -1
  253. package/src/runtime/evidence/event-ledger.ts +1 -1
  254. package/src/runtime/execution/jobs/store.ts +58 -4
  255. package/src/runtime/execution/jobs/types.ts +1 -1
  256. package/src/runtime/execution/managed-workspace.ts +203 -1
  257. package/src/runtime/execution/process-runtime/check-facade.ts +52 -14
  258. package/src/runtime/execution/process-runtime/check-result.ts +63 -2
  259. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  260. package/src/runtime/execution/process-runtime/command-facade.ts +346 -40
  261. package/src/runtime/execution/process-runtime/gc.ts +98 -12
  262. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
  263. package/src/runtime/execution/process-runtime/persisted-check.ts +57 -6
  264. package/src/runtime/execution/process-runtime/resource-claims.ts +97 -8
  265. package/src/runtime/execution/process-runtime/runtime.ts +59 -4
  266. package/src/runtime/execution/process-runtime/store.ts +7 -0
  267. package/src/runtime/execution/process-runtime/types.ts +2 -0
  268. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  269. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  270. package/src/runtime/execution/workers/executor.ts +0 -48
  271. package/src/runtime/gateway/mcp/execution-tools.ts +1219 -126
  272. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  273. package/src/runtime/gateway/mcp/router.ts +185 -83
  274. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
  275. package/src/runtime/gateway/mcp/runtime-tools.ts +2555 -1616
  276. package/src/runtime/model-clients/deepseek-adapter.ts +0 -32
  277. package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
  278. package/src/runtime/plugins/browser-adapter.ts +2925 -318
  279. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  280. package/src/runtime/plugins/browser-handoff-host.ts +6 -31
  281. package/src/runtime/plugins/browser-handoff.ts +92 -5
  282. package/src/runtime/plugins/browser-macos-bridge.ts +586 -45
  283. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  284. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  285. package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
  286. package/src/runtime/plugins/browser-runtime.ts +183 -0
  287. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  288. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  289. package/src/runtime/plugins/desktop-operator-registration.ts +15 -12
  290. package/src/runtime/plugins/external-adapter.ts +324 -3
  291. package/src/runtime/plugins/external-registration.ts +84 -5
  292. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  293. package/src/runtime/plugins/first-party-registry.ts +4 -2
  294. package/src/runtime/plugins/github-adapter.ts +125 -0
  295. package/src/runtime/plugins/gmail-adapter.ts +28 -2
  296. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  297. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  298. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  299. package/src/runtime/plugins/ios-adapter.ts +106 -16
  300. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  301. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  302. package/src/runtime/plugins/lightweight-action.ts +153 -0
  303. package/src/runtime/plugins/local-system-adapter.ts +125 -8
  304. package/src/runtime/plugins/macos-capability-broker.ts +55 -9
  305. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  306. package/src/runtime/plugins/plugin-management-adapter.ts +181 -0
  307. package/src/runtime/plugins/resend-adapter.ts +1 -1
  308. package/src/runtime/plugins/store.ts +366 -24
  309. package/src/runtime/plugins/types.ts +39 -2
  310. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  311. package/src/runtime/projections/git-status-sampler.ts +16 -16
  312. package/src/runtime/projections/materialized-view.ts +28 -10
  313. package/src/runtime/recovery/actions.ts +0 -10
  314. package/src/runtime/recovery/classifier.ts +0 -9
  315. package/src/runtime/recovery/maintenance-executor.ts +415 -18
  316. package/src/runtime/recovery/probe.ts +0 -1
  317. package/src/runtime/recovery/types.ts +0 -1
  318. package/src/runtime/root/mcp-transport.ts +180 -10
  319. package/src/runtime/root/package-connector-service.ts +186 -8
  320. package/src/runtime/root/package-runtime-release.ts +143 -17
  321. package/src/runtime/root/package-runtime-service.ts +430 -22
  322. package/src/runtime/root/release-manifest.ts +7 -2
  323. package/src/runtime/root/release-materialize.ts +162 -19
  324. package/src/runtime/root/release-store.ts +48 -11
  325. package/src/runtime/root/runtime.ts +23 -5
  326. package/src/runtime/root/service.ts +100 -27
  327. package/src/runtime/root/types.ts +2 -0
  328. package/src/runtime/safe-tooling/index.ts +0 -1
  329. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  330. package/src/runtime/safe-tooling/types.ts +0 -30
  331. package/src/runtime/shared/trusted-executable.ts +62 -0
  332. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  333. package/src/runtime/standalone-recovery/core.ts +702 -94
  334. package/src/runtime/standalone-recovery/entry.ts +99 -23
  335. package/src/runtime/standalone-recovery/installer.ts +19 -3
  336. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  337. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  338. package/src/runtime/workflow/schedules/browser-probe.ts +258 -0
  339. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +40 -0
  340. package/src/runtime/workflow/schedules/engine.ts +509 -80
  341. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  342. package/src/runtime/workflow/schedules/settlement.ts +48 -4
  343. package/src/runtime/workflow/schedules/store.ts +131 -10
  344. package/src/runtime/workflow/schedules/types.ts +6 -3
  345. package/src/runtime/workflow/schedules/work-continuation.ts +120 -34
  346. package/src/testing/test-governance.ts +8 -40
  347. package/assets/reference-configs/heartbeat-triage.md +0 -57
  348. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  349. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  350. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  351. package/bin/forge-desktop-helper.mjs +0 -204
  352. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  353. package/docs/architecture/current/architecture-invariants.md +0 -331
  354. package/docs/architecture/current/automation-and-schedule-engine.md +0 -453
  355. package/docs/architecture/current/codegraph-context-provider.md +0 -226
  356. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  357. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  358. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -354
  359. package/docs/architecture/current/entity-model.md +0 -592
  360. package/docs/architecture/current/external-plugin-governance.md +0 -396
  361. package/docs/architecture/current/failure-recovery.md +0 -447
  362. package/docs/architecture/current/governance.md +0 -213
  363. package/docs/architecture/current/human-interaction-plane.md +0 -87
  364. package/docs/architecture/current/implementation-status.md +0 -128
  365. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  366. package/docs/architecture/current/legacy-governance.md +0 -58
  367. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  368. package/docs/architecture/current/migration-roadmap.md +0 -105
  369. package/docs/architecture/current/multi-repository-execution.md +0 -371
  370. package/docs/architecture/current/operations-runbook.md +0 -45
  371. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  372. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  373. package/docs/architecture/current/repository-access-modes.md +0 -102
  374. package/docs/architecture/current/route-policy.md +0 -15
  375. package/docs/architecture/current/route-session-concurrency.md +0 -85
  376. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  377. package/docs/architecture/current/runtime-directory-map.md +0 -49
  378. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  379. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  380. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  381. package/docs/architecture/current/system-overview.md +0 -144
  382. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  383. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  384. package/docs/architecture/current/thin-harness-v1.md +0 -311
  385. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  386. package/docs/forge-autonomous-goal-loop.md +0 -9
  387. package/docs/forge-provider-configuration.md +0 -7
  388. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -83
  389. package/docs/operations/controller-desktop-plugin.md +0 -112
  390. package/docs/operations/gmail-assistant-routines.md +0 -186
  391. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  392. package/docs/operations/provider-configuration.md +0 -31
  393. package/scripts/harness-trace-grade.sh +0 -150
  394. package/scripts/heartbeat-triage.sh +0 -361
  395. package/scripts/maintenance-triage.sh +0 -167
  396. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  397. package/src/cli/repositories/goal-registry.ts +0 -239
  398. package/src/runtime/assistant/action-proposals.ts +0 -279
  399. package/src/runtime/assistant/intent.ts +0 -395
  400. package/src/runtime/assistant/model-provider.ts +0 -460
  401. package/src/runtime/assistant/openapi.ts +0 -223
  402. package/src/runtime/assistant/policy.ts +0 -89
  403. package/src/runtime/assistant/readiness.ts +0 -258
  404. package/src/runtime/assistant/routine-runtime.ts +0 -477
  405. package/src/runtime/assistant/schedule-binding.ts +0 -171
  406. package/src/runtime/assistant/standing-grants.ts +0 -375
  407. package/src/runtime/assistant/store.ts +0 -243
  408. package/src/runtime/assistant/types.ts +0 -135
  409. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  410. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  411. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  412. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  413. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  414. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  415. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  416. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  417. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  418. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  419. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  420. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  421. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  422. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  423. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  424. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  425. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  426. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  427. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  428. package/src/runtime/plugins/desktop-adapter.ts +0 -374
  429. package/src/runtime/safe-tooling/browser-safe.ts +0 -133
  430. package/src/runtime/workflow/findings/store.ts +0 -204
  431. package/src/runtime/workflow/findings/types.ts +0 -58
  432. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  433. package/src/runtime/workflow/portfolio/store.ts +0 -185
  434. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -4,6 +4,13 @@ export type RepositoryCommandRisk = 'readonly' | 'workspace_write' | 'remote_wri
4
4
  export type RepositoryCommandAuthorization = 'explicit_user_request' | 'confirmed_plan' | 'policy' | 'full_access' | 'goal_delegation' | 'gpt_risk_delegate' | 'user_confirmation';
5
5
  export type RepositoryCommandConfirmation = 'none' | 'authorization' | 'strong_confirmation';
6
6
 
7
+ /**
8
+ * Advisory command metadata only. This classifier is intentionally heuristic:
9
+ * consumers may use it for observability, replay hints, and conservative
10
+ * resource-claim selection, but it is not an execution-permission authority.
11
+ * Repository command admission is defined by concrete repository/cwd/capability
12
+ * scope and the Process Runtime rather than an exhaustive command allow/deny list.
13
+ */
7
14
  export interface RepositoryCommandClassification {
8
15
  risk: RepositoryCommandRisk;
9
16
  confirmation: RepositoryCommandConfirmation;
@@ -80,6 +87,77 @@ function shellSegments(command: string): string[] {
80
87
  return segments;
81
88
  }
82
89
 
90
+ function shellWordsPreservingQuotes(segment: string): string[] {
91
+ const words: string[] = [];
92
+ let current = '';
93
+ let quote: "'" | '"' | undefined;
94
+ let escaped = false;
95
+ const flush = () => {
96
+ if (current) words.push(current);
97
+ current = '';
98
+ };
99
+ for (let index = 0; index < segment.length; index += 1) {
100
+ const char = segment[index]!;
101
+ if (escaped) { current += char; escaped = false; continue; }
102
+ if (char === '\\' && quote !== "'") { escaped = true; continue; }
103
+ if (quote) {
104
+ if (char === quote) quote = undefined;
105
+ else current += char;
106
+ continue;
107
+ }
108
+ if (char === "'" || char === '"') { quote = char; continue; }
109
+ if (/\s/.test(char)) { flush(); continue; }
110
+ current += char;
111
+ }
112
+ flush();
113
+ return words;
114
+ }
115
+
116
+ const SAFE_SQLITE_READ_OPTIONS = new Set([
117
+ '-safe', '--safe', '-readonly', '--readonly', '-batch', '--batch',
118
+ '-header', '--header', '-noheader', '--noheader', '-json', '--json',
119
+ '-csv', '--csv', '-list', '--list', '-line', '--line', '-column', '--column',
120
+ '-tabs', '--tabs', '-table', '--table', '-box', '--box', '-markdown', '--markdown',
121
+ '-quote', '--quote', '-ascii', '--ascii',
122
+ ]);
123
+
124
+ function isSingleReadOnlySql(sql: string): boolean {
125
+ const normalized = sql.trim();
126
+ if (!normalized || normalized.startsWith('.')) return false;
127
+ const withoutTrailingSemicolon = normalized.endsWith(';') ? normalized.slice(0, -1).trimEnd() : normalized;
128
+ if (withoutTrailingSemicolon.includes(';')) return false;
129
+ if (!/^(?:select\b|with\b)/i.test(withoutTrailingSemicolon)) return false;
130
+ return !/\b(?:insert|update|delete|replace|create|drop|alter|vacuum|attach|detach|reindex|analyze|pragma|begin|commit|rollback|savepoint|release)\b/i.test(withoutTrailingSemicolon);
131
+ }
132
+
133
+ function isSafeReadOnlySqliteWords(rawWords: string[]): boolean {
134
+ const words = rawWords.filter(Boolean);
135
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
136
+ if (program !== 'sqlite3') return false;
137
+ const args = words.slice(1);
138
+ if (args.some((word) => /^(?:--?nonce)(?:=|$)/i.test(word) || /^(?:--?unsafe-testing)(?:=|$)/i.test(word))) return false;
139
+ let safe = false;
140
+ let readonly = false;
141
+ let index = 0;
142
+ for (; index < args.length; index += 1) {
143
+ const arg = args[index]!;
144
+ if (!arg.startsWith('-')) break;
145
+ if (!SAFE_SQLITE_READ_OPTIONS.has(arg.toLowerCase())) return false;
146
+ if (arg === '-safe' || arg === '--safe') safe = true;
147
+ if (arg === '-readonly' || arg === '--readonly') readonly = true;
148
+ }
149
+ if (!safe || !readonly) return false;
150
+ const database = args[index];
151
+ const sql = args[index + 1];
152
+ if (!database || !sql || args.length !== index + 2) return false;
153
+ return isSingleReadOnlySql(sql);
154
+ }
155
+
156
+ function isSafeReadOnlySqliteSegment(segment: string): boolean {
157
+ const stripped = segment.replace(/^\s*(?:[A-Za-z_][A-Za-z0-9_]*=[^\s]+\s+)*/, '');
158
+ return isSafeReadOnlySqliteWords(shellWordsPreservingQuotes(stripped));
159
+ }
160
+
83
161
  function isSedInPlaceSegment(segment: string): boolean {
84
162
  const words = firstWords(segment);
85
163
  if (words[0]?.toLowerCase() !== 'sed') return false;
@@ -177,22 +255,125 @@ function readOnlyGitSegment(words: string[], _segment: string): boolean {
177
255
  return isReadOnlyGitCommand(words);
178
256
  }
179
257
 
258
+ function isReadOnlyCodegraphCommand(words: string[]): boolean {
259
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
260
+ return program === 'codegraph' && words[1]?.toLowerCase() === 'status';
261
+ }
262
+
263
+ function githubCliApiMethod(words: string[]): string | undefined {
264
+ for (let index = 2; index < words.length; index += 1) {
265
+ const word = words[index]?.toLowerCase();
266
+ if (word === '-x' || word === '--method') return words[index + 1]?.toUpperCase();
267
+ if (word?.startsWith('--method=')) return word.slice('--method='.length).toUpperCase();
268
+ }
269
+ return undefined;
270
+ }
271
+
272
+ function isReadOnlyGitHubCliCommand(words: string[]): boolean {
273
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
274
+ if (program !== 'gh') return false;
275
+ const group = words[1]?.toLowerCase() ?? '';
276
+ const action = words[2]?.toLowerCase() ?? '';
277
+ if (['--version', 'version', 'help', '--help', '-h'].includes(group)) return true;
278
+ if (group === 'auth' && action === 'status') return true;
279
+ if (group === 'search' && ['code', 'commits', 'issues', 'prs', 'repos'].includes(action)) return true;
280
+ if (group === 'repo' && action === 'view') return true;
281
+ if (group === 'pr' && ['list', 'view', 'status', 'checks', 'diff'].includes(action)) return true;
282
+ if (group === 'issue' && ['list', 'view'].includes(action)) return true;
283
+ if (group === 'run' && ['list', 'view', 'watch'].includes(action)) return true;
284
+ if (group === 'workflow' && ['list', 'view'].includes(action)) return true;
285
+ if (group === 'release' && ['list', 'view', 'download'].includes(action)) return true;
286
+ if (group !== 'api') return false;
287
+
288
+ const method = githubCliApiMethod(words);
289
+ if (method) return method === 'GET' || method === 'HEAD';
290
+ const hasBodyInput = words.slice(2).some((word) => {
291
+ const lower = word.toLowerCase();
292
+ return lower === '-f' || lower === '--raw-field' || lower === '--field'
293
+ || lower === '--input' || lower.startsWith('--raw-field=') || lower.startsWith('--field=') || lower.startsWith('--input=');
294
+ });
295
+ return !hasBodyInput;
296
+ }
297
+
298
+ function isLocalGitHubCliWorkspaceCommand(words: string[]): boolean {
299
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
300
+ if (program !== 'gh') return false;
301
+ const group = words[1]?.toLowerCase() ?? '';
302
+ const action = words[2]?.toLowerCase() ?? '';
303
+ return (group === 'repo' && action === 'clone') || (group === 'pr' && action === 'checkout');
304
+ }
305
+
306
+ function isGitHubCliExternalMutation(words: string[]): boolean {
307
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
308
+ if (program !== 'gh') return false;
309
+ if (isReadOnlyGitHubCliCommand(words) || isLocalGitHubCliWorkspaceCommand(words)) return false;
310
+ return true;
311
+ }
312
+
180
313
  function isReadOnlySegment(segment: string): boolean {
181
314
  const words = firstWords(segment);
182
315
  const program = words[0]?.toLowerCase();
183
316
  if (!program) return false;
184
317
  if (program === 'git') return readOnlyGitSegment(words, segment);
318
+ if (isReadOnlyCodegraphCommand(words)) return true;
319
+ if (program === 'curl') return isReadOnlyLoopbackCurl(words);
320
+ if (program === 'sqlite3') return isSafeReadOnlySqliteSegment(segment);
185
321
  if (program === 'find') return !/(?:-delete|-exec|-execdir|-ok|-okdir)\b/.test(segment);
186
322
  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
- }
323
+ if (program === 'gh') return isReadOnlyGitHubCliCommand(words);
190
324
  return READ_ONLY_PROGRAMS.has(program);
191
325
  }
192
326
 
193
327
  /** Package scripts that are local validation (not install/publish/mutate deps). */
194
328
  const SAFE_PACKAGE_SCRIPT = /^(?:test|check|lint|typecheck|format:check|tsc)(?::|$)/i;
195
329
 
330
+ function isReadOnlyLoopbackCurl(words: string[]): boolean {
331
+ const program = words[0]?.split(/[\\/]/).at(-1)?.toLowerCase();
332
+ if (program !== 'curl') return false;
333
+ const args = words.slice(1);
334
+ const urls: string[] = [];
335
+ const safeLongFlags = new Set(['--fail', '--fail-with-body', '--silent', '--show-error', '--head']);
336
+ const safeValueFlags = new Set(['--connect-timeout', '--max-time', '--retry', '--retry-delay', '--retry-max-time']);
337
+ for (let index = 0; index < args.length; index += 1) {
338
+ const arg = args[index] ?? '';
339
+ if (arg.startsWith('http://') || arg.startsWith('https://')) {
340
+ urls.push(arg);
341
+ continue;
342
+ }
343
+ const lower = arg.toLowerCase();
344
+ if (lower === '-x' || lower === '--request') {
345
+ const method = (args[index + 1] ?? '').toUpperCase();
346
+ if (method !== 'GET' && method !== 'HEAD') return false;
347
+ index += 1;
348
+ continue;
349
+ }
350
+ if (lower.startsWith('--request=')) {
351
+ const method = arg.slice(arg.indexOf('=') + 1).toUpperCase();
352
+ if (method !== 'GET' && method !== 'HEAD') return false;
353
+ continue;
354
+ }
355
+ if (safeLongFlags.has(lower)) continue;
356
+ if (['>/dev/null', '1>/dev/null', '2>/dev/null', '>>/dev/null', '1>>/dev/null', '2>>/dev/null'].includes(arg)) continue;
357
+ if (['>', '1>', '2>', '>>', '1>>', '2>>'].includes(arg) && args[index + 1] === '/dev/null') {
358
+ index += 1;
359
+ continue;
360
+ }
361
+ if (safeValueFlags.has(lower)) {
362
+ const value = Number(args[index + 1]);
363
+ if (!Number.isFinite(value) || value < 0) return false;
364
+ index += 1;
365
+ continue;
366
+ }
367
+ if (arg.startsWith('-') && arg.length > 1 && Array.from(arg.slice(1)).every((flag) => ['f', 's', 'S', 'I'].includes(flag))) continue;
368
+ return false;
369
+ }
370
+ if (urls.length === 0) return false;
371
+ return urls.every((url) => {
372
+ try { return ['127.0.0.1', 'localhost', '::1'].includes(new URL(url).hostname.toLowerCase()); }
373
+ catch { return false; }
374
+ });
375
+ }
376
+
196
377
  function isSafePackageRunner(program: string, words: string[]): boolean {
197
378
  if (!['bun', 'npm', 'pnpm', 'yarn', 'node'].includes(program)) return false;
198
379
  // bun test <path>, npm test, etc.
@@ -440,6 +621,15 @@ function classifyArgvCommand(
440
621
  if (program === 'git' && isReadOnlyGitCommand(argv)) {
441
622
  return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command is a recognized repository-local read operation'] };
442
623
  }
624
+ if (isReadOnlyCodegraphCommand(argv)) {
625
+ return { risk: 'readonly', confirmation: 'none', reasons: ['CodeGraph status only observes the local semantic index'] };
626
+ }
627
+ if (program === 'curl' && isReadOnlyLoopbackCurl(argv)) {
628
+ return { risk: 'readonly', confirmation: 'none', reasons: ['curl performs a read-only loopback HTTP observation without writing response data to disk'] };
629
+ }
630
+ if (program === 'sqlite3' && isSafeReadOnlySqliteWords(argv)) {
631
+ return { risk: 'readonly', confirmation: 'none', reasons: ['sqlite3 is constrained by safe mode, readonly database access, and one read-only SQL statement'] };
632
+ }
443
633
  // Explicit shell wrappers are common in generated diagnostics. Re-classify
444
634
  // the fixed inner command instead of treating `sh -c` / `bash -lc` wrappers
445
635
  // as workspace mutations. Unsafe shell constructs are still rejected by the
@@ -463,19 +653,16 @@ function classifyArgvCommand(
463
653
  if (program === 'log' && ['show', 'stream', 'stats', 'config'].includes(subcommand ?? '') && subcommand !== 'config') {
464
654
  return { risk: 'readonly', confirmation: 'none', reasons: ['system log observation is read-only'] };
465
655
  }
466
- // Explicit readonly GitHub CLI observations (must not be treated as workspace write).
467
656
  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) {
657
+ if (isReadOnlyGitHubCliCommand(argv)) {
477
658
  return { risk: 'readonly', confirmation: 'none', reasons: ['the argv command is a recognized GitHub read operation'] };
478
659
  }
660
+ if (isLocalGitHubCliWorkspaceCommand(argv)) {
661
+ return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['the GitHub CLI command changes only the local checkout'] };
662
+ }
663
+ if (isGitHubCliExternalMutation(argv)) {
664
+ return { risk: 'remote_write', confirmation: 'authorization', reasons: ['the GitHub CLI command may mutate external GitHub state'] };
665
+ }
479
666
  }
480
667
  if (program === 'git' && ['add', 'commit', 'pull', 'fetch', 'merge', 'rebase', 'checkout', 'switch', 'cherry-pick', 'revert', 'stash', 'mv', 'restore', 'apply', 'am', 'bisect'].includes(subcommand ?? '')) {
481
668
  return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['changes the checkout, local refs, index, or working tree'] };
@@ -484,6 +671,12 @@ function classifyArgvCommand(
484
671
  || (['npm', 'bun', 'pnpm', 'yarn'].includes(program) && ['install', 'add', 'remove', 'update', 'run'].includes(subcommand ?? ''))) {
485
672
  return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['writes repository files'] };
486
673
  }
674
+ // Package-manager `version` is a mutation command (for example
675
+ // `npm version 1.5.1 --no-git-tag-version` updates package metadata). Keep
676
+ // flag-style queries such as `npm --version` on the readonly path below.
677
+ if (['npm', 'pnpm', 'yarn'].includes(program) && subcommand === 'version') {
678
+ return { risk: 'workspace_write', confirmation: 'authorization', reasons: ['package-manager version command may update package metadata'] };
679
+ }
487
680
  // Lightweight project script info queries stay readonly when they only request help/version.
488
681
  if (['bun', 'node', 'npm', 'pnpm', 'yarn', 'python', 'python3', 'cargo', 'go', 'swift'].includes(program)
489
682
  && argv.slice(1).some((word) => word === '--help' || word === '-h' || word === '--version' || word === '-V' || word === 'version' || word === 'help')) {
@@ -548,10 +741,12 @@ function classifyShellCommand(
548
741
 
549
742
  const remoteWritePatterns: Array<[RegExp, string]> = [
550
743
  [/\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
744
  [/\b(?:npm|bun)\s+publish\b/i, 'publishes a package'],
553
745
  ];
554
746
  for (const [pattern, reason] of remoteWritePatterns) if (pattern.test(normalized)) reasons.push(reason);
747
+ for (const segment of shellSegments(normalized)) {
748
+ if (isGitHubCliExternalMutation(firstWords(segment))) reasons.push('writes GitHub remote state');
749
+ }
555
750
  if (reasons.length > 0) return { risk: 'remote_write', confirmation: 'authorization', reasons };
556
751
 
557
752
  if (hasRepositoryOutputRedirection(normalized)) reasons.push('redirects output into a repository file');