@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
@@ -1,3 +1,4 @@
1
+ import { FORGE_INSTANCE_SCOPE_KEY } from '../../src/cli/repositories/controller-home';
1
2
  import { withControllerLock } from '../../src/cli/repositories/locks';
2
3
  import { readControlPlaneRecord, writeControlPlaneRecord } from '../../src/runtime/control-plane/persistence/sqlite-store';
3
4
  import type { ControllerBinding } from '../../packages/kernel/controller/api/index';
@@ -7,7 +8,8 @@ const NAMESPACE = 'chatgpt_controller_binding';
7
8
  export interface ChatgptControllerBindingPayload {
8
9
  schemaVersion: 1;
9
10
  bindingId: string;
10
- repoId: string;
11
+ /** Optional repository provenance only. */
12
+ repoId?: string;
11
13
  workId: string;
12
14
  sessionId: string;
13
15
  browserSessionId?: string;
@@ -17,39 +19,116 @@ export interface ChatgptControllerBindingPayload {
17
19
  reasoning?: 'medium' | 'high' | 'xhigh';
18
20
  tabPolicy?: 'auto' | 'reuse' | 'new';
19
21
  timeoutMs?: number;
22
+ /** Provider transport choice captured by launcher admission; not lifecycle authority. */
23
+ transportConversation?: 'bound' | 'fresh';
24
+ /** Initial provider hint captured for the queued ControllerRound only. */
25
+ continuationPrompt?: string;
26
+ authorizationGrantRefs?: string[];
20
27
  createdAt: string;
21
28
  updatedAt: string;
22
29
  }
23
30
 
24
- function bindingId(repoId: string, workId: string): string {
31
+ export function chatgptControllerProviderBindingId(workId: string): string {
32
+ return `chatgpt-controller:${workId}`;
33
+ }
34
+
35
+ function canonicalBindingId(workId: string): string {
36
+ return chatgptControllerProviderBindingId(workId);
37
+ }
38
+
39
+ function legacyBindingId(repoId: string, workId: string): string {
25
40
  return `chatgpt-controller:${repoId}:${workId}`;
26
41
  }
27
42
 
43
+ function readBinding(
44
+ controllerHome: string,
45
+ workId: string,
46
+ repoId?: string,
47
+ ): { value: ChatgptControllerBindingPayload; revision: number } | undefined {
48
+ const canonicalId = canonicalBindingId(workId);
49
+ const canonical = readControlPlaneRecord<ChatgptControllerBindingPayload>(
50
+ controllerHome,
51
+ NAMESPACE,
52
+ FORGE_INSTANCE_SCOPE_KEY,
53
+ canonicalId,
54
+ );
55
+ const legacy = repoId?.trim()
56
+ ? readControlPlaneRecord<ChatgptControllerBindingPayload>(
57
+ controllerHome,
58
+ NAMESPACE,
59
+ repoId.trim(),
60
+ legacyBindingId(repoId.trim(), workId),
61
+ )
62
+ : undefined;
63
+ if (canonical && legacy) {
64
+ const left = canonical.value;
65
+ const right = legacy.value;
66
+ if (left.workId !== right.workId
67
+ || left.sessionId !== right.sessionId
68
+ || (left.conversationUrl ?? '') !== (right.conversationUrl ?? '')) {
69
+ throw new Error(`CHATGPT_CONTROLLER_BINDING_COLLISION: ${workId}`);
70
+ }
71
+ }
72
+ return canonical ?? legacy;
73
+ }
74
+
28
75
  export function upsertChatgptControllerBinding(
29
- options: { controllerHome: string; repoId: string; now?: () => string },
76
+ options: { controllerHome: string; repoId?: string; now?: () => string },
30
77
  input: Omit<ChatgptControllerBindingPayload, 'schemaVersion' | 'bindingId' | 'repoId' | 'createdAt' | 'updatedAt'>,
31
78
  ): { binding: ControllerBinding; payload: ChatgptControllerBindingPayload } {
32
- const id = bindingId(options.repoId, input.workId);
33
- return withControllerLock(options.controllerHome, { scope: 'task', repoId: options.repoId, taskId: `chatgpt-controller-binding-${input.workId}` }, `chatgpt-controller-binding:${id}`, () => {
34
- const current = readControlPlaneRecord<ChatgptControllerBindingPayload>(options.controllerHome, NAMESPACE, options.repoId, id);
35
- const at = options.now?.() ?? new Date().toISOString();
36
- const payload: ChatgptControllerBindingPayload = {
37
- ...(current?.value ?? {} as ChatgptControllerBindingPayload),
38
- ...input,
39
- schemaVersion: 1, bindingId: id, repoId: options.repoId,
40
- createdAt: current?.value.createdAt ?? at, updatedAt: at,
41
- };
42
- writeControlPlaneRecord(options.controllerHome, {
43
- namespace: NAMESPACE, scope: options.repoId, key: id, schemaVersion: 1, value: payload,
44
- action: current ? 'chatgpt_controller_binding_update' : 'chatgpt_controller_binding_create',
45
- expectedRevision: current?.revision ?? null,
46
- });
47
- return { binding: { bindingId: id, hostKind: 'chatgpt', adapterRef: id }, payload };
48
- });
79
+ const id = canonicalBindingId(input.workId);
80
+ return withControllerLock(
81
+ options.controllerHome,
82
+ { scope: 'global', resource: `chatgpt-controller-binding:${input.workId}` },
83
+ `chatgpt-controller-binding:${id}`,
84
+ () => {
85
+ const current = readBinding(options.controllerHome, input.workId, options.repoId);
86
+ const at = options.now?.() ?? new Date().toISOString();
87
+ const payload: ChatgptControllerBindingPayload = {
88
+ ...(current?.value ?? {} as ChatgptControllerBindingPayload),
89
+ ...input,
90
+ schemaVersion: 1,
91
+ bindingId: id,
92
+ ...(options.repoId?.trim() ? { repoId: options.repoId.trim() } : {}),
93
+ createdAt: current?.value.createdAt ?? at,
94
+ updatedAt: at,
95
+ };
96
+ writeControlPlaneRecord(options.controllerHome, {
97
+ namespace: NAMESPACE,
98
+ scope: FORGE_INSTANCE_SCOPE_KEY,
99
+ key: id,
100
+ schemaVersion: 1,
101
+ value: payload,
102
+ action: current ? 'chatgpt_controller_binding_update' : 'chatgpt_controller_binding_create',
103
+ expectedRevision: readControlPlaneRecord<ChatgptControllerBindingPayload>(
104
+ options.controllerHome,
105
+ NAMESPACE,
106
+ FORGE_INSTANCE_SCOPE_KEY,
107
+ id,
108
+ )?.revision ?? null,
109
+ });
110
+ return { binding: { bindingId: id, hostKind: 'chatgpt', adapterRef: id }, payload };
111
+ },
112
+ );
49
113
  }
50
114
 
51
115
  export function getChatgptControllerBindingPayload(
52
- options: { controllerHome: string; repoId: string }, adapterRef: string,
116
+ options: { controllerHome: string; repoId?: string },
117
+ adapterRef: string,
53
118
  ): ChatgptControllerBindingPayload | undefined {
54
- return readControlPlaneRecord<ChatgptControllerBindingPayload>(options.controllerHome, NAMESPACE, options.repoId, adapterRef)?.value;
119
+ const canonical = readControlPlaneRecord<ChatgptControllerBindingPayload>(
120
+ options.controllerHome,
121
+ NAMESPACE,
122
+ FORGE_INSTANCE_SCOPE_KEY,
123
+ adapterRef,
124
+ )?.value;
125
+ if (canonical) return canonical;
126
+ const repoId = options.repoId?.trim();
127
+ if (!repoId) return undefined;
128
+ return readControlPlaneRecord<ChatgptControllerBindingPayload>(
129
+ options.controllerHome,
130
+ NAMESPACE,
131
+ repoId,
132
+ adapterRef,
133
+ )?.value;
55
134
  }
@@ -14,31 +14,31 @@ export function buildChatgptControllerRoundPrompt(
14
14
  const snapshot = readControllerRoundContextSnapshot(options, record);
15
15
  const requirementLine = snapshot.requirement
16
16
  ? `Requirement ${snapshot.requirement.requirementId}:state=${snapshot.requirement.state};outcome=${snapshot.requirement.outcomeStatement}`
17
- : `当前未绑定 durable Requirement;语义 relay scope 为 ${snapshot.relayScopeId}。`;
17
+ : '当前未绑定 durable Requirement。';
18
18
  const workLines = snapshot.works.length > 0
19
19
  ? snapshot.works.map((work) => {
20
- const summary = `- ${work.workId}:status=${work.status};phase=${work.phase};updated=${work.updatedAt};objective=${work.objective}`;
20
+ const summary = `- ${work.workId}:updated=${work.updatedAt};objective=${work.objective}`;
21
21
  if (work.workId !== snapshot.originWorkId || work.acceptanceCriteria.length === 0) return summary;
22
22
  return [
23
23
  summary,
24
- ' origin Work acceptanceCriteria(durable semantic contract):',
24
+ ' origin Work acceptanceCriteria:',
25
25
  ...work.acceptanceCriteria.map((criterion, index) => ` ${index + 1}. ${criterion}`),
26
26
  ].join('\n');
27
27
  }).join('\n')
28
28
  : '- 未找到关联 Work 快照';
29
29
  const originWork = snapshot.works.find((work) => work.workId === snapshot.originWorkId);
30
- const terminalOriginGuidance = originWork?.status === 'completed'
31
- ? `origin Work ${snapshot.originWorkId} 已 completed。禁止再次 controller_claim/reclaim 这个 terminal Work。若它是 validating 的 Plan predecessor:先用当前 round authority 做 plan_accept_step;再显式 start 唯一 successor(related_work_id=${snapshot.originWorkId}, work_relation=continue,并显式提供 work_kind/所需 engineering_preconditions 以及同一 controller_authority_id + relay_scope_id);start 成功后 successor 只做 mechanical bind、不得抢占 ownership;随后显式提交 continue_immediately 得到 pending_release,最后 controller_release predecessor 触发新的 successor ControllerRound。`
30
+ const terminalOriginGuidance = originWork?.state === 'completed'
31
+ ? `origin Work ${snapshot.originWorkId} 的持久状态已完成。不要重新打开它;重新读取 Requirement/Plan/Work 语义事实,由模型决定是否仍有新的明确工作。`
32
32
  : undefined;
33
33
  const handoffLines = snapshot.handoffs.length > 0
34
34
  ? snapshot.handoffs.map((handoff) => `- ${handoff.id}:status=${handoff.status};work=${handoff.workId ?? 'repo'};${handoff.title};reason=${handoff.reason}`).join('\n')
35
35
  : '- 当前没有 active linked Handoff';
36
36
  return [
37
- `继续 Forge Requirement/Goal relay ${snapshot.relayScopeId},repo=${snapshot.repoId}。`,
38
- '这是新的 ChatGPT controller round。第一步必须重新读取最新 Forge Requirement/Work/Handoff 状态;下面的快照只用于启动提示,不能代替 durable state。',
37
+ `继续 Forge ${snapshot.requirement ? `Requirement ${snapshot.requirement.requirementId}` : `Work ${snapshot.originWorkId}`},repo=${snapshot.repoId}。`,
38
+ '下面快照来自本轮 claim-time durable state,用它直接恢复上下文。只有某个事实的新鲜度会实质改变下一次具体 domain action 时,才针对性重新读取;不要把本轮先消耗在重复读取 Requirement/Plan/Work/UserRequest 或 lifecycle bookkeeping 上。',
39
39
  requirementLine,
40
40
  `关联 Work 快照:\n${workLines}`,
41
- 'origin Work 的 objective 与 acceptanceCriteria 是本轮必须显式检查的 durable semantic contract;若最新事实满足其中更具体的终态义务,不得仅凭通用 disposition 指导改写成另一种终态。',
41
+ 'origin Work 的 objective 与 acceptanceCriteria 是需要显式检查的 durable semantic contract;语义结论只来自最新事实与模型判断。',
42
42
  `Active Handoff 快照:\n${handoffLines}`,
43
43
  ...(snapshot.assistantContext ? [snapshot.assistantContext] : []),
44
44
  ...(snapshot.executionQualitySignals?.length ? [
@@ -46,24 +46,14 @@ export function buildChatgptControllerRoundPrompt(
46
46
  'Review this evidence before repeating the same operation. Diagnose semantically; record whether an adjustment is justified. Do not infer a bug from edit counts, discard mandatory checks, widen authority or create another supervisor.',
47
47
  ] : []),
48
48
  promptOptions.exactOriginWork
49
- ? `这是 Work-bound scheduled round。只允许 claim 并推进 origin Work ${snapshot.originWorkId}。不得选择、启动、delegate、resume sibling Work,不得新建 schedule,也不得扩大 scope。如果经过一次有界诊断或修复后仍无法安全推进,记录精确证据,提交 wait 或带 active Handoff 的 wait_for_user,释放 ownership,然后结束本轮。`
50
- : `上一轮 relay 的 origin Work 是 ${snapshot.originWorkId}。不要假设下一步必须继续该 Work;必须依据最新 semantic state 选择、启动或 claim 正确的 Work。`,
49
+ ? `只推进 origin Work ${snapshot.originWorkId} 的既定范围。若存在真实用户授权/判断 blocker,记录一个去重的 UserRequest;否则继续可执行工作。`
50
+ : `origin Work 是 ${snapshot.originWorkId}。不要假设下一步必须继续它;依据最新 semantic state 选择现有或新的明确 Work。`,
51
51
  ...(terminalOriginGuidance ? [terminalOriginGuidance] : []),
52
- `机械 relay 预算:round=${snapshot.round.count}/${snapshot.round.maxRounds};repeated_state=${snapshot.round.repeatedStateCount}/${snapshot.round.maxRepeatedState};consecutive_failures=${snapshot.round.consecutiveFailures}/${snapshot.round.maxFailures}。`,
53
- '仓库中的工程、验收、安全和权限约束始终有效。但如果某条 Skill/tool 指令明确限定为其他 Controller host/runtime(例如“仅 Codex 使用/发现的 Skill”),它不是 ChatGPT 当前 round 的硬 capability gate,也不得仅为了满足该 host wording 而 delegate;应使用当前 ChatGPT/Forge 已有能力完成同一工程目标,或基于真实缺失能力提交精确 blocker。',
54
- record.authorityId
55
- ? `本轮 durable controller authority 为 controller_authority_id=${record.authorityId}。在 controller_claim、plan_accept_step、continue、verify、review、finalize、stop、controller_release 以及 terminal-successor start 中,必须保持同一个 controller_authority_id 与 relay_scope_id=${record.relayScopeId}。Frozen client 第一次 claim 使用 controller.round:controller_claim:${record.authorityId}:${record.relayScopeId};plan_accept_step、continue、verify、finalize、stop、controller_release 使用 controller.round:<operation>:${record.authorityId}:${record.relayScopeId} authority;review 必须使用 controller.round:review:<approved|changes_required|blocked>:${record.authorityId}:${record.relayScopeId},并通过 reason 携带 review rationale。若 terminal-successor start 的旧 schema 缺 work_kind/engineering_preconditions/round 字段,使用 bounded semantic start compatibility carrier。绝不能用 transport session id 或其他 Work/conversation authority 替代。`
56
- : '这是没有 controller authority capability 的 legacy relay record;只能沿用已经 claim 的 controller lineage,直到显式恢复本轮。',
57
- ...(snapshot.recoveryReason
58
- ? ['上一轮 ChatGPT 在 liveness grace 到期前没有提交显式 disposition。必须重新读取 durable state,并显式关闭本轮。']
59
- : []),
60
- terminalOriginGuidance
61
- ? `terminal predecessor 必须在显式 successor start 完成 mechanical bind 后,再显式提交一次 continue_immediately;得到 pending_release 后仅释放 predecessor。若没有可执行 successor,则按最新 Plan/Requirement 事实使用 wait、带 active Handoff 的 wait_for_user 或 goal_complete。`
62
- : `如果 Requirement/Goal 需要下一个 controller round,在释放 Work 前提交 continue_immediately,并带 relay_scope_id=${record.relayScopeId}。否则使用 wait、带 active Handoff 的 wait_for_user,或 goal_complete。Frozen MCP client 可使用 controller.disposition:<disposition>:${record.relayScopeId}。`,
63
- '本轮结束协议是强制的:在向用户输出本轮最终回复之前,必须先提交且仅提交一次 semantic disposition,并完成 controller_release;不得只报告“继续中”“下一步继续”或输出进度后结束本轮。',
64
- '如果最新 durable state 表明 Requirement/Goal 尚有可执行工作,且不存在真实 external blocker、active Handoff 或必须由用户决定的边界,则必须选择 continue_immediately。wait 只用于真实等待条件;wait_for_user 必须绑定 active Handoff;goal_complete 只用于 Requirement/Goal 已语义完成。',
65
- '提交 continue_immediately 后必须立即 controller_release 当前 Work。controller_release 是立即续跑的 canonical trigger:Forge 将通过现有 ChatGPT launcher 复用 durable conversation binding 并投递下一 ControllerRound prompt。正常连续推进不得依赖用户再次发送“继续”,也不得用 interval schedule 代替该即时 relay;schedule 只能作为故障恢复/watchdog。',
66
- 'Forge 不得自行推断 semantic next step。现有 Work ownership、Handoff authority 与 external-effect authorization 始终是权威。',
52
+ 'Provider/session binding、transport recovery、dedupe、retry 和 continuation bookkeeping 由 Forge 内部维护,不属于模型工作流,也不是 Requirement/Plan/Work 的第二套语义权威。',
53
+ '执行与验证直接使用当前 domain capability;只有 durable 语义实际变化时才更新 Requirement/Plan/Work。Forge 不替模型推断语义 next step。',
54
+ '如果 origin Work 尚未完成且没有真实 UserRequest/外部 blocker,本轮结束前必须完成至少一个直接推进 objective 的具体 domain action,例如源码修改、进程/检查、typed external effect,或对实现决策有实质作用的源码调查。仅汇报状态、重复读取 lifecycle、刷新进度或说明“下一步要做什么”不算推进。',
55
+ '仓库工程、安全、权限和资源 fence 始终有效。若真实外部条件或用户判断阻塞,记录精确 UserRequest/Handoff;不要为了机械续跑创建 sibling Work、PlanStep 或额外 lifecycle。',
56
+ 'Presentation-only progress:持续较久或包含多轮工具调用时,在关键阶段用 1–2 句 user-visible 进度说明已确认结果、下一件事或真实 blocker。不要逐工具播报,不要输出 private reasoning / chain-of-thought。',
67
57
  ].join('\n');
68
58
  }
69
59
 
@@ -1,7 +1,8 @@
1
+ import { createHash } from 'crypto';
1
2
  import { withControllerLock } from '../../src/cli/repositories/locks';
2
3
  import { readControlPlaneRecord, writeControlPlaneRecord } from '../../src/runtime/control-plane/persistence/sqlite-store';
3
4
 
4
- // Resource-cleanup evidence only. Provider dispatch authority is ControllerRoundRelayRecord.lifecycleStage/providerDispatchReceiptId.
5
+ // Resource-cleanup evidence only. Autonomous outer-turn dispatch authority is the Workflow Supervisor Effect ledger; ControllerRound fields are lower-layer/bootstrap compatibility mirrors.
5
6
  const NAMESPACE = 'chatgpt_controller_round_settlement';
6
7
 
7
8
  export type ChatgptControllerRoundSettlementStatus =
@@ -21,15 +22,67 @@ export interface ChatgptControllerRoundSettlement {
21
22
  status: ChatgptControllerRoundSettlementStatus;
22
23
  recordedAt: string;
23
24
  error?: string;
25
+ /**
26
+ * Opaque identity of the browser resource and grants used for this settlement
27
+ * attempt. A matching failed attempt must not repeatedly call the provider.
28
+ */
29
+ attemptIdentity?: string;
30
+ }
31
+
32
+ function settlementKey(workId: string, relayScopeId: string): string {
33
+ return `${workId}:${relayScopeId}`;
34
+ }
35
+
36
+ /**
37
+ * Keep browser-session and grant identifiers out of durable settlement evidence
38
+ * while preserving the exact retry boundary: a changed session or grant set may
39
+ * be retried, an unchanged failed attempt may not.
40
+ */
41
+ export function chatgptControllerRoundSettlementAttemptIdentity(input: {
42
+ browserSessionId: string;
43
+ authorizationGrantRefs?: readonly string[];
44
+ }): string {
45
+ const identity = {
46
+ browserSessionId: input.browserSessionId.trim(),
47
+ authorizationGrantRefs: [...new Set((input.authorizationGrantRefs ?? [])
48
+ .map((grantRef) => grantRef.trim())
49
+ .filter(Boolean))].sort(),
50
+ };
51
+ return `sha256:${createHash('sha256').update(JSON.stringify(identity)).digest('hex')}`;
52
+ }
53
+
54
+ export function getChatgptControllerRoundSettlement(
55
+ options: { controllerHome: string; repoId: string },
56
+ input: { workId: string; relayScopeId: string },
57
+ ): ChatgptControllerRoundSettlement | undefined {
58
+ return readControlPlaneRecord<ChatgptControllerRoundSettlement>(
59
+ options.controllerHome,
60
+ NAMESPACE,
61
+ options.repoId,
62
+ settlementKey(input.workId, input.relayScopeId),
63
+ )?.value;
24
64
  }
25
65
 
26
66
  export function recordChatgptControllerRoundSettlement(
27
67
  options: { controllerHome: string; repoId: string; now?: () => string },
28
- input: { workId: string; relayScopeId: string; status: ChatgptControllerRoundSettlementStatus; error?: string },
68
+ input: {
69
+ workId: string;
70
+ relayScopeId: string;
71
+ status: ChatgptControllerRoundSettlementStatus;
72
+ error?: string;
73
+ attemptIdentity?: string;
74
+ },
29
75
  ): ChatgptControllerRoundSettlement {
30
- const key = `${input.workId}:${input.relayScopeId}`;
76
+ const key = settlementKey(input.workId, input.relayScopeId);
31
77
  return withControllerLock(options.controllerHome, { scope: 'task', repoId: options.repoId, taskId: `chatgpt-round-settlement-${input.workId}` }, `chatgpt-round-settlement:${key}`, () => {
32
78
  const existing = readControlPlaneRecord<ChatgptControllerRoundSettlement>(options.controllerHome, NAMESPACE, options.repoId, key);
79
+ const error = input.error?.trim().slice(0, 2_000) || undefined;
80
+ const attemptIdentity = input.attemptIdentity?.trim().slice(0, 200) || undefined;
81
+ if (
82
+ existing?.value.status === input.status
83
+ && existing.value.error === error
84
+ && existing.value.attemptIdentity === attemptIdentity
85
+ ) return existing.value;
33
86
  const value: ChatgptControllerRoundSettlement = {
34
87
  schemaVersion: 1,
35
88
  repoId: options.repoId,
@@ -37,7 +90,8 @@ export function recordChatgptControllerRoundSettlement(
37
90
  relayScopeId: input.relayScopeId,
38
91
  status: input.status,
39
92
  recordedAt: options.now?.() ?? new Date().toISOString(),
40
- ...(input.error?.trim() ? { error: input.error.trim().slice(0, 2_000) } : {}),
93
+ ...(error ? { error } : {}),
94
+ ...(attemptIdentity ? { attemptIdentity } : {}),
41
95
  };
42
96
  writeControlPlaneRecord(options.controllerHome, { namespace: NAMESPACE, scope: options.repoId, key, schemaVersion: 1, value, action: 'chatgpt_controller_round_settlement', expectedRevision: existing?.revision ?? null });
43
97
  return value;
@@ -4,6 +4,62 @@ export const DEFAULT_CHATGPT_AUTOMATION_MODEL = 'gpt-5.6';
4
4
  export const DEFAULT_CHATGPT_AUTOMATION_REASONING = 'high';
5
5
  export const DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY = 'auto';
6
6
  export const CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN = 'CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN';
7
+ export const CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT = 'CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT';
8
+ export const CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE = 'CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE';
9
+ export const CHATGPT_AUTOMATION_RATE_LIMITED = 'CHATGPT_AUTOMATION_RATE_LIMITED';
10
+ export const CHATGPT_AUTOMATION_RATE_LIMITED_AFTER_SUBMIT = 'CHATGPT_AUTOMATION_RATE_LIMITED_AFTER_SUBMIT';
11
+ export const CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED = 'CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED';
12
+
13
+ export type ChatgptProviderPageFailureCode =
14
+ | typeof CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT
15
+ | typeof CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE
16
+ | typeof CHATGPT_AUTOMATION_RATE_LIMITED
17
+ | typeof CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED;
18
+
19
+ function normalizeChatgptProviderPageText(value: string): string {
20
+ return value.replace(/\s+/g, ' ').trim().toLowerCase();
21
+ }
22
+
23
+ /** Shared provider-page failure detection used by both direct delivery and durable Supervisor observation. */
24
+ export function chatgptProviderPageFailure(
25
+ bodyText: string | undefined,
26
+ ): ChatgptProviderPageFailureCode | undefined {
27
+ const normalized = normalizeChatgptProviderPageText(bodyText ?? '');
28
+ // Dedicated live provider-status text only. Callers must not pass an
29
+ // unrestricted historical conversation transcript into this classifier.
30
+ if (normalized.includes('你已达到此对话的长度上限')
31
+ || normalized.includes('此对话已达到长度上限')
32
+ || normalized.includes('you have reached the maximum length for this conversation')
33
+ || normalized.includes("you've reached the maximum length for this conversation")
34
+ || normalized.includes('this conversation has reached its maximum length')
35
+ || normalized.includes('you have reached the conversation length limit')) {
36
+ return CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED;
37
+ }
38
+ if (
39
+ normalized.includes('resume stream unavailable')
40
+ || normalized.includes('tokenless_resume_unavailable')
41
+ || normalized.includes('stream recovery polling timed out')
42
+ || normalized.includes('连接已中断,正在等待完整答复')
43
+ || normalized.includes('connection interrupted, waiting for the full response')
44
+ || (normalized.includes('出了点问题') && normalized.includes('请重试'))
45
+ // A standalone current status is termination evidence. The same words in
46
+ // ordinary chat prose or a historical whole-page transcript are not.
47
+ || /^(?:已分析\s+)?(?:分析已暂停|analysis paused)(?:\s+(?:分析已暂停|analysis paused))*$/.test(normalized)
48
+ ) {
49
+ return CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE;
50
+ }
51
+ if (
52
+ normalized.includes('too many requests')
53
+ || normalized.includes('rate limit exceeded')
54
+ || (normalized.includes('http 429') && normalized.includes('rate limit'))
55
+ ) {
56
+ return CHATGPT_AUTOMATION_RATE_LIMITED;
57
+ }
58
+ return ((normalized.includes('message delivery timed out') && normalized.includes('please try again'))
59
+ || (normalized.includes('消息传输超时') && normalized.includes('请重试')))
60
+ ? CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT
61
+ : undefined;
62
+ }
7
63
 
8
64
  export type ChatgptAutomationReasoning = 'medium' | 'high' | 'xhigh';
9
65
  export type ChatgptAutomationTabPolicy = 'auto' | 'reuse' | 'new';
@@ -58,6 +114,172 @@ export interface ChatgptProviderDeliveryHost {
58
114
  dispatch(input: ChatgptProviderDeliveryInput): Promise<ChatgptProviderDeliveryResult>;
59
115
  }
60
116
 
117
+ interface ChatgptProviderDispatchGate {
118
+ tail: Promise<void>;
119
+ queued: number;
120
+ pressureLevel: number;
121
+ cooldownUntilMs: number;
122
+ }
123
+
124
+ const CHATGPT_PROVIDER_BACKPRESSURE_BASE_MS = 2_000;
125
+ const CHATGPT_PROVIDER_BACKPRESSURE_MAX_MS = 30_000;
126
+ const CHATGPT_PROVIDER_EXPLICIT_RETRY_MAX_MS = 120_000;
127
+ const chatgptProviderDispatchGates = new Map<string, ChatgptProviderDispatchGate>();
128
+
129
+ function providerGateKey(controllerHome: string): string {
130
+ return controllerHome.trim() || 'forge-controller';
131
+ }
132
+
133
+ function chatgptProviderDispatchGate(controllerHome: string): ChatgptProviderDispatchGate {
134
+ const key = providerGateKey(controllerHome);
135
+ let gate = chatgptProviderDispatchGates.get(key);
136
+ if (!gate) {
137
+ gate = { tail: Promise.resolve(), queued: 0, pressureLevel: 0, cooldownUntilMs: 0 };
138
+ chatgptProviderDispatchGates.set(key, gate);
139
+ }
140
+ return gate;
141
+ }
142
+
143
+ function retryAfterDelayMs(message: string | undefined): number | undefined {
144
+ if (!message) return undefined;
145
+ const match = message.match(/\bretry[- ]?after\s*[:=]?\s*(\d+(?:\.\d+)?)\s*(ms|milliseconds?|s|sec(?:ond)?s?)?\b/i);
146
+ if (!match) return undefined;
147
+ const amount = Number(match[1]);
148
+ if (!Number.isFinite(amount) || amount <= 0) return undefined;
149
+ const milliseconds = match[2]?.toLowerCase().startsWith('m') ? amount : amount * 1_000;
150
+ return Math.max(1_000, Math.min(CHATGPT_PROVIDER_EXPLICIT_RETRY_MAX_MS, Math.round(milliseconds)));
151
+ }
152
+
153
+ /** Deterministic jitter keeps concurrent callers from reconverging on one provider boundary after cooldown. */
154
+ export function chatgptProviderBackoffDelayMs(
155
+ pressureLevel: number,
156
+ key = 'chatgpt',
157
+ message?: string,
158
+ ): number {
159
+ const explicit = retryAfterDelayMs(message);
160
+ if (explicit !== undefined) return explicit;
161
+ const exponent = Math.max(0, Math.min(8, Math.trunc(pressureLevel) - 1));
162
+ const base = Math.min(CHATGPT_PROVIDER_BACKPRESSURE_MAX_MS, CHATGPT_PROVIDER_BACKPRESSURE_BASE_MS * 2 ** exponent);
163
+ const jitterByte = createHash('sha256').update(`${key}\n${pressureLevel}`).digest()[0] ?? 128;
164
+ const jitter = 0.8 + (jitterByte / 255) * 0.4;
165
+ return Math.max(1_000, Math.min(CHATGPT_PROVIDER_BACKPRESSURE_MAX_MS, Math.round(base * jitter)));
166
+ }
167
+
168
+ export function chatgptProviderFailureRequiresBackpressure(
169
+ status: ChatgptProviderDeliveryStatus | undefined,
170
+ code?: string,
171
+ message?: string,
172
+ ): boolean {
173
+ if (status === 'outcome_unknown') return true;
174
+ const normalized = `${code ?? ''}\n${message ?? ''}`.toUpperCase();
175
+ return normalized.includes('RATE_LIMITED')
176
+ || normalized.includes('TOO MANY REQUESTS')
177
+ || normalized.includes('HTTP 429')
178
+ || normalized.includes('TOKENLESS_RESUME_UNAVAILABLE')
179
+ || normalized.includes('RESPONSE_STREAM_UNAVAILABLE')
180
+ || normalized.includes('MESSAGE_DELIVERY_TIMED_OUT');
181
+ }
182
+
183
+ export function noteChatgptProviderBackpressure(
184
+ controllerHome: string,
185
+ message?: string,
186
+ nowMs = Date.now(),
187
+ ): number {
188
+ const key = providerGateKey(controllerHome);
189
+ const gate = chatgptProviderDispatchGate(controllerHome);
190
+ gate.pressureLevel += 1;
191
+ const delayMs = chatgptProviderBackoffDelayMs(gate.pressureLevel, key, message);
192
+ gate.cooldownUntilMs = Math.max(gate.cooldownUntilMs, nowMs + delayMs);
193
+ return delayMs;
194
+ }
195
+
196
+ export function chatgptProviderBackpressureRemainingMs(
197
+ controllerHome: string,
198
+ nowMs = Date.now(),
199
+ ): number {
200
+ const gate = chatgptProviderDispatchGates.get(providerGateKey(controllerHome));
201
+ return gate ? Math.max(0, gate.cooldownUntilMs - nowMs) : 0;
202
+ }
203
+
204
+ export interface ChatgptProviderDispatchOutcome {
205
+ status?: ChatgptProviderDeliveryStatus;
206
+ code?: string;
207
+ message?: string;
208
+ /**
209
+ * True only when the provider actually accepted this submission. A local
210
+ * transport failure (foreground required, composer missing, transport
211
+ * unavailable) is neither acceptance nor provider backpressure, so it must
212
+ * not clear pressure that a real provider limit established.
213
+ */
214
+ providerAccepted?: boolean;
215
+ }
216
+
217
+ /**
218
+ * One active Runtime owns one transient ChatGPT provider dispatch lane. This is
219
+ * deliberately mechanical and in-memory: ControllerRound effect identity remains
220
+ * the durable replay fence across Runtime rotation, while provider pressure must
221
+ * not become Work/Plan lifecycle state.
222
+ *
223
+ * Provider rate limiting is an account-level resource, so *every* transport that
224
+ * can submit a provider prompt through this Runtime must enter the same lane and
225
+ * obey the same cooldown. A separate lane that only reads the cooldown still
226
+ * submits concurrently with this one, which is exactly how one ChatGPT account
227
+ * observes request concurrency that no single session produced.
228
+ */
229
+ export async function withChatgptProviderDispatchLane<T>(
230
+ controllerHome: string,
231
+ operation: () => Promise<T>,
232
+ outcomeOf: (result: T) => ChatgptProviderDispatchOutcome | undefined,
233
+ ): Promise<T> {
234
+ const key = providerGateKey(controllerHome);
235
+ const gate = chatgptProviderDispatchGate(controllerHome);
236
+
237
+ const predecessor = gate.tail;
238
+ let release!: () => void;
239
+ gate.tail = new Promise<void>((resolve) => { release = resolve; });
240
+ gate.queued += 1;
241
+ await predecessor;
242
+
243
+ try {
244
+ const waitMs = gate.cooldownUntilMs - Date.now();
245
+ if (waitMs > 0) await new Promise((resolve) => setTimeout(resolve, waitMs));
246
+
247
+ const result = await operation();
248
+ const outcome = outcomeOf(result);
249
+ if (outcome && chatgptProviderFailureRequiresBackpressure(outcome.status, outcome.code, outcome.message)) {
250
+ noteChatgptProviderBackpressure(controllerHome, outcome.message);
251
+ } else if (outcome?.providerAccepted === true) {
252
+ gate.pressureLevel = 0;
253
+ gate.cooldownUntilMs = 0;
254
+ }
255
+ return result;
256
+ } catch (error) {
257
+ const message = error instanceof Error ? error.message : String(error);
258
+ if (chatgptProviderFailureRequiresBackpressure(undefined, undefined, message)) {
259
+ noteChatgptProviderBackpressure(controllerHome, message);
260
+ }
261
+ throw error;
262
+ } finally {
263
+ gate.queued -= 1;
264
+ release();
265
+ if (gate.queued === 0 && gate.pressureLevel === 0 && gate.cooldownUntilMs <= Date.now()) {
266
+ chatgptProviderDispatchGates.delete(key);
267
+ }
268
+ }
269
+ }
270
+
271
+ /** Controller-relay delivery: one serialized provider prompt submission lane. */
272
+ export async function dispatchWithChatgptProviderBackpressure(
273
+ controllerHome: string,
274
+ dispatch: () => Promise<ChatgptProviderDeliveryResult>,
275
+ ): Promise<ChatgptProviderDeliveryResult> {
276
+ return await withChatgptProviderDispatchLane(controllerHome, dispatch, (result) => (
277
+ chatgptProviderFailureRequiresBackpressure(result.status, result.error?.code, result.error?.message)
278
+ ? { code: result.error?.code, message: result.error?.message }
279
+ : { providerAccepted: result.status === 'dispatch_confirmed' }
280
+ ));
281
+ }
282
+
61
283
  const CHATGPT_WAIT_FOR_USER_MARKERS = [
62
284
  'LOGIN_REQUIRED',
63
285
  'AUTH_REQUIRED',
@@ -73,7 +295,12 @@ export function classifyChatgptProviderFailure(
73
295
  message?: string,
74
296
  ): ChatgptProviderFailureDisposition {
75
297
  const normalized = `${code ?? ''}\n${message ?? ''}`.toUpperCase();
76
- if (normalized.includes('OUTCOME_UNKNOWN') || normalized.includes('SUBMISSION_NOT_CONFIRMED')) return 'outcome_unknown';
298
+ if (
299
+ normalized.includes('OUTCOME_UNKNOWN')
300
+ || normalized.includes('MESSAGE_DELIVERY_TIMED_OUT')
301
+ || normalized.includes('RESPONSE_STREAM_UNAVAILABLE')
302
+ || normalized.includes('RATE_LIMITED_AFTER_SUBMIT')
303
+ ) return 'outcome_unknown';
77
304
  if (CHATGPT_WAIT_FOR_USER_MARKERS.some((marker) => normalized.includes(marker))) return 'wait_for_user';
78
305
  return 'failed';
79
306
  }