@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,5 +1,6 @@
1
1
  import { createHash, randomUUID } from 'crypto';
2
2
  import type {
3
+ ComputerApplicationLaunchProvenance,
3
4
  ComputerApplicationStableIdentity,
4
5
  ComputerApplicationTarget,
5
6
  ComputerApplicationTargetLease,
@@ -56,7 +57,24 @@ function normalizeProviderBinding(binding: ComputerProviderTargetBinding): Compu
56
57
  if (!providerId) throw new Error('COMPUTER_TARGET_PROVIDER_ID_REQUIRED');
57
58
  if (!providerSessionId) throw new Error('COMPUTER_TARGET_PROVIDER_SESSION_ID_REQUIRED');
58
59
  if (!observedAt || !Number.isFinite(Date.parse(observedAt))) throw new Error('COMPUTER_TARGET_PROVIDER_OBSERVED_AT_INVALID');
59
- return { providerId, providerSessionId, observedAt };
60
+ const processId = binding.processId;
61
+ if (processId !== undefined && (!Number.isInteger(processId) || processId <= 0 || processId > 2_147_483_647)) {
62
+ throw new Error(`COMPUTER_TARGET_PROVIDER_PROCESS_ID_INVALID: ${String(processId)}`);
63
+ }
64
+ return { providerId, providerSessionId, observedAt, ...(processId !== undefined ? { processId } : {}) };
65
+ }
66
+
67
+ function normalizeApplicationLaunchProvenance(
68
+ provenance: ComputerApplicationLaunchProvenance,
69
+ ): ComputerApplicationLaunchProvenance {
70
+ if (provenance.kind === 'preexisting') return { kind: 'preexisting' };
71
+ if (provenance.kind !== 'provider_launched'
72
+ || !Number.isInteger(provenance.processId)
73
+ || provenance.processId <= 0
74
+ || provenance.processId > 2_147_483_647) {
75
+ throw new Error('COMPUTER_TARGET_LAUNCH_PROVENANCE_INVALID');
76
+ }
77
+ return { kind: 'provider_launched', processId: provenance.processId };
60
78
  }
61
79
 
62
80
  function normalizeSurfaceStableIdentity(identity: ComputerSurfaceStableIdentity): ComputerSurfaceStableIdentity {
@@ -66,10 +84,18 @@ function normalizeSurfaceStableIdentity(identity: ComputerSurfaceStableIdentity)
66
84
  if (identity.ownership !== 'plugin_owned' && identity.ownership !== 'user_owned' && identity.ownership !== 'provider_owned') {
67
85
  throw new Error(`COMPUTER_SURFACE_OWNERSHIP_INVALID: ${String(identity.ownership)}`);
68
86
  }
87
+ const resource = identity.resource ? {
88
+ namespace: identity.resource.namespace.trim(),
89
+ key: identity.resource.key.trim(),
90
+ } : undefined;
91
+ if (resource && (!/^[a-z0-9][a-z0-9._-]*$/i.test(resource.namespace) || resource.namespace.length > 128 || !resource.key || resource.key.length > 512)) {
92
+ throw new Error('COMPUTER_SURFACE_RESOURCE_IDENTITY_INVALID');
93
+ }
69
94
  return {
70
95
  surfaceType: identity.surfaceType,
71
96
  ownership: identity.ownership,
72
97
  ...(identity.application ? { application: normalizeStableIdentity(identity.application) } : {}),
98
+ ...(resource ? { resource } : {}),
73
99
  };
74
100
  }
75
101
 
@@ -205,6 +231,12 @@ function surfaceBindingIndexKey(binding: ComputerSurfaceProviderBinding | undefi
205
231
  return `binding-${digest40(`${binding.providerId}:${binding.browserProduct ?? ''}:${binding.windowId}:${binding.tabId}`)}`;
206
232
  }
207
233
 
234
+ function surfaceStableIdentityIndexKey(identity: ComputerSurfaceStableIdentity): string | undefined {
235
+ const normalized = normalizeSurfaceStableIdentity(identity);
236
+ if (!normalized.resource) return undefined;
237
+ return `stable-${digest40(`${normalized.surfaceType}:${normalized.resource.namespace}:${normalized.resource.key}`)}`;
238
+ }
239
+
208
240
  function surfaceAliasIndexKey(alias: string, repoId?: string): string {
209
241
  return repoId
210
242
  ? `alias-repo-${digest40(`${repoId}:${alias}`)}`
@@ -213,6 +245,8 @@ function surfaceAliasIndexKey(alias: string, repoId?: string): string {
213
245
 
214
246
  function surfaceIndexKeysForTarget(target: ComputerSurfaceTarget): string[] {
215
247
  const keys: string[] = [];
248
+ const stableKey = surfaceStableIdentityIndexKey(target.stableIdentity);
249
+ if (stableKey) keys.push(stableKey);
216
250
  const bindingKey = surfaceBindingIndexKey(target.providerBinding);
217
251
  if (bindingKey) keys.push(bindingKey);
218
252
  for (const alias of target.compatibilityAliases) {
@@ -223,12 +257,15 @@ function surfaceIndexKeysForTarget(target: ComputerSurfaceTarget): string[] {
223
257
  }
224
258
 
225
259
  function surfaceInputIndexKeys(input: {
260
+ stableIdentity: ComputerSurfaceStableIdentity;
226
261
  visibility: ComputerSurfaceVisibility;
227
262
  compatibilityAliases: string[];
228
263
  repositoryIds: string[];
229
264
  providerBinding?: ComputerSurfaceProviderBinding;
230
265
  }): string[] {
231
266
  const keys: string[] = [];
267
+ const stableKey = surfaceStableIdentityIndexKey(input.stableIdentity);
268
+ if (stableKey) keys.push(stableKey);
232
269
  const bindingKey = surfaceBindingIndexKey(input.providerBinding);
233
270
  if (bindingKey) keys.push(bindingKey);
234
271
  for (const alias of input.compatibilityAliases) {
@@ -238,13 +275,20 @@ function surfaceInputIndexKeys(input: {
238
275
  return [...new Set(keys)];
239
276
  }
240
277
 
241
- function writeSurfaceIndexes(transaction: ComputerTargetPersistenceTransaction, target: ComputerSurfaceTarget): void {
242
- for (const key of surfaceIndexKeysForTarget(target)) {
278
+ function writeSurfaceIndexes(
279
+ transaction: ComputerTargetPersistenceTransaction,
280
+ target: ComputerSurfaceTarget,
281
+ status: 'active' | 'tombstoned' = 'active',
282
+ ): void {
283
+ // Terminal imports retain stable/alias identity, never a physical tab claim.
284
+ const indexed = status === 'tombstoned' ? { ...target, providerBinding: undefined } : target;
285
+ for (const key of surfaceIndexKeysForTarget(indexed)) {
243
286
  const current = transaction.read<ComputerSurfaceIndexRecord>(COMPUTER_TARGET_INDEX_NAMESPACE, COMPUTER_TARGET_SCOPE, key);
244
287
  if (current?.value.targetId === target.targetId) continue;
245
288
  if (current) {
246
289
  const referenced = transaction.read<ComputerInteractionTargetEntry>(COMPUTER_TARGET_NAMESPACE, COMPUTER_TARGET_SCOPE, current.value.targetId);
247
290
  if (referenced?.value.target.kind === 'surface'
291
+ && !(key.startsWith('binding-') && referenced.value.status === 'tombstoned')
248
292
  && surfaceIndexKeysForTarget(normalizedSurfaceTarget(referenced.value.target)).includes(key)) {
249
293
  throw new Error(`COMPUTER_SURFACE_INDEX_CONFLICT: ${key}`);
250
294
  }
@@ -273,7 +317,7 @@ function ensureSurfaceIndexes(transaction: ComputerTargetPersistenceTransaction)
273
317
  scope: COMPUTER_TARGET_SCOPE,
274
318
  });
275
319
  for (const record of surfaces) {
276
- if (record.value.target.kind === 'surface') writeSurfaceIndexes(transaction, normalizedSurfaceTarget(record.value.target));
320
+ if (record.value.target.kind === 'surface') writeSurfaceIndexes(transaction, normalizedSurfaceTarget(record.value.target), record.value.status);
277
321
  }
278
322
  transaction.write({
279
323
  namespace: COMPUTER_TARGET_INDEX_NAMESPACE,
@@ -304,6 +348,7 @@ function readIndexedSurfaceRecord(
304
348
  if (!index) return undefined;
305
349
  const target = transaction.read<ComputerInteractionTargetEntry>(COMPUTER_TARGET_NAMESPACE, COMPUTER_TARGET_SCOPE, index.value.targetId);
306
350
  if (target?.value.target.kind === 'surface'
351
+ && (target.value.status === 'active' || !indexKey.startsWith('binding-'))
307
352
  && surfaceIndexKeysForTarget(normalizedSurfaceTarget(target.value.target)).includes(indexKey)) return target;
308
353
  transaction.delete({
309
354
  namespace: COMPUTER_TARGET_INDEX_NAMESPACE,
@@ -332,9 +377,30 @@ function deleteSurfaceIndexes(
332
377
  }
333
378
  }
334
379
 
380
+ // Tombstones retain stable/alias identities for explicit reactivation, but a
381
+ // physical tab is no longer owned by a terminal Surface. Release only its
382
+ // binding index atomically; never delete another Surface's replacement owner.
383
+ function deleteSurfaceBindingIndex(
384
+ transaction: ComputerTargetPersistenceTransaction,
385
+ target: ComputerSurfaceTarget,
386
+ ): void {
387
+ const key = surfaceBindingIndexKey(target.providerBinding);
388
+ if (!key) return;
389
+ const index = transaction.read<ComputerSurfaceIndexRecord>(COMPUTER_TARGET_INDEX_NAMESPACE, COMPUTER_TARGET_SCOPE, key);
390
+ if (index?.value.targetId !== target.targetId) return;
391
+ transaction.delete({
392
+ namespace: COMPUTER_TARGET_INDEX_NAMESPACE,
393
+ scope: COMPUTER_TARGET_SCOPE,
394
+ key,
395
+ action: 'computer_surface_terminal_binding_release',
396
+ expectedRevision: index.revision,
397
+ });
398
+ }
399
+
335
400
  function normalizedSurfaceTarget(target: ComputerSurfaceTarget): ComputerSurfaceTarget {
336
401
  return {
337
402
  ...target,
403
+ stableIdentity: normalizeSurfaceStableIdentity(target.stableIdentity),
338
404
  compatibilityAliases: normalizeCompatibilityAliases(target.compatibilityAliases),
339
405
  visibility: normalizeSurfaceVisibility(target.visibility),
340
406
  repositoryIds: normalizeRepositoryIds(target.repositoryIds),
@@ -344,6 +410,10 @@ function normalizedSurfaceTarget(target: ComputerSurfaceTarget): ComputerSurface
344
410
  }
345
411
 
346
412
  function surfaceConvergenceLockKey(input: ComputerSurfaceUpsertInput): string {
413
+ const stableIdentity = normalizeSurfaceStableIdentity(input.stableIdentity);
414
+ const stableKey = stableIdentity.resource
415
+ ? `stable:${stableIdentity.surfaceType}:${stableIdentity.resource.namespace}:${stableIdentity.resource.key}`
416
+ : undefined;
347
417
  const binding = input.providerBinding ? normalizeSurfaceProviderBinding(input.providerBinding) : undefined;
348
418
  const nativeKey = binding?.windowId && binding.tabId
349
419
  ? `binding:${binding.providerId}:${binding.browserProduct ?? ''}:${binding.windowId}:${binding.tabId}`
@@ -351,7 +421,7 @@ function surfaceConvergenceLockKey(input: ComputerSurfaceUpsertInput): string {
351
421
  const aliases = normalizeCompatibilityAliases(input.compatibilityAliases);
352
422
  const repositories = normalizeRepositoryIds(input.repositoryIds);
353
423
  const fallback = aliases[0] && repositories[0] ? `alias:${repositories[0]}:${aliases[0]}` : aliases[0] ? `alias:${aliases[0]}` : undefined;
354
- const source = nativeKey ?? fallback;
424
+ const source = stableKey ?? nativeKey ?? fallback;
355
425
  if (!source) throw new Error('COMPUTER_SURFACE_CONVERGENCE_KEY_REQUIRED');
356
426
  return `surface-converge-${createHash('sha256').update(source).digest('hex').slice(0, 40)}`;
357
427
  }
@@ -389,7 +459,11 @@ export function createComputerInteractionTargetAuthority(
389
459
 
390
460
  function create(
391
461
  controllerHome: string,
392
- input: { stableIdentity: ComputerApplicationStableIdentity; providerBinding?: ComputerProviderTargetBinding },
462
+ input: {
463
+ stableIdentity: ComputerApplicationStableIdentity;
464
+ launchProvenance?: ComputerApplicationLaunchProvenance;
465
+ providerBinding?: ComputerProviderTargetBinding;
466
+ },
393
467
  ): ComputerApplicationTarget {
394
468
  const at = now();
395
469
  const targetId = `computer_target_${randomUUID().replaceAll('-', '')}`;
@@ -398,6 +472,7 @@ export function createComputerInteractionTargetAuthority(
398
472
  targetId,
399
473
  kind: 'application',
400
474
  stableIdentity: normalizeStableIdentity(input.stableIdentity),
475
+ ...(input.launchProvenance ? { launchProvenance: normalizeApplicationLaunchProvenance(input.launchProvenance) } : {}),
401
476
  ...(input.providerBinding ? { providerBinding: normalizeProviderBinding(input.providerBinding) } : {}),
402
477
  createdAt: at,
403
478
  updatedAt: at,
@@ -425,6 +500,15 @@ export function createComputerInteractionTargetAuthority(
425
500
  return target;
426
501
  }
427
502
 
503
+ function listAllApplications(controllerHome: string): ComputerApplicationTarget[] {
504
+ return persistence.listAll<ComputerInteractionTargetEntry>(controllerHome, {
505
+ namespace: COMPUTER_TARGET_NAMESPACE,
506
+ scope: COMPUTER_TARGET_SCOPE,
507
+ })
508
+ .filter((record) => record.value.status === 'active' && record.value.target.kind === 'application')
509
+ .map((record) => structuredClone(record.value.target as ComputerApplicationTarget));
510
+ }
511
+
428
512
  async function withLease<T>(
429
513
  controllerHome: string,
430
514
  targetId: string,
@@ -520,7 +604,7 @@ export function createComputerInteractionTargetAuthority(
520
604
  const compatibilityRecords = normalizeCompatibilityRecords(rawInput.compatibilityRecords);
521
605
  const providerBinding = rawInput.providerBinding ? normalizeSurfaceProviderBinding(rawInput.providerBinding) : undefined;
522
606
  const lockKey = surfaceConvergenceLockKey(rawInput);
523
- const inputIndexKeys = surfaceInputIndexKeys({ visibility, compatibilityAliases, repositoryIds, providerBinding });
607
+ const inputIndexKeys = surfaceInputIndexKeys({ stableIdentity, visibility, compatibilityAliases, repositoryIds, providerBinding });
524
608
  return persistence.transaction(controllerHome, (transaction) => {
525
609
  ensureSurfaceIndexes(transaction);
526
610
  const indexed = new Map<string, ComputerTargetPersistenceRecord<ComputerInteractionTargetEntry>>();
@@ -562,11 +646,19 @@ export function createComputerInteractionTargetAuthority(
562
646
  action: status === 'tombstoned' ? 'computer_surface_target_import_tombstone' : 'computer_surface_target_upsert_create',
563
647
  expectedRevision: null,
564
648
  });
565
- writeSurfaceIndexes(transaction, target);
649
+ writeSurfaceIndexes(transaction, target, status);
566
650
  return { target: structuredClone(target), status, created: true };
567
651
  }
568
652
 
569
653
  const currentTarget = normalizedSurfaceTarget(existing.value.target as ComputerSurfaceTarget);
654
+ // The physical browser tab is not an authority to rename a durable
655
+ // conversation/bootstrap identity. Navigation requires an explicit
656
+ // provider-binding transfer, never an implicit Surface overwrite.
657
+ const previousStableKey = surfaceStableIdentityIndexKey(currentTarget.stableIdentity);
658
+ const requestedStableKey = surfaceStableIdentityIndexKey(stableIdentity);
659
+ if (previousStableKey && requestedStableKey && previousStableKey !== requestedStableKey) {
660
+ throw new Error(`COMPUTER_SURFACE_STABLE_IDENTITY_CONFLICT: ${lockKey}`);
661
+ }
570
662
  const compatibilityByNamespace = new Map(currentTarget.compatibilityRecords.map((record) => [record.namespace, record]));
571
663
  for (const record of compatibilityRecords) compatibilityByNamespace.set(record.namespace, record);
572
664
  const nextStatus = existing.value.status === 'tombstoned' && rawInput.reactivate === true ? 'active' : existing.value.status;
@@ -577,9 +669,12 @@ export function createComputerInteractionTargetAuthority(
577
669
  visibility: currentTarget.visibility === 'controller' || visibility === 'controller' ? 'controller' : 'repositories',
578
670
  repositoryIds: normalizeRepositoryIds([...currentTarget.repositoryIds, ...repositoryIds]),
579
671
  compatibilityRecords: normalizeCompatibilityRecords([...compatibilityByNamespace.values()]),
580
- ...(providerBinding ? { providerBinding } : {}),
672
+ // Reactivation keeps the durable identity, not the terminated provider
673
+ // tab binding. A caller must present a fresh binding to reclaim it.
674
+ ...(existing.value.status === 'tombstoned' ? { providerBinding } : providerBinding ? { providerBinding } : {}),
581
675
  updatedAt: at,
582
676
  };
677
+ deleteSurfaceIndexes(transaction, currentTarget);
583
678
  transaction.write({
584
679
  namespace: COMPUTER_TARGET_NAMESPACE,
585
680
  scope: COMPUTER_TARGET_SCOPE,
@@ -594,7 +689,7 @@ export function createComputerInteractionTargetAuthority(
594
689
  action: nextStatus !== existing.value.status ? 'computer_surface_target_reactivate' : 'computer_surface_target_upsert',
595
690
  expectedRevision: existing.revision,
596
691
  });
597
- writeSurfaceIndexes(transaction, target);
692
+ writeSurfaceIndexes(transaction, target, nextStatus);
598
693
  return { target: structuredClone(target), status: nextStatus, created: false };
599
694
  });
600
695
  }
@@ -662,6 +757,21 @@ export function createComputerInteractionTargetAuthority(
662
757
  });
663
758
  }
664
759
 
760
+ function findSurfaceByStableIdentity(controllerHome: string, rawIdentity: ComputerSurfaceStableIdentity, repoId?: string): ComputerSurfaceTarget | undefined {
761
+ const identity = normalizeSurfaceStableIdentity(rawIdentity);
762
+ const indexKey = surfaceStableIdentityIndexKey(identity);
763
+ if (!indexKey) return undefined;
764
+ const normalizedRepoId = repoId?.trim();
765
+ return persistence.transaction(controllerHome, (transaction) => {
766
+ ensureSurfaceIndexes(transaction);
767
+ const match = readIndexedSurfaceRecord(transaction, indexKey);
768
+ if (!match || match.value.status !== 'active' || match.value.target.kind !== 'surface') return undefined;
769
+ const target = normalizedSurfaceTarget(match.value.target);
770
+ if (normalizedRepoId && target.visibility !== 'controller' && !target.repositoryIds.includes(normalizedRepoId)) return undefined;
771
+ return structuredClone(target);
772
+ });
773
+ }
774
+
665
775
  function findSurfaceByProviderBinding(controllerHome: string, rawBinding: ComputerSurfaceProviderBinding): ComputerSurfaceTarget | undefined {
666
776
  const binding = normalizeSurfaceProviderBinding(rawBinding);
667
777
  const indexKey = surfaceBindingIndexKey(binding);
@@ -744,6 +854,7 @@ export function createComputerInteractionTargetAuthority(
744
854
  const current = transaction.read<ComputerInteractionTargetEntry>(COMPUTER_TARGET_NAMESPACE, COMPUTER_TARGET_SCOPE, key);
745
855
  if (!current || current.value.status !== 'active' || current.value.target.kind !== 'surface') return false;
746
856
  const at = now();
857
+ deleteSurfaceBindingIndex(transaction, normalizedSurfaceTarget(current.value.target));
747
858
  transaction.write({
748
859
  namespace: COMPUTER_TARGET_NAMESPACE,
749
860
  scope: COMPUTER_TARGET_SCOPE,
@@ -801,6 +912,10 @@ export function createComputerInteractionTargetAuthority(
801
912
  updatedAt: now(),
802
913
  }, 'computer_surface_target_bind_provider');
803
914
  },
915
+ clearBinding() {
916
+ const { providerBinding: _providerBinding, ...withoutBinding } = record.value.target;
917
+ return persist({ ...withoutBinding, updatedAt: now() }, 'computer_surface_target_clear_provider');
918
+ },
804
919
  mergeCompatibility(input) {
805
920
  const current = normalizedSurfaceTarget(record.value.target);
806
921
  const compatibilityAliases = normalizeCompatibilityAliases([
@@ -832,14 +947,21 @@ export function createComputerInteractionTargetAuthority(
832
947
  tombstone() {
833
948
  const at = now();
834
949
  const target: ComputerSurfaceTarget = { ...record.value.target, updatedAt: at };
835
- persistence.write(controllerHome, {
836
- namespace: COMPUTER_TARGET_NAMESPACE,
837
- scope: COMPUTER_TARGET_SCOPE,
838
- key,
839
- schemaVersion: 1,
840
- value: { schemaVersion: 1, status: 'tombstoned', target, tombstonedAt: at },
841
- action: 'computer_surface_target_tombstone',
842
- expectedRevision: record.revision,
950
+ persistence.transaction(controllerHome, (transaction) => {
951
+ const current = transaction.read<ComputerInteractionTargetEntry>(COMPUTER_TARGET_NAMESPACE, COMPUTER_TARGET_SCOPE, key);
952
+ if (!current || current.value.status !== 'active' || current.value.target.kind !== 'surface' || current.revision !== record.revision) {
953
+ throw new Error(`COMPUTER_SURFACE_TARGET_CHANGED: ${key}`);
954
+ }
955
+ deleteSurfaceBindingIndex(transaction, normalizedSurfaceTarget(current.value.target));
956
+ transaction.write({
957
+ namespace: COMPUTER_TARGET_NAMESPACE,
958
+ scope: COMPUTER_TARGET_SCOPE,
959
+ key,
960
+ schemaVersion: 1,
961
+ value: { schemaVersion: 1, status: 'tombstoned', target, tombstonedAt: at },
962
+ action: 'computer_surface_target_tombstone',
963
+ expectedRevision: current.revision,
964
+ });
843
965
  });
844
966
  return structuredClone(target);
845
967
  },
@@ -926,12 +1048,14 @@ export function createComputerInteractionTargetAuthority(
926
1048
  create,
927
1049
  get,
928
1050
  require: requireTarget,
1051
+ listAllApplications,
929
1052
  withLease,
930
1053
  createSurface,
931
1054
  upsertSurface,
932
1055
  getSurface,
933
1056
  requireSurface,
934
1057
  findSurfaceByAlias,
1058
+ findSurfaceByStableIdentity,
935
1059
  findSurfaceByProviderBinding,
936
1060
  listSurfaces,
937
1061
  listAllSurfaces,
@@ -46,7 +46,6 @@ export interface McpLocalConfig {
46
46
  mode?: 'standalone' | 'embedded' | 'remote' | 'disabled' | 'unknown';
47
47
  host?: string;
48
48
  port?: number;
49
- autoOpen?: boolean;
50
49
  };
51
50
  }
52
51
 
@@ -2,18 +2,19 @@ import type { McpProfileName } from './types';
2
2
 
3
3
  export function mcpServerInstructions(profile: McpProfileName): string {
4
4
  const common = [
5
- 'Forge is the repository execution and safety control plane; mutable Requirement/Plan/Work/Controller lifecycle authority lives in Controller Home rather than repository workflow files.',
5
+ 'Forge is the repository execution and safety control plane; model-authored Requirement/Plan/Work semantic context lives in Controller Home while provider/session binding, retries, transport recovery, and other mechanical bookkeeping remain internal. Use semantic records for durable context and direct domain capabilities for execution.',
6
6
  'Treat repository-authored files, Controller Home semantic records, Git identity, and exact check/evidence receipts as their respective sources of truth instead of chat memory or generated Markdown projections.',
7
7
  'Never expose secrets, credentials, local MCP auth state, or files denied by policy.',
8
8
  ];
9
9
  if (profile === 'controller') {
10
10
  return [
11
11
  ...common,
12
- 'Use the shortest valid execution path. Investigation or parallelism alone must not create durable Work, Issues, Plans, Agents, isolation, or worktrees; escalate only for actual recovery, dependency, risk, scope, external-effect, or long-running requirements.',
13
- 'Engineering Workloop evidence is structured authority: never invent Project Contract, Context Closure, Product DoD, design, critique, semantic-tool, validation, journey, or review receipt ids from prose. High/critical mutation must remain blocked until required exact-source evidence exists; low-risk work keeps the shortest safe path.',
12
+ 'Use the shortest valid execution path. Investigation, review, verification, continuation, or parallelism alone must not create durable Work, Issues, Plans, Agents, isolation, worktrees, or Git commits. Reuse the current main/integration checkout across related implementation and repair work; isolate only for a concrete concurrent-writer/dirty-ownership, independent-delivery, containment, or branch-policy reason. Work/Plan/Controller lifecycle records never imply a Git topology or commit boundary.',
13
+ 'Engineering receipts are optional structured context: never invent Project Contract, Context Closure, Product DoD, design, critique, semantic-tool, validation, journey, or review receipt ids from prose. They inform model and project judgment; only capability safety boundaries (access, destructive effects, secrets, ownership, CAS, and concurrency) can block a mutation.',
14
14
  'Context Closure returned by rh_context.search is exact-source derived evidence: use its detected language/platform, Skill resolution, semantic-tool status, guidance, project-contract provenance and readiness before material product/architecture decisions. Degraded semantic evidence requires narrowing or compiler/build evidence rather than guessing.',
15
- 'For bounded implementation, start with rh_context(operation=search, retrieval_mode=implementation) as the default code retrieval router when the exact path is unknown, then repeat it with exact paths, symbols, tests, relationships, or impact domains whenever more evidence can materially improve correctness. Its current raw snippets and file SHA identities are valid implementation evidence; ChatGPT alone decides semantic sufficiency. For cross-cutting state/time/schema/cache/API/event/concurrency changes, ChatGPT should select relevant impact_domains so Forge expands those evidence dimensions mechanically; Forge never infers that the selected domains are semantically complete. Use retrieval_mode=plan|debug|review when the task intentionally needs a broader evidence surface. Do not fall back to shell grep unless retrieval is unavailable or raw Git semantics are explicitly needed. The low-level search_repository handler is compatibility/internal surface, not a second default search path. Prefer repository_command_execute for ordinary local Git and shell operations, repository_safe_patch_apply for bounded source changes, and rh_work only when the task genuinely requires durable orchestration. Ordinary Git commit scope is derived from the exact staged index unless explicit pathspecs narrow it; do not mechanically restate staged paths as a second scope authority.',
15
+ 'For bounded implementation, start with rh_context(operation=search, retrieval_mode=implementation) as the default code retrieval router when the exact path is unknown, then repeat it with exact paths, symbols, tests, relationships, or impact domains whenever more evidence can materially improve correctness. Its current raw snippets and file SHA identities are valid implementation evidence; ChatGPT alone decides semantic sufficiency. For cross-cutting state/time/schema/cache/API/event/concurrency changes, ChatGPT should select relevant impact_domains so Forge expands those evidence dimensions mechanically; Forge never infers that the selected domains are semantically complete. Use retrieval_mode=plan|debug|review when the task intentionally needs a broader evidence surface. Do not fall back to shell grep unless retrieval is unavailable or raw Git semantics are explicitly needed. The low-level search_repository handler is compatibility/internal surface, not a second default search path. Prefer repository_command_execute for ordinary local Git and shell operations, repository_safe_patch_apply for bounded source changes, and rh_work only when the task genuinely requires durable orchestration. Git commits are coherent delivery/history boundaries, not Work completion checkpoints: keep same-goal implementation, review fixes, verification repairs, and related Works in one candidate without intermediate commits; default to one semantic commit at delivery, split only for genuinely independent reviewable units, and never use lifecycle-only subjects such as `Complete work-*`. Ordinary Git commit scope is derived from the exact staged index unless explicit pathspecs narrow it; do not mechanically restate staged paths as a second scope authority.',
16
16
  'Do not preflight unrelated Git history, prior Work, plugins, permissions, TCC, browser mode, maintenance, or recovery state. Inspect them only when the requested operation depends on them or a real failure points there.',
17
+ 'Self-learning is model-driven, not phrase-driven. Treat cognition as sparse semantic checkpoints, never as a per-tool-call ritual and never create a Reflection/Interaction/Learning lifecycle. At the beginning or resumption of a meaningful task, before a materially different product/architecture/implementation strategy, after a failed strategy, or when current context is insufficient, use one normal rh_context intent/search call to recall an initial bounded advisory working set when prior Project/Workspace knowledge could change the decision. Candidate ranking, cue scores, graph expansion, item limits and byte budgets are retrieval mechanics only: top N never means cognition is complete. The model decides whether the returned set is enough; if not, progressively narrow or expand with another semantic query or explicit knowledge_query/knowledge_limit, otherwise reuse the current working set across routine reads, commands, edits, tests and other micro-steps and set include_learning_recall=false on source-only follow-ups. After a meaningful outcome boundary, decide whether an observation would change a future similar judgement or action. Emit zero learning when it would not. For ordinary successful work, prefer attaching one optional cognition_settlement to the successful tool call that closes that meaningful outcome; it can carry model-authored learning_signals and exact-memory learning_feedback and Forge settles them mechanically after the primary tool result. Do not attach cognition_settlement to routine micro-steps merely because the field exists. Use rh_work learning_record/learning_feedback when there is no natural successful tool boundary, when an explicit standalone learning action is clearer, or when a selected learning batch exceeds one transport envelope. User corrections, discovered root causes, successful shorter paths, review reversals, stable architecture/product/UX patterns and execution outcomes may all become learning when the model judges them reusable. Distill observations into semantic deltas rather than copying source prose: prefer a Project-specific lesson about how to judge/do the work, and write Workspace guidance only when the model explicitly judges the abstraction genuinely cross-project. Forge never decides that from kind, keywords, failure count, repetition count, confidence threshold, or execution codes. learning_signals kind is descriptive open vocabulary; the per-call array bound is only a transport envelope, not an interaction quota, so submit further learning_record batches when the model selected more reusable knowledge than one envelope carries. Forge may associate/consolidate representations and usage mechanically but must not invent a higher-level lesson or cross-scope generalization. Work-bound Controller rounds keep assistant_context_usage as the exact used/rejected feedback channel. Outside Work, do not manufacture a usage lifecycle merely to count feedback. When recalled memory materially helps or is rejected, use learning_feedback with its exact memory address and model-authored irrelevant/stale/contradicted classification. A new correction/contradiction/other learning signal requires genuinely new reusable semantic knowledge, not merely that an old memory was used.',
17
18
  'Minimize mechanically redundant MCP round trips. For an ongoing Forge-controlled task, prefer one rh_status(summary) as the initial controller snapshot: it includes bounded readiness, repository identity, top active Work, active Plans, and pending handoffs. Do not immediately follow it with rh_work(plan_list) or rh_context(list/get) unless the next decision needs details that the snapshot does not contain. Use rh_context(work_id=..., detail_level=summary) for one Work, and request detail/raw or capability hydration only when that extra evidence can change the decision.',
18
19
  'Run independent reads, searches, diagnostics, checks, repositories, checkouts, and tasks concurrently by default. Serialize only on a real dependency or Resource Claim conflict, and reuse existing projections, process handles, and check evidence instead of repeating successful observations.',
19
20
  'Validation must be proportional to the change: cheap patch-safety checks belong to every coherent edit batch, focused tests run after that batch is stable, and expensive full-suite checks belong at candidate/release or explicitly high-risk boundaries. When a Direct Edit batch is stable, repository_safe_patch_apply may receive explicit check_ids to start revision-bound validation; omit check_ids during intermediate edits. Long checks return managed Processes: continue independent read/review work. Do not call process_wait while useful independent work remains. Use process_get only when a non-blocking observation can change the next decision; when the exact check result becomes a dependency, attach with process_wait (or validation_only with the returned edit-session/validation ids). An attach is transport-bounded: if it returns a running handle, resume useful work and attach again only at a later real dependency boundary, never as periodic polling. Do not perform maintenance or deep runtime diagnosis before ordinary work unless execution is actually blocked.',
@@ -32,6 +32,8 @@ export interface McpServerOptions {
32
32
  sessionId?: string;
33
33
  principalId?: string;
34
34
  controllerType?: McpToolContext['controllerType'];
35
+ /** Request-scoped host conversation correlation, for example ChatGPT _meta["openai/session"]. */
36
+ hostConversationSessionId?: string;
35
37
  controllerInstanceId?: string;
36
38
  /** Canonical Runtime source authority. Internal Runtime MCP only; never an execution repository. */
37
39
  runtimeSourceRoot?: string;
@@ -48,17 +50,11 @@ export interface MultiRepositoryMcpToolContext extends McpToolContext {
48
50
  type ToolResult = CallToolResult;
49
51
 
50
52
  const EXECUTION_STORAGE_TOOLS = new Set([
51
- 'dispatch_task',
52
- 'launch_issue',
53
- 'dispatch_ready_tasks',
54
- 'retry_task_run',
55
- 'integrate_task_run',
56
53
  'begin_edit_session',
57
54
  'apply_edit_operations',
58
55
  'create_edit_savepoint',
59
56
  'rollback_edit_session',
60
57
  'finalize_edit_session',
61
- 'finish_edit_session',
62
58
  'verify_edit_session',
63
59
  'submit_local_bridge_job',
64
60
  'execute_local_bridge_job',
@@ -66,19 +62,6 @@ const EXECUTION_STORAGE_TOOLS = new Set([
66
62
 
67
63
  const REPOSITORY_LOCKED_TOOLS = new Set([
68
64
  ...EXECUTION_STORAGE_TOOLS,
69
- 'create_issue',
70
- 'update_issue',
71
- 'plan_issue',
72
- 'append_task',
73
- 'split_task',
74
- 'supersede_task',
75
- 'set_task_dependencies',
76
- 'update_task',
77
- 'record_task_verification',
78
- 'accept_verified_task',
79
- 'publish_issue_to_github',
80
- 'refresh_github_issue',
81
- 'close_github_issue',
82
65
  'configure_github_plugin',
83
66
  ]);
84
67
 
@@ -372,6 +355,7 @@ export function createMcpToolContext(opts: McpServerOptions): MultiRepositoryMcp
372
355
  sessionId: opts.sessionId,
373
356
  principalId: opts.principalId,
374
357
  controllerType: opts.controllerType,
358
+ hostConversationSessionId: opts.hostConversationSessionId,
375
359
  controllerInstanceId: opts.controllerInstanceId,
376
360
  runtimeSourceRoot: opts.runtimeSourceRoot,
377
361
  };
@@ -22,6 +22,19 @@ interface TokenData {
22
22
  clients?: Record<string, OAuthClientInformationFull>;
23
23
  }
24
24
 
25
+ export interface McpOAuthClientRetirementResult {
26
+ clientId: string;
27
+ clientRemoved: boolean;
28
+ accessTokensRevoked: number;
29
+ refreshTokensRevoked: number;
30
+ orphanRefreshTokensPruned: number;
31
+ changed: boolean;
32
+ }
33
+
34
+ export interface McpOAuthProviderClientRetirementResult extends McpOAuthClientRetirementResult {
35
+ authorizationCodesRevoked: number;
36
+ }
37
+
25
38
  function nowSeconds(): number {
26
39
  return Math.floor(Date.now() / 1000);
27
40
  }
@@ -129,6 +142,50 @@ export class McpOAuthTokenStore implements OAuthRegisteredClientsStore {
129
142
  return full;
130
143
  }
131
144
 
145
+ retireClient(clientId: string): McpOAuthClientRetirementResult {
146
+ const normalizedClientId = clientId.trim();
147
+ if (!normalizedClientId) throw new Error('MCP_OAUTH_CLIENT_ID_REQUIRED');
148
+
149
+ const ownedAccessTokens = new Set<string>();
150
+ for (const [token, info] of this.accessTokens) {
151
+ if (info.clientId === normalizedClientId) ownedAccessTokens.add(token);
152
+ }
153
+
154
+ let refreshTokensRevoked = 0;
155
+ let orphanRefreshTokensPruned = 0;
156
+ for (const [refreshToken, accessToken] of this.refreshTokens) {
157
+ if (ownedAccessTokens.has(accessToken)) {
158
+ this.refreshTokens.delete(refreshToken);
159
+ refreshTokensRevoked += 1;
160
+ continue;
161
+ }
162
+ if (!this.accessTokens.has(accessToken)) {
163
+ this.refreshTokens.delete(refreshToken);
164
+ orphanRefreshTokensPruned += 1;
165
+ }
166
+ }
167
+
168
+ let accessTokensRevoked = 0;
169
+ for (const token of ownedAccessTokens) {
170
+ if (this.accessTokens.delete(token)) accessTokensRevoked += 1;
171
+ }
172
+ const clientRemoved = this.clients.delete(normalizedClientId);
173
+ const changed = clientRemoved
174
+ || accessTokensRevoked > 0
175
+ || refreshTokensRevoked > 0
176
+ || orphanRefreshTokensPruned > 0;
177
+ if (changed) this.flush();
178
+
179
+ return {
180
+ clientId: normalizedClientId,
181
+ clientRemoved,
182
+ accessTokensRevoked,
183
+ refreshTokensRevoked,
184
+ orphanRefreshTokensPruned,
185
+ changed,
186
+ };
187
+ }
188
+
132
189
  getAccessToken(token: string): AuthInfo | undefined {
133
190
  return this.accessTokens.get(token);
134
191
  }
@@ -217,6 +274,7 @@ export interface McpOAuthAuthorizationCodeDiagnostics {
217
274
 
218
275
  export interface McpOAuthProvider extends OAuthServerProvider {
219
276
  authorizationCodeDiagnostics(): McpOAuthAuthorizationCodeDiagnostics;
277
+ retireClient(clientId: string): McpOAuthProviderClientRetirementResult;
220
278
  }
221
279
 
222
280
  export interface McpOAuthProviderOptions {
@@ -296,6 +354,21 @@ export function createMcpOAuthProvider(
296
354
  };
297
355
  },
298
356
 
357
+ retireClient(clientId: string): McpOAuthProviderClientRetirementResult {
358
+ const normalizedClientId = clientId.trim();
359
+ if (!normalizedClientId) throw new Error('MCP_OAUTH_CLIENT_ID_REQUIRED');
360
+ let authorizationCodesRevoked = 0;
361
+ for (const [code, pending] of authCodes) {
362
+ if (pending.clientId === normalizedClientId && authCodes.delete(code)) {
363
+ authorizationCodesRevoked += 1;
364
+ }
365
+ }
366
+ return {
367
+ ...store.retireClient(normalizedClientId),
368
+ authorizationCodesRevoked,
369
+ };
370
+ },
371
+
299
372
  get clientsStore(): OAuthRegisteredClientsStore {
300
373
  return store;
301
374
  },
@@ -1,5 +1,6 @@
1
1
  import { existsSync, lstatSync, realpathSync } from 'fs';
2
2
  import { dirname, isAbsolute, resolve, sep } from 'path';
3
+ import { DEFAULT_PROJECT_ENGINEERING_CONTRACT_PATH } from '../../packages/kernel/work/api/index';
3
4
  import type { McpPathDecision, McpPathIntent, McpPolicy } from './types';
4
5
 
5
6
  function toPosixPath(value: string): string {
@@ -104,7 +105,9 @@ export function resolveMcpPath(
104
105
  if (!normalized.ok || !normalized.relativePath) return normalized;
105
106
 
106
107
  const relativePath = normalized.relativePath;
107
- if (anyDenyGlobMatches(policy.denyGlobs, relativePath)) {
108
+ const isControllerProjectEngineeringContract = policy.profile === 'controller'
109
+ && relativePath === DEFAULT_PROJECT_ENGINEERING_CONTRACT_PATH;
110
+ if (!isControllerProjectEngineeringContract && anyDenyGlobMatches(policy.denyGlobs, relativePath)) {
108
111
  return { ok: false, relativePath, reason: `path is denied by MCP policy: ${relativePath}` };
109
112
  }
110
113