@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
@@ -0,0 +1,493 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { createHash } from 'node:crypto';
3
+ import { getRepository } from '../../cli/repositories/registry';
4
+ import { getWorkContract, semanticWorkState } from '../../../packages/kernel/work/api/index';
5
+ import {
6
+ controllerRoundBlockerClass,
7
+ controllerRoundProviderEffectId,
8
+ finishControllerRoundRelayDispatch,
9
+ getControllerRoundRelay,
10
+ getRequirementControllerRoundRelay,
11
+ } from '../../../packages/kernel/controller/api/index';
12
+ import {
13
+ bindChatgptWorkConversation,
14
+ getChatgptWorkConversationBinding,
15
+ rebindChatgptWorkConversation,
16
+ type ChatgptWorkConversationBinding,
17
+ } from '../../../adapters/chatgpt/work-conversation-binding-store';
18
+ import { readRequirement } from '../control-plane/persistence/requirement-store';
19
+ import { getWorkflowSupervisorCurrentConversation, getWorkflowSupervisorTaskByConversationId, registerWorkflowSupervisorTask, reserveWorkflowSupervisorEnrollment } from '../../../supervisor/client';
20
+ import { resolveWorkflowSupervisorForgeHome, workflowSupervisorSocketPath } from '../../../supervisor/paths';
21
+ import type { WorkflowSupervisorLifecycleHooks, WorkflowSupervisorTask } from '../../../supervisor/types';
22
+ import { getRuntimeWriteClaim } from './write-fence';
23
+ import { renderCognitiveAttentionForWork } from '../context/cognitive-attention';
24
+
25
+ export type WorkflowSupervisorBoundary =
26
+ | { status: 'not_eligible' }
27
+ | { status: 'conversation_pending'; reason: 'EXACT_WORK_CONVERSATION_BINDING_REQUIRED' }
28
+ | { status: 'outer_turn'; workId?: string; requirementId?: string; conversationId: string; conversationUrl: string };
29
+
30
+ export type WorkflowSupervisorEnrollmentStatus =
31
+ | 'not_eligible'
32
+ | 'conversation_pending'
33
+ | 'current_conversation_unbound'
34
+ | 'daemon_unavailable'
35
+ | 'enrolled'
36
+ | 'lower_layer_not_ready';
37
+
38
+ export function workflowSupervisorLowerLayerReadyForWork(
39
+ options: { controllerHome: string; repoId: string },
40
+ workId: string,
41
+ ): { ready: true; workId: string; providerEffectId: string } | { ready: false; reason: string } {
42
+ const directRelay = getControllerRoundRelay(options, workId);
43
+ const work = getWorkContract(options, workId);
44
+ const relay = directRelay ?? (work?.requirementId ? getRequirementControllerRoundRelay(options, work.requirementId) : undefined);
45
+ if (!relay) return { ready: false, reason: 'CONTROLLER_ROUND_NOT_PREPARED' };
46
+ if (!relay.authorityId?.trim()) return { ready: false, reason: `CONTROLLER_ROUND_AUTHORITY_REQUIRED:${relay.originWorkId}` };
47
+ const outcomeUnknownEffectAwaitingObservation = relay.status === 'blocked'
48
+ && controllerRoundBlockerClass(relay) === 'provider_dispatch_outcome_unknown'
49
+ && (relay.providerDispatchAttempt ?? 0) > 0
50
+ && Boolean(relay.providerDispatchEffectId?.trim());
51
+ if (!['dispatching', 'dispatched', 'claimed'].includes(relay.status) && !outcomeUnknownEffectAwaitingObservation) {
52
+ return { ready: false, reason: `CONTROLLER_ROUND_NOT_DISPATCHABLE:${relay.status}:${relay.blockedReason ?? relay.originWorkId}` };
53
+ }
54
+ return {
55
+ ready: true,
56
+ workId: relay.originWorkId,
57
+ providerEffectId: relay.providerDispatchEffectId ?? controllerRoundProviderEffectId(relay),
58
+ };
59
+ }
60
+
61
+ function taskIdForWork(repoId: string, workId: string): string {
62
+ return `forge:${repoId}:work:${workId}`;
63
+ }
64
+ export function getWorkflowSupervisorConversationBindingForWork(
65
+ options: { controllerHome: string; repoId: string },
66
+ workId: string,
67
+ ): ChatgptWorkConversationBinding | undefined {
68
+ return getChatgptWorkConversationBinding(options, workId);
69
+ }
70
+
71
+ export function bindWorkflowSupervisorConversationForWork(
72
+ options: { controllerHome: string; repoId: string },
73
+ input: { workId: string; conversationUrl: string; localAlias?: string },
74
+ ): ChatgptWorkConversationBinding {
75
+ return bindChatgptWorkConversation(options, input);
76
+ }
77
+
78
+ /**
79
+ * The boundary is derived from canonical lower-layer facts, never copied into
80
+ * Scheduler or ControllerRound state. Once one Requirement-backed Work has an
81
+ * exact ChatGPT conversation, lower layers may prepare/claim ControllerRounds
82
+ * but may no longer submit the next outer assistant turn.
83
+ */
84
+ export function workflowSupervisorBoundaryForWork(
85
+ options: { controllerHome: string; repoId: string },
86
+ workId: string,
87
+ ): WorkflowSupervisorBoundary {
88
+ const work = getWorkContract(options, workId);
89
+ if (!work || semanticWorkState(work) !== 'open') return { status: 'not_eligible' };
90
+ const binding = getChatgptWorkConversationBinding(options, workId);
91
+ if (!binding) return { status: 'conversation_pending', reason: 'EXACT_WORK_CONVERSATION_BINDING_REQUIRED' };
92
+ return {
93
+ status: 'outer_turn',
94
+ workId: work.workId,
95
+ ...(work.requirementId ? { requirementId: work.requirementId } : {}),
96
+ conversationId: binding.conversationId,
97
+ conversationUrl: binding.conversationUrl,
98
+ };
99
+ }
100
+
101
+ export function inheritWorkflowSupervisorConversationBinding(
102
+ options: { controllerHome: string; repoId: string },
103
+ fromWorkId: string,
104
+ toWorkId: string,
105
+ ): ChatgptWorkConversationBinding | undefined {
106
+ if (fromWorkId === toWorkId) return getChatgptWorkConversationBinding(options, toWorkId);
107
+ const sourceWork = getWorkContract(options, fromWorkId);
108
+ const targetWork = getWorkContract(options, toWorkId);
109
+ if (!sourceWork?.requirementId || sourceWork.requirementId !== targetWork?.requirementId) return undefined;
110
+ // Requirement membership is goal identity, not conversation lineage. Only an
111
+ // explicit Work predecessor edge proves that the successor belongs to the
112
+ // same logical controller conversation. Sibling Works must bind their own
113
+ // current conversation instead of silently reusing historical delivery.
114
+ if (targetWork?.predecessorWorkId?.trim() !== fromWorkId) return undefined;
115
+ const source = getChatgptWorkConversationBinding(options, fromWorkId);
116
+ if (!source) return undefined;
117
+ const existing = getChatgptWorkConversationBinding(options, toWorkId);
118
+ if (existing) {
119
+ if (existing.conversationId !== source.conversationId) {
120
+ throw new Error(`WORKFLOW_SUPERVISOR_CONVERSATION_CONFLICT:${sourceWork.requirementId}`);
121
+ }
122
+ return existing;
123
+ }
124
+ return bindChatgptWorkConversation(options, {
125
+ workId: toWorkId,
126
+ conversationUrl: source.conversationUrl,
127
+ latestBrowserSessionId: source.latestBrowserSessionId,
128
+ authorizationGrantRefs: source.authorizationGrantRefs,
129
+ localAlias: source.localAlias,
130
+ });
131
+ }
132
+
133
+ function workflowSupervisorContractText(task: WorkflowSupervisorTask, key: string): string | undefined {
134
+ const value = task.completionContract[key] ?? task.userBlockerPolicy[key];
135
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined;
136
+ }
137
+
138
+ function workflowSupervisorOriginWorkId(task: WorkflowSupervisorTask, repoId: string): string | undefined {
139
+ const legacyWorkPrefix = `forge:${repoId}:work:`;
140
+ return workflowSupervisorContractText(task, 'work_id')
141
+ ?? (task.taskId.startsWith(legacyWorkPrefix) ? task.taskId.slice(legacyWorkPrefix.length) || undefined : undefined);
142
+ }
143
+
144
+ /**
145
+ * Mechanical Work projection used to decide whether a provider turn advanced
146
+ * anything. `updatedAt` is deliberately excluded: mechanical Supervisor and
147
+ * Controller bookkeeping touches the record every turn, while only a real Work
148
+ * mutation (authored revision/state, phase evidence, execution evidence,
149
+ * observable changed paths, or a delivery receipt) means the turn did work.
150
+ */
151
+ function workflowSupervisorWorkProgressFingerprint(controllerHome: string, task: WorkflowSupervisorTask): string | undefined {
152
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
153
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
154
+ if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
155
+ const workId = workflowSupervisorOriginWorkId(task, repoId);
156
+ if (!workId) return undefined;
157
+ const work = getWorkContract({ controllerHome, repoId }, workId);
158
+ if (!work) return undefined;
159
+ return createHash('sha256').update(JSON.stringify({
160
+ semanticRevision: work.semanticRevision ?? null,
161
+ semanticState: work.semanticState,
162
+ phase: work.phase,
163
+ phaseEvidence: work.phaseEvidence,
164
+ dispatchState: work.dispatchState,
165
+ evidenceState: work.evidenceState,
166
+ completionOutcome: work.completionOutcome ?? null,
167
+ completionReceipt: work.completionReceipt ?? null,
168
+ evidenceRefs: work.evidenceRefs,
169
+ changedPaths: work.scopeEvidence?.actualChangedPaths ?? [],
170
+ })).digest('hex');
171
+ }
172
+
173
+ function workflowSupervisorProjectAliases(task: WorkflowSupervisorTask): string[] {
174
+ const requirementId = workflowSupervisorContractText(task, 'requirement_id');
175
+ if (!requirementId) return [];
176
+ // Requirement ids intentionally carry the product key before the structural
177
+ // suffix. ChatGPT Project slugs may insert word separators (for example
178
+ // shenbaobao -> shen-bao-bao), so the browser adapter compares compact ids.
179
+ const productKey = /^REQ-([a-z0-9]{4,})-/i.exec(requirementId.trim())?.[1];
180
+ return productKey ? [productKey] : [];
181
+ }
182
+
183
+ /**
184
+ * Enrollment gives Supervisor authority over this exact conversation. Work and
185
+ * ControllerRound are execution context, not another cross-turn lifecycle.
186
+ * Goal cancellation and explicit conversation rebind revoke new-send authority.
187
+ * Provider observation remains governed separately by the effect ledger.
188
+ */
189
+ function createForgeWorkflowSupervisorBrowserTaskActive(controllerHome: string): (task: WorkflowSupervisorTask) => boolean {
190
+ return (task) => {
191
+ if (task.continuationPolicy.kind === 'standalone_supervisor') return true;
192
+ if (task.continuationPolicy.kind !== 'forge_goal_outer_turn') return false;
193
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
194
+ const requirementId = workflowSupervisorContractText(task, 'requirement_id');
195
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
196
+ if (!repoId || taskControllerHome !== controllerHome) return false;
197
+ if (requirementId && readRequirement({ controllerHome }, requirementId)?.value.state === 'cancelled') return false;
198
+ const workId = workflowSupervisorOriginWorkId(task, repoId);
199
+ if (!requirementId && !workId) return false;
200
+ // An existing task may outlive the Work that originally enrolled it. Its
201
+ // durable task/effect chain still owns the original Goal; absence cannot
202
+ // mean DONE, NEEDS_USER, nor permit a replacement provider send.
203
+ const binding = workId ? getChatgptWorkConversationBinding({ controllerHome, repoId }, workId) : undefined;
204
+ return !binding || binding.conversationId === task.conversationId;
205
+ };
206
+ }
207
+
208
+ export function forgeWorkflowSupervisorLifecycleHooks(controllerHome: string): WorkflowSupervisorLifecycleHooks {
209
+ const browserTaskActive = createForgeWorkflowSupervisorBrowserTaskActive(controllerHome);
210
+ return {
211
+ canonicalObjectiveForTask: (task) => {
212
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
213
+ const requirementId = workflowSupervisorContractText(task, 'requirement_id');
214
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
215
+ if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
216
+ // Requirement is the durable Goal root. Its outcome is therefore the
217
+ // canonical Supervisor goal; a Work objective is lower-layer execution
218
+ // context and must not become a permanent outer-turn instruction surface.
219
+ if (requirementId) {
220
+ const outcome = readRequirement({ controllerHome }, requirementId)?.value.outcomeStatement?.trim();
221
+ if (outcome) return outcome;
222
+ }
223
+ const workId = workflowSupervisorOriginWorkId(task, repoId);
224
+ if (!workId) return undefined;
225
+ const work = getWorkContract({ controllerHome, repoId }, workId);
226
+ // Legacy / independent Work without Requirement authority keeps the
227
+ // existing fallback. Absence never manufactures a replacement Work.
228
+ return work?.objective;
229
+ },
230
+ advisoryCognitionForTask: (task) => {
231
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
232
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
233
+ if (!repoId || (taskControllerHome && taskControllerHome !== controllerHome)) return undefined;
234
+ const workId = workflowSupervisorOriginWorkId(task, repoId);
235
+ if (!workId) return undefined;
236
+ return renderCognitiveAttentionForWork({ controllerHome, repoId, workId, query: task.objective, maxItems: 6, maxBytes: 8 * 1024 });
237
+ },
238
+ effectDispatchEvidence: ({ task }) => {
239
+ const claim = getRuntimeWriteClaim();
240
+ const progress = workflowSupervisorWorkProgressFingerprint(controllerHome, task);
241
+ return {
242
+ ...(claim && !claim.unmanaged
243
+ ? {
244
+ runtime_instance_id: claim.runtimeInstanceId,
245
+ runtime_fencing_generation: claim.fencingGeneration,
246
+ active_release_id: claim.releaseId,
247
+ active_release_authority_revision: claim.releaseAuthorityRevision,
248
+ }
249
+ : {}),
250
+ ...(progress ? { work_progress_fingerprint: progress } : {}),
251
+ };
252
+ },
253
+ workProgressFingerprint: (task) => workflowSupervisorWorkProgressFingerprint(controllerHome, task),
254
+ inheritedEffectDispatch: (task, effect) => {
255
+ if (effect.kind !== 'enrollment') return undefined;
256
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
257
+ const requirementId = workflowSupervisorContractText(task, 'requirement_id');
258
+ const workId = repoId ? workflowSupervisorOriginWorkId(task, repoId) : undefined;
259
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
260
+ if (!repoId || (!requirementId && !workId) || taskControllerHome !== controllerHome) return undefined;
261
+ const store = { controllerHome, repoId };
262
+ const relay = workId
263
+ ? getControllerRoundRelay(store, workId)
264
+ : getRequirementControllerRoundRelay(store, requirementId!);
265
+ const legacyStartedDispatch = Boolean(
266
+ relay
267
+ && (relay.providerDispatchAttempt ?? 0) >= 1
268
+ && relay.providerDispatchEffectId === effect.effectId
269
+ && (
270
+ (relay.status === 'blocked' && controllerRoundBlockerClass(relay) === 'provider_dispatch_outcome_unknown')
271
+ || (relay.status === 'dispatched' && Boolean(relay.providerDispatchReceiptId))
272
+ )
273
+ );
274
+ if (!relay || !legacyStartedDispatch) return undefined;
275
+ const boundary = workflowSupervisorBoundaryForWork(store, relay.originWorkId);
276
+ if (boundary.status !== 'outer_turn'
277
+ || boundary.conversationId !== task.conversationId
278
+ || boundary.conversationUrl !== task.conversationUrl) return undefined;
279
+ return {
280
+ generation: 1,
281
+ dispatchId: `controller-round:${relay.relayScopeId}:${relay.providerDispatchAttempt}`,
282
+ evidence: {
283
+ surface: 'controller_round_reconciliation',
284
+ inherited_provider_dispatch: true,
285
+ relay_scope_id: relay.relayScopeId,
286
+ provider_dispatch_attempt: relay.providerDispatchAttempt,
287
+ ...(relay.providerDispatchStartedAt ? { provider_dispatch_started_at: relay.providerDispatchStartedAt } : {}),
288
+ },
289
+ };
290
+ },
291
+ projectScopeForTask: (task) => {
292
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
293
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
294
+ if (!repoId) return undefined;
295
+ if (taskControllerHome && taskControllerHome !== controllerHome) return undefined;
296
+ if (!taskControllerHome && task.continuationPolicy.kind !== 'standalone_supervisor') return undefined;
297
+ try {
298
+ const repository = getRepository(repoId, controllerHome);
299
+ const aliases = workflowSupervisorProjectAliases(task);
300
+ return {
301
+ title: repository.displayName,
302
+ ...(aliases.length > 0 ? { aliases } : {}),
303
+ repoId,
304
+ controllerHome,
305
+ };
306
+ } catch { return undefined; }
307
+ },
308
+ browserTaskActive,
309
+ bootstrapConversationBound: (task, context) => {
310
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
311
+ const workId = workflowSupervisorContractText(task, 'work_id');
312
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
313
+ if (!repoId || !workId || taskControllerHome !== controllerHome) return;
314
+ const existing = getChatgptWorkConversationBinding({ controllerHome, repoId }, workId);
315
+ if (existing && existing.conversationId !== task.conversationId) {
316
+ if (!context?.migratedFromConversationId || context.migratedFromConversationId !== existing.conversationId) {
317
+ throw new Error('WORKFLOW_SUPERVISOR_BOOTSTRAP_WORK_CONVERSATION_CONFLICT');
318
+ }
319
+ rebindChatgptWorkConversation({ controllerHome, repoId }, {
320
+ workId,
321
+ previousConversationId: existing.conversationId,
322
+ conversationUrl: task.conversationUrl,
323
+ localAlias: existing.localAlias,
324
+ });
325
+ return;
326
+ }
327
+ if (!existing) {
328
+ bindChatgptWorkConversation({ controllerHome, repoId }, {
329
+ workId,
330
+ conversationUrl: task.conversationUrl,
331
+ localAlias: 'Forge autonomous execution',
332
+ });
333
+ }
334
+ },
335
+ effectApplied: (task, effect, observation) => {
336
+ if (effect.kind !== 'enrollment') return;
337
+ const repoId = workflowSupervisorContractText(task, 'repo_id');
338
+ const requirementId = workflowSupervisorContractText(task, 'requirement_id');
339
+ const workId = repoId ? workflowSupervisorOriginWorkId(task, repoId) : undefined;
340
+ const taskControllerHome = workflowSupervisorContractText(task, 'controller_home');
341
+ if (!repoId || (!requirementId && !workId) || taskControllerHome !== controllerHome) return;
342
+ const store = { controllerHome, repoId };
343
+ const relay = workId
344
+ ? getControllerRoundRelay(store, workId)
345
+ : getRequirementControllerRoundRelay(store, requirementId!);
346
+ if (!relay || !['dispatching', 'blocked'].includes(relay.status)) return;
347
+ // Receipt projection can settle only the enrolled lower effect. A newer
348
+ // occurrence or sibling Work must never inherit an old conversation send.
349
+ if ((relay.providerDispatchEffectId ?? controllerRoundProviderEffectId(relay)) !== effect.effectId) return;
350
+ const boundary = workflowSupervisorBoundaryForWork(store, relay.originWorkId);
351
+ if (boundary.status !== 'outer_turn' || boundary.conversationId !== task.conversationId) return;
352
+ finishControllerRoundRelayDispatch(store, {
353
+ workId: relay.originWorkId,
354
+ ok: true,
355
+ providerDispatchEffectId: effect.effectId,
356
+ providerDispatchReceiptId: `workflow-supervisor:${effect.effectId}:${observation.observationId}`,
357
+ });
358
+ },
359
+ };
360
+ }
361
+ export async function workflowSupervisorCurrentConversationMatchesWork(
362
+ options: { controllerHome: string; repoId: string },
363
+ workId: string,
364
+ ): Promise<boolean> {
365
+ const boundary = workflowSupervisorBoundaryForWork(options, workId);
366
+ if (boundary.status !== 'outer_turn') return false;
367
+ const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
368
+ if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return false;
369
+ try {
370
+ const current = await getWorkflowSupervisorCurrentConversation(forgeHome);
371
+ // The same ChatGPT conversation may be rendered with or without its Project
372
+ // route. Its durable conversation id, not that route, proves continuity.
373
+ return Boolean(current
374
+ && current.conversationId === boundary.conversationId);
375
+ } catch {
376
+ return false;
377
+ }
378
+ }
379
+
380
+ export async function bindCurrentWorkflowSupervisorConversationForWork(
381
+ options: { controllerHome: string; repoId: string },
382
+ workId: string,
383
+ ): Promise<
384
+ | { status: 'bound'; binding: ChatgptWorkConversationBinding }
385
+ | { status: 'not_eligible' | 'current_conversation_unbound' | 'daemon_unavailable'; reason?: string }
386
+ > {
387
+ const work = getWorkContract(options, workId);
388
+ if (!work || semanticWorkState(work) !== 'open') return { status: 'not_eligible' };
389
+ const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
390
+ if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'daemon_unavailable', reason: 'WORKFLOW_SUPERVISOR_DAEMON_UNAVAILABLE' };
391
+ const existing = getChatgptWorkConversationBinding(options, workId);
392
+ const current = await getWorkflowSupervisorCurrentConversation(forgeHome);
393
+ // Browser focus is ephemeral observation, not a second authority over an
394
+ // already-bound Work. When a durable exact binding exists, a missing current
395
+ // marker cannot revoke it; a fresh conflicting marker still fails closed.
396
+ if (existing) {
397
+ if (current && existing.conversationId !== current.conversationId) {
398
+ throw new Error(`WORKFLOW_SUPERVISOR_CURRENT_CONVERSATION_CONFLICT:${workId}:${existing.conversationId}:${current.conversationId}`);
399
+ }
400
+ return { status: 'bound', binding: existing };
401
+ }
402
+ if (!current) return { status: 'current_conversation_unbound', reason: 'WORKFLOW_SUPERVISOR_CURRENT_CONVERSATION_UNBOUND' };
403
+ const binding = bindChatgptWorkConversation(options, {
404
+ workId,
405
+ conversationUrl: current.canonicalUrl,
406
+ localAlias: current.title,
407
+ });
408
+ return { status: 'bound', binding };
409
+ }
410
+
411
+ export async function ensureWorkflowSupervisorEnrollmentForWork(
412
+ options: { controllerHome: string; repoId: string },
413
+ workId: string,
414
+ ): Promise<{ status: WorkflowSupervisorEnrollmentStatus; taskId?: string; effectId?: string; reason?: string }> {
415
+ const boundary = workflowSupervisorBoundaryForWork(options, workId);
416
+ if (boundary.status === 'not_eligible') return { status: boundary.status };
417
+ const forgeHome = resolveWorkflowSupervisorForgeHome(options.controllerHome);
418
+ // Work-derived task ids are only bootstrap reservation identities. Once an
419
+ // exact conversation exists, the task-registration RPC returns the canonical
420
+ // Supervisor task already owning that conversation, including across successor Work.
421
+ const taskId = taskIdForWork(options.repoId, workId);
422
+ if (!existsSync(workflowSupervisorSocketPath(forgeHome))) return { status: 'daemon_unavailable', taskId };
423
+
424
+ // Once an exact conversation is already owned by a Supervisor task, that
425
+ // task is the outer-turn authority. ControllerRound is only first-admission
426
+ // execution context and must not regain veto power over later continuation.
427
+ // Read before any lower-layer admission check so a blocked/exhausted old
428
+ // Round cannot strand an already-enrolled exact conversation.
429
+ if (boundary.status === 'outer_turn') {
430
+ const existingAuthority = await getWorkflowSupervisorTaskByConversationId(forgeHome, boundary.conversationId);
431
+ if (existingAuthority) {
432
+ const existingRepoId = typeof existingAuthority.task.completionContract.repo_id === 'string'
433
+ ? existingAuthority.task.completionContract.repo_id
434
+ : existingAuthority.task.continuationPolicy.repo_id;
435
+ if (typeof existingRepoId === 'string' && existingRepoId !== options.repoId) {
436
+ throw new Error(`WORKFLOW_SUPERVISOR_TASK_REPOSITORY_CONFLICT:${boundary.conversationId}`);
437
+ }
438
+ if (existingAuthority.terminal) {
439
+ // Terminal Supervisor authority must never be resurrected by a lower
440
+ // ControllerRound. Report the outer-turn boundary as already owned so
441
+ // Scheduler/Controller composition cannot create another provider turn.
442
+ return {
443
+ status: 'enrolled',
444
+ taskId: existingAuthority.task.taskId,
445
+ reason: `WORKFLOW_SUPERVISOR_TASK_TERMINAL:${existingAuthority.terminal}`,
446
+ };
447
+ }
448
+ const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, existingAuthority.task.taskId);
449
+ return { status: 'enrolled', taskId: existingAuthority.task.taskId, effectId: effect.effectId };
450
+ }
451
+ }
452
+
453
+ const lowerLayer = workflowSupervisorLowerLayerReadyForWork(options, workId);
454
+ if (!lowerLayer.ready) return { status: 'lower_layer_not_ready', reason: lowerLayer.reason };
455
+ const work = getWorkContract(options, workId);
456
+ const requirement = work?.requirementId
457
+ ? readRequirement({ controllerHome: options.controllerHome }, work.requirementId)?.value
458
+ : undefined;
459
+ const registeredTask = await registerWorkflowSupervisorTask(forgeHome, {
460
+ taskId,
461
+ // This is a durable pre-send reservation, not a conversation identity.
462
+ // The Computer adapter replaces it atomically after the first confirmed
463
+ // submission exposes ChatGPT's canonical conversation URL.
464
+ conversationId: boundary.status === 'outer_turn' ? boundary.conversationId : `bootstrap:${workId}`,
465
+ conversationUrl: boundary.status === 'outer_turn' ? boundary.conversationUrl : 'https://chatgpt.com/',
466
+ objective: requirement?.outcomeStatement ?? work?.objective ?? workId,
467
+ completionContract: {
468
+ kind: requirement ? 'forge_requirement_done' : 'forge_work_done',
469
+ controller_home: options.controllerHome,
470
+ repo_id: options.repoId,
471
+ work_id: workId,
472
+ ...(requirement ? { requirement_id: requirement.requirementId } : {}),
473
+ },
474
+ continuationPolicy: {
475
+ kind: 'forge_goal_outer_turn',
476
+ ...(boundary.status === 'outer_turn'
477
+ ? { exact_conversation_id: boundary.conversationId, exact_conversation_url: boundary.conversationUrl }
478
+ : { bootstrap: true }),
479
+ outer_turn_owner: 'workflow_supervisor',
480
+ },
481
+ userBlockerPolicy: {
482
+ kind: requirement ? 'forge_requirement_waiting_for_user' : 'forge_work_waiting_for_user',
483
+ controller_home: options.controllerHome,
484
+ repo_id: options.repoId,
485
+ work_id: workId,
486
+ ...(requirement ? { requirement_id: requirement.requirementId } : {}),
487
+ },
488
+ });
489
+ const effect = await reserveWorkflowSupervisorEnrollment(forgeHome, registeredTask.taskId, lowerLayer.providerEffectId);
490
+ // Runtime owns only enrollment. Provider send/reconcile/re-dispatch budgeting
491
+ // stays entirely inside the Supervisor effect ledger and Browser adapter.
492
+ return { status: 'enrolled', taskId: registeredTask.taskId, effectId: effect.effectId };
493
+ }