@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
@@ -6,7 +6,7 @@ import type {
6
6
  } from './types';
7
7
  import { AssistantPluginError, toAssistantPluginError } from './errors';
8
8
  import { bootstrapManagedRuntimeEnv } from '../shared/managed-env';
9
- import { readStoredGoogleRefreshToken } from '../safe-tooling/google-credential-store';
9
+ import { readStoredGoogleClientSecret, readStoredGoogleRefreshToken } from '../safe-tooling/google-credential-store';
10
10
  import { readRepositoryPluginConfig, writeRepositoryPluginConfig, type RepositoryPluginConfigContext } from './config-store';
11
11
 
12
12
  export type GoogleProviderKind = 'mock' | 'google-workspace';
@@ -128,8 +128,15 @@ function refreshCredential(service: GoogleService): { name: string; value: strin
128
128
  return stored ? { name: stored.source, value: stored.token } : undefined;
129
129
  }
130
130
 
131
+ function clientSecretCredential(service: GoogleService): { name: string; value: string } | undefined {
132
+ const fromEnv = firstEnv(clientSecretEnvNames(service));
133
+ if (fromEnv) return fromEnv;
134
+ const stored = readStoredGoogleClientSecret(service);
135
+ return stored ? { name: stored.source, value: stored.secret } : undefined;
136
+ }
137
+
131
138
  function refreshCredentialsReady(service: GoogleService): boolean {
132
- return Boolean(refreshCredential(service) && firstEnv(clientIdEnvNames(service)) && firstEnv(clientSecretEnvNames(service)));
139
+ return Boolean(refreshCredential(service) && firstEnv(clientIdEnvNames(service)));
133
140
  }
134
141
 
135
142
  export function installGoogleAccessToken(service: GoogleService, accessToken: string, expiresInSeconds = 3600, source = 'oauth'): void {
@@ -289,9 +296,9 @@ function tokenEnvNames(service: GoogleService): string[] {
289
296
  export function resolveGoogleAuth(
290
297
  service: GoogleService,
291
298
  config: GooglePluginConfig,
292
- options: { repoRoot?: string } = {},
299
+ options: { repoRoot?: string; controllerHome?: string } = {},
293
300
  ): GoogleAuthState {
294
- bootstrapManagedRuntimeEnv({ repoRoot: options.repoRoot });
301
+ bootstrapManagedRuntimeEnv({ repoRoot: options.repoRoot, controllerHome: options.controllerHome });
295
302
  if (config.provider === 'mock') {
296
303
  return {
297
304
  provider: 'mock', ready: true, authenticated: true, probed: true,
@@ -428,8 +435,8 @@ function serviceBaseUrl(service: GoogleService): string {
428
435
  async function refreshGoogleAccessToken(service: GoogleService, timeoutMs: number): Promise<string | undefined> {
429
436
  const refreshToken = refreshCredential(service);
430
437
  const clientId = firstEnv(clientIdEnvNames(service));
431
- const clientSecret = firstEnv(clientSecretEnvNames(service));
432
- if (!refreshToken || !clientId || !clientSecret) return undefined;
438
+ const clientSecret = clientSecretCredential(service);
439
+ if (!refreshToken || !clientId) return undefined;
433
440
  const controller = new AbortController();
434
441
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
435
442
  try {
@@ -437,8 +444,8 @@ async function refreshGoogleAccessToken(service: GoogleService, timeoutMs: numbe
437
444
  grant_type: 'refresh_token',
438
445
  refresh_token: refreshToken.value,
439
446
  client_id: clientId.value,
440
- client_secret: clientSecret.value,
441
447
  });
448
+ if (clientSecret) body.set('client_secret', clientSecret.value);
442
449
  const response = await fetch('https://oauth2.googleapis.com/token', {
443
450
  method: 'POST',
444
451
  headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
@@ -457,7 +457,7 @@ function tasksProvider(config: GoogleTasksPluginConfig, repoRoot?: string): Task
457
457
  export function buildGoogleTasksPluginManifest(previousRevision = 0, previousUpdatedAt?: string, repoRoot?: string, context?: AssistantPluginBuildContext): AssistantPluginManifest {
458
458
  const root = repoRoot ?? process.cwd();
459
459
  const config = loadGoogleTasksPluginConfig(root, context);
460
- const auth = resolveGoogleAuth('tasks', config, { repoRoot: root });
460
+ const auth = resolveGoogleAuth('tasks', config, { repoRoot: root, controllerHome: context?.controllerHome });
461
461
  const state = pluginStateFromGoogleAuth(config, auth);
462
462
  return {
463
463
  schemaVersion: 1,
@@ -504,7 +504,7 @@ export async function executeGoogleTasksPluginAction(input: AssistantPluginActio
504
504
  });
505
505
  return {
506
506
  config,
507
- auth: resolveGoogleAuth('tasks', config, { repoRoot: input.repoRoot }),
507
+ auth: resolveGoogleAuth('tasks', config, { repoRoot: input.repoRoot, controllerHome: input.controllerHome }),
508
508
  };
509
509
  }
510
510
  case 'list_tasklists':
@@ -345,7 +345,7 @@ function actions(): AssistantPluginActionDescriptor[] {
345
345
  description: 'Capture a simulator screenshot into controller artifact storage.',
346
346
  readOnly: false,
347
347
  risk: 'workspace_write',
348
- confirmation: 'none',
348
+ confirmation: 'authorization',
349
349
  defaultTimeoutMs: 60_000,
350
350
  cancellable: true,
351
351
  idempotent: false,
@@ -2,16 +2,22 @@ import { createHash } from 'crypto';
2
2
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
3
3
  import { dirname, join, resolve } from 'path';
4
4
  import type { RepositoryRecord } from '../../cli/repositories/types';
5
- import { repositoryControllerRoot } from '../../cli/repositories/controller-home';
5
+ import { controllerSystemRoot, repositoryControllerRoot } from '../../cli/repositories/controller-home';
6
6
  import { resolveTrustedNodeExecutable } from '../shared/trusted-node-executable';
7
7
  import { startLightweightInternalProcess, waitForLightweightProcess } from '../execution/process-runtime/lightweight-managed';
8
+ import { getProcessHandle, spawnManagedProcess, waitForProcess } from '../execution/process-runtime/runtime';
9
+ import { getProcessRecord, getProcessRequestBinding } from '../execution/process-runtime/store';
8
10
  import type { ProcessHandle } from '../execution/process-runtime/types';
11
+ import { FORGE_INSTANCE_PROCESS_SCOPE_KEY } from '../execution/process-runtime/process-scope';
12
+ import type { ResolvedExecutionIdentity } from '../control-plane/execution/execution-identity';
9
13
  import type { AssistantPluginActionRequest } from './types';
10
14
 
11
15
  interface LightweightPluginActionEnvelope {
12
16
  schemaVersion: 1;
13
17
  controllerHome: string;
14
- repoId: string;
18
+ /** Legacy repository envelope coordinate; absent for ForgeInstance-scoped controller plugins. */
19
+ repoId?: string;
20
+ scope?: { kind: 'controller' } | { kind: 'repository'; repoId: string };
15
21
  request: Omit<AssistantPluginActionRequest, 'signal'>;
16
22
  }
17
23
 
@@ -28,6 +34,18 @@ function envelopeBytes(controllerHome: string, repository: RepositoryRecord, req
28
34
  schemaVersion: 1,
29
35
  controllerHome,
30
36
  repoId: repository.repoId,
37
+ scope: { kind: 'repository', repoId: repository.repoId },
38
+ request: serializableRequest,
39
+ };
40
+ return `${JSON.stringify(envelope)}\n`;
41
+ }
42
+
43
+ function controllerEnvelopeBytes(controllerHome: string, request: AssistantPluginActionRequest): string {
44
+ const { signal: _signal, ...serializableRequest } = request;
45
+ const envelope: LightweightPluginActionEnvelope = {
46
+ schemaVersion: 1,
47
+ controllerHome,
48
+ scope: { kind: 'controller' },
31
49
  request: serializableRequest,
32
50
  };
33
51
  return `${JSON.stringify(envelope)}\n`;
@@ -142,6 +160,194 @@ export async function startLightweightPluginAction(input: {
142
160
  return { handle, requestSha256 };
143
161
  }
144
162
 
163
+ export async function startManagedControllerPluginAction(input: {
164
+ controllerHome: string;
165
+ request: AssistantPluginActionRequest;
166
+ interactiveWaitMs?: number;
167
+ timeoutMs: number;
168
+ }): Promise<LightweightPluginActionStart> {
169
+ const scopeKey = FORGE_INSTANCE_PROCESS_SCOPE_KEY;
170
+ const requestToken = createHash('sha256')
171
+ .update(`${scopeKey}\u0000${input.request.requestId}`)
172
+ .digest('hex')
173
+ .slice(0, 24);
174
+ const instanceRoot = controllerSystemRoot(input.controllerHome);
175
+ const requestRoot = join(instanceRoot, 'plugin-action-processes');
176
+ const requestPath = join(requestRoot, `${requestToken}.request.json`);
177
+ const bytes = controllerEnvelopeBytes(input.controllerHome, input.request);
178
+ const requestSha256 = createHash('sha256').update(bytes).digest('hex');
179
+ const existingBinding = getProcessRequestBinding(input.controllerHome, scopeKey, undefined, input.request.requestId);
180
+ if (existingBinding) {
181
+ if (existsSync(requestPath)) {
182
+ const existingBytes = readFileSync(requestPath, 'utf8');
183
+ if (createHash('sha256').update(existingBytes).digest('hex') !== requestSha256) {
184
+ throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
185
+ }
186
+ }
187
+ const existing = getProcessHandle(input.controllerHome, scopeKey, existingBinding.processId);
188
+ if (!existing) throw new Error(`PROCESS_REQUEST_INCOMPLETE: plugin request ${input.request.requestId} is bound to missing process ${existingBinding.processId}; refusing re-execution`);
189
+ const processRecord = getProcessRecord(input.controllerHome, scopeKey, existingBinding.processId);
190
+ if (processRecord?.origin?.requestSemanticFingerprint && processRecord.origin.requestSemanticFingerprint !== requestSha256) {
191
+ throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
192
+ }
193
+ return { handle: { ...existing, deduplicated: true, requestId: input.request.requestId }, requestSha256 };
194
+ }
195
+ if (existsSync(requestPath)) {
196
+ const existingBytes = readFileSync(requestPath, 'utf8');
197
+ if (createHash('sha256').update(existingBytes).digest('hex') !== requestSha256) {
198
+ throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
199
+ }
200
+ } else {
201
+ privateAtomicWrite(requestPath, bytes);
202
+ }
203
+ const invocation = resolveLightweightPluginActionRuntimeInvocation();
204
+ const executionIdentity: ResolvedExecutionIdentity = Object.freeze({
205
+ schemaVersion: 1 as const,
206
+ authority: 'forge_instance' as const,
207
+ repositoryId: scopeKey,
208
+ checkoutId: scopeKey,
209
+ canonicalRoot: instanceRoot,
210
+ });
211
+ const handle = await spawnManagedProcess({
212
+ controllerHome: input.controllerHome,
213
+ repoId: scopeKey,
214
+ principalId: input.request.origin.actor?.trim() || undefined,
215
+ executionIdentity,
216
+ commandId: `plugin-action:${input.request.requestId}`,
217
+ trustedRuntimeChild: 'plugin_action_sidecar',
218
+ command: {
219
+ kind: 'argv',
220
+ executable: invocation.executable,
221
+ args: [...invocation.argsPrefix, '--request', requestPath, '--expected-sha256', requestSha256],
222
+ cwd: instanceRoot,
223
+ },
224
+ interactiveWaitMs: Math.max(0, input.interactiveWaitMs ?? 750),
225
+ timeoutMs: input.timeoutMs,
226
+ maxOutputBytes: 64 * 1024,
227
+ origin: {
228
+ surface: 'mcp',
229
+ toolName: 'plugin_action_execute',
230
+ requestId: input.request.requestId,
231
+ requestSemanticFingerprint: requestSha256,
232
+ correlationId: input.request.workId,
233
+ },
234
+ signal: input.request.signal,
235
+ });
236
+ return { handle, requestSha256 };
237
+ }
238
+
239
+ export async function startManagedPluginAction(input: {
240
+ controllerHome: string;
241
+ repository: RepositoryRecord;
242
+ request: AssistantPluginActionRequest;
243
+ interactiveWaitMs?: number;
244
+ timeoutMs: number;
245
+ }): Promise<LightweightPluginActionStart> {
246
+ const requestToken = createHash('sha256')
247
+ .update(`${input.repository.repoId}\u0000${input.request.requestId}`)
248
+ .digest('hex')
249
+ .slice(0, 24);
250
+ const requestRoot = join(repositoryControllerRoot(input.controllerHome, input.repository.repoId), 'plugin-action-processes');
251
+ const requestPath = join(requestRoot, `${requestToken}.request.json`);
252
+ const bytes = envelopeBytes(input.controllerHome, input.repository, input.request);
253
+ const requestSha256 = createHash('sha256').update(bytes).digest('hex');
254
+
255
+ const existingBinding = getProcessRequestBinding(
256
+ input.controllerHome,
257
+ input.repository.repoId,
258
+ input.repository.activeCheckoutId,
259
+ input.request.requestId,
260
+ );
261
+ if (existingBinding) {
262
+ if (existsSync(requestPath)) {
263
+ const existingBytes = readFileSync(requestPath, 'utf8');
264
+ const existingSha256 = createHash('sha256').update(existingBytes).digest('hex');
265
+ if (existingSha256 !== requestSha256) {
266
+ throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
267
+ }
268
+ }
269
+ const existing = getProcessHandle(input.controllerHome, input.repository.repoId, existingBinding.processId);
270
+ if (!existing) {
271
+ throw new Error(`PROCESS_REQUEST_INCOMPLETE: plugin request ${input.request.requestId} is bound to missing process ${existingBinding.processId}; refusing re-execution`);
272
+ }
273
+ const processRecord = getProcessRecord(input.controllerHome, input.repository.repoId, existingBinding.processId);
274
+ if (processRecord?.origin?.requestSemanticFingerprint && processRecord.origin.requestSemanticFingerprint !== requestSha256) {
275
+ throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
276
+ }
277
+ return { handle: { ...existing, deduplicated: true, requestId: input.request.requestId }, requestSha256 };
278
+ }
279
+
280
+ if (existsSync(requestPath)) {
281
+ const existingBytes = readFileSync(requestPath, 'utf8');
282
+ const existingSha256 = createHash('sha256').update(existingBytes).digest('hex');
283
+ if (existingSha256 !== requestSha256) {
284
+ throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
285
+ }
286
+ } else {
287
+ privateAtomicWrite(requestPath, bytes);
288
+ }
289
+
290
+ const invocation = resolveLightweightPluginActionRuntimeInvocation();
291
+ const executionIdentity: ResolvedExecutionIdentity = Object.freeze({
292
+ schemaVersion: 1 as const,
293
+ authority: 'ephemeral_workspace' as const,
294
+ repositoryId: input.repository.repoId,
295
+ checkoutId: input.repository.activeCheckoutId,
296
+ canonicalRoot: input.repository.canonicalRoot,
297
+ ...(input.request.workId ? { workId: input.request.workId } : {}),
298
+ });
299
+ const handle = await spawnManagedProcess({
300
+ controllerHome: input.controllerHome,
301
+ repoId: input.repository.repoId,
302
+ checkoutId: input.repository.activeCheckoutId,
303
+ executionIdentity,
304
+ workId: input.request.workId,
305
+ commandId: `plugin-action:${input.request.requestId}`,
306
+ trustedRuntimeChild: 'plugin_action_sidecar',
307
+ command: {
308
+ kind: 'argv',
309
+ executable: invocation.executable,
310
+ args: [
311
+ ...invocation.argsPrefix,
312
+ '--request', requestPath,
313
+ '--expected-sha256', requestSha256,
314
+ ],
315
+ cwd: input.repository.canonicalRoot,
316
+ },
317
+ interactiveWaitMs: Math.max(0, input.interactiveWaitMs ?? 750),
318
+ timeoutMs: input.timeoutMs,
319
+ maxOutputBytes: 64 * 1024,
320
+ origin: {
321
+ surface: 'mcp',
322
+ toolName: 'plugin_action_execute',
323
+ requestId: input.request.requestId,
324
+ requestSemanticFingerprint: requestSha256,
325
+ correlationId: input.request.workId,
326
+ },
327
+ signal: input.request.signal,
328
+ });
329
+ return { handle, requestSha256 };
330
+ }
331
+
332
+ export async function waitManagedControllerPluginAction(
333
+ controllerHome: string,
334
+ processId: string,
335
+ timeoutMs: number,
336
+ signal?: AbortSignal,
337
+ ): Promise<ProcessHandle> {
338
+ return waitForProcess(controllerHome, FORGE_INSTANCE_PROCESS_SCOPE_KEY, processId, { timeoutMs, signal });
339
+ }
340
+
341
+ export async function waitManagedPluginAction(
342
+ controllerHome: string,
343
+ repoId: string,
344
+ processId: string,
345
+ timeoutMs: number,
346
+ signal?: AbortSignal,
347
+ ): Promise<ProcessHandle> {
348
+ return waitForProcess(controllerHome, repoId, processId, { timeoutMs, signal });
349
+ }
350
+
145
351
  export async function waitLightweightPluginAction(
146
352
  controllerHome: string,
147
353
  repoId: string,
@@ -16,6 +16,7 @@ import {
16
16
  } from 'fs';
17
17
  import { dirname, extname, join, resolve } from 'path';
18
18
  import { forgeRuntimeServicePaths } from '../root/service';
19
+ import { installWorkflowSupervisorBrowserAdapter, inspectWorkflowSupervisorBrowserAdapter } from './computer-chatgpt-browser-adapter-installer';
19
20
  import { createRecoveryConfig, loadRecoveryConfig, repairPublicTunnel } from '../standalone-recovery/core';
20
21
  import { activateRecoveryRelease, recoverySourceIdentity, stageRecoveryRelease } from '../standalone-recovery/installer';
21
22
  import { readCurrentRecoveryRelease, type RecoveryReleaseDescriptor } from '../standalone-recovery/release';
@@ -78,6 +79,8 @@ export interface LocalSystemPluginHooks {
78
79
  signalProcess?: (pid: number, signal: NodeJS.Signals) => void;
79
80
  scheduleLaunchAgentRestart?: (service: string) => { pid: number };
80
81
  upgradeStandaloneRecovery?: (controllerHome: string) => Promise<Record<string, unknown>>;
82
+ installWorkflowSupervisorBrowserAdapter?: typeof installWorkflowSupervisorBrowserAdapter;
83
+ inspectWorkflowSupervisorBrowserAdapter?: typeof inspectWorkflowSupervisorBrowserAdapter;
81
84
  repairPublicTunnel?: typeof repairPublicTunnel;
82
85
  recoverySourceIdentity?: typeof recoverySourceIdentity;
83
86
  stageRecoveryRelease?: typeof stageRecoveryRelease;
@@ -802,6 +805,7 @@ async function repairStandaloneRecoveryTunnel(controllerHome: string): Promise<R
802
805
  function actions(): AssistantPluginActionDescriptor[] {
803
806
  const controllerRead = [{ resource: 'repo-state' as const, mode: 'read' as const }];
804
807
  const controllerWrite = [{ resource: 'repo-state' as const, mode: 'write' as const }];
808
+ const providerWrite = [{ resource: 'provider-state' as const, mode: 'write' as const }];
805
809
  const targetProperties = {
806
810
  target_key: { type: 'string' },
807
811
  path: { type: 'string' },
@@ -815,6 +819,8 @@ function actions(): AssistantPluginActionDescriptor[] {
815
819
  { actionId: 'start_user_launch_agent', title: 'Start verified user LaunchAgent', description: 'Bootstrap or start one exact current-user LaunchAgent from ~/Library/LaunchAgents only after the installed plist matches the expected program identity.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: true, scopes: ['local-system.process'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { label: { type: 'string' }, expected_program_contains: { type: 'string' } }, required: ['label', 'expected_program_contains'], additionalProperties: false } },
816
820
  { actionId: 'upgrade_standalone_recovery', title: 'Upgrade standalone Recovery', description: 'Upgrade the installed standalone Recovery from its configured primary Runtime source using the existing immutable Recovery release authority. No caller source path or command is accepted.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 240_000, cancellable: false, idempotent: true, scopes: ['local-system.process'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
817
821
  { actionId: 'repair_standalone_recovery_tunnel', title: 'Repair standalone Recovery tunnel', description: 'Repair only the installed standalone Recovery public tunnel using its existing configured tunnel identity and Recovery repair authority. No caller tunnel identity, path, executable, or command is accepted.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 60_000, cancellable: false, idempotent: true, scopes: ['local-system.process'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
822
+ { actionId: 'workflow_supervisor_browser_adapter_status', title: 'Workflow Supervisor browser adapter status', description: 'Inspect the Controller-owned Workflow Supervisor Chrome adapter projection and exact package-derived Native Messaging registration.', readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true, scopes: ['local-system.browser-adapter'], resourceClaims: [], argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
823
+ { actionId: 'install_workflow_supervisor_browser_adapter', title: 'Install Workflow Supervisor browser adapter', description: 'Project the active immutable Runtime browser adapter into Controller-owned paths and register Native Messaging only for the extension package-derived stable id. No caller path, command, extension id, or browser profile is accepted.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: false, idempotent: true, scopes: ['local-system.browser-adapter'], resourceClaims: providerWrite, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
818
824
  { actionId: 'open_application', title: 'Open application', description: 'Open one macOS application by name or bundle id in the background without stealing foreground focus.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.open'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { app_name: { type: 'string' }, bundle_id: { type: 'string' } }, additionalProperties: false } },
819
825
  { actionId: 'list_targets', title: 'List filesystem targets', description: 'List active expiring local filesystem grants.', readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 10_000, cancellable: true, idempotent: true, scopes: ['local-system.files.read'], resourceClaims: controllerRead, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
820
826
  { actionId: 'authorize_target', title: 'Authorize filesystem target', description: 'Authorize an expiring filesystem target. By default, a path inside a Git project authorizes the whole project/repository root; use scope=directory only when intentionally granting a narrower directory.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, root_path: { type: 'string' }, scope: { type: 'string', enum: ['auto', 'project', 'directory'] }, expires_in_minutes: { type: 'number' }, reason: { type: 'string' }, access: { type: 'string', enum: ['read_only', 'read_write'] } }, required: ['target_key', 'root_path', 'reason'], additionalProperties: false } },
@@ -825,7 +831,7 @@ function actions(): AssistantPluginActionDescriptor[] {
825
831
  { actionId: 'delete_file', title: 'Delete file', description: 'Delete one exact regular file below an authorized read-write target. Arbitrary recursive or directory deletion is never exposed.', readOnly: false, risk: 'destructive', confirmation: 'strong_confirmation', requiredConfirmationText: 'delete-local-system-file', defaultTimeoutMs: 15_000, cancellable: true, idempotent: false, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: targetProperties, required: ['target_key', 'path'], additionalProperties: false } },
826
832
  { actionId: 'delete_empty_directory', title: 'Delete empty directory', description: 'Delete one exact empty directory below an authorized read-write target. Target roots and recursive directory deletion are never allowed.', readOnly: false, risk: 'destructive', confirmation: 'strong_confirmation', requiredConfirmationText: 'delete-local-system-empty-directory', defaultTimeoutMs: 15_000, cancellable: true, idempotent: false, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: targetProperties, required: ['target_key', 'path'], additionalProperties: false } },
827
833
  { actionId: 'initialize_git', title: 'Initialize local Git repository', description: 'Run only git init inside an authorized read-write target without registering it in Repository Registry.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: true, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, cwd: { type: 'string' }, initial_branch: { type: 'string' } }, required: ['target_key'], additionalProperties: false } },
828
- { actionId: 'execute_command', title: 'Execute target command', description: 'Execute one bounded typed-argv command inside an authorized target without repository registration. Shell strings, target escapes, destructive/remote writes, and Git mutations other than the dedicated initialize_git action are denied.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.read', 'local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, command: { type: 'array', items: { type: 'string' } }, cwd: { type: 'string' }, max_output_bytes: { type: 'number' } }, required: ['target_key', 'command'], additionalProperties: false } },
834
+ { actionId: 'execute_command', title: 'Execute target command', description: 'Execute one bounded typed-argv command inside an authorized filesystem target. This is the narrow target-scoped alternative to broad ForgeInstance process_exec: shell strings, target escapes, destructive/remote writes, and Git mutations other than the dedicated initialize_git action are denied.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.read', 'local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, command: { type: 'array', items: { type: 'string' } }, cwd: { type: 'string' }, max_output_bytes: { type: 'number' } }, required: ['target_key', 'command'], additionalProperties: false } },
829
835
  { actionId: 'execute_project_script', title: 'Execute verified project script', description: 'Execute one exact script below an authorized read-write target through a fixed interpreter after its SHA-256 digest and strong confirmation match. Eval flags and shell command strings are never accepted.', readOnly: false, risk: 'destructive', confirmation: 'strong_confirmation', requiredConfirmationText: 'execute-local-system-project-script', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.read', 'local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, runtime: { type: 'string', enum: ['node', 'bun', 'python3', 'ruby', 'bash', 'sh'] }, script_path: { type: 'string' }, expected_sha256: { type: 'string' }, arguments: { type: 'array', items: { type: 'string' } }, cwd: { type: 'string' }, max_output_bytes: { type: 'number' } }, required: ['target_key', 'runtime', 'script_path', 'expected_sha256'], additionalProperties: false } },
830
836
  { actionId: 'create_directory', title: 'Create directory', description: 'Create a directory below an authorized target without leaving that root.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: targetProperties, required: ['target_key', 'path'], additionalProperties: false } },
831
837
  { actionId: 'copy_file', title: 'Copy file', description: 'Copy a file between authorized targets without overwriting.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { source_target_key: { type: 'string' }, source_path: { type: 'string' }, destination_target_key: { type: 'string' }, destination_path: { type: 'string' } }, required: ['source_target_key', 'source_path', 'destination_target_key', 'destination_path'], additionalProperties: false } },
@@ -859,6 +865,7 @@ function permissions(): AssistantPluginPermissionScope[] {
859
865
  { scope: 'local-system.read', mode: 'read', description: 'Read bounded local process and memory diagnostics.', granted: true, required: true },
860
866
  { scope: 'local-system.process', mode: 'write', description: 'Terminate one verified PID or control one verified current-user LaunchAgent after explicit authorization.', granted: true, required: false },
861
867
  { scope: 'local-system.open', mode: 'write', description: 'Open applications or authorized files.', granted: true, required: false },
868
+ { scope: 'local-system.browser-adapter', mode: 'write', description: 'Install and inspect the Controller-owned Workflow Supervisor Chrome adapter and exact Native Messaging registration.', granted: true, required: false },
862
869
  { scope: 'local-system.files.read', mode: 'read', description: 'Read files only below active target grants.', granted: true, required: false },
863
870
  { scope: 'local-system.files.write', mode: 'write', description: 'Create, copy, move, rename, or explicitly delete bounded files and empty directories below active read-write target grants.', granted: true, required: false },
864
871
  ];
@@ -870,6 +877,7 @@ function capabilities(): AssistantPluginCapability[] {
870
877
  { capabilityId: 'local-system-process-control', title: 'Verified process lifecycle', description: 'Terminate one verified PID or stop/start/restart one verified macOS user LaunchAgent without exposing arbitrary shell execution.', scopes: ['local-system.process'], actions: ['terminate_process', 'restart_user_launch_agent', 'stop_user_launch_agent', 'start_user_launch_agent'] },
871
878
  { capabilityId: 'local-system-recovery-upgrade', title: 'Managed standalone Recovery upgrade', description: 'Upgrade standalone Recovery only from its installed configured source through the immutable Recovery release and rollback authority.', scopes: ['local-system.process'], actions: ['upgrade_standalone_recovery'] },
872
879
  { capabilityId: 'local-system-recovery-tunnel-repair', title: 'Managed standalone Recovery tunnel repair', description: 'Repair only the installed Recovery public tunnel through the existing Recovery tunnel repair authority when the Recovery transport itself is unreachable.', scopes: ['local-system.process'], actions: ['repair_standalone_recovery_tunnel'] },
880
+ { capabilityId: 'local-system-workflow-supervisor-browser-adapter', title: 'Workflow Supervisor browser adapter', description: 'Inspect or install the stateless Chrome adapter projection used by the Goal-level Workflow Supervisor authority.', scopes: ['local-system.browser-adapter'], actions: ['workflow_supervisor_browser_adapter_status', 'install_workflow_supervisor_browser_adapter'] },
873
881
  { capabilityId: 'local-system-open', title: 'Open local applications and files', description: 'Open applications and authorized files without arbitrary shell access.', scopes: ['local-system.open'], actions: ['open_application', 'reveal_in_finder', 'open_file'] },
874
882
  { capabilityId: 'local-system-files', title: 'Authorized local files', description: 'Use expiring target grants for bounded local file operations and typed-argv commands without repository registration.', scopes: ['local-system.files.read', 'local-system.files.write'], actions: ['list_targets', 'authorize_target', 'revoke_target', 'list_directory', 'read_text', 'write_text', 'delete_file', 'delete_empty_directory', 'initialize_git', 'execute_command', 'execute_project_script', 'create_directory', 'copy_file', 'move_file', 'rename_file'] },
875
883
  ];
@@ -884,7 +892,7 @@ export function buildLocalSystemPluginManifest(previousRevision = 0, previousUpd
884
892
  pluginId: PLUGIN_ID,
885
893
  provider: 'local-macos',
886
894
  displayName: 'Local System Assistant',
887
- pluginVersion: '1.5.1',
895
+ pluginVersion: '1.5.3',
888
896
  authority: { strategy: 'derived', duplicateStateAllowed: false, sourceOfTruth: ['controllerHome:system/local-system'] },
889
897
  enabled: true,
890
898
  lifecycle: { state: currentHealth.ready ? 'enabled' : 'degraded', reason: currentHealth.ready ? 'Local system capabilities are ready.' : currentHealth.warnings[0] },
@@ -927,6 +935,8 @@ export async function executeLocalSystemPluginAction(input: AssistantPluginActio
927
935
  case 'start_user_launch_agent': return startVerifiedUserLaunchAgent(input.args.label, input.args.expected_program_contains);
928
936
  case 'upgrade_standalone_recovery': return await upgradeStandaloneRecovery(input.controllerHome);
929
937
  case 'repair_standalone_recovery_tunnel': return await repairStandaloneRecoveryTunnel(input.controllerHome);
938
+ case 'workflow_supervisor_browser_adapter_status': return (hooks.inspectWorkflowSupervisorBrowserAdapter ?? inspectWorkflowSupervisorBrowserAdapter)(input.controllerHome, { repository: { repoId: input.repoId, repoRoot: input.repoRoot } }) as unknown as Record<string, unknown>;
939
+ case 'install_workflow_supervisor_browser_adapter': return (hooks.installWorkflowSupervisorBrowserAdapter ?? installWorkflowSupervisorBrowserAdapter)(input.controllerHome, { repository: { repoId: input.repoId, repoRoot: input.repoRoot } }) as unknown as Record<string, unknown>;
930
940
  case 'open_application': {
931
941
  const appName = optionalString(input.args, 'app_name');
932
942
  const bundleId = optionalString(input.args, 'bundle_id');
@@ -1,14 +1,14 @@
1
1
  import { spawn, spawnSync } from 'child_process';
2
2
  import { existsSync, statSync } from 'fs';
3
3
  import { dirname, isAbsolute, resolve } from 'path';
4
- import { AssistantPluginError } from './errors';
4
+ import { MAX_PLUGIN_ACTION_TIMEOUT_MS } from '../../../packages/plugin-runtime/external/index';
5
+ import { AssistantPluginError, type AssistantPluginEffectOutcome } from './errors';
5
6
 
6
7
  export const MANAGED_PLUGIN_PROTOCOL_VERSION = 1;
7
8
  const DEFAULT_MAX_REQUEST_BYTES = 1_048_576;
8
9
  const DEFAULT_MAX_RESPONSE_BYTES = 1_048_576;
9
10
  const DEFAULT_MAX_STDERR_CHARS = 8_000;
10
11
  const DEFAULT_TIMEOUT_MS = 30_000;
11
- const MAX_TIMEOUT_MS = 120_000;
12
12
 
13
13
  interface ManagedPluginHandshake {
14
14
  schemaVersion: 1;
@@ -60,12 +60,14 @@ export interface ManagedPluginProcessRequest {
60
60
  actionId: string;
61
61
  input: Record<string, unknown>;
62
62
  timeoutMs?: number;
63
+ effectOutcomeOnTimeout?: AssistantPluginEffectOutcome;
63
64
  signal?: AbortSignal;
64
65
  }
65
66
 
66
- function managedError(code: string, message: string, options: { retryable?: boolean; details?: Record<string, unknown> } = {}): AssistantPluginError {
67
+ function managedError(code: string, message: string, options: { retryable?: boolean; effectOutcome?: AssistantPluginEffectOutcome; details?: Record<string, unknown> } = {}): AssistantPluginError {
67
68
  return new AssistantPluginError(code, message, {
68
69
  retryable: options.retryable ?? true,
70
+ effectOutcome: options.effectOutcome,
69
71
  details: options.details,
70
72
  });
71
73
  }
@@ -73,7 +75,7 @@ function managedError(code: string, message: string, options: { retryable?: bool
73
75
  function boundedTimeout(spec: ManagedPluginProcessSpec, request: ManagedPluginProcessRequest): number {
74
76
  const requested = request.timeoutMs ?? spec.timeoutMs ?? DEFAULT_TIMEOUT_MS;
75
77
  if (!Number.isFinite(requested)) return DEFAULT_TIMEOUT_MS;
76
- return Math.min(Math.max(Math.trunc(requested), 50), MAX_TIMEOUT_MS);
78
+ return Math.min(Math.max(Math.trunc(requested), 50), MAX_PLUGIN_ACTION_TIMEOUT_MS);
77
79
  }
78
80
 
79
81
  function minimalEnvironment(runtimeExecutable: string): NodeJS.ProcessEnv {
@@ -257,6 +259,7 @@ export async function executeManagedPluginProcess(
257
259
  let stdoutBytes = 0;
258
260
  let stderr = '';
259
261
  let handshakeReceived = false;
262
+ let requestDispatched = false;
260
263
  let settled = false;
261
264
  let timer: ReturnType<typeof setTimeout> | undefined;
262
265
  let killTimer: ReturnType<typeof setTimeout> | undefined;
@@ -298,6 +301,7 @@ export async function executeManagedPluginProcess(
298
301
  if (!handshakeReceived) {
299
302
  validateHandshake(parsed, spec);
300
303
  handshakeReceived = true;
304
+ requestDispatched = true;
301
305
  child.stdin.end(`${requestEnvelope}\n`);
302
306
  return;
303
307
  }
@@ -318,7 +322,10 @@ export async function executeManagedPluginProcess(
318
322
  };
319
323
 
320
324
  timer = setTimeout(() => {
321
- fail(managedError('PLUGIN_MANAGED_PROCESS_TIMEOUT', 'Managed plugin helper timed out.', { retryable: true }));
325
+ fail(managedError('PLUGIN_MANAGED_PROCESS_TIMEOUT', 'Managed plugin helper timed out.', {
326
+ retryable: true,
327
+ effectOutcome: requestDispatched ? request.effectOutcomeOnTimeout : 'failed',
328
+ }));
322
329
  }, boundedTimeout(spec, request));
323
330
  request.signal?.addEventListener('abort', onAbort, { once: true });
324
331
 
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { createHash } from 'crypto';
3
- import { readFileSync, rmSync } from 'fs';
3
+ import { readFileSync, rmSync, writeFileSync } from 'fs';
4
4
  import { getRepository } from '../../cli/repositories/registry';
5
5
  import type { AssistantPluginActionRequest } from './types';
6
- import { submitAssistantPluginAction } from './store';
6
+ import { submitAssistantPluginAction, submitControllerPluginAction } from './store';
7
7
 
8
8
  interface Envelope {
9
9
  schemaVersion: 1;
10
10
  controllerHome: string;
11
- repoId: string;
11
+ repoId?: string;
12
+ scope?: { kind: 'controller' } | { kind: 'repository'; repoId: string };
12
13
  request: Omit<AssistantPluginActionRequest, 'signal'>;
13
14
  }
14
15
 
@@ -30,13 +31,16 @@ export async function runPluginActionSidecar(argv = process.argv.slice(2)): Prom
30
31
  }
31
32
  const envelope = JSON.parse(bytes) as Envelope;
32
33
  if (envelope.schemaVersion !== 1) throw new Error('PLUGIN_ACTION_REQUEST_VERSION_UNSUPPORTED');
33
- const repository = getRepository(envelope.repoId, envelope.controllerHome);
34
- const submitted = await submitAssistantPluginAction(
35
- envelope.controllerHome,
36
- repository,
37
- envelope.request,
38
- );
39
- process.stdout.write(`${JSON.stringify({
34
+ const controllerScoped = envelope.scope?.kind === 'controller';
35
+ const repoId = envelope.scope?.kind === 'repository' ? envelope.scope.repoId : envelope.repoId;
36
+ const submitted = controllerScoped
37
+ ? await submitControllerPluginAction(envelope.controllerHome, envelope.request)
38
+ : await submitAssistantPluginAction(
39
+ envelope.controllerHome,
40
+ getRepository(repoId ?? '', envelope.controllerHome),
41
+ envelope.request,
42
+ );
43
+ writeFileSync(1, `${JSON.stringify({
40
44
  ok: true,
41
45
  requestId: submitted.receipt.requestId,
42
46
  receiptId: submitted.receipt.receiptId,
@@ -51,9 +55,9 @@ export async function runPluginActionSidecar(argv = process.argv.slice(2)): Prom
51
55
  const direct = typeof process.argv[1] === 'string' && process.argv[1].includes('plugin-action-sidecar');
52
56
  if (direct) {
53
57
  void runPluginActionSidecar()
54
- .then((code) => { process.exitCode = code; })
58
+ .then((code) => { process.exit(code); })
55
59
  .catch((error) => {
56
- console.error(error instanceof Error ? error.message : String(error));
57
- process.exitCode = 1;
60
+ writeFileSync(2, `${error instanceof Error ? error.message : String(error)}\n`);
61
+ process.exit(1);
58
62
  });
59
63
  }
@@ -129,7 +129,7 @@ export function buildPluginManagementManifest(previousRevision = 0, previousUpda
129
129
  return {
130
130
  schemaVersion: 1, manifestVersion: 1, revision: Math.max(1, previousRevision || 1), pluginId: PLUGIN_ID,
131
131
  provider: 'forge-controller', displayName: 'Forge Plugin Management', pluginVersion: '1.0.0',
132
- authority: { strategy: 'derived', duplicateStateAllowed: false, sourceOfTruth: ['controller-home:plugins/external/registrations', 'controller-home:system/plugin-capability-authorizations/grants.json'] },
132
+ authority: { strategy: 'derived', duplicateStateAllowed: false, sourceOfTruth: ['controller-home:plugins/external/registrations', 'controller-home:system/authorization-grants/grants.json'] },
133
133
  enabled: true, lifecycle: { state: 'enabled', reason: 'Canonical external plugin registration authority is available.' },
134
134
  health: { state: 'ready', checkedAt: now(), ready: true, probed: true, errors: [], warnings: [] },
135
135
  permissions: permissions(), capabilities: capabilities(), actions: actions(), updatedAt: previousUpdatedAt ?? now(),