@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
@@ -33,6 +33,13 @@ export function browserPermissions(ready: boolean): AssistantPluginPermissionSco
33
33
  granted: ready,
34
34
  required: true,
35
35
  },
36
+ {
37
+ scope: 'browser.extensions',
38
+ mode: 'write',
39
+ description: 'List or load bounded unpacked extensions through the existing Browser provider control plane.',
40
+ granted: ready,
41
+ required: false,
42
+ },
36
43
  ];
37
44
  }
38
45
 
@@ -64,6 +71,13 @@ export function browserCapabilities(): AssistantPluginCapability[] {
64
71
  'get_console_errors', 'get_failed_requests',
65
72
  ],
66
73
  },
74
+ {
75
+ capabilityId: 'browser-extensions',
76
+ title: 'Browser Extensions',
77
+ description: 'List or load unpacked extensions from policy-bounded local directories without exposing raw CDP methods.',
78
+ scopes: ['browser.extensions', 'browser.profile'],
79
+ actions: ['list_unpacked_extensions', 'install_unpacked_extension'],
80
+ },
67
81
  {
68
82
  capabilityId: 'browser-interaction',
69
83
  title: 'Browser Interaction',
@@ -112,11 +126,11 @@ function interactSchema(extra: Record<string, unknown>, required: string[]): Rec
112
126
  export function browserActions(): AssistantPluginActionDescriptor[] {
113
127
  const readRemote = [
114
128
  { resource: 'remote' as const, mode: 'read' as const },
115
- { resource: 'repo-state' as const, mode: 'write' as const },
129
+ { resource: 'provider-state' as const, mode: 'write' as const },
116
130
  ];
117
131
  const writeRemote = [
118
132
  { resource: 'remote' as const, mode: 'exclusive' as const },
119
- { resource: 'repo-state' as const, mode: 'write' as const },
133
+ { resource: 'provider-state' as const, mode: 'write' as const },
120
134
  ];
121
135
  const descriptors: AssistantPluginActionDescriptor[] = [
122
136
  {
@@ -130,7 +144,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
130
144
  cancellable: true,
131
145
  idempotent: true,
132
146
  scopes: ['browser.profile'],
133
- resourceClaims: [{ resource: 'repo-state', mode: 'write' }],
147
+ resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
134
148
  argumentsSchema: {
135
149
  type: 'object',
136
150
  properties: {
@@ -158,12 +172,31 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
158
172
  additionalProperties: false,
159
173
  },
160
174
  },
175
+ {
176
+ actionId: 'list_unpacked_extensions',
177
+ title: 'List unpacked browser extensions',
178
+ description: 'List unpacked extensions visible to the selected Browser provider. No arbitrary CDP method is accepted.',
179
+ readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 30_000, cancellable: true, idempotent: true,
180
+ scopes: ['browser.extensions', 'browser.profile'], resourceClaims: readRemote,
181
+ argumentsSchema: sessionTargetSchema({}, []),
182
+ },
183
+ {
184
+ actionId: 'install_unpacked_extension',
185
+ title: 'Install unpacked browser extension',
186
+ description: 'Load one policy-bounded unpacked extension directory through the selected Browser provider and verify its exact installed identity.',
187
+ readOnly: false, risk: 'remote_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: false, idempotent: false,
188
+ scopes: ['browser.extensions', 'browser.profile'], resourceClaims: writeRemote,
189
+ argumentsSchema: sessionTargetSchema({
190
+ extension_path: { type: 'string' },
191
+ enable_in_incognito: { type: 'boolean' },
192
+ }, ['extension_path']),
193
+ },
161
194
  {
162
195
  actionId: 'create_session',
163
196
  title: 'Create browser session',
164
197
  description: 'Open an HTTP(S) URL or explicitly adopt the matching frontmost native tab, then persist a reusable session id.',
165
198
  readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 60_000, cancellable: true, idempotent: false,
166
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'write' }, ...readRemote],
199
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: readRemote,
167
200
  argumentsSchema: sessionTargetSchema({
168
201
  extract_text: { type: 'boolean' },
169
202
  max_chars: { type: 'number' },
@@ -178,7 +211,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
178
211
  title: 'List browser sessions',
179
212
  description: 'List saved browser session metadata without secrets or cookies.',
180
213
  readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 10_000, cancellable: true, idempotent: true,
181
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'read' }],
214
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'read' }],
182
215
  argumentsSchema: {
183
216
  type: 'object',
184
217
  properties: {
@@ -193,7 +226,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
193
226
  title: 'Reconcile browser sessions',
194
227
  description: 'Prune only saved managed-session metadata whose exact Runtime-bound page is positively proven gone. Never removes profiles, cookies, or unverified native sessions.',
195
228
  readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true,
196
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'write' }],
229
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
197
230
  argumentsSchema: { type: 'object', properties: {}, additionalProperties: false },
198
231
  },
199
232
  {
@@ -201,7 +234,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
201
234
  title: 'Close browser session',
202
235
  description: 'Remove one saved session metadata record.',
203
236
  readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true,
204
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'write' }],
237
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
205
238
  argumentsSchema: { type: 'object', properties: { session_id: { type: 'string' } }, required: ['session_id'], additionalProperties: false },
206
239
  },
207
240
  {
@@ -209,7 +242,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
209
242
  title: 'Clear all browser sessions',
210
243
  description: 'Remove all saved session metadata while keeping the profile.',
211
244
  readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true,
212
- scopes: ['browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'write' }],
245
+ scopes: ['browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
213
246
  argumentsSchema: { type: 'object', properties: {}, additionalProperties: false },
214
247
  },
215
248
  {
@@ -229,7 +262,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
229
262
  title: 'Get browser handoff status',
230
263
  description: 'Read durable browser handoff status and reconcile a stale or crashed host.',
231
264
  readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 10_000, cancellable: true, idempotent: true,
232
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'read' }],
265
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'read' }],
233
266
  argumentsSchema: { type: 'object', properties: { interaction_id: { type: 'string' } }, required: ['interaction_id'], additionalProperties: false },
234
267
  },
235
268
  {
@@ -237,7 +270,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
237
270
  title: 'Resolve browser handoff',
238
271
  description: 'Resume or cancel a foreground browser handoff.',
239
272
  readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true,
240
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'write' }],
273
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
241
274
  argumentsSchema: {
242
275
  type: 'object',
243
276
  properties: {
@@ -605,7 +638,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
605
638
  title: 'Close session',
606
639
  description: 'Remove saved session metadata while keeping the persistent profile.',
607
640
  readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true,
608
- scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'repo-state', mode: 'write' }],
641
+ scopes: ['browser.read', 'browser.profile'], resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
609
642
  argumentsSchema: { type: 'object', properties: { session_id: { type: 'string' } }, required: ['session_id'], additionalProperties: false },
610
643
  },
611
644
  ];
@@ -618,6 +651,7 @@ export function browserActions(): AssistantPluginActionDescriptor[] {
618
651
  ]);
619
652
  return descriptors.map((descriptor) => ({
620
653
  ...descriptor,
654
+ executionMode: 'runtime',
621
655
  foregroundEffect: foregroundRequired.has(descriptor.actionId)
622
656
  ? 'required'
623
657
  : foregroundPossible.has(descriptor.actionId)
@@ -1,9 +1,9 @@
1
1
  import { AssistantPluginError } from './errors';
2
2
  import {
3
- closeMacOsBrowserOwnedTab,
3
+ closeResolvedMacOsBrowserOwnedTab,
4
4
  listMacOsBrowserTabs,
5
5
  macOsBrowserPageHandleStale,
6
- readMacOsBrowserOwnedTabMetadata,
6
+ readResolvedMacOsBrowserOwnedTabMetadata,
7
7
  type MacOsBrowserProduct,
8
8
  } from './browser-macos-bridge';
9
9
  import { listSavedBrowserSessions, removeBrowserSession } from './browser-session-store';
@@ -19,12 +19,22 @@ export interface NativeOwnedSessionInspection {
19
19
  failedCleanupCount: number;
20
20
  }
21
21
 
22
+ const MAX_NATIVE_INVENTORY_TIMEOUT_MS = 3_000;
23
+
24
+ function nativeInventoryTimeoutMs(timeoutMs: number): number {
25
+ return Math.max(1, Math.min(timeoutMs, MAX_NATIVE_INVENTORY_TIMEOUT_MS));
26
+ }
27
+
22
28
  export function nativeTabInventoryUnsupported(error: unknown): boolean {
23
29
  if (error instanceof AssistantPluginError && error.code === 'BROWSER_AUTOMATION_ACTION_UNSUPPORTED') return true;
24
30
  const message = error instanceof Error ? error.message : String(error ?? '');
25
31
  return /\bBROWSER_AUTOMATION_ACTION_UNSUPPORTED\b/.test(message);
26
32
  }
27
33
 
34
+ function nativeBrowserApplicationNotRunning(error: unknown): boolean {
35
+ return error instanceof AssistantPluginError && error.code === 'PLUGIN_BROWSER_NATIVE_APP_NOT_RUNNING';
36
+ }
37
+
28
38
  function isDiscardableNativeOwnedTabUrl(url: string): boolean {
29
39
  const normalized = url.trim().toLowerCase();
30
40
  return normalized === ''
@@ -35,6 +45,20 @@ function isDiscardableNativeOwnedTabUrl(url: string): boolean {
35
45
  || normalized === 'vivaldi://startpage/';
36
46
  }
37
47
 
48
+ /**
49
+ * Native tab ids are only stable while the browser keeps the same tab alive.
50
+ * If a later inventory resolves that id to a different URL, the saved binding
51
+ * no longer proves ownership of that live tab. Treat the session as detached;
52
+ * never close the replacement tab merely because it inherited an old id.
53
+ */
54
+ function nativeTabMatchesSessionUrl(session: BrowserSessionState, url: string): boolean {
55
+ try {
56
+ return new URL(session.url).toString() === new URL(url).toString();
57
+ } catch {
58
+ return session.url.trim() === url.trim();
59
+ }
60
+ }
61
+
38
62
  /**
39
63
  * Native tab liveness/cleanup belongs to one service so the Browser adapter does
40
64
  * not reinterpret stable native identity or prune policy action-by-action.
@@ -75,13 +99,26 @@ export async function inspectNativeOwnedSessions(input: {
75
99
  let inventory = inventories.get(product);
76
100
  if (!inventory) {
77
101
  try {
78
- inventory = await listMacOsBrowserTabs(product, timeoutMs);
102
+ inventory = await listMacOsBrowserTabs(product, nativeInventoryTimeoutMs(timeoutMs));
79
103
  } catch (error) {
80
104
  inventory = error instanceof Error ? error : new Error(String(error));
81
105
  }
82
106
  inventories.set(product, inventory);
83
107
  }
84
108
  if (inventory instanceof Error) {
109
+ // A plugin-owned tab cannot outlive its native browser process. This is
110
+ // stronger than an unavailable inventory: retire the stale transport
111
+ // metadata so a later continuation opens a fresh effect-scoped tab.
112
+ if (nativeBrowserApplicationNotRunning(inventory)) {
113
+ const pruned = input.pruneDead === true;
114
+ if (pruned) {
115
+ for (const session of group) removeBrowserSession(repoRoot, session.sessionId);
116
+ prunedCount += group.length;
117
+ }
118
+ for (const session of group) items.set(session.sessionId, { session, liveness: 'dead', evidence: 'native_tab_missing', pruned });
119
+ deadCount += group.length;
120
+ continue;
121
+ }
85
122
  if (!nativeTabInventoryUnsupported(inventory)) {
86
123
  for (const session of group) items.set(session.sessionId, { session, liveness: 'unverified', evidence: 'native_inventory_unavailable', cleanupError: inventory.message });
87
124
  unverifiedCount += group.length;
@@ -89,9 +126,9 @@ export async function inspectNativeOwnedSessions(input: {
89
126
  }
90
127
 
91
128
  const ref = { windowId: tab.windowId!, tabId: tab.tabId! };
92
- let metadata: Awaited<ReturnType<typeof readMacOsBrowserOwnedTabMetadata>>;
129
+ let metadata: Awaited<ReturnType<typeof readResolvedMacOsBrowserOwnedTabMetadata>>;
93
130
  try {
94
- metadata = await readMacOsBrowserOwnedTabMetadata(product, ref, timeoutMs);
131
+ metadata = await readResolvedMacOsBrowserOwnedTabMetadata(product, ref, timeoutMs);
95
132
  } catch (metadataError) {
96
133
  if (macOsBrowserPageHandleStale(metadataError)) {
97
134
  const pruned = input.pruneDead === true;
@@ -113,7 +150,7 @@ export async function inspectNativeOwnedSessions(input: {
113
150
  deadCount += group.length;
114
151
  if (input.pruneDead === true) {
115
152
  try {
116
- await closeMacOsBrowserOwnedTab(product, ref, timeoutMs);
153
+ await closeResolvedMacOsBrowserOwnedTab(product, ref, timeoutMs);
117
154
  for (const session of group) removeBrowserSession(repoRoot, session.sessionId);
118
155
  prunedCount += group.length;
119
156
  closedInvalidCount += 1;
@@ -134,7 +171,7 @@ export async function inspectNativeOwnedSessions(input: {
134
171
  }
135
172
 
136
173
  const live = inventory.tabs.find((entry) => entry.windowId === tab.windowId && entry.tabId === tab.tabId);
137
- if (!live) {
174
+ if (!live || !nativeTabMatchesSessionUrl(canonical, live.url)) {
138
175
  const pruned = input.pruneDead === true;
139
176
  if (pruned) {
140
177
  for (const session of group) removeBrowserSession(repoRoot, session.sessionId);
@@ -149,7 +186,11 @@ export async function inspectNativeOwnedSessions(input: {
149
186
  deadCount += group.length;
150
187
  if (input.pruneDead === true) {
151
188
  try {
152
- await closeMacOsBrowserOwnedTab(product, { windowId: tab.windowId!, tabId: tab.tabId! }, timeoutMs);
189
+ await closeResolvedMacOsBrowserOwnedTab(
190
+ product,
191
+ { windowId: live.windowId, tabId: live.tabId },
192
+ timeoutMs,
193
+ );
153
194
  for (const session of group) removeBrowserSession(repoRoot, session.sessionId);
154
195
  prunedCount += group.length;
155
196
  closedInvalidCount += 1;
@@ -189,20 +230,29 @@ export async function closeTrackedNativeOwnedSession(
189
230
  const ref = { windowId: tab.windowId, tabId: tab.tabId };
190
231
  let inventory: Awaited<ReturnType<typeof listMacOsBrowserTabs>> | undefined;
191
232
  try {
192
- inventory = await listMacOsBrowserTabs(browser.browserProduct, timeoutMs);
233
+ inventory = await listMacOsBrowserTabs(browser.browserProduct, nativeInventoryTimeoutMs(timeoutMs));
193
234
  } catch (error) {
235
+ if (nativeBrowserApplicationNotRunning(error)) return { resourceClosed: false, resourceAlreadyMissing: true };
194
236
  if (!nativeTabInventoryUnsupported(error)) throw error;
195
237
  try {
196
- await readMacOsBrowserOwnedTabMetadata(browser.browserProduct, ref, timeoutMs);
238
+ await readResolvedMacOsBrowserOwnedTabMetadata(browser.browserProduct, ref, timeoutMs);
197
239
  } catch (metadataError) {
198
240
  if (macOsBrowserPageHandleStale(metadataError)) return { resourceClosed: false, resourceAlreadyMissing: true };
199
241
  throw metadataError;
200
242
  }
201
243
  }
202
- if (inventory && !inventory.tabs.some((entry) => entry.windowId === tab.windowId && entry.tabId === tab.tabId)) {
203
- return { resourceClosed: false, resourceAlreadyMissing: true };
244
+ if (inventory) {
245
+ const live = inventory.tabs.find((entry) => entry.windowId === tab.windowId && entry.tabId === tab.tabId);
246
+ if (!live) return { resourceClosed: false, resourceAlreadyMissing: true };
247
+ if (!nativeTabMatchesSessionUrl(session, live.url)) return { resourceClosed: false, resourceAlreadyMissing: true };
248
+ await closeResolvedMacOsBrowserOwnedTab(
249
+ browser.browserProduct,
250
+ { windowId: live.windowId, tabId: live.tabId },
251
+ timeoutMs,
252
+ );
253
+ return { resourceClosed: true, resourceAlreadyMissing: false };
204
254
  }
205
- await closeMacOsBrowserOwnedTab(browser.browserProduct, ref, timeoutMs);
255
+ await closeResolvedMacOsBrowserOwnedTab(browser.browserProduct, ref, timeoutMs);
206
256
  return { resourceClosed: true, resourceAlreadyMissing: false };
207
257
  }
208
258
 
@@ -5,6 +5,19 @@ import {
5
5
  } from './browser-adapter';
6
6
  import type { AssistantPluginAdapter } from './types';
7
7
 
8
+ /** Browser manifests derive from config plus saved-session and active-handoff authority. */
9
+ const BROWSER_MANIFEST_MUTATING_ACTIONS = new Set([
10
+ 'configure',
11
+ 'reconcile_sessions',
12
+ 'close_session',
13
+ 'close_page',
14
+ 'clear_session',
15
+ 'request_human_handoff',
16
+ 'resolve_handoff',
17
+ 'create_session',
18
+ 'open_page',
19
+ ]);
20
+
8
21
  /** Thin first-party registration. Browser execution remains an adapter implementation detail. */
9
22
  export const browserPluginAdapter: AssistantPluginAdapter = {
10
23
  pluginId: 'browser',
@@ -13,4 +26,7 @@ export const browserPluginAdapter: AssistantPluginAdapter = {
13
26
  buildManifest: buildBrowserPluginManifest,
14
27
  executeAction: executeBrowserPluginAction,
15
28
  resolveAuthorizationContext: resolveBrowserPluginAuthorizationContext,
29
+ shouldRefreshManifestAfterAction(actionId) {
30
+ return BROWSER_MANIFEST_MUTATING_ACTIONS.has(actionId);
31
+ },
16
32
  };
@@ -56,6 +56,8 @@ const READ_ACTIONS = new Set([
56
56
  'wait_for_load_state', 'wait_for_selector', 'await_file_transfer',
57
57
  ]);
58
58
  const SCREENSHOT_ACTIONS = new Set(['screenshot']);
59
+ const INTERNAL_RESOURCE_READ_ACTIONS = new Set(['list_unpacked_extensions']);
60
+ const INTERNAL_RESOURCE_MUTATION_ACTIONS = new Set(['install_unpacked_extension']);
59
61
  const TRUSTED_INPUT_ACTIONS = new Set(['trusted_input', 'activate_page']);
60
62
  const DOM_INTERACTION_ACTIONS = new Set([
61
63
  'create_session', 'open_page', 'navigate', 'reload', 'go_back',
@@ -89,6 +91,12 @@ export function browserRuntimeActionPolicy(actionId: string): BrowserRuntimeActi
89
91
  if (SCREENSHOT_ACTIONS.has(actionId)) {
90
92
  return { requiredCapabilities: ['browser.screenshot', 'browser.transaction'], foreground: 'none', replaySafety: 'read_only' };
91
93
  }
94
+ if (INTERNAL_RESOURCE_READ_ACTIONS.has(actionId)) {
95
+ return { requiredCapabilities: ['browser.internal_resources', 'browser.transaction'], foreground: 'none', replaySafety: 'read_only' };
96
+ }
97
+ if (INTERNAL_RESOURCE_MUTATION_ACTIONS.has(actionId)) {
98
+ return { requiredCapabilities: ['browser.internal_resources', 'browser.transaction'], foreground: 'none', replaySafety: 'non_idempotent' };
99
+ }
92
100
  if (TRUSTED_INPUT_ACTIONS.has(actionId)) {
93
101
  return {
94
102
  requiredCapabilities: ['browser.trusted_input', 'browser.foreground', 'browser.transaction'],
@@ -125,6 +133,9 @@ function stringArgument(args: Record<string, unknown>, key: string): string | un
125
133
  }
126
134
 
127
135
  function stableTargetFor(input: AssistantPluginActionExecutionInput, providerId: string): BrowserTargetIdentity {
136
+ if (INTERNAL_RESOURCE_READ_ACTIONS.has(input.actionId) || INTERNAL_RESOURCE_MUTATION_ACTIONS.has(input.actionId)) {
137
+ return { providerId, resourceKind: 'browser_internal_resource', resourceId: 'unpacked-extensions', ownership: 'provider_owned' };
138
+ }
128
139
  const sessionId = stringArgument(input.args, 'session_id');
129
140
  const nativeProduct = stringArgument(input.args, 'native_browser_product');
130
141
  const nativeWindowId = stringArgument(input.args, 'native_window_id');
@@ -166,7 +177,9 @@ function transactionFor(
166
177
  foreground: policy.foreground,
167
178
  replaySafety: policy.replaySafety,
168
179
  action: {
169
- kind: policy.replaySafety === 'read_only' ? 'read' : policy.foreground === 'explicit_required' ? 'trusted_input' : 'dom',
180
+ kind: INTERNAL_RESOURCE_READ_ACTIONS.has(input.actionId) || INTERNAL_RESOURCE_MUTATION_ACTIONS.has(input.actionId)
181
+ ? 'internal_resource'
182
+ : policy.replaySafety === 'read_only' ? 'read' : policy.foreground === 'explicit_required' ? 'trusted_input' : 'dom',
170
183
  operation: input.actionId,
171
184
  arguments: input.args,
172
185
  },
@@ -39,8 +39,8 @@ export {
39
39
  withRuntimeBrowserSessionExecutionContext as withBrowserSessionAuthorityContext,
40
40
  } from '../root/browser-session-composition';
41
41
 
42
- function withContext<T>(controllerHome: string, repoId: string, operation: () => T): T {
43
- return withRuntimeBrowserSessionExecutionContext({ controllerHome, repoId }, operation);
42
+ function withContext<T>(controllerHome: string, repoId: string | undefined, operation: () => T): T {
43
+ return withRuntimeBrowserSessionExecutionContext({ controllerHome, ...(repoId?.trim() ? { repoId: repoId.trim() } : {}) }, operation);
44
44
  }
45
45
 
46
46
  export function ensureLegacyBrowserSessionsImported(controllerHome: string, repoId: string, repoRoot: string): number {
@@ -1,5 +1,5 @@
1
- import { cpSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmSync } from 'fs';
2
- import { basename, join, resolve } from 'path';
1
+ import { cpSync, lstatSync, mkdirSync, readlinkSync, rmSync } from 'fs';
2
+ import { join, resolve } from 'path';
3
3
  import type {
4
4
  ComputerSurfaceProviderBinding,
5
5
  ComputerSurfaceTarget,
@@ -12,13 +12,24 @@ import {
12
12
  cleanupLegacyBrowserSessionJson,
13
13
  readLegacyBrowserSessionMigrationEntries,
14
14
  } from './browser-session-legacy-migration';
15
- import { writeJsonAtomic } from '../shared/json-files';
16
15
  import { AssistantPluginError } from './errors';
17
16
 
18
17
  const BROWSER_STATE_ROOT = '.forge/browser';
19
18
  const BROWSER_SESSION_COMPATIBILITY_NAMESPACE = 'browser.session.v1';
20
19
  const BROWSER_SESSION_COMPUTER_MIGRATION_ID = 'browser-session-authority-v1-to-computer-surface-v1';
21
20
 
21
+ function requireBrowserSessionExecutionContext() {
22
+ const context = currentRuntimeBrowserSessionExecutionContext();
23
+ if (!context) {
24
+ throw new AssistantPluginError(
25
+ 'PLUGIN_BROWSER_SESSION_CONTEXT_REQUIRED',
26
+ 'Browser session identity is owned by the Computer target authority and requires an explicit Controller execution context.',
27
+ { retryable: false },
28
+ );
29
+ }
30
+ return context;
31
+ }
32
+
22
33
  function unique(values: readonly string[]): string[] {
23
34
  return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
24
35
  }
@@ -109,9 +120,9 @@ function surfaceInput(
109
120
  * Browser actions never read or write Browser-owned durable session state.
110
121
  */
111
122
  export function ensureBrowserSessionsMigratedToComputer(repoRoot: string): number {
112
- const context = currentRuntimeBrowserSessionExecutionContext();
113
- if (!context) return 0;
123
+ const context = requireBrowserSessionExecutionContext();
114
124
  const computer = runtimeComputerInteractionTargetAuthority();
125
+ if (!context.repoId) return 0;
115
126
  if (computer.compatibilityMigrationMarker(context.controllerHome, BROWSER_SESSION_COMPUTER_MIGRATION_ID, context.repoId)) {
116
127
  cleanupLegacyBrowserSessionJson(context.controllerHome, context.repoId, repoRoot);
117
128
  return 0;
@@ -146,8 +157,10 @@ export function ensureBrowserSessionsMigratedToComputer(repoRoot: string): numbe
146
157
  }
147
158
 
148
159
  /** Move legacy provider files out of the repository and retire the old path after migration. */
149
- export function ensureBrowserStateInControllerHome(controllerHome: string, repoId: string, repoRoot: string): string {
150
- const targetRoot = join(controllerHome, 'repositories', repoId, 'browser');
160
+ export function ensureBrowserStateInControllerHome(controllerHome: string, repoId: string | undefined, repoRoot: string): string {
161
+ const targetRoot = repoId
162
+ ? join(controllerHome, 'repositories', repoId, 'browser')
163
+ : join(controllerHome, 'browser');
151
164
  const compatibilityParent = join(repoRoot, '.forge');
152
165
  const compatibilityRoot = join(compatibilityParent, 'browser');
153
166
  mkdirSync(targetRoot, { recursive: true });
@@ -178,50 +191,25 @@ export function ensureBrowserStateInControllerHome(controllerHome: string, repoI
178
191
  /**
179
192
  * Browser semantic identity belongs to Computer SurfaceTarget authority. Provider
180
193
  * working state (profiles, screenshots, downloads, diagnostics) remains
181
- * repository-scoped under Controller Home. Repo-local session JSON exists only
182
- * for standalone compatibility when no Controller execution context is present.
194
+ * repository-scoped under Controller Home. Session identity has no standalone
195
+ * repository-local fallback; callers must supply Controller execution context.
183
196
  */
184
197
  export function browserStateDir(
185
198
  repoRoot: string,
186
199
  name: 'sessions' | 'screenshots' | 'profiles' | 'downloads' | 'diagnostics',
187
200
  ): string {
188
201
  const context = currentRuntimeBrowserSessionExecutionContext();
202
+ if (name === 'sessions') {
203
+ const sessionContext = context ?? requireBrowserSessionExecutionContext();
204
+ return join(ensureBrowserStateInControllerHome(sessionContext.controllerHome, sessionContext.repoId, repoRoot), name);
205
+ }
189
206
  return context
190
207
  ? join(ensureBrowserStateInControllerHome(context.controllerHome, context.repoId, repoRoot), name)
191
208
  : join(repoRoot, BROWSER_STATE_ROOT, name);
192
209
  }
193
210
 
194
- function sessionPath(repoRoot: string, sessionId: string): string {
195
- return join(browserStateDir(repoRoot, 'sessions'), `${sessionId.replace(/[^a-zA-Z0-9_-]/g, '_')}.json`);
196
- }
197
-
198
- function readLegacyBrowserSessionJson(path: string): BrowserSessionState | undefined {
199
- let raw: string;
200
- try {
201
- raw = readFileSync(path, 'utf-8');
202
- } catch (error) {
203
- if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return undefined;
204
- throw new AssistantPluginError('PLUGIN_BROWSER_SESSION_STATE_READ_FAILED', 'Saved browser session metadata could not be read.', {
205
- retryable: true,
206
- details: { fileName: basename(path), cause: error instanceof Error ? error.message : String(error) },
207
- });
208
- }
209
- try {
210
- return JSON.parse(raw) as BrowserSessionState;
211
- } catch (error) {
212
- throw new AssistantPluginError('PLUGIN_BROWSER_SESSION_STATE_CORRUPT', 'Saved browser session metadata is malformed; refusing to treat corrupt state as a missing session.', {
213
- retryable: false,
214
- details: { fileName: basename(path), cause: error instanceof Error ? error.message : String(error) },
215
- });
216
- }
217
- }
218
-
219
211
  export function saveBrowserSession(repoRoot: string, session: BrowserSessionState): BrowserSessionState {
220
- const context = currentRuntimeBrowserSessionExecutionContext();
221
- if (!context) {
222
- writeJsonAtomic(sessionPath(repoRoot, session.sessionId), session);
223
- return session;
224
- }
212
+ const context = requireBrowserSessionExecutionContext();
225
213
  ensureBrowserSessionsMigratedToComputer(repoRoot);
226
214
  const computer = runtimeComputerInteractionTargetAuthority();
227
215
  const binding = surfaceProviderBinding(session);
@@ -235,7 +223,8 @@ export function saveBrowserSession(repoRoot: string, session: BrowserSessionStat
235
223
  if (!existing) {
236
224
  existing = computer.upsertSurface(context.controllerHome, surfaceInput(session, {
237
225
  aliases: [session.sessionId],
238
- repositoryIds: [context.repoId],
226
+ repositoryIds: context.repoId ? [context.repoId] : [],
227
+ visibility: context.repoId ? undefined : 'controller',
239
228
  includeCompatibility: false,
240
229
  reactivate: true,
241
230
  })).target;
@@ -248,7 +237,8 @@ export function saveBrowserSession(repoRoot: string, session: BrowserSessionStat
248
237
  if (normalized.browser?.sessionResume) normalized.browser.sessionResume.sessionId = canonicalSessionId;
249
238
  const saved = computer.upsertSurface(context.controllerHome, surfaceInput(normalized, {
250
239
  aliases: [session.sessionId, canonicalSessionId],
251
- repositoryIds: [context.repoId],
240
+ repositoryIds: context.repoId ? [context.repoId] : [],
241
+ visibility: context.repoId ? undefined : 'controller',
252
242
  reactivate: true,
253
243
  }));
254
244
  return browserSessionFromSurface(saved.target) ?? normalized;
@@ -256,49 +246,29 @@ export function saveBrowserSession(repoRoot: string, session: BrowserSessionStat
256
246
 
257
247
  export function findBrowserSession(repoRoot: string, sessionId?: string): BrowserSessionState | undefined {
258
248
  if (!sessionId) return undefined;
259
- const context = currentRuntimeBrowserSessionExecutionContext();
260
- if (!context) return readLegacyBrowserSessionJson(sessionPath(repoRoot, sessionId));
249
+ const context = requireBrowserSessionExecutionContext();
261
250
  ensureBrowserSessionsMigratedToComputer(repoRoot);
262
251
  const target = runtimeComputerInteractionTargetAuthority().findSurfaceByAlias(context.controllerHome, sessionId, context.repoId);
263
- return target ? browserSessionFromSurface(target) : undefined;
252
+ if (!target || (!context.repoId && target.visibility !== 'controller')) return undefined;
253
+ return browserSessionFromSurface(target);
264
254
  }
265
255
 
266
256
  export function listSavedBrowserSessions(repoRoot: string): BrowserSessionState[] {
267
- const context = currentRuntimeBrowserSessionExecutionContext();
268
- if (context) {
269
- ensureBrowserSessionsMigratedToComputer(repoRoot);
270
- return runtimeComputerInteractionTargetAuthority().listAllSurfaces(context.controllerHome, { repoId: context.repoId })
271
- .map(browserSessionFromSurface)
272
- .filter((session): session is BrowserSessionState => Boolean(session))
273
- .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt) || left.sessionId.localeCompare(right.sessionId));
274
- }
275
- const root = browserStateDir(repoRoot, 'sessions');
276
- let names: string[];
277
- try {
278
- names = readdirSync(root);
279
- } catch (error) {
280
- if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return [];
281
- throw new AssistantPluginError('PLUGIN_BROWSER_SESSION_STATE_READ_FAILED', 'Saved browser session directory could not be read.', {
282
- retryable: true,
283
- details: { cause: error instanceof Error ? error.message : String(error) },
284
- });
285
- }
286
- return names
287
- .filter((name) => name.endsWith('.json'))
288
- .map((name) => readLegacyBrowserSessionJson(join(root, name)))
289
- .filter((session): session is BrowserSessionState => Boolean(session));
257
+ const context = requireBrowserSessionExecutionContext();
258
+ ensureBrowserSessionsMigratedToComputer(repoRoot);
259
+ return runtimeComputerInteractionTargetAuthority().listAllSurfaces(context.controllerHome, { repoId: context.repoId })
260
+ .filter((target) => Boolean(context.repoId) || target.visibility === 'controller')
261
+ .map(browserSessionFromSurface)
262
+ .filter((session): session is BrowserSessionState => Boolean(session))
263
+ .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt) || left.sessionId.localeCompare(right.sessionId));
290
264
  }
291
265
 
292
266
  export function removeBrowserSession(repoRoot: string, sessionId: string): void {
293
- const context = currentRuntimeBrowserSessionExecutionContext();
294
- if (context) {
295
- ensureBrowserSessionsMigratedToComputer(repoRoot);
296
- const computer = runtimeComputerInteractionTargetAuthority();
297
- const target = computer.findSurfaceByAlias(context.controllerHome, sessionId, context.repoId);
298
- if (target) computer.tombstoneSurface(context.controllerHome, target.targetId);
299
- return;
300
- }
301
- rmSync(sessionPath(repoRoot, sessionId), { force: true });
267
+ const context = requireBrowserSessionExecutionContext();
268
+ ensureBrowserSessionsMigratedToComputer(repoRoot);
269
+ const computer = runtimeComputerInteractionTargetAuthority();
270
+ const target = computer.findSurfaceByAlias(context.controllerHome, sessionId, context.repoId);
271
+ if (target && (context.repoId || target.visibility === 'controller')) computer.tombstoneSurface(context.controllerHome, target.targetId);
302
272
  }
303
273
 
304
274
  export function loadBrowserSession(repoRoot: string, sessionId?: string): BrowserSessionState | undefined {