@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,105 +1,53 @@
1
- import { randomUUID } from 'crypto';
2
1
  import type { IncomingMessage, ServerResponse } from 'http';
3
- import { Server, type Tool } from '@modelcontextprotocol/server';
4
- import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
5
- import { McpSessionRegistry, type McpSessionRoute, type McpSessionSnapshot } from '../../../adapters/mcp/transports/session-registry';
2
+ import { createMcpHandler, Server, type Tool } from '@modelcontextprotocol/server';
3
+ import { toNodeHandler } from '@modelcontextprotocol/node';
6
4
  import { FORGE_VERSION } from '../../version';
7
5
 
8
- export const RECOVERY_MCP_SESSION_ROUTE: McpSessionRoute = '/recovery/mcp';
9
- const RECOVERY_MCP_PRINCIPAL_ID = 'standalone-recovery-oauth-client';
10
- const RECOVERY_MCP_CONNECTION_ID = 'forge-standalone-recovery';
11
-
12
6
  export interface RecoveryMcpRequestContext {
13
7
  remoteAddress: string;
14
8
  }
15
9
 
16
- export interface RecoveryMcpSessionServerOptions {
10
+ export interface RecoveryMcpServerOptions {
17
11
  tools: readonly Tool[];
18
12
  dispatchTool(name: string, args: Record<string, unknown>, context: RecoveryMcpRequestContext): Promise<unknown>;
19
13
  }
20
14
 
21
- type RecoveryMcpSessionContext = RecoveryMcpRequestContext;
22
- type RecoveryMcpRegistry = McpSessionRegistry<NodeStreamableHTTPServerTransport, RecoveryMcpSessionContext>;
23
-
24
- function sessionId(request: IncomingMessage): string | undefined {
25
- const value = request.headers['mcp-session-id'];
26
- return Array.isArray(value) ? value[0] : value;
27
- }
28
-
29
- function isInitialize(body: unknown): boolean {
30
- return Boolean(body && typeof body === 'object' && !Array.isArray(body) && (body as { method?: unknown }).method === 'initialize');
31
- }
32
-
33
- function initializeClientIdentity(body: unknown): string {
34
- if (!body || typeof body !== 'object' || Array.isArray(body)) return 'unknown-client';
35
- const params = (body as { params?: unknown }).params;
36
- if (!params || typeof params !== 'object' || Array.isArray(params)) return 'unknown-client';
37
- const clientInfo = (params as { clientInfo?: unknown }).clientInfo;
38
- if (!clientInfo || typeof clientInfo !== 'object' || Array.isArray(clientInfo)) return 'unknown-client';
39
- const name = typeof (clientInfo as { name?: unknown }).name === 'string' ? (clientInfo as { name: string }).name.trim() : 'unknown';
40
- const version = typeof (clientInfo as { version?: unknown }).version === 'string' ? (clientInfo as { version: string }).version.trim() : 'unknown';
41
- return `${name || 'unknown'}/${version || 'unknown'}`.slice(0, 200);
42
- }
43
-
44
- function sendSessionLookupError(response: ServerResponse, id: string | undefined): void {
45
- const missing = !id?.trim();
46
- response.statusCode = missing ? 400 : 404;
47
- response.setHeader('content-type', 'application/json; charset=utf-8');
48
- response.setHeader('cache-control', 'no-store');
49
- response.setHeader('Mcp-Session-Reset', 'reinitialize');
50
- response.setHeader('x-forge-session-reset', 'reinitialize');
51
- response.end(JSON.stringify(missing ? {
52
- error: 'missing_session',
53
- code: 'MCP_SESSION_REQUIRED',
54
- message: 'Mcp-Session-Id header is required for this request.',
55
- recoverable: true,
56
- action: 'reinitialize',
57
- } : {
58
- error: 'session_not_found',
59
- code: 'MCP_SESSION_EXPIRED',
60
- message: 'MCP session not found or expired; initialize a new session.',
61
- recoverable: true,
62
- action: 'reinitialize',
63
- }));
64
- }
65
-
66
- export class RecoveryMcpSessionServer {
67
- private readonly registry: RecoveryMcpRegistry;
68
-
69
- constructor(private readonly options: RecoveryMcpSessionServerOptions) {
70
- this.registry = new McpSessionRegistry<NodeStreamableHTTPServerTransport, RecoveryMcpSessionContext>({
71
- maximumSessions: 16,
72
- maximumSessionsPerPrincipal: 16,
73
- });
74
- }
75
-
76
- snapshot(): McpSessionSnapshot {
77
- return this.registry.snapshot();
78
- }
15
+ /**
16
+ * Standalone Recovery owns durable recovery/release authority, never MCP
17
+ * transport-session authority. Both MCP 2026-07-28 and the bounded 2025-era
18
+ * compatibility protocol are served statelessly so a Gateway process
19
+ * replacement cannot invalidate the Recovery control path.
20
+ */
21
+ export class RecoveryMcpServer {
22
+ constructor(private readonly options: RecoveryMcpServerOptions) {}
79
23
 
80
24
  async close(): Promise<void> {
81
- await this.registry.closeAll('shutdown');
25
+ // Stateless handlers retain no cross-request transport resources.
82
26
  }
83
27
 
84
28
  async handle(request: IncomingMessage, response: ServerResponse, body?: unknown): Promise<void> {
85
- await this.registry.prune();
86
- if (request.method === 'POST') {
87
- await this.handlePost(request, response, body);
88
- return;
89
- }
90
- if (request.method === 'GET') {
91
- await this.handleGet(request, response);
29
+ if (request.method !== 'POST') {
30
+ response.statusCode = 405;
31
+ response.setHeader('allow', 'POST');
32
+ response.end();
92
33
  return;
93
34
  }
94
- if (request.method === 'DELETE') {
95
- await this.handleDelete(request, response);
96
- return;
35
+
36
+ const context: RecoveryMcpRequestContext = {
37
+ remoteAddress: request.socket.remoteAddress ?? 'unknown',
38
+ };
39
+ const handler = createMcpHandler(async () => this.createServer(context), {
40
+ legacy: 'stateless',
41
+ responseMode: 'auto',
42
+ });
43
+ try {
44
+ await toNodeHandler(handler)(request, response, body);
45
+ } finally {
46
+ await handler.close();
97
47
  }
98
- response.statusCode = 405;
99
- response.end();
100
48
  }
101
49
 
102
- private createServer(context: RecoveryMcpSessionContext): Server {
50
+ private createServer(context: RecoveryMcpRequestContext): Server {
103
51
  const server = new Server(
104
52
  { name: 'forge-standalone-recovery', version: FORGE_VERSION },
105
53
  { capabilities: { tools: {} } },
@@ -128,116 +76,4 @@ export class RecoveryMcpSessionServer {
128
76
  });
129
77
  return server;
130
78
  }
131
-
132
- private async handlePost(request: IncomingMessage, response: ServerResponse, body: unknown): Promise<void> {
133
- const currentSessionId = sessionId(request);
134
- if (isInitialize(body)) {
135
- if (currentSessionId) {
136
- response.setHeader('Mcp-Session-Reset', 'reinitialized');
137
- response.setHeader('x-forge-session-reset', 'reinitialized');
138
- }
139
- const reservationId = await this.registry.reserveForInitialize({
140
- principalId: RECOVERY_MCP_PRINCIPAL_ID,
141
- connectionId: RECOVERY_MCP_CONNECTION_ID,
142
- route: RECOVERY_MCP_SESSION_ROUTE,
143
- ...(currentSessionId ? { supersedeSessionId: currentSessionId } : {}),
144
- });
145
- if (!reservationId) {
146
- response.statusCode = 503;
147
- response.setHeader('retry-after', '1');
148
- response.setHeader('content-type', 'application/json; charset=utf-8');
149
- response.end(JSON.stringify({
150
- error: 'session_capacity',
151
- code: 'MCP_SESSION_CAPACITY',
152
- recoverable: true,
153
- retryable: true,
154
- action: 'retry',
155
- }));
156
- return;
157
- }
158
- const context: RecoveryMcpSessionContext = { remoteAddress: request.socket.remoteAddress ?? 'unknown' };
159
- let transport: NodeStreamableHTTPServerTransport | undefined;
160
- let initializedSessionId: string | undefined;
161
- try {
162
- transport = new NodeStreamableHTTPServerTransport({
163
- sessionIdGenerator: () => randomUUID(),
164
- onsessioninitialized: (newSessionId: string): void => {
165
- this.registry.commitInitialize(reservationId, {
166
- sessionId: newSessionId,
167
- transport: transport!,
168
- toolContext: context,
169
- route: RECOVERY_MCP_SESSION_ROUTE,
170
- principalId: RECOVERY_MCP_PRINCIPAL_ID,
171
- connectionId: RECOVERY_MCP_CONNECTION_ID,
172
- clientIdentity: initializeClientIdentity(body),
173
- });
174
- initializedSessionId = newSessionId;
175
- },
176
- });
177
- transport.onclose = () => {
178
- if (transport?.sessionId) this.registry.detach(transport.sessionId);
179
- };
180
- const server = this.createServer(context);
181
- await server.connect(transport);
182
- await transport.handleRequest(request, response, body);
183
- } finally {
184
- if (initializedSessionId) this.registry.endPost(initializedSessionId);
185
- this.registry.releaseInitialize(reservationId);
186
- if (!transport?.sessionId) await transport?.close().catch(() => undefined);
187
- }
188
- return;
189
- }
190
-
191
- if (!currentSessionId) {
192
- sendSessionLookupError(response, currentSessionId);
193
- return;
194
- }
195
- const managed = this.registry.get(currentSessionId);
196
- if (!managed || managed.route !== RECOVERY_MCP_SESSION_ROUTE || managed.principalId !== RECOVERY_MCP_PRINCIPAL_ID) {
197
- sendSessionLookupError(response, currentSessionId);
198
- return;
199
- }
200
- this.registry.beginPost(currentSessionId);
201
- try {
202
- await managed.transport.handleRequest(request, response, body);
203
- } finally {
204
- this.registry.endPost(currentSessionId);
205
- }
206
- }
207
-
208
- private async handleGet(request: IncomingMessage, response: ServerResponse): Promise<void> {
209
- const currentSessionId = sessionId(request);
210
- const managed = currentSessionId ? this.registry.get(currentSessionId) : undefined;
211
- if (!managed || managed.route !== RECOVERY_MCP_SESSION_ROUTE || managed.principalId !== RECOVERY_MCP_PRINCIPAL_ID) {
212
- sendSessionLookupError(response, currentSessionId);
213
- return;
214
- }
215
- this.registry.beginStream(currentSessionId!);
216
- let released = false;
217
- const release = (): void => {
218
- if (released) return;
219
- released = true;
220
- this.registry.endStream(currentSessionId!);
221
- };
222
- request.once('aborted', release);
223
- response.once('close', release);
224
- try {
225
- await managed.transport.handleRequest(request, response);
226
- } catch (error) {
227
- release();
228
- throw error;
229
- }
230
- }
231
-
232
- private async handleDelete(request: IncomingMessage, response: ServerResponse): Promise<void> {
233
- const currentSessionId = sessionId(request);
234
- const managed = currentSessionId ? this.registry.get(currentSessionId) : undefined;
235
- if (!managed || managed.route !== RECOVERY_MCP_SESSION_ROUTE || managed.principalId !== RECOVERY_MCP_PRINCIPAL_ID) {
236
- sendSessionLookupError(response, currentSessionId);
237
- return;
238
- }
239
- this.registry.setPendingCloseReason(currentSessionId!, 'client_delete');
240
- await managed.transport.handleRequest(request, response);
241
- if (this.registry.get(currentSessionId!)) await this.registry.close(currentSessionId!, 'client_delete');
242
- }
243
79
  }
@@ -72,7 +72,7 @@ export function recoveryOperationLockOwnerAlive(lock: RecoveryOperationLockRecor
72
72
  if (!isProcessAlive(lock.pid)) return false;
73
73
  if (!lock.processStartTime) return true;
74
74
  const observed = processStartTime(lock.pid);
75
- return observed === undefined || observed === lock.processStartTime;
75
+ return observed === lock.processStartTime;
76
76
  }
77
77
 
78
78
  export function acquireRecoveryOperationLock(input: {
@@ -10,7 +10,7 @@ export interface RuntimePerformanceIdentity {
10
10
  }
11
11
 
12
12
  export interface RuntimePerformanceEvidence extends RuntimePerformanceIdentity {
13
- policy: 'idle-cpu-v1';
13
+ policy: 'runaway-cpu-v4';
14
14
  measuredFrom: string;
15
15
  measuredUntil: string;
16
16
  warmupMs: number;
@@ -18,10 +18,43 @@ export interface RuntimePerformanceEvidence extends RuntimePerformanceIdentity {
18
18
  sampleCount: number;
19
19
  meanCpuPercent: number;
20
20
  p95CpuPercent: number;
21
+ /** Windows whose CPU consumption reached the per-window runaway ceiling. */
22
+ sustainedHighWindowCount: number;
21
23
  }
22
24
 
23
25
  export interface RuntimeCpuReading { cpuMs: number; processStartTime: string }
24
26
 
27
+ const PERFORMANCE_WINDOW_MS = 2_500;
28
+ const PERFORMANCE_MAX_WINDOW_MS = 3_750;
29
+ const PERFORMANCE_WARMUP_WINDOWS = 4;
30
+ const PERFORMANCE_SAMPLE_WINDOWS = 20;
31
+ const PERFORMANCE_WARMUP_MS = PERFORMANCE_WINDOW_MS * PERFORMANCE_WARMUP_WINDOWS;
32
+ const PERFORMANCE_DURATION_MS = PERFORMANCE_WINDOW_MS * PERFORMANCE_SAMPLE_WINDOWS;
33
+
34
+ // Recovery known-good is a runaway safety gate, not the comparative release benchmark.
35
+ // The v4 sampler keeps the same 60-second budget, the same twenty 2.5-second windows
36
+ // and the same 25%/50% ceilings as v2/v3, but decides runaway from *sustained*
37
+ // consumption instead of from nearest-rank p95.
38
+ //
39
+ // Why p95 cannot be the decision rule: the Canonical Runtime performs bounded,
40
+ // scheduled maintenance (the release-fenced periodic cleanup child and the in-process
41
+ // scheduler/recovery passes). Such a pass lasts several seconds and recurs about once
42
+ // per minute, so in any 50-second observation at least two windows necessarily land
43
+ // inside it. nearest-rank p95 is exactly the second-highest window, so a healthy
44
+ // Runtime with an ~11% mean was deterministically rejected (live evidence:
45
+ // mean=12.60% p95=65.05% and mean=11.41% p95=65.13%, both rolled back within minutes
46
+ // of cutover) and every automatic release progression converged on rollback.
47
+ //
48
+ // A watchdog duty must distinguish "unbounded spin" from "bounded periodic work", so
49
+ // v4 rejects a sample only when the process is high for at least half of the observed
50
+ // windows (sustainedHighWindowCount * 2 >= sampleCount) or when the mean exceeds the
51
+ // ceiling. The historical runaway population (mean >= 90.64%, p95 >= 104.72%) fails
52
+ // both tests by a wide margin, while a once-per-minute bounded pass (<= 4 of 20
53
+ // windows) can no longer be mistaken for runaway. p95 stays in the evidence for audit.
54
+ // Relative <=10% regression remains Benchmark/Release Evaluation authority.
55
+ export const RECOVERY_RUNAWAY_MEAN_CPU_PERCENT = 25;
56
+ export const RECOVERY_RUNAWAY_P95_CPU_PERCENT = 50;
57
+
25
58
  /** Dependencies are in-process test seams; no transport accepts evidence or threshold overrides. */
26
59
  export interface RuntimePerformanceDependencies {
27
60
  readCpu?: (pid: number) => RuntimeCpuReading;
@@ -54,20 +87,24 @@ export function assertRuntimePerformanceEvidence(
54
87
  now = Date.now(),
55
88
  ): void {
56
89
  const age = now - Date.parse(evidence.measuredUntil);
57
- if (evidence.policy !== 'idle-cpu-v1' || !samePerformanceIdentity(evidence, identity)
90
+ if (evidence.policy !== 'runaway-cpu-v4' || !samePerformanceIdentity(evidence, identity)
58
91
  || !Number.isFinite(age) || age < 0 || age > 60_000
59
- || evidence.warmupMs < 60_000 || evidence.warmupMs > 90_000
60
- || evidence.durationMs < 300_000 || evidence.durationMs > 450_000 || evidence.sampleCount !== 30
92
+ || evidence.warmupMs < PERFORMANCE_WARMUP_MS || evidence.warmupMs > PERFORMANCE_MAX_WINDOW_MS * PERFORMANCE_WARMUP_WINDOWS
93
+ || evidence.durationMs < PERFORMANCE_DURATION_MS || evidence.durationMs > PERFORMANCE_MAX_WINDOW_MS * PERFORMANCE_SAMPLE_WINDOWS || evidence.sampleCount !== PERFORMANCE_SAMPLE_WINDOWS
61
94
  || !Number.isFinite(evidence.meanCpuPercent) || evidence.meanCpuPercent < 0
62
- || !Number.isFinite(evidence.p95CpuPercent) || evidence.p95CpuPercent < 0) {
95
+ || !Number.isFinite(evidence.p95CpuPercent) || evidence.p95CpuPercent < 0
96
+ || !Number.isInteger(evidence.sustainedHighWindowCount)
97
+ || evidence.sustainedHighWindowCount < 0
98
+ || evidence.sustainedHighWindowCount > evidence.sampleCount) {
63
99
  throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: incomplete, stale or mismatched performance evidence');
64
100
  }
65
- if (evidence.meanCpuPercent > 5 || evidence.p95CpuPercent > 10) {
66
- throw new Error(`RECOVERY_PERFORMANCE_REJECTED: mean=${evidence.meanCpuPercent.toFixed(2)}% p95=${evidence.p95CpuPercent.toFixed(2)}%`);
101
+ const sustained = evidence.sustainedHighWindowCount * 2 >= evidence.sampleCount;
102
+ if (evidence.meanCpuPercent > RECOVERY_RUNAWAY_MEAN_CPU_PERCENT || sustained) {
103
+ throw new Error(`RECOVERY_PERFORMANCE_REJECTED: mean=${evidence.meanCpuPercent.toFixed(2)}% p95=${evidence.p95CpuPercent.toFixed(2)}% sustained=${evidence.sustainedHighWindowCount}/${evidence.sampleCount}`);
67
104
  }
68
105
  }
69
106
 
70
- /** Observe 60 seconds of warmup followed by thirty 10-second CPU-time delta windows. */
107
+ /** Observe 10 seconds of warmup followed by twenty 2.5-second CPU-time delta windows. */
71
108
  export async function measureRuntimePerformance(
72
109
  observeIdentity: () => RuntimePerformanceIdentity,
73
110
  dependencies: RuntimePerformanceDependencies = {},
@@ -90,12 +127,12 @@ export async function measureRuntimePerformance(
90
127
  };
91
128
  const warmingAt = monotonicNow();
92
129
  let previousWarmupAt = warmingAt;
93
- for (let i = 0; i < 6; i++) {
94
- await sleep(10_000);
130
+ for (let i = 0; i < PERFORMANCE_WARMUP_WINDOWS; i++) {
131
+ await sleep(PERFORMANCE_WINDOW_MS);
95
132
  observe();
96
133
  const nextWarmupAt = monotonicNow();
97
134
  const elapsed = nextWarmupAt - previousWarmupAt;
98
- if (elapsed < 10_000 || elapsed > 15_000) {
135
+ if (elapsed < PERFORMANCE_WINDOW_MS || elapsed > PERFORMANCE_MAX_WINDOW_MS) {
99
136
  throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: interrupted CPU warmup window');
100
137
  }
101
138
  previousWarmupAt = nextWarmupAt;
@@ -107,14 +144,14 @@ export async function measureRuntimePerformance(
107
144
  const startedAt = previousAt;
108
145
  let totalCpuMs = 0;
109
146
  const windows: number[] = [];
110
- for (let i = 0; i < 30; i++) {
111
- await sleep(10_000);
147
+ for (let i = 0; i < PERFORMANCE_SAMPLE_WINDOWS; i++) {
148
+ await sleep(PERFORMANCE_WINDOW_MS);
112
149
  const nextCpu = observe().cpuMs;
113
150
  const nextAt = monotonicNow();
114
151
  const elapsed = nextAt - previousAt;
115
152
  const cpuDelta = nextCpu - previousCpu;
116
- // Suspended/overloaded collectors cannot pass as thirty ordinary windows.
117
- if (elapsed < 10_000 || elapsed > 15_000 || cpuDelta < 0) {
153
+ // Suspended/overloaded collectors cannot pass as ordinary sample windows.
154
+ if (elapsed < PERFORMANCE_WINDOW_MS || elapsed > PERFORMANCE_MAX_WINDOW_MS || cpuDelta < 0) {
118
155
  throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: interrupted CPU observation window');
119
156
  }
120
157
  windows.push(cpuDelta / elapsed * 100);
@@ -125,10 +162,11 @@ export async function measureRuntimePerformance(
125
162
  const durationMs = previousAt - startedAt;
126
163
  windows.sort((a, b) => a - b);
127
164
  const evidence: RuntimePerformanceEvidence = {
128
- ...identity, policy: 'idle-cpu-v1', measuredFrom, measuredUntil: new Date(wallNow()).toISOString(),
165
+ ...identity, policy: 'runaway-cpu-v4', measuredFrom, measuredUntil: new Date(wallNow()).toISOString(),
129
166
  warmupMs, durationMs, sampleCount: windows.length,
130
167
  meanCpuPercent: totalCpuMs / durationMs * 100,
131
168
  p95CpuPercent: windows[Math.ceil(windows.length * 0.95) - 1]!,
169
+ sustainedHighWindowCount: windows.filter((cpuPercent) => cpuPercent >= RECOVERY_RUNAWAY_P95_CPU_PERCENT).length,
132
170
  };
133
171
  assertRuntimePerformanceEvidence(evidence, observeIdentity(), wallNow());
134
172
  return evidence;
@@ -15,8 +15,8 @@ import {
15
15
  import { dirname, join, relative, resolve, sep } from 'path';
16
16
  import { writeJsonAtomic } from '../shared/json-files';
17
17
 
18
- export const RECOVERY_RELEASE_BINARIES = [
19
- 'forge-recovery',
18
+ export const RECOVERY_RELEASE_BINARIES = ['forge-recovery'] as const;
19
+ export const RECOVERY_RELEASE_COMPATIBILITY_BINARIES = [
20
20
  'forge-recovery-gateway',
21
21
  'forge-recovery-watchdog',
22
22
  ] as const;
@@ -24,7 +24,8 @@ export const RECOVERY_RELEASE_BINARIES = [
24
24
  export const RECOVERY_RELEASE_ROLE_CANARY_ARG = '--forge-release-role-canary';
25
25
 
26
26
  export type RecoveryReleaseBinary = (typeof RECOVERY_RELEASE_BINARIES)[number];
27
- export type RecoveryRuntimeRole = 'gateway' | 'watchdog';
27
+ /** daemon is the only current persistent owner; gateway/watchdog remain legacy CLI compatibility roles. */
28
+ export type RecoveryRuntimeRole = 'daemon' | 'gateway' | 'watchdog';
28
29
  export interface RecoveryReleaseManifest {
29
30
  schemaVersion: 1;
30
31
  releaseRevision: string;
@@ -84,6 +85,49 @@ export function recoveryRuntimeStatePath(controllerHome: string, role: RecoveryR
84
85
  return join(recoveryRoot(controllerHome), 'state', `${role}-runtime.json`);
85
86
  }
86
87
 
88
+ export function recoveryGatewayDrainMarkerPath(controllerHome: string): string {
89
+ return join(recoveryRoot(controllerHome), 'state', 'gateway-draining.json');
90
+ }
91
+
92
+ const RECOVERY_GATEWAY_DRAIN_MARKER_TTL_MS = 5 * 60_000;
93
+
94
+ export function recoveryGatewayIsDraining(controllerHome: string, now = Date.now()): boolean {
95
+ const path = recoveryGatewayDrainMarkerPath(controllerHome);
96
+ if (!existsSync(path)) return false;
97
+ try {
98
+ const marker = JSON.parse(readFileSync(path, 'utf8')) as { pid?: unknown; at?: unknown };
99
+ const pid = Number(marker.pid);
100
+ const at = typeof marker.at === 'string' ? Date.parse(marker.at) : Number.NaN;
101
+ if (!Number.isInteger(pid) || pid <= 0 || !Number.isFinite(at) || now - at > RECOVERY_GATEWAY_DRAIN_MARKER_TTL_MS) {
102
+ rmSync(path, { force: true });
103
+ return false;
104
+ }
105
+ try {
106
+ process.kill(pid, 0);
107
+ return true;
108
+ } catch (error) {
109
+ const code = (error as NodeJS.ErrnoException).code;
110
+ if (code === 'EPERM') return true;
111
+ rmSync(path, { force: true });
112
+ return false;
113
+ }
114
+ } catch {
115
+ rmSync(path, { force: true });
116
+ return false;
117
+ }
118
+ }
119
+
120
+ export function setRecoveryGatewayDraining(controllerHome: string, draining: boolean): void {
121
+ const path = recoveryGatewayDrainMarkerPath(controllerHome);
122
+ if (!draining) {
123
+ rmSync(path, { force: true });
124
+ return;
125
+ }
126
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
127
+ writeJsonAtomic(path, { schemaVersion: 1, draining: true, pid: process.pid, at: new Date().toISOString() });
128
+ chmodSync(path, 0o600);
129
+ }
130
+
87
131
  function fileSha256(path: string): string {
88
132
  return createHash('sha256').update(readFileSync(path)).digest('hex');
89
133
  }
@@ -184,11 +228,15 @@ export function publishRecoveryCompatibilityLinks(controllerHome: string): void
184
228
  assertRecoveryReleaseContained(controllerHome, current);
185
229
  const binRoot = join(recoveryRoot(controllerHome), 'bin');
186
230
  mkdirSync(binRoot, { recursive: true, mode: 0o700 });
187
- for (const binary of RECOVERY_RELEASE_BINARIES) {
231
+ const compatibilityTargets = [
232
+ ...RECOVERY_RELEASE_BINARIES.map((binary) => ({ binary, target: binary })),
233
+ ...RECOVERY_RELEASE_COMPATIBILITY_BINARIES.map((binary) => ({ binary, target: 'forge-recovery' as const })),
234
+ ];
235
+ for (const { binary, target } of compatibilityTargets) {
188
236
  const destination = join(binRoot, binary);
189
237
  const temporary = `${destination}.${process.pid}.tmp`;
190
238
  rmSync(temporary, { force: true });
191
- symlinkSync(join('..', 'current', binary), temporary);
239
+ symlinkSync(join('..', 'current', target), temporary);
192
240
  renameSync(temporary, destination);
193
241
  }
194
242
  }
@@ -1,2 +1,5 @@
1
- export const RECOVERY_GATEWAY_LABEL = 'com.moretea.forge-recovery-gateway';
2
- export const RECOVERY_WATCHDOG_LABEL = 'com.moretea.forge-recovery-watchdog';
1
+ export {
2
+ FORGE_RECOVERY_DAEMON_LABEL as RECOVERY_DAEMON_LABEL,
3
+ FORGE_RECOVERY_GATEWAY_LABEL as RECOVERY_GATEWAY_LABEL,
4
+ FORGE_RECOVERY_WATCHDOG_LABEL as RECOVERY_WATCHDOG_LABEL,
5
+ } from '../platform/service-inventory';
@@ -151,10 +151,13 @@ export function evaluateRecoveryWatchdogHealth(input: {
151
151
  return { ok: true, detail: 'Recovery Watchdog heartbeat, PID, and immutable release identity are current', pulseAgeMs, heartbeat, runtimeIdentity, currentReleaseRevision: current.releaseRevision };
152
152
  }
153
153
 
154
- export function observeRecoveryWatchdogHealth(controllerHome: string): RecoveryWatchdogHealth {
154
+ export function observeRecoveryWatchdogHealth(controllerHome: string, enabled = true): RecoveryWatchdogHealth {
155
+ if (!enabled) {
156
+ return { ok: true, detail: 'Recovery Watchdog is disabled by the configured install profile' };
157
+ }
155
158
  return evaluateRecoveryWatchdogHealth({
156
159
  heartbeat: readRecoveryWatchdogHeartbeat(controllerHome),
157
- runtimeIdentity: readRecoveryRuntimeIdentity(controllerHome, 'watchdog'),
160
+ runtimeIdentity: readRecoveryRuntimeIdentity(controllerHome, 'daemon'),
158
161
  currentRelease: readCurrentRecoveryRelease(controllerHome),
159
162
  });
160
163
  }
@@ -82,6 +82,7 @@ async function browserAction(
82
82
  occurrenceId: string,
83
83
  actionId: string,
84
84
  args: Record<string, unknown>,
85
+ authorizationGrantRefs: readonly string[],
85
86
  ): Promise<Record<string, unknown>> {
86
87
  return executeBrowserPluginAction({
87
88
  controllerHome,
@@ -92,9 +93,16 @@ async function browserAction(
92
93
  requestId: `schedule-browser-probe:${occurrenceId}:${actionId}`,
93
94
  args,
94
95
  origin: { surface: 'schedule', actor: 'browser-probe', correlationId: occurrenceId },
96
+ authorizationGrantRefs,
95
97
  });
96
98
  }
97
99
 
100
+ /** Exact interactive grants attached to this Schedule; contents remain Controller-owned. */
101
+ export function scheduledBrowserProbeAuthorizationGrantRefs(args: Record<string, unknown>): string[] {
102
+ if (!Array.isArray(args.authorization_grant_refs)) return [];
103
+ return [...new Set(args.authorization_grant_refs.map(String).map((value) => value.trim()).filter(Boolean))];
104
+ }
105
+
98
106
  interface ScheduledBrowserSessionMetadata {
99
107
  url?: string;
100
108
  ownership?: string;
@@ -137,8 +145,9 @@ async function scheduledBrowserSessionMetadata(
137
145
  repository: RepositoryRecord,
138
146
  occurrenceId: string,
139
147
  sessionId: string,
148
+ authorizationGrantRefs: readonly string[],
140
149
  ): Promise<ScheduledBrowserSessionMetadata | undefined> {
141
- const inventory = await browserAction(controllerHome, repository, occurrenceId, 'list_sessions', {});
150
+ const inventory = await browserAction(controllerHome, repository, occurrenceId, 'list_sessions', {}, authorizationGrantRefs);
142
151
  const sessions = Array.isArray(inventory.sessions) ? inventory.sessions : [];
143
152
  const saved = sessions
144
153
  .map((entry) => recordValue(entry))
@@ -170,10 +179,12 @@ export async function executeScheduledBrowserProbe(input: {
170
179
  const url = stringValue(input.args.probe_url) ?? stringValue(input.args.url);
171
180
  if (!requestedSessionId && !url) throw new Error('SCHEDULE_BROWSER_PROBE_TARGET_REQUIRED');
172
181
 
182
+ const authorizationGrantRefs = scheduledBrowserProbeAuthorizationGrantRefs(input.args);
183
+
173
184
  const waitUntil = stringValue(input.args.wait_until) ?? 'domcontentloaded';
174
185
  const timeoutMs = boundedNumber(input.args.timeout_ms, 60_000, 1_000, 120_000);
175
186
  const savedSession = requestedSessionId
176
- ? await scheduledBrowserSessionMetadata(input.controllerHome, input.repository, input.occurrenceId, requestedSessionId)
187
+ ? await scheduledBrowserSessionMetadata(input.controllerHome, input.repository, input.occurrenceId, requestedSessionId, authorizationGrantRefs)
177
188
  : undefined;
178
189
  const navigationAction = scheduledBrowserProbeNavigationAction(savedSession?.ownership, Boolean(url));
179
190
  const managedRehydrateIntent = scheduledBrowserProbeManagedRehydrateIntent(savedSession);
@@ -188,7 +199,7 @@ export async function executeScheduledBrowserProbe(input: {
188
199
  state: waitUntil,
189
200
  timeout_ms: timeoutMs,
190
201
  ...managedRehydrateIntent,
191
- });
202
+ }, authorizationGrantRefs);
192
203
  } else if (navigationAction === 'navigate') {
193
204
  navigation = await browserAction(input.controllerHome, input.repository, input.occurrenceId, 'navigate', {
194
205
  ...(requestedSessionId ? { session_id: requestedSessionId } : {}),
@@ -197,14 +208,14 @@ export async function executeScheduledBrowserProbe(input: {
197
208
  timeout_ms: timeoutMs,
198
209
  retries: 1,
199
210
  ...managedRehydrateIntent,
200
- });
211
+ }, authorizationGrantRefs);
201
212
  } else {
202
213
  navigation = await browserAction(input.controllerHome, input.repository, input.occurrenceId, 'reload', {
203
214
  session_id: requestedSessionId!,
204
215
  wait_until: waitUntil,
205
216
  timeout_ms: timeoutMs,
206
217
  ...managedRehydrateIntent,
207
- });
218
+ }, authorizationGrantRefs);
208
219
  }
209
220
 
210
221
  const session = recordValue(navigation.session);
@@ -224,7 +235,7 @@ export async function executeScheduledBrowserProbe(input: {
224
235
  session_id: sessionId,
225
236
  ...(stringValue(input.args.selector) ? { selector: stringValue(input.args.selector) } : {}),
226
237
  max_chars: boundedNumber(input.args.max_chars, 20_000, 256, 100_000),
227
- });
238
+ }, authorizationGrantRefs);
228
239
  rawText = stringValue(textResult.text) ?? '';
229
240
  truncated = textResult.truncated === true;
230
241
  }
@@ -1,9 +1,16 @@
1
1
  import type { RepositorySchedule } from '../../../../packages/kernel/scheduler/api/index';
2
+ import {
3
+ DEFAULT_CHATGPT_AUTOMATION_MODEL,
4
+ DEFAULT_CHATGPT_AUTOMATION_REASONING,
5
+ DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY,
6
+ } from '../../../../adapters/chatgpt/provider-delivery';
2
7
 
3
8
  export const CHATGPT_AUTOMATION_EXECUTION_PROFILE = 'chatgpt_browser_v1';
4
- export const CHATGPT_AUTOMATION_DEFAULT_MODEL = 'gpt-5.6';
5
- export const CHATGPT_AUTOMATION_DEFAULT_REASONING = 'high';
6
- export const CHATGPT_AUTOMATION_DEFAULT_TAB_POLICY = 'auto';
9
+ // Missing legacy Schedule preferences inherit the single provider defaults.
10
+ // Explicit saved preferences remain authoritative and are never overwritten.
11
+ export const CHATGPT_AUTOMATION_DEFAULT_MODEL = DEFAULT_CHATGPT_AUTOMATION_MODEL;
12
+ export const CHATGPT_AUTOMATION_DEFAULT_REASONING = DEFAULT_CHATGPT_AUTOMATION_REASONING;
13
+ export const CHATGPT_AUTOMATION_DEFAULT_TAB_POLICY = DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY;
7
14
 
8
15
  export interface ChatgptAutomationScheduleMigrationResult {
9
16
  changed: boolean;