@moretea-labs/forge 1.8.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/AGENTS.md +70 -7
  2. package/CHANGELOG.md +14 -0
  3. package/CLAUDE.md +17 -2
  4. package/CONTRIBUTING.md +3 -2
  5. package/THIRD_PARTY_NOTICES.md +1 -1
  6. package/adapters/chatgpt/browser-delivery-host.ts +7 -1
  7. package/adapters/chatgpt/browser-delivery-runtime.ts +529 -56
  8. package/adapters/chatgpt/controller-binding-store.ts +101 -22
  9. package/adapters/chatgpt/controller-round-host.ts +15 -25
  10. package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
  11. package/adapters/chatgpt/provider-delivery.ts +228 -1
  12. package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
  13. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  14. package/adapters/computer/chatgpt-target-router.ts +103 -0
  15. package/adapters/computer/chrome-extension/background.js +385 -0
  16. package/adapters/computer/chrome-extension/content.js +378 -0
  17. package/adapters/computer/chrome-extension/core.js +24 -0
  18. package/adapters/computer/chrome-extension/manifest.json +30 -0
  19. package/adapters/computer/desktop-operator-discovery.ts +11 -31
  20. package/adapters/computer/interaction-target-authority.ts +142 -18
  21. package/adapters/mcp/auth.ts +0 -1
  22. package/adapters/mcp/instructions.ts +5 -4
  23. package/adapters/mcp/multi-repository.ts +3 -19
  24. package/adapters/mcp/oauth.ts +73 -0
  25. package/adapters/mcp/paths.ts +4 -1
  26. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  27. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  28. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  29. package/adapters/mcp/runtime-gateway/context-adapter.ts +411 -73
  30. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  31. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
  32. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  33. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
  34. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  35. package/adapters/mcp/runtime-gateway/execution-tools.ts +8 -42
  36. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
  37. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
  38. package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
  39. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
  40. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
  41. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
  42. package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
  43. package/adapters/mcp/runtime-gateway/router.ts +18 -504
  44. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  45. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
  46. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  47. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
  48. package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
  49. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
  50. package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
  51. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
  52. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  53. package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
  54. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  55. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  56. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  57. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  58. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  59. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  60. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  61. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  62. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  63. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  64. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  65. package/adapters/mcp/server.ts +67 -23
  66. package/adapters/mcp/setup.ts +1 -3
  67. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
  68. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
  69. package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
  70. package/adapters/mcp/toolset-names.ts +5 -0
  71. package/adapters/mcp/toolset.ts +6 -5
  72. package/adapters/mcp/transports/http-observation.ts +365 -0
  73. package/adapters/mcp/transports/http.ts +154 -677
  74. package/adapters/mcp/transports/oauth-http.ts +322 -0
  75. package/adapters/mcp/transports/session-registry.ts +6 -0
  76. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
  77. package/assets/plugin-registry.v1.json +6 -4
  78. package/assets/reference-configs/agentic-development-flow.md +25 -0
  79. package/assets/reference-configs/global-working-rules.md +19 -0
  80. package/assets/skill-version.json +2 -2
  81. package/docs/architecture/CURRENT.md +111 -41
  82. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  83. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  84. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
  85. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
  86. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  87. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  88. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  89. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  90. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  91. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  92. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  93. package/docs/architecture/domains/verification.md +1 -0
  94. package/docs/architecture/domains/workflow-engine.md +6 -0
  95. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  96. package/docs/forge-plugin-management.md +2 -2
  97. package/docs/operations/controller-performance-and-502.md +17 -0
  98. package/docs/operations/controller-reliability-runbook.md +2 -2
  99. package/docs/operations/features.md +1 -1
  100. package/docs/operations/features.zh-CN.md +1 -1
  101. package/docs/operations/homebrew.md +2 -2
  102. package/docs/operations/mcp-tool-exposure.md +2 -0
  103. package/docs/operations/releasing.md +2 -0
  104. package/docs/operations/standalone-disaster-recovery.md +14 -6
  105. package/docs/wiki/Implementation.md +1 -1
  106. package/package.json +25 -14
  107. package/packages/kernel/cognition/api/index.ts +6 -0
  108. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  109. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  110. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  111. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  112. package/packages/kernel/cognition/domain/learning.ts +106 -0
  113. package/packages/kernel/cognition/domain/memory.ts +254 -0
  114. package/packages/kernel/controller/api/index.ts +1 -0
  115. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  116. package/packages/kernel/controller/application/controller-round-service.ts +12 -0
  117. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
  118. package/packages/kernel/controller/domain/controller-round.ts +4 -1
  119. package/packages/kernel/controller/domain/execution-quality.ts +3 -1
  120. package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
  121. package/packages/kernel/controller/infrastructure/controller-session-store.ts +297 -71
  122. package/packages/kernel/controller/ports/controller-host.ts +2 -0
  123. package/packages/kernel/identity/api/index.ts +10 -0
  124. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  125. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  126. package/packages/kernel/identity/domain/grant.ts +72 -0
  127. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  128. package/packages/kernel/identity/domain/user-request.ts +93 -0
  129. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  130. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  131. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  132. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  133. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  134. package/packages/kernel/scheduler/api/index.ts +0 -2
  135. package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
  136. package/packages/kernel/scheduler/application/settlement.ts +0 -15
  137. package/packages/kernel/scheduler/domain/schedule.ts +87 -0
  138. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +153 -133
  139. package/packages/kernel/work/api/index.ts +3 -2
  140. package/packages/kernel/work/application/work-service.ts +17 -42
  141. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  142. package/packages/kernel/work/domain/engineering-design.ts +10 -5
  143. package/packages/kernel/work/domain/engineering-profile.ts +8 -12
  144. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  145. package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
  146. package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
  147. package/packages/kernel/work/domain/implementation-review.ts +14 -331
  148. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  149. package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
  150. package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
  151. package/packages/kernel/work/domain/state-machine.ts +25 -63
  152. package/packages/kernel/work/domain/types.ts +57 -51
  153. package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
  154. package/packages/kernel/work/ports/work-contract-store.ts +5 -2
  155. package/packages/plugin-runtime/browser/session-authority.ts +2 -1
  156. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  157. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  158. package/packages/plugin-runtime/computer/index.ts +2 -0
  159. package/packages/plugin-runtime/computer/target-authority.ts +26 -1
  160. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
  161. package/packages/protocols/computer/contract.ts +27 -1
  162. package/scripts/activate-source-baseline.ts +7 -9
  163. package/scripts/canary-controller-semantic-wait.ts +12 -24
  164. package/scripts/check-mcp-compatibility.ts +48 -136
  165. package/scripts/check-runtime-architecture.mjs +622 -217
  166. package/scripts/forge-local-recovery-helper.mjs +93 -15
  167. package/scripts/lib/project-init-lib.sh +3 -0
  168. package/scripts/open-source-audit-allowlist.txt +1 -2
  169. package/scripts/run-bounded-command.mjs +5 -0
  170. package/scripts/run-governed-gate.ts +0 -1
  171. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  172. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  173. package/scripts/smoke-mcp-http-runtime.ts +5 -0
  174. package/scripts/smoke-runtime-recovery.ts +12 -43
  175. package/scripts/smoke-schedule-engine.ts +23 -15
  176. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  177. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  178. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  179. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  180. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  181. package/scripts/smoke-workflow-supervisor.ts +103 -0
  182. package/scripts/verify-forge-runtime.sh +2 -1
  183. package/src/cli/agent-jobs/executor-health.ts +11 -34
  184. package/src/cli/agent-jobs/integration.ts +18 -49
  185. package/src/cli/agent-jobs/job-manager.ts +7 -3
  186. package/src/cli/commands/brain-assistant.ts +27 -13
  187. package/src/cli/commands/brain.ts +13 -15
  188. package/src/cli/commands/chatgpt.ts +1 -163
  189. package/src/cli/commands/recovery.ts +135 -121
  190. package/src/cli/commands/runtime.ts +3 -3
  191. package/src/cli/commands/setup-profile.ts +8 -0
  192. package/src/cli/controller/check-runner.ts +13 -2
  193. package/src/cli/controller/completion-backlog.ts +3 -3
  194. package/src/cli/controller/completion-orchestrator.ts +4 -43
  195. package/src/cli/controller/completion-target.ts +3 -72
  196. package/src/cli/controller/context/source-materializer.ts +81 -100
  197. package/src/cli/controller/context-pack.ts +10 -8
  198. package/src/cli/controller/execution-completion.ts +4 -7
  199. package/src/cli/controller/execution-policy.ts +36 -153
  200. package/src/cli/controller/governance.ts +2 -3
  201. package/src/cli/controller/issue-store.ts +4 -99
  202. package/src/cli/controller/launch-agents.ts +59 -18
  203. package/src/cli/controller/operational-plan.ts +24 -51
  204. package/src/cli/controller/runtime-config.ts +5 -1
  205. package/src/cli/controller/stuck-state-migration.ts +2 -3
  206. package/src/cli/controller/systemd-user.ts +39 -1
  207. package/src/cli/editing/edit-session.ts +1 -7
  208. package/src/cli/local-bridge/console-automations.ts +18 -13
  209. package/src/cli/local-bridge/console-view-models.ts +3 -12
  210. package/src/cli/local-bridge/facade-api.ts +64 -191
  211. package/src/cli/local-bridge/server.ts +24 -147
  212. package/src/cli/local-bridge/types.ts +0 -1
  213. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  214. package/src/cli/repositories/command-executor.ts +29 -23
  215. package/src/cli/repositories/command-scope.ts +35 -16
  216. package/src/cli/repositories/controller-home.ts +48 -0
  217. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  218. package/src/cli/repositories/git-command-executor.ts +2 -2
  219. package/src/cli/repositories/registry.ts +77 -11
  220. package/src/cli/repositories/structured-git.ts +62 -2
  221. package/src/cli/repository/session-cache.ts +92 -6
  222. package/src/runtime/context/assistant-context.ts +20 -7
  223. package/src/runtime/context/assistant-work-context.ts +89 -27
  224. package/src/runtime/context/automatic-learning.ts +565 -0
  225. package/src/runtime/context/cognitive-attention.ts +173 -0
  226. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  227. package/src/runtime/context/context-closure.ts +46 -9
  228. package/src/runtime/context/context-pack-process.ts +103 -0
  229. package/src/runtime/context/context-plane.ts +1 -9
  230. package/src/runtime/context/direct-controller-learning.ts +298 -0
  231. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  232. package/src/runtime/context/semantic-navigation.ts +6 -34
  233. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  234. package/src/runtime/context/typescript-navigation.ts +89 -3
  235. package/src/runtime/control-plane/cleanup-artifact-retention.ts +212 -9
  236. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
  237. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
  238. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
  239. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  240. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  241. package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
  242. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  243. package/src/runtime/control-plane/execution/validation.ts +6 -8
  244. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
  245. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  246. package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
  247. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  248. package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
  249. package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
  250. package/src/runtime/control-plane/execution/work-handle-authority.ts +188 -109
  251. package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
  252. package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
  253. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
  254. package/src/runtime/control-plane/execution/work-operation-service.ts +43 -27
  255. package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
  256. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  257. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  258. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +173 -186
  259. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
  260. package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
  261. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
  262. package/src/runtime/control-plane/facade/capability-registry.ts +362 -37
  263. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  264. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  265. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  266. package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
  267. package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
  268. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
  269. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
  270. package/src/runtime/control-plane/facade/index.ts +0 -1
  271. package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
  272. package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
  273. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  274. package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
  275. package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
  276. package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
  277. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
  278. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  279. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
  280. package/src/runtime/control-plane/facade/types.ts +49 -108
  281. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  282. package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
  283. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  284. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
  285. package/src/runtime/control-plane/global-scheduler/maintenance.ts +239 -112
  286. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
  287. package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
  288. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  289. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  290. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  291. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
  292. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -300
  293. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  294. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
  295. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
  296. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  297. package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
  298. package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
  299. package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
  300. package/src/runtime/control-plane/release-retention.ts +135 -47
  301. package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
  302. package/src/runtime/control-plane/runtime-cleanup.ts +290 -21
  303. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  304. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
  305. package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
  306. package/src/runtime/diagnostics/incident-repair.ts +313 -146
  307. package/src/runtime/diagnostics/mcp-timing.ts +114 -0
  308. package/src/runtime/evidence/artifact-store.ts +158 -40
  309. package/src/runtime/evidence/evidence-store.ts +112 -8
  310. package/src/runtime/evidence/output-handle-index.ts +225 -0
  311. package/src/runtime/evidence/result-store.ts +158 -44
  312. package/src/runtime/execution/jobs/store.ts +3 -4
  313. package/src/runtime/execution/managed-workspace.ts +57 -0
  314. package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
  315. package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
  316. package/src/runtime/execution/process-runtime/check-result.ts +105 -1
  317. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
  318. package/src/runtime/execution/process-runtime/command-facade.ts +79 -27
  319. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  320. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  321. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  322. package/src/runtime/execution/process-runtime/index.ts +3 -0
  323. package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
  324. package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
  325. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  326. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  327. package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
  328. package/src/runtime/execution/process-runtime/runtime.ts +35 -2
  329. package/src/runtime/execution/process-runtime/store.ts +30 -2
  330. package/src/runtime/execution/process-runtime/types.ts +6 -1
  331. package/src/runtime/execution/workers/executor.ts +2 -6
  332. package/src/runtime/platform/service-inventory.ts +130 -0
  333. package/src/runtime/platform/service-manager.ts +8 -0
  334. package/src/runtime/plugins/action-application.ts +85 -28
  335. package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
  336. package/src/runtime/plugins/browser-adapter.ts +757 -34
  337. package/src/runtime/plugins/browser-automation-service.ts +23 -3
  338. package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
  339. package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
  340. package/src/runtime/plugins/browser-native-session-service.ts +63 -13
  341. package/src/runtime/plugins/browser-registration.ts +16 -0
  342. package/src/runtime/plugins/browser-runtime.ts +14 -1
  343. package/src/runtime/plugins/browser-session-authority.ts +2 -2
  344. package/src/runtime/plugins/browser-session-store.ts +46 -76
  345. package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
  346. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  347. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  348. package/src/runtime/plugins/computer-registration.ts +222 -11
  349. package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
  350. package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
  351. package/src/runtime/plugins/external-adapter.ts +42 -6
  352. package/src/runtime/plugins/external-registration.ts +21 -1
  353. package/src/runtime/plugins/gmail-adapter.ts +23 -2
  354. package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
  355. package/src/runtime/plugins/google-shared.ts +14 -7
  356. package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
  357. package/src/runtime/plugins/ios-adapter.ts +1 -1
  358. package/src/runtime/plugins/lightweight-action.ts +208 -2
  359. package/src/runtime/plugins/local-system-adapter.ts +12 -2
  360. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  361. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  362. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  363. package/src/runtime/plugins/store.ts +602 -428
  364. package/src/runtime/plugins/types.ts +20 -0
  365. package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
  366. package/src/runtime/projections/invalidation.ts +7 -3
  367. package/src/runtime/projections/materialized-view.ts +80 -36
  368. package/src/runtime/recovery/actions.ts +3 -3
  369. package/src/runtime/recovery/capability-action-application.ts +46 -45
  370. package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
  371. package/src/runtime/recovery/maintenance-executor.ts +374 -123
  372. package/src/runtime/recovery/store.ts +29 -11
  373. package/src/runtime/release/release-coordinator.ts +296 -0
  374. package/src/runtime/release/release-session.ts +716 -0
  375. package/src/runtime/release/release-state-migration.ts +25 -0
  376. package/src/runtime/resources/leases/store.ts +56 -25
  377. package/src/runtime/root/computer-composition.ts +191 -6
  378. package/src/runtime/root/controller-progression-composition.ts +192 -0
  379. package/src/runtime/root/controller-round-composition.ts +20 -1
  380. package/src/runtime/root/deployment-topology.ts +106 -0
  381. package/src/runtime/root/entry.ts +4 -3
  382. package/src/runtime/root/known-good-recovery.ts +184 -0
  383. package/src/runtime/root/local-bridge.ts +0 -1
  384. package/src/runtime/root/mcp-transport.ts +111 -18
  385. package/src/runtime/root/ownership.ts +261 -9
  386. package/src/runtime/root/package-connector-service.ts +105 -19
  387. package/src/runtime/root/package-runtime-release.ts +117 -18
  388. package/src/runtime/root/package-runtime-service.ts +17 -11
  389. package/src/runtime/root/release-execution-canary.ts +44 -12
  390. package/src/runtime/root/release-loader.ts +90 -8
  391. package/src/runtime/root/release-manifest.ts +80 -6
  392. package/src/runtime/root/release-materialize.ts +372 -28
  393. package/src/runtime/root/release-store.ts +395 -36
  394. package/src/runtime/root/runtime-lane.ts +191 -0
  395. package/src/runtime/root/runtime.ts +159 -27
  396. package/src/runtime/root/scheduled-controller-composition.ts +28 -3
  397. package/src/runtime/root/service-runner.ts +2 -2
  398. package/src/runtime/root/service.ts +36 -33
  399. package/src/runtime/root/status.ts +48 -0
  400. package/src/runtime/root/types.ts +32 -3
  401. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  402. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  403. package/src/runtime/root/write-fence.ts +50 -2
  404. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  405. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  406. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  407. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  408. package/src/runtime/shared/process-environment.ts +20 -9
  409. package/src/runtime/shared/response-budget.ts +1 -3
  410. package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
  411. package/src/runtime/standalone-recovery/core.ts +3702 -342
  412. package/src/runtime/standalone-recovery/entry.ts +469 -39
  413. package/src/runtime/standalone-recovery/installer.ts +262 -148
  414. package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
  415. package/src/runtime/standalone-recovery/operation-lock.ts +1 -1
  416. package/src/runtime/standalone-recovery/performance.ts +54 -16
  417. package/src/runtime/standalone-recovery/release.ts +53 -5
  418. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  419. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  420. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  421. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +10 -3
  422. package/src/runtime/workflow/schedules/engine.ts +138 -172
  423. package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
  424. package/src/runtime/workflows/runtime.ts +15 -19
  425. package/src/testing/test-governance.ts +5 -1
  426. package/supervisor/chatgpt-conversation.ts +23 -0
  427. package/supervisor/client.ts +201 -0
  428. package/supervisor/control-plane.ts +868 -0
  429. package/supervisor/entry.ts +15 -0
  430. package/supervisor/forge-validators.ts +80 -0
  431. package/supervisor/index.ts +5 -0
  432. package/supervisor/native-browser-adapter.ts +786 -0
  433. package/supervisor/native-messaging/host.ts +39 -0
  434. package/supervisor/native-messaging/manifest.ts +26 -0
  435. package/supervisor/native-messaging/protocol.ts +27 -0
  436. package/supervisor/paths.ts +18 -0
  437. package/supervisor/protocol.ts +202 -0
  438. package/supervisor/server.ts +404 -0
  439. package/supervisor/store.ts +1451 -0
  440. package/supervisor/tsconfig.json +8 -0
  441. package/supervisor/types.ts +255 -0
  442. package/adapters/chatgpt/controller-host.ts +0 -119
  443. package/adapters/mcp/controller-round-compatibility.ts +0 -184
  444. package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
  445. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
  446. package/packages/kernel/progression/api/index.ts +0 -2
  447. package/packages/kernel/progression/application/projector.ts +0 -211
  448. package/packages/kernel/progression/domain/types.ts +0 -116
  449. package/packages/kernel/progression/index.ts +0 -1
  450. package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
  451. package/packages/kernel/scheduler/domain/continuation.ts +0 -38
  452. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
  453. package/packages/kernel/work/domain/admission-policy.ts +0 -34
  454. package/scripts/benchmark-background-check-overlap.ts +0 -228
  455. package/scripts/benchmark-computer-hotpath.ts +0 -255
  456. package/scripts/benchmark-controller-hotpath.ts +0 -212
  457. package/scripts/benchmark-controller-round2.ts +0 -191
  458. package/scripts/benchmark-ios-agent-device.ts +0 -511
  459. package/scripts/benchmark-mcp-host.sh +0 -117
  460. package/scripts/benchmark-mcp-transport.ts +0 -169
  461. package/scripts/benchmark-operational-memory-activation.ts +0 -235
  462. package/scripts/benchmark-operational-shadow.ts +0 -28
  463. package/scripts/benchmark-quality-harness.ts +0 -146
  464. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  465. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  466. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  467. package/scripts/benchmark-thin-harness.ts +0 -251
  468. package/scripts/benchmark-typescript-navigation.ts +0 -186
  469. package/scripts/benchmark-work-efficiency.ts +0 -334
  470. package/scripts/build-controller-ui.ts +0 -28
  471. package/scripts/check-npm-release.sh +0 -32
  472. package/scripts/check-public-release-surface.sh +0 -19
  473. package/scripts/check-release-published.sh +0 -57
  474. package/scripts/check-release-readiness.sh +0 -37
  475. package/scripts/check-release-version.mjs +0 -74
  476. package/scripts/check-tarball-install-smoke.sh +0 -150
  477. package/scripts/package-source-archive.sh +0 -147
  478. package/scripts/public-release-files.txt +0 -39
  479. package/scripts/public-release.ts +0 -174
  480. package/scripts/publish-release-tarball.sh +0 -27
  481. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  482. package/scripts/stage-runtime-release.ts +0 -44
  483. package/src/cli/controller/progress.ts +0 -656
  484. package/src/cli/controller/work-mode.ts +0 -181
  485. package/src/cli/local-bridge/console-assets.ts +0 -17
  486. package/src/cli/local-bridge/dashboard.ts +0 -17
  487. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  488. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  489. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  490. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  491. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  492. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  493. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  494. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  495. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  496. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  497. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  498. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  499. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  500. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  501. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  502. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  503. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  504. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  505. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  506. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  507. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  508. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  509. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  510. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  511. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  512. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  513. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  514. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  515. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
  516. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
  517. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
  518. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
  519. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  520. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
  521. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
  522. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
  523. package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
  524. package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
  525. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  526. package/src/runtime/control-plane/routing/index.ts +0 -1
  527. package/src/runtime/control-plane/routing/route-policy.ts +0 -401
  528. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -7,6 +7,7 @@ import {
7
7
  DEFAULT_CHATGPT_AUTOMATION_MODEL,
8
8
  DEFAULT_CHATGPT_AUTOMATION_REASONING,
9
9
  DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY,
10
+ dispatchWithChatgptProviderBackpressure,
10
11
  type ChatgptAutomationReasoning,
11
12
  type ChatgptAutomationTabCleanupStatus,
12
13
  type ChatgptAutomationTabPolicy,
@@ -21,16 +22,6 @@ import {
21
22
  submitChatgptPrompt,
22
23
  withChatgptBrowserActionOrigin,
23
24
  } from '../../../../adapters/chatgpt/browser-delivery-runtime';
24
- import { getWorkContract } from '../../../../packages/kernel/work/api/index';
25
- import { readForgeInstanceIdentity } from '../../../../packages/kernel/identity/api/index';
26
- import {
27
- bindChatgptWorkConversation,
28
- getChatgptWorkConversationBinding,
29
- hasChatgptConversationIdentity,
30
- parseChatgptConversationIdentity,
31
- rebindChatgptWorkConversation,
32
- type ChatgptWorkConversationBinding,
33
- } from '../../../../adapters/chatgpt/work-conversation-binding-store';
34
25
 
35
26
  export {
36
27
  CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN,
@@ -56,48 +47,8 @@ export {
56
47
  settleWorkChatgptAutomationTab,
57
48
  } from '../../../../adapters/chatgpt/browser-delivery-runtime';
58
49
 
59
- const LEGACY_CONTROLLER_CHATGPT_SESSION_ID = 'forge-chatgpt-supercontroller';
60
50
  export const DEFAULT_CHATGPT_AUTOMATION_PLUGIN_MENTION = '@forge';
61
51
 
62
- export class ChatgptExecutionPlacementError extends Error {
63
- readonly code = 'CHATGPT_EXECUTION_PLACEMENT_MISMATCH';
64
- readonly targetForgeInstanceId: string;
65
- readonly currentForgeInstanceId?: string;
66
-
67
- constructor(targetForgeInstanceId: string, currentForgeInstanceId?: string) {
68
- super(`CHATGPT_EXECUTION_PLACEMENT_MISMATCH: target=${targetForgeInstanceId} current=${currentForgeInstanceId ?? 'unavailable'}`);
69
- this.name = 'ChatgptExecutionPlacementError';
70
- this.targetForgeInstanceId = targetForgeInstanceId;
71
- this.currentForgeInstanceId = currentForgeInstanceId;
72
- }
73
- }
74
-
75
-
76
- export interface WorkChatgptContinuationInput {
77
- controllerHome: string;
78
- repoId: string;
79
- repoRoot: string;
80
- workId: string;
81
- prompt: string;
82
- /** Durable per-round capability minted before ChatGPT dispatch. */
83
- controllerAuthorityId?: string;
84
- /** Durable semantic relay scope paired with controllerAuthorityId. */
85
- relayScopeId?: string;
86
- title?: string;
87
- browserSessionId?: string;
88
- conversationUrl?: string;
89
- model?: string;
90
- reasoning?: ChatgptAutomationReasoning;
91
- tabPolicy?: ChatgptAutomationTabPolicy;
92
- /** Transport-only conversation policy. `fresh` starts a new ChatGPT conversation while preserving the same durable Work/ControllerRound authority. */
93
- transportConversation?: 'bound' | 'fresh';
94
- timeoutMs?: number;
95
- /** Authorization provenance for Browser actions. Immediate/source launches default to chatgpt-action; Scheduler resume must pass schedule. */
96
- originSurface?: 'chatgpt-action' | 'schedule';
97
- /** Explicit controller-scoped Browser grant refs already authorized for this Work transport. */
98
- authorizationGrantRefs?: readonly string[];
99
- }
100
-
101
52
  export interface WorkChatgptContinuationDependencies {
102
53
  bridgeRuntime?: boolean;
103
54
  browserHost?: ChatgptProviderDeliveryHost;
@@ -137,27 +88,8 @@ export interface StandaloneChatgptPromptInput {
137
88
  reasoning?: ChatgptAutomationReasoning;
138
89
  tabPolicy?: ChatgptAutomationTabPolicy;
139
90
  timeoutMs?: number;
140
- }
141
-
142
- function workflowToolAttributionInstruction(input: WorkChatgptContinuationInput): string {
143
- const workId = input.workId;
144
- const authorityId = input.controllerAuthorityId?.trim();
145
- const relayScopeId = input.relayScopeId?.trim();
146
- const requirementScoped = relayScopeId?.startsWith('requirement:') === true;
147
- const repositoryAttribution = requirementScoped
148
- ? `本轮普通 repository_command_execute 和 repository_safe_patch_apply 必须显式传入实际被本轮语义选择且已成功 claim 的 repository-change Work 的 work_id;如果仍在推进 origin Work,则使用 work_id=${workId}。不得把只读/编排 Supervisor Work 的 work_id 用来归属 child Work 的源码修改,也不得省略 work_id。`
149
- : `本轮每一次 repository_command_execute 和 repository_safe_patch_apply 都必须显式传 work_id=${workId},不得省略。`;
150
- if (authorityId && relayScopeId) {
151
- return `Forge Workflow 执行契约:精确 Work ${workId}。本次启动的 controller round 已具备 durable controller authority:controller_authority_id=${authorityId},relay_scope_id=${relayScopeId}。第一次 controller_claim 必须使用这组完全相同的 authority;不得先调用不带 scope 的 controller_claim,也不得等待 claim 响应后再生成另一份 authority。如果当前 client 暴露 controller_authority_id 与 relay_scope_id,controller_claim 时必须同时传入。如果当前 frozen client schema 缺少任一字段,调用 rh_work operation=repair, work_id=${workId}, capability_id=controller.round:controller_claim:${authorityId}:${relayScopeId};Forge 会把它映射到同一个 fenced claim。claim 成功后,data.controllerAuthorityId 必须等于 ${authorityId};continue、verify、finalize、stop、controller_release 必须原样沿用同一 durable authority,必要时使用对应 compatibility capability。绝不能把 data.session.sessionId 当作 durable capability,因为 MCP execution session 可能轮换。${repositoryAttribution}唯一例外是 prompt 明确标记为 exact current-source Controller lifecycle invocation 的 repository_command_execute,它必须使用给定 source checkout_id 且不得传 wrapper work_id,因为 CLI 内部 --work-id 与 ControllerRound authority 才是该控制面变更的 fenced authority。`;
152
- }
153
- return `Forge Workflow 执行契约:首先 claim 精确 Work ${workId}。从成功的 controller_claim 响应中取得 data.controllerAuthorityId;此后该 Work 的每一次 rh_work lifecycle 调用(continue、verify、finalize、stop、controller_release)都必须把它原样作为 controller_authority_id 传入。如果当前 frozen client schema 不暴露 controller_authority_id,则把同一个 opaque value 作为 session_id compatibility carrier。绝不能把 data.session.sessionId 当作 durable capability,因为 MCP execution session 可能在工具调用之间被替换或失效。本轮每一次 repository_command_execute 和 repository_safe_patch_apply 都必须显式传 work_id=${workId},不得省略;唯一例外是 prompt 明确标记为 exact current-source Controller lifecycle invocation 的 repository_command_execute,它必须使用给定 source checkout_id 且不得传 wrapper work_id,因为 CLI 内部 --work-id 与 ControllerRound authority 才是该控制面变更的 fenced authority。`;
154
- }
155
-
156
- function controllerRoundAuthorityInputError(input: WorkChatgptContinuationInput): Error | undefined {
157
- const hasAuthority = Boolean(input.controllerAuthorityId?.trim());
158
- const hasRelayScope = Boolean(input.relayScopeId?.trim());
159
- if (hasAuthority === hasRelayScope) return undefined;
160
- return new Error('CHATGPT_CONTROLLER_ROUND_AUTHORITY_INCOMPLETE: controllerAuthorityId and relayScopeId must be supplied together');
91
+ /** Explicit Browser grant refs already authorized by the owning durable workflow/controller binding. */
92
+ authorizationGrantRefs?: readonly string[];
161
93
  }
162
94
 
163
95
  function normalizeModel(value?: string): string {
@@ -170,12 +102,6 @@ function normalizeReasoning(value?: ChatgptAutomationReasoning): ChatgptAutomati
170
102
  return value ?? DEFAULT_CHATGPT_AUTOMATION_REASONING;
171
103
  }
172
104
 
173
- const DEFAULT_CHATGPT_CONTROLLER_REASONING: ChatgptAutomationReasoning = 'xhigh';
174
-
175
- function normalizeControllerReasoning(value?: ChatgptAutomationReasoning): ChatgptAutomationReasoning {
176
- return value ?? DEFAULT_CHATGPT_CONTROLLER_REASONING;
177
- }
178
-
179
105
  function normalizeTabPolicy(value?: ChatgptAutomationTabPolicy): ChatgptAutomationTabPolicy {
180
106
  return value ?? DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY;
181
107
  }
@@ -195,18 +121,13 @@ function resolveChatgptProviderDeliveryHost(
195
121
  return { bridgeRuntime, host };
196
122
  }
197
123
 
198
- export function stableChatgptWorkBrowserSessionId(repoId: string, workId: string): string {
199
- const digest = createHash('sha256').update(`${repoId}\n${workId}`).digest('hex').slice(0, 20);
200
- return `forge-chatgpt-work-${digest}`;
201
- }
202
-
203
- export function stableChatgptWorkBridgeSessionId(repoId: string, workId: string): string {
204
- const digest = createHash('sha256').update(`${repoId}\nbridge\n${workId}`).digest('hex').slice(0, 20);
124
+ export function stableChatgptWorkBridgeSessionId(_repoId: string, workId: string): string {
125
+ const digest = createHash('sha256').update(`bridge\n${workId}`).digest('hex').slice(0, 20);
205
126
  return `forge-chatgpt-bridge-${digest}`;
206
127
  }
207
128
 
208
- export function stableStandaloneChatgptBrowserSessionId(repoId: string, scopeId: string): string {
209
- const digest = createHash('sha256').update(`${repoId}\nstandalone\n${scopeId}`).digest('hex').slice(0, 20);
129
+ export function stableStandaloneChatgptBrowserSessionId(_repoId: string, scopeId: string): string {
130
+ const digest = createHash('sha256').update(`standalone\n${scopeId}`).digest('hex').slice(0, 20);
210
131
  return `forge-chatgpt-standalone-${digest}`;
211
132
  }
212
133
 
@@ -217,23 +138,6 @@ function resolveStandaloneChatgptBrowserSessionId(input: StandaloneChatgptPrompt
217
138
  return input.browserSessionId?.trim() || stable;
218
139
  }
219
140
 
220
- export function resolveChatgptWorkBrowserSessionId(input: {
221
- repoId: string;
222
- workId: string;
223
- tabPolicy?: ChatgptAutomationTabPolicy;
224
- explicitSessionId?: string;
225
- boundSessionId?: string;
226
- }): string {
227
- const policy = normalizeTabPolicy(input.tabPolicy);
228
- const stable = stableChatgptWorkBrowserSessionId(input.repoId, input.workId);
229
- if (policy === 'new') return `${stable}-${randomUUID().slice(0, 8)}`;
230
- const explicit = input.explicitSessionId?.trim();
231
- if (explicit && explicit !== LEGACY_CONTROLLER_CHATGPT_SESSION_ID) return explicit;
232
- const bound = input.boundSessionId?.trim();
233
- if (bound && bound !== LEGACY_CONTROLLER_CHATGPT_SESSION_ID) return bound;
234
- return stable;
235
- }
236
-
237
141
  export function withForgePluginMention(prompt: string): string {
238
142
  const value = prompt.trim();
239
143
  if (!value) throw new Error('CHATGPT_AUTOMATION_PROMPT_REQUIRED');
@@ -260,20 +164,27 @@ export async function runStandaloneChatgptPrompt(
260
164
  ? stableChatgptWorkBridgeSessionId(input.repoId, browserScopeId)
261
165
  : resolveStandaloneChatgptBrowserSessionId(input);
262
166
  const targetUrl = seedUrl ?? 'https://chatgpt.com/';
167
+ const authorizationGrantRefs = new Set(
168
+ (input.authorizationGrantRefs ?? []).map((ref) => ref.trim()).filter(Boolean),
169
+ );
263
170
 
264
171
  try {
265
- const delivery = await host.dispatch({
266
- controllerHome: input.controllerHome,
267
- repoId: input.repoId,
268
- repoRoot: input.repoRoot ?? process.cwd(),
269
- workId: browserScopeId,
270
- prompt: input.prompt,
271
- browserSessionId: sessionId,
272
- targetUrl,
273
- model,
274
- reasoning,
275
- timeoutMs: input.timeoutMs,
276
- });
172
+ const delivery = await withChatgptBrowserActionOrigin(
173
+ { surface: 'chatgpt-action', actor: 'chatgpt-standalone-prompt' },
174
+ () => dispatchWithChatgptProviderBackpressure(input.controllerHome, () => host.dispatch({
175
+ controllerHome: input.controllerHome,
176
+ repoId: input.repoId,
177
+ repoRoot: input.repoRoot ?? process.cwd(),
178
+ workId: browserScopeId,
179
+ prompt: input.prompt,
180
+ browserSessionId: sessionId,
181
+ targetUrl,
182
+ model,
183
+ reasoning,
184
+ timeoutMs: input.timeoutMs,
185
+ })),
186
+ authorizationGrantRefs,
187
+ );
277
188
  if (delivery.status !== 'dispatch_confirmed') {
278
189
  return {
279
190
  status: 'failed',
@@ -285,6 +196,7 @@ export async function runStandaloneChatgptPrompt(
285
196
  reasoning,
286
197
  tabPolicy,
287
198
  executionPreferenceVerified: delivery.executionPreferenceVerified,
199
+ authorizationGrantRefs: [...authorizationGrantRefs],
288
200
  providerDeliveryStatus: delivery.status,
289
201
  error: delivery.error ?? { code: `CHATGPT_PROVIDER_${delivery.status.toUpperCase()}`, message: delivery.status },
290
202
  };
@@ -322,193 +234,9 @@ export async function runStandaloneChatgptPrompt(
322
234
  reasoning,
323
235
  tabPolicy,
324
236
  executionPreferenceVerified: false,
325
- error: {
326
- code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
327
- message: error instanceof Error ? error.message : String(error),
328
- },
329
- };
330
- }
331
- }
332
-
333
- /**
334
- * Dispatches a bounded resume prompt to one controller-owned ChatGPT Web tab.
335
- * Chat history is transport context only. Forge Work/Plan/evidence remain authoritative.
336
- */
337
- export async function runWorkChatgptContinuation(
338
- input: WorkChatgptContinuationInput,
339
- dependencies: WorkChatgptContinuationDependencies = {},
340
- ): Promise<WorkChatgptContinuationResult> {
341
- const store = { controllerHome: input.controllerHome, repoId: input.repoId };
342
- const existing = getChatgptWorkConversationBinding(store, input.workId);
343
- const authorizationGrantRefs = new Set(
344
- [...(existing?.authorizationGrantRefs ?? []), ...(input.authorizationGrantRefs ?? [])]
345
- .map((ref) => ref.trim())
346
- .filter(Boolean),
347
- );
348
- const transportConversation = input.transportConversation ?? 'bound';
349
- const seedUrl = transportConversation === 'fresh' ? undefined : input.conversationUrl?.trim() || existing?.conversationUrl;
350
- const model = normalizeModel(input.model);
351
- const reasoning = normalizeControllerReasoning(input.reasoning);
352
- const tabPolicy = transportConversation === 'fresh' ? 'new' : normalizeTabPolicy(input.tabPolicy);
353
- const { bridgeRuntime, host } = resolveChatgptProviderDeliveryHost(dependencies);
354
- const authorityInputError = controllerRoundAuthorityInputError(input);
355
- if (authorityInputError) {
356
- const browserSessionId = bridgeRuntime
357
- ? stableChatgptWorkBridgeSessionId(input.repoId, input.workId)
358
- : resolveChatgptWorkBrowserSessionId({
359
- repoId: input.repoId,
360
- workId: input.workId,
361
- tabPolicy,
362
- explicitSessionId: input.browserSessionId,
363
- boundSessionId: existing?.latestBrowserSessionId,
364
- });
365
- return {
366
- status: 'failed',
367
- provider: bridgeRuntime ? 'chatgpt-bridge' : 'controller-browser',
368
- browserSessionId,
369
- conversationUrl: seedUrl,
370
- conversationId: existing?.conversationId,
371
- localAlias: existing?.localAlias,
372
- resumedFromBinding: Boolean(existing),
373
- model,
374
- reasoning,
375
- tabPolicy,
376
- executionPreferenceVerified: false,
377
237
  authorizationGrantRefs: [...authorizationGrantRefs],
378
238
  error: {
379
- code: 'CHATGPT_CONTROLLER_ROUND_AUTHORITY_INCOMPLETE',
380
- message: authorityInputError.message,
381
- },
382
- };
383
- }
384
-
385
- const sessionId = resolveChatgptWorkBrowserSessionId({
386
- repoId: input.repoId,
387
- workId: input.workId,
388
- tabPolicy,
389
- explicitSessionId: input.browserSessionId,
390
- boundSessionId: existing?.latestBrowserSessionId,
391
- });
392
- let binding: ChatgptWorkConversationBinding | undefined = existing;
393
- const deliverySessionId = bridgeRuntime
394
- ? stableChatgptWorkBridgeSessionId(input.repoId, input.workId)
395
- : sessionId;
396
-
397
- try {
398
- const work = getWorkContract(store, input.workId);
399
- if (!work || work.repoId !== input.repoId) {
400
- throw new Error(`CHATGPT_WORK_CONTRACT_NOT_FOUND: ${input.repoId}:${input.workId}`);
401
- }
402
- const targetForgeInstanceId = work.executionPlacement?.forgeInstanceId?.trim();
403
- if (targetForgeInstanceId) {
404
- const currentForgeInstanceId = readForgeInstanceIdentity(input.controllerHome)?.instanceId?.trim();
405
- if (currentForgeInstanceId !== targetForgeInstanceId) {
406
- throw new ChatgptExecutionPlacementError(targetForgeInstanceId, currentForgeInstanceId);
407
- }
408
- }
409
- if (!bridgeRuntime && seedUrl && !binding && hasChatgptConversationIdentity(seedUrl)) {
410
- binding = bindChatgptWorkConversation(store, {
411
- workId: input.workId,
412
- conversationUrl: seedUrl,
413
- latestBrowserSessionId: deliverySessionId,
414
- authorizationGrantRefs: [...authorizationGrantRefs],
415
- localAlias: input.title,
416
- });
417
- }
418
- const targetUrl = transportConversation === 'fresh' ? 'https://chatgpt.com/' : binding?.conversationUrl ?? seedUrl ?? 'https://chatgpt.com/';
419
- const renderedPrompt = `${workflowToolAttributionInstruction(input)}\n\n${input.prompt}`;
420
- const delivery = await withChatgptBrowserActionOrigin(
421
- { surface: input.originSurface ?? 'chatgpt-action', actor: 'chatgpt-work-continuation' },
422
- () => host.dispatch({
423
- controllerHome: input.controllerHome,
424
- repoId: input.repoId,
425
- repoRoot: input.repoRoot,
426
- workId: input.workId,
427
- prompt: renderedPrompt,
428
- browserSessionId: deliverySessionId,
429
- targetUrl,
430
- model,
431
- reasoning,
432
- timeoutMs: input.timeoutMs,
433
- }),
434
- authorizationGrantRefs,
435
- );
436
- const observedUrl = delivery.conversationUrl ?? targetUrl;
437
- const mayPersistObservedConversation = delivery.status === 'dispatch_confirmed' || delivery.status === 'outcome_unknown';
438
- if (mayPersistObservedConversation && /\/c\/[^/?#]+/.test(observedUrl)) {
439
- const observedIdentity = parseChatgptConversationIdentity(observedUrl);
440
- binding = binding && binding.conversationId !== observedIdentity.conversationId
441
- ? rebindChatgptWorkConversation(store, {
442
- workId: input.workId,
443
- previousConversationId: binding.conversationId,
444
- conversationUrl: observedUrl,
445
- latestBrowserSessionId: delivery.browserSessionId,
446
- authorizationGrantRefs: [...authorizationGrantRefs],
447
- localAlias: binding.localAlias ?? input.title,
448
- })
449
- : bindChatgptWorkConversation(store, {
450
- workId: input.workId,
451
- conversationUrl: observedUrl,
452
- latestBrowserSessionId: delivery.browserSessionId,
453
- authorizationGrantRefs: [...authorizationGrantRefs],
454
- localAlias: binding?.localAlias ?? input.title,
455
- });
456
- }
457
- if (delivery.status !== 'dispatch_confirmed') {
458
- return {
459
- status: 'failed',
460
- provider: delivery.provider,
461
- browserSessionId: delivery.browserSessionId,
462
- conversationUrl: binding?.conversationUrl ?? delivery.conversationUrl ?? seedUrl,
463
- conversationId: binding?.conversationId,
464
- localAlias: binding?.localAlias,
465
- resumedFromBinding: Boolean(existing),
466
- model,
467
- reasoning,
468
- tabPolicy,
469
- executionPreferenceVerified: delivery.executionPreferenceVerified,
470
- authorizationGrantRefs: [...authorizationGrantRefs],
471
- providerDeliveryStatus: delivery.status,
472
- error: delivery.error ?? { code: `CHATGPT_PROVIDER_${delivery.status.toUpperCase()}`, message: delivery.status },
473
- };
474
- }
475
- return {
476
- status: 'dispatched',
477
- provider: delivery.provider,
478
- browserSessionId: delivery.browserSessionId,
479
- conversationUrl: binding?.conversationUrl ?? observedUrl,
480
- conversationId: binding?.conversationId,
481
- localAlias: binding?.localAlias,
482
- resumedFromBinding: Boolean(existing),
483
- model,
484
- reasoning,
485
- tabPolicy,
486
- executionPreferenceVerified: delivery.executionPreferenceVerified,
487
- authorizationGrantRefs: [...authorizationGrantRefs],
488
- providerDeliveryStatus: delivery.status,
489
- };
490
- } catch (error) {
491
- const provider = bridgeRuntime ? 'chatgpt-bridge' : 'controller-browser';
492
- const fallbackSessionId = bridgeRuntime ? deliverySessionId : sessionId;
493
- return {
494
- status: 'failed',
495
- provider,
496
- browserSessionId: fallbackSessionId,
497
- conversationUrl: binding?.conversationUrl ?? seedUrl,
498
- conversationId: binding?.conversationId,
499
- localAlias: binding?.localAlias,
500
- resumedFromBinding: Boolean(existing),
501
- model,
502
- reasoning,
503
- tabPolicy,
504
- executionPreferenceVerified: false,
505
- authorizationGrantRefs: [...authorizationGrantRefs],
506
- error: {
507
- code: error instanceof ChatgptExecutionPlacementError
508
- ? error.code
509
- : error instanceof Error && error.message.includes(':')
510
- ? error.message.split(':', 1)[0]
511
- : bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
239
+ code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
512
240
  message: error instanceof Error ? error.message : String(error),
513
241
  },
514
242
  };
@@ -0,0 +1,238 @@
1
+ import { spawn } from 'child_process';
2
+ import { mkdirSync } from 'fs';
3
+ import { tmpdir } from 'os';
4
+ import { join } from 'path';
5
+ import { redactProcessOutput } from '../../../effects/process-runner';
6
+ import { resolveProviderMcpBootstrap } from './provider-mcp-bootstrap';
7
+ import {
8
+ buildCodexControllerInvocation,
9
+ launcherProcessEnvironment,
10
+ resolveLauncherExecutable,
11
+ } from './thin-launcher';
12
+
13
+ const LOCAL_CONVERSATION_TIMEOUT_MS = 5 * 60_000;
14
+ const LOCAL_CONVERSATION_MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
15
+ const LOCAL_CONVERSATION_MAX_PROMPT_CHARS = 20_000;
16
+ const LOCAL_CONVERSATION_ID = /^[A-Za-z0-9._:-]{1,160}$/;
17
+
18
+ export interface LocalConversationProviderStatus {
19
+ provider: 'codex';
20
+ status: 'ready' | 'not_configured' | 'unavailable';
21
+ label: string;
22
+ detail: string;
23
+ streaming: boolean;
24
+ tools: boolean;
25
+ }
26
+
27
+ export interface LocalConversationSendInput {
28
+ controllerHome: string;
29
+ conversationId: string;
30
+ providerSessionId?: string;
31
+ prompt: string;
32
+ repoId?: string;
33
+ timeoutMs?: number;
34
+ }
35
+
36
+ export interface LocalConversationSendResult {
37
+ provider: 'codex';
38
+ status: 'completed';
39
+ conversationId: string;
40
+ providerSessionId: string;
41
+ output: string;
42
+ toolActivityCount: number;
43
+ }
44
+
45
+ export interface ParsedCodexConversationEvents {
46
+ providerSessionId?: string;
47
+ output?: string;
48
+ toolActivityCount: number;
49
+ }
50
+
51
+ function record(value: unknown): Record<string, unknown> | undefined {
52
+ return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
53
+ }
54
+
55
+ function boundedTimeout(value: number | undefined): number {
56
+ if (!Number.isFinite(value)) return LOCAL_CONVERSATION_TIMEOUT_MS;
57
+ return Math.max(5_000, Math.min(10 * 60_000, Math.trunc(value!)));
58
+ }
59
+
60
+ function agentMessageText(item: Record<string, unknown>): string | undefined {
61
+ if (typeof item.text === 'string' && item.text.trim()) return item.text.trim();
62
+ if (typeof item.output_text === 'string' && item.output_text.trim()) return item.output_text.trim();
63
+ if (!Array.isArray(item.content)) return undefined;
64
+ const text = item.content.map((entry) => {
65
+ const content = record(entry);
66
+ if (!content) return '';
67
+ if (typeof content.text === 'string') return content.text;
68
+ if (typeof content.output_text === 'string') return content.output_text;
69
+ return '';
70
+ }).filter(Boolean).join('\n').trim();
71
+ return text || undefined;
72
+ }
73
+
74
+ export function parseCodexConversationJsonl(stdout: string): ParsedCodexConversationEvents {
75
+ let providerSessionId: string | undefined;
76
+ let output: string | undefined;
77
+ let toolActivityCount = 0;
78
+ for (const line of stdout.split(/\r?\n/)) {
79
+ const trimmed = line.trim();
80
+ if (!trimmed.startsWith('{')) continue;
81
+ let event: Record<string, unknown> | undefined;
82
+ try { event = record(JSON.parse(trimmed)); } catch { continue; }
83
+ if (!event) continue;
84
+ const type = typeof event.type === 'string' ? event.type : '';
85
+ if (type === 'thread.started' && typeof event.thread_id === 'string' && event.thread_id.trim()) {
86
+ providerSessionId = event.thread_id.trim();
87
+ }
88
+ if (type !== 'item.completed') continue;
89
+ const item = record(event.item);
90
+ if (!item) continue;
91
+ const itemType = typeof item.type === 'string' ? item.type : '';
92
+ if (itemType === 'agent_message') {
93
+ output = agentMessageText(item) ?? output;
94
+ continue;
95
+ }
96
+ if (['mcp_tool_call', 'command_execution', 'file_change', 'web_search'].includes(itemType)) {
97
+ toolActivityCount += 1;
98
+ }
99
+ }
100
+ return { providerSessionId, output, toolActivityCount };
101
+ }
102
+
103
+ function localConversationCwd(): string {
104
+ const root = join(tmpdir(), 'forge-local-controller');
105
+ mkdirSync(root, { recursive: true, mode: 0o700 });
106
+ return root;
107
+ }
108
+
109
+ function conversationPrompt(prompt: string, repoId?: string): string {
110
+ return [
111
+ 'You are the Forge Desktop local controller.',
112
+ 'Use the injected Forge MCP capabilities for repository, Runtime, and other Forge operations. Do not create Requirement, Plan, Work, ControllerRound, or a scheduled continuation unless the user explicitly requests that durable lifecycle.',
113
+ repoId
114
+ ? `Attached repository: ${repoId}. Pass repo_id=${repoId} to Forge capabilities that require repository scope.`
115
+ : 'No repository is attached. Do not guess a repository identity.',
116
+ '',
117
+ prompt,
118
+ ].join('\n');
119
+ }
120
+
121
+ export function readLocalConversationProviderStatus(cwd: string = process.cwd()): LocalConversationProviderStatus {
122
+ try {
123
+ resolveLauncherExecutable({ controllerType: 'codex', cwd });
124
+ return {
125
+ provider: 'codex',
126
+ status: 'ready',
127
+ label: 'Codex 已连接',
128
+ detail: '使用 Codex CLI 的现有登录;Forge 操作通过当前 Runtime MCP capability 执行。',
129
+ streaming: false,
130
+ tools: true,
131
+ };
132
+ } catch (error) {
133
+ const message = error instanceof Error ? error.message : String(error);
134
+ const missing = message.startsWith('LAUNCHER_EXECUTABLE_UNAVAILABLE');
135
+ return {
136
+ provider: 'codex',
137
+ status: missing ? 'not_configured' : 'unavailable',
138
+ label: missing ? 'Codex CLI 未安装' : 'Codex 暂不可用',
139
+ detail: missing ? '安装并登录 Codex CLI 后即可使用本地会话。' : message,
140
+ streaming: false,
141
+ tools: false,
142
+ };
143
+ }
144
+ }
145
+
146
+ function runCodexConversation(
147
+ executable: string,
148
+ args: string[],
149
+ env: NodeJS.ProcessEnv,
150
+ cwd: string,
151
+ timeoutMs: number,
152
+ ): Promise<{ stdout: string; stderr: string }> {
153
+ return new Promise((resolve, reject) => {
154
+ const child = spawn(executable, args, {
155
+ cwd,
156
+ env,
157
+ stdio: ['ignore', 'pipe', 'pipe'],
158
+ });
159
+ let stdout = '';
160
+ let stderr = '';
161
+ let settled = false;
162
+ const fail = (error: Error) => {
163
+ if (settled) return;
164
+ settled = true;
165
+ clearTimeout(timer);
166
+ reject(error);
167
+ };
168
+ const append = (current: string, chunk: unknown, stream: 'stdout' | 'stderr'): string => {
169
+ const next = `${current}${Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk ?? '')}`;
170
+ if (Buffer.byteLength(next, 'utf8') > LOCAL_CONVERSATION_MAX_OUTPUT_BYTES) {
171
+ child.kill('SIGTERM');
172
+ fail(new Error(`LOCAL_CONVERSATION_${stream.toUpperCase()}_TOO_LARGE`));
173
+ return current;
174
+ }
175
+ return next;
176
+ };
177
+ child.stdout?.on('data', (chunk) => { stdout = append(stdout, chunk, 'stdout'); });
178
+ child.stderr?.on('data', (chunk) => { stderr = append(stderr, chunk, 'stderr'); });
179
+ child.once('error', (error) => fail(new Error(`LOCAL_CONVERSATION_PROVIDER_START_FAILED: ${error.message}`)));
180
+ child.once('close', (code, signal) => {
181
+ if (settled) return;
182
+ settled = true;
183
+ clearTimeout(timer);
184
+ if (code !== 0) {
185
+ const detail = redactProcessOutput(stderr.trim() || stdout.trim()).replace(/\s+/g, ' ').slice(0, 1200);
186
+ reject(new Error(`LOCAL_CONVERSATION_PROVIDER_FAILED: code=${String(code ?? 'null')} signal=${signal ?? 'none'}${detail ? `; ${detail}` : ''}`));
187
+ return;
188
+ }
189
+ resolve({ stdout, stderr });
190
+ });
191
+ const timer = setTimeout(() => {
192
+ child.kill('SIGTERM');
193
+ fail(new Error('LOCAL_CONVERSATION_PROVIDER_TIMEOUT'));
194
+ }, timeoutMs);
195
+ });
196
+ }
197
+
198
+ export async function sendLocalConversation(input: LocalConversationSendInput): Promise<LocalConversationSendResult> {
199
+ const conversationId = input.conversationId.trim();
200
+ const prompt = input.prompt.trim();
201
+ const providerSessionId = input.providerSessionId?.trim();
202
+ const repoId = input.repoId?.trim();
203
+ if (!LOCAL_CONVERSATION_ID.test(conversationId)) throw new Error('LOCAL_CONVERSATION_ID_INVALID');
204
+ if (!prompt || prompt.length > LOCAL_CONVERSATION_MAX_PROMPT_CHARS) throw new Error('LOCAL_CONVERSATION_PROMPT_INVALID');
205
+ if (providerSessionId && !LOCAL_CONVERSATION_ID.test(providerSessionId)) throw new Error('LOCAL_CONVERSATION_PROVIDER_SESSION_INVALID');
206
+ if (repoId && repoId.length > 256) throw new Error('LOCAL_CONVERSATION_REPOSITORY_INVALID');
207
+
208
+ const cwd = localConversationCwd();
209
+ const executable = resolveLauncherExecutable({ controllerType: 'codex', cwd });
210
+ const bootstrap = resolveProviderMcpBootstrap(input.controllerHome, 'codex', `local-${conversationId}`);
211
+ const invocation = buildCodexControllerInvocation({
212
+ executable,
213
+ prompt: conversationPrompt(prompt, repoId),
214
+ mcpBootstrap: bootstrap,
215
+ sandbox: 'read-only',
216
+ resumeSessionId: providerSessionId,
217
+ json: true,
218
+ });
219
+ const completed = await runCodexConversation(
220
+ invocation.executable,
221
+ invocation.args,
222
+ launcherProcessEnvironment(bootstrap.env),
223
+ cwd,
224
+ boundedTimeout(input.timeoutMs),
225
+ );
226
+ const parsed = parseCodexConversationJsonl(completed.stdout);
227
+ const resolvedProviderSessionId = parsed.providerSessionId ?? providerSessionId;
228
+ if (!resolvedProviderSessionId) throw new Error('LOCAL_CONVERSATION_PROVIDER_SESSION_MISSING');
229
+ if (!parsed.output?.trim()) throw new Error('LOCAL_CONVERSATION_RESPONSE_MISSING');
230
+ return {
231
+ provider: 'codex',
232
+ status: 'completed',
233
+ conversationId,
234
+ providerSessionId: resolvedProviderSessionId,
235
+ output: parsed.output.trim(),
236
+ toolActivityCount: parsed.toolActivityCount,
237
+ };
238
+ }
@@ -73,8 +73,11 @@ export function codexMcpConfigArgs(bootstrap: ProviderMcpBootstrap): string[] {
73
73
  .map(([key, value]) => `${JSON.stringify(key)}=${JSON.stringify(value)}`)
74
74
  .join(',')}}`;
75
75
  return [
76
+ // Replace the entire table: Codex rejects a merged URL + persisted stdio
77
+ // transport even when command/args are overridden separately.
78
+ '-c', `mcp_servers.forge={url=${JSON.stringify(bootstrap.url)}, bearer_token_env_var=${JSON.stringify(bootstrap.bearerTokenEnvVar)}, http_headers=${headerTable}}`,
79
+ // Keep the explicit URL override visible for diagnostics; the complete
80
+ // table above has already removed the persisted stdio transport.
76
81
  '-c', `mcp_servers.forge.url=${JSON.stringify(bootstrap.url)}`,
77
- '-c', `mcp_servers.forge.bearer_token_env_var=${JSON.stringify(bootstrap.bearerTokenEnvVar)}`,
78
- '-c', `mcp_servers.forge.http_headers=${headerTable}`,
79
82
  ];
80
83
  }