@moretea-labs/forge 1.6.0 → 1.7.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 (469) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +39 -0
  3. package/CLAUDE.md +4 -0
  4. package/README.md +2 -2
  5. package/README.zh-CN.md +1 -1
  6. package/SKILL.md +2 -2
  7. package/THIRD_PARTY_NOTICES.md +1 -1
  8. package/agents/openai.yaml +1 -1
  9. package/assets/hooks/hook-input.sh +11 -8
  10. package/assets/hooks/lib/session-state.sh +10 -7
  11. package/assets/hooks/lib/workflow-state.sh +13 -177
  12. package/assets/hooks/post-tool-observer.sh +8 -2
  13. package/assets/hooks/prompt-guard.sh +5 -81
  14. package/assets/hooks/session-start-context.sh +56 -1
  15. package/assets/partials/05-workflow.partial.md +1 -1
  16. package/assets/partials-agents/02-operating-mode.partial.md +2 -0
  17. package/assets/partials-agents/03-orchestration.partial.md +1 -1
  18. package/assets/plugin-registry.v1.json +3 -3
  19. package/assets/reference-configs/document-generation.md +1 -1
  20. package/assets/reference-configs/harness-overview.md +1 -1
  21. package/assets/reference-configs/sprint-contracts.md +3 -3
  22. package/assets/skill-version.json +2 -2
  23. package/assets/templates/contract.template.md +2 -7
  24. package/assets/templates/helpers/capture-plan.sh +2 -2
  25. package/assets/templates/helpers/check-architecture-sync.sh +17 -0
  26. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  27. package/assets/templates/helpers/contract-worktree.sh +1 -21
  28. package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
  29. package/assets/templates/helpers/inspect-project-state.ts +8 -6
  30. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  31. package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
  32. package/assets/templates/helpers/new-plan.sh +1 -1
  33. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  34. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  35. package/assets/templates/helpers/verify-contract.sh +1 -111
  36. package/assets/templates/helpers/verify-sprint.sh +3 -180
  37. package/assets/templates/helpers/workflow-contract.ts +5 -1
  38. package/assets/templates/plan.template.md +1 -1
  39. package/assets/templates/review.template.md +9 -34
  40. package/assets/workflow-contract.v1.json +10 -19
  41. package/docs/README.md +10 -10
  42. package/docs/architecture/CURRENT.md +178 -0
  43. package/docs/architecture/EVOLUTION.md +42 -0
  44. package/docs/architecture/current/README.md +4 -156
  45. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  46. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  47. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  48. package/docs/architecture/history/README.md +7 -0
  49. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  50. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  51. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  52. package/docs/architecture/history.md +3 -34
  53. package/docs/architecture/index.md +15 -98
  54. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  55. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  56. package/docs/architecture/versions/1.6.md +38 -0
  57. package/docs/architecture/versions/1.7.md +41 -0
  58. package/docs/forge-chatgpt-browser-engine.md +2 -2
  59. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  60. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  61. package/docs/forge-github-issue-launcher.md +1 -1
  62. package/docs/forge-plugin-management.md +1 -1
  63. package/docs/forge-runtime-self-healing-loop.md +1 -1
  64. package/docs/operations/controller-browser-plugin.md +26 -6
  65. package/docs/operations/controller-performance-and-502.md +143 -0
  66. package/docs/operations/controller-reliability-runbook.md +1 -1
  67. package/docs/operations/features.md +2 -2
  68. package/docs/operations/github-repository.md +1 -1
  69. package/docs/operations/homebrew.md +2 -2
  70. package/docs/operations/mcp-tool-exposure.md +5 -3
  71. package/docs/wiki/Architecture.md +6 -6
  72. package/docs/wiki/Implementation.md +2 -2
  73. package/docs/wiki/Integrations.md +2 -2
  74. package/docs/wiki/Work-Lifecycle.md +1 -1
  75. package/package.json +33 -11
  76. package/scripts/activate-source-baseline.ts +17 -13
  77. package/scripts/architecture-event.ts +2 -820
  78. package/scripts/architecture-queue.sh +2 -645
  79. package/scripts/archive-architecture-request.sh +2 -242
  80. package/scripts/archive-workflow.sh +1 -291
  81. package/scripts/benchmark-background-check-overlap.ts +228 -0
  82. package/scripts/benchmark-mcp-host.sh +117 -0
  83. package/scripts/benchmark-mcp-transport.ts +170 -0
  84. package/scripts/benchmark-quality-harness.ts +146 -0
  85. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  86. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  87. package/scripts/benchmark-typescript-navigation.ts +186 -0
  88. package/scripts/benchmark-work-efficiency.ts +334 -0
  89. package/scripts/capability-config.ts +2 -392
  90. package/scripts/capability-resolver.ts +2 -503
  91. package/scripts/capture-plan.sh +1 -332
  92. package/scripts/check-agent-tooling.sh +2 -1558
  93. package/scripts/check-architecture-sync.sh +2 -371
  94. package/scripts/check-brain-manifest.sh +2 -253
  95. package/scripts/check-context-files.sh +2 -47
  96. package/scripts/check-deploy-sql-order.sh +2 -115
  97. package/scripts/check-mcp-compatibility.ts +14 -0
  98. package/scripts/check-runtime-architecture.mjs +349 -79
  99. package/scripts/check-skill-version.ts +3 -191
  100. package/scripts/check-source-duplication.mjs +61 -0
  101. package/scripts/check-stable-baseline.ts +92 -0
  102. package/scripts/check-task-sync.sh +2 -63
  103. package/scripts/check-task-workflow.sh +2 -1000
  104. package/scripts/codex-handoff-resume.sh +2 -267
  105. package/scripts/context-contract-sync.sh +2 -514
  106. package/scripts/contract-run.ts +2 -463
  107. package/scripts/contract-worktree.sh +1 -722
  108. package/scripts/ensure-task-workflow.sh +1 -1225
  109. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  110. package/scripts/inspect-project-state.ts +4 -279
  111. package/scripts/install-standalone-recovery.ts +24 -0
  112. package/scripts/lib/project-init-lib.sh +22 -46
  113. package/scripts/lib/run-forge-helper.sh +19 -0
  114. package/scripts/lib/run-forge-helper.ts +26 -0
  115. package/scripts/migrate-project-template.sh +1 -1189
  116. package/scripts/migrate-workflow-docs.ts +4 -412
  117. package/scripts/new-plan.sh +1 -180
  118. package/scripts/new-spec.sh +1 -47
  119. package/scripts/new-sprint.sh +1 -46
  120. package/scripts/plan-to-todo.sh +1 -796
  121. package/scripts/prepare-codex-handoff.sh +2 -201
  122. package/scripts/prepare-handoff.sh +1 -78
  123. package/scripts/refresh-current-status.sh +2 -467
  124. package/scripts/run-governed-gate.ts +5 -1
  125. package/scripts/select-agent-context-blocks.sh +2 -64
  126. package/scripts/ship-worktrees.sh +1 -558
  127. package/scripts/smoke-ios-physical-device.ts +4 -2
  128. package/scripts/smoke-runtime-recovery.ts +1 -35
  129. package/scripts/smoke-schedule-engine.ts +1 -20
  130. package/scripts/sprint-backlog.sh +1 -834
  131. package/scripts/stage-runtime-release.ts +2 -1
  132. package/scripts/summarize-failures.sh +2 -123
  133. package/scripts/switch-plan.sh +1 -150
  134. package/scripts/sync-brain-docs.sh +2 -379
  135. package/scripts/sync-generated-authority.mjs +175 -0
  136. package/scripts/verify-contract.sh +2 -703
  137. package/scripts/verify-forge-runtime.sh +0 -1
  138. package/scripts/verify-sprint.sh +1 -677
  139. package/scripts/workflow-contract.ts +4 -205
  140. package/scripts/workstream-sync.sh +2 -261
  141. package/src/cli/agent-jobs/executor-health.ts +1 -1
  142. package/src/cli/commands/init-hook.ts +3 -3
  143. package/src/cli/commands/mcp.ts +9 -5
  144. package/src/cli/commands/plugin.ts +12 -3
  145. package/src/cli/commands/recovery.ts +25 -3
  146. package/src/cli/commands/runtime.ts +55 -3
  147. package/src/cli/commands/security.ts +12 -1
  148. package/src/cli/commands/setup-profile.ts +31 -21
  149. package/src/cli/controller/check-runner.ts +113 -5
  150. package/src/cli/controller/composite-result.ts +1 -1
  151. package/src/cli/controller/context/focus.ts +51 -0
  152. package/src/cli/controller/context/instruction-context.ts +114 -0
  153. package/src/cli/controller/context/known-paths.ts +76 -0
  154. package/src/cli/controller/context/query-planning.ts +110 -0
  155. package/src/cli/controller/context/rule-resolution.ts +532 -0
  156. package/src/cli/controller/context/source-materializer.ts +278 -0
  157. package/src/cli/controller/context/structural.ts +16 -0
  158. package/src/cli/controller/context/types.ts +286 -0
  159. package/src/cli/controller/context-pack.ts +828 -487
  160. package/src/cli/controller/launch-agents.ts +77 -2
  161. package/src/cli/controller/operational-plan.ts +2 -2
  162. package/src/cli/controller/work-mode.ts +6 -4
  163. package/src/cli/editing/edit-session.ts +60 -7
  164. package/src/cli/github/contracts.ts +16 -0
  165. package/src/cli/github/github.ts +135 -16
  166. package/src/cli/github/session.ts +2 -1
  167. package/src/cli/installer/managed-entries.ts +15 -1
  168. package/src/cli/local-bridge/console-automations.ts +54 -78
  169. package/src/cli/local-bridge/console-view-models.ts +1 -35
  170. package/src/cli/local-bridge/facade-api.ts +37 -264
  171. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  172. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
  173. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  174. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
  175. package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
  176. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  177. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
  178. package/src/cli/local-bridge/frontend/src/styles.css +1 -1
  179. package/src/cli/local-bridge/frontend/src/types.ts +5 -8
  180. package/src/cli/local-bridge/job-store.ts +1 -490
  181. package/src/cli/local-bridge/server.ts +2 -515
  182. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  183. package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
  184. package/src/cli/mcp/auth.ts +5 -5
  185. package/src/cli/mcp/instructions.ts +3 -2
  186. package/src/cli/mcp/legacy-tool-service.ts +10 -222
  187. package/src/cli/mcp/multi-repository.ts +16 -5
  188. package/src/cli/mcp/oauth.ts +175 -26
  189. package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
  190. package/src/cli/mcp/repository-tools.ts +282 -146
  191. package/src/cli/mcp/server.ts +586 -116
  192. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  193. package/src/cli/mcp/tool-contract.ts +14 -0
  194. package/src/cli/mcp/toolset-selection.ts +1 -1
  195. package/src/cli/mcp/toolset.ts +44 -7
  196. package/src/cli/mcp/transports/http.ts +124 -14
  197. package/src/cli/mcp/transports/session-registry.ts +43 -5
  198. package/src/cli/mcp/types.ts +3 -3
  199. package/src/cli/repositories/command-classifier.ts +103 -21
  200. package/src/cli/repositories/command-executor.ts +78 -526
  201. package/src/cli/repositories/command-process.ts +108 -0
  202. package/src/cli/repositories/command-scope.ts +99 -41
  203. package/src/cli/repositories/controller-home.ts +7 -8
  204. package/src/cli/repositories/git-command-executor.ts +2 -0
  205. package/src/cli/repositories/locks.ts +53 -16
  206. package/src/cli/repositories/repository-snapshot.ts +124 -0
  207. package/src/cli/repositories/selected-path-actions.ts +17 -9
  208. package/src/cli/repositories/structured-git.ts +118 -6
  209. package/src/cli/repository/inspector.ts +563 -65
  210. package/src/cli/repository/session-cache.ts +58 -17
  211. package/src/cli/v81-entry.ts +1 -4
  212. package/src/effects/fs-transaction.ts +85 -17
  213. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  214. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  215. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  216. package/src/runtime/context/lsp-client.ts +283 -0
  217. package/src/runtime/context/semantic-navigation-contract.ts +61 -0
  218. package/src/runtime/context/semantic-navigation.ts +223 -0
  219. package/src/runtime/context/swift-navigation.ts +565 -0
  220. package/src/runtime/context/typescript-navigation.ts +226 -0
  221. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  222. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +48 -16
  223. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  224. package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
  225. package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
  226. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  227. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  228. package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
  229. package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
  230. package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
  231. package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
  232. package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
  233. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  234. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  235. package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
  236. package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
  237. package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
  238. package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
  239. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  240. package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
  241. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
  242. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
  243. package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
  244. package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
  245. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
  246. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  247. package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
  248. package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
  249. package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
  250. package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
  251. package/src/runtime/control-plane/facade/index.ts +3 -0
  252. package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
  253. package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
  254. package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
  255. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  256. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  257. package/src/runtime/control-plane/facade/types.ts +90 -10
  258. package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
  259. package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
  260. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  261. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  262. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  263. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  264. package/src/runtime/control-plane/global-scheduler/maintenance.ts +152 -0
  265. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  266. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  267. package/src/runtime/control-plane/global-scheduler/scheduler.ts +278 -543
  268. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  269. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  270. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  271. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  272. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  273. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  274. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  275. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  276. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  277. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  278. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +63 -0
  279. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
  280. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
  281. package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
  282. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  283. package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
  284. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  285. package/src/runtime/control-plane/release-retention.ts +62 -2
  286. package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
  287. package/src/runtime/control-plane/routing/route-policy.ts +24 -21
  288. package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
  289. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  290. package/src/runtime/diagnostics/mcp-timing.ts +13 -0
  291. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  292. package/src/runtime/diagnostics/performance.ts +24 -1
  293. package/src/runtime/evidence/event-ledger.ts +1 -1
  294. package/src/runtime/evidence/process-check-execution.ts +18 -0
  295. package/src/runtime/execution/jobs/child-reference.ts +6 -2
  296. package/src/runtime/execution/jobs/store.ts +58 -4
  297. package/src/runtime/execution/jobs/types.ts +1 -1
  298. package/src/runtime/execution/managed-workspace.ts +203 -1
  299. package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
  300. package/src/runtime/execution/process-runtime/check-result.ts +88 -0
  301. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
  302. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  303. package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
  304. package/src/runtime/execution/process-runtime/gc.ts +38 -6
  305. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
  306. package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
  307. package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
  308. package/src/runtime/execution/process-runtime/runtime.ts +53 -3
  309. package/src/runtime/execution/process-runtime/store.ts +1 -0
  310. package/src/runtime/execution/process-runtime/types.ts +4 -12
  311. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  312. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  313. package/src/runtime/execution/work-activity.ts +21 -0
  314. package/src/runtime/execution/workers/executor.ts +18 -61
  315. package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
  316. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
  317. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  318. package/src/runtime/gateway/mcp/router.ts +186 -84
  319. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
  320. package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
  321. package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
  322. package/src/runtime/plugins/browser-adapter.ts +2662 -829
  323. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  324. package/src/runtime/plugins/browser-handoff-host.ts +2 -25
  325. package/src/runtime/plugins/browser-handoff.ts +110 -5
  326. package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
  327. package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
  328. package/src/runtime/plugins/browser-native-session-service.ts +222 -0
  329. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  330. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  331. package/src/runtime/plugins/browser-runtime-contract.ts +154 -0
  332. package/src/runtime/plugins/browser-runtime.ts +193 -0
  333. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  334. package/src/runtime/plugins/browser-session-store.ts +121 -0
  335. package/src/runtime/plugins/browser-session-types.ts +98 -0
  336. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  337. package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
  338. package/src/runtime/plugins/external-adapter.ts +358 -3
  339. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  340. package/src/runtime/plugins/first-party-registry.ts +2 -0
  341. package/src/runtime/plugins/github-adapter.ts +125 -0
  342. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  343. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  344. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  345. package/src/runtime/plugins/ios-adapter.ts +106 -16
  346. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  347. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  348. package/src/runtime/plugins/lightweight-action.ts +153 -0
  349. package/src/runtime/plugins/local-system-adapter.ts +123 -6
  350. package/src/runtime/plugins/macos-capability-broker.ts +47 -9
  351. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  352. package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
  353. package/src/runtime/plugins/resend-adapter.ts +1 -1
  354. package/src/runtime/plugins/store.ts +330 -33
  355. package/src/runtime/plugins/types.ts +38 -3
  356. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  357. package/src/runtime/projections/git-status-sampler.ts +16 -16
  358. package/src/runtime/projections/materialized-view.ts +28 -10
  359. package/src/runtime/recovery/maintenance-executor.ts +426 -25
  360. package/src/runtime/root/mcp-transport.ts +180 -10
  361. package/src/runtime/root/package-connector-service.ts +230 -10
  362. package/src/runtime/root/package-runtime-release.ts +143 -17
  363. package/src/runtime/root/package-runtime-service.ts +461 -22
  364. package/src/runtime/root/release-manifest.ts +144 -18
  365. package/src/runtime/root/release-materialize.ts +125 -32
  366. package/src/runtime/root/release-store.ts +48 -11
  367. package/src/runtime/root/runtime.ts +23 -5
  368. package/src/runtime/root/service.ts +100 -29
  369. package/src/runtime/root/types.ts +12 -0
  370. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  371. package/src/runtime/shared/trusted-executable.ts +62 -0
  372. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  373. package/src/runtime/standalone-recovery/core.ts +1079 -240
  374. package/src/runtime/standalone-recovery/entry.ts +100 -24
  375. package/src/runtime/standalone-recovery/installer.ts +20 -4
  376. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  377. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  378. package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
  379. package/src/runtime/workflow/schedules/engine.ts +364 -202
  380. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  381. package/src/runtime/workflow/schedules/settlement.ts +64 -17
  382. package/src/runtime/workflow/schedules/store.ts +209 -19
  383. package/src/runtime/workflow/schedules/types.ts +2 -4
  384. package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
  385. package/src/testing/test-governance.ts +8 -40
  386. package/assets/reference-configs/heartbeat-triage.md +0 -57
  387. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  388. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  389. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  390. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  391. package/docs/architecture/current/architecture-invariants.md +0 -331
  392. package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
  393. package/docs/architecture/current/codegraph-context-provider.md +0 -238
  394. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  395. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  396. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
  397. package/docs/architecture/current/entity-model.md +0 -612
  398. package/docs/architecture/current/external-plugin-governance.md +0 -396
  399. package/docs/architecture/current/failure-recovery.md +0 -447
  400. package/docs/architecture/current/governance.md +0 -213
  401. package/docs/architecture/current/human-interaction-plane.md +0 -87
  402. package/docs/architecture/current/implementation-status.md +0 -128
  403. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  404. package/docs/architecture/current/legacy-governance.md +0 -58
  405. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  406. package/docs/architecture/current/migration-roadmap.md +0 -105
  407. package/docs/architecture/current/multi-repository-execution.md +0 -371
  408. package/docs/architecture/current/operations-runbook.md +0 -45
  409. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  410. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  411. package/docs/architecture/current/repository-access-modes.md +0 -102
  412. package/docs/architecture/current/route-policy.md +0 -15
  413. package/docs/architecture/current/route-session-concurrency.md +0 -85
  414. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  415. package/docs/architecture/current/runtime-directory-map.md +0 -49
  416. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  417. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  418. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  419. package/docs/architecture/current/system-overview.md +0 -169
  420. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  421. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  422. package/docs/architecture/current/thin-harness-v1.md +0 -321
  423. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  424. package/docs/forge-autonomous-goal-loop.md +0 -9
  425. package/docs/forge-provider-configuration.md +0 -7
  426. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
  427. package/docs/operations/gmail-assistant-routines.md +0 -186
  428. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  429. package/docs/operations/provider-configuration.md +0 -31
  430. package/scripts/harness-trace-grade.sh +0 -150
  431. package/scripts/heartbeat-triage.sh +0 -361
  432. package/scripts/maintenance-triage.sh +0 -167
  433. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  434. package/src/cli/repositories/goal-registry.ts +0 -239
  435. package/src/runtime/assistant/action-proposals.ts +0 -279
  436. package/src/runtime/assistant/intent.ts +0 -395
  437. package/src/runtime/assistant/model-provider.ts +0 -460
  438. package/src/runtime/assistant/openapi.ts +0 -223
  439. package/src/runtime/assistant/policy.ts +0 -89
  440. package/src/runtime/assistant/readiness.ts +0 -258
  441. package/src/runtime/assistant/routine-runtime.ts +0 -477
  442. package/src/runtime/assistant/schedule-binding.ts +0 -171
  443. package/src/runtime/assistant/standing-grants.ts +0 -375
  444. package/src/runtime/assistant/store.ts +0 -243
  445. package/src/runtime/assistant/types.ts +0 -135
  446. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  447. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  448. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  449. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  450. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  451. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  452. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  453. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  454. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  455. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  456. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  457. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  458. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  459. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  460. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  461. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  462. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  463. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  464. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  465. package/src/runtime/workflow/findings/store.ts +0 -204
  466. package/src/runtime/workflow/findings/types.ts +0 -58
  467. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  468. package/src/runtime/workflow/portfolio/store.ts +0 -185
  469. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -0,0 +1,98 @@
1
+ export type BrowserMode = 'attach_preferred' | 'managed_persistent' | 'isolated';
2
+ export type BrowserProfileMode = 'repo_local' | 'custom';
3
+ export type BrowserCdpAttachFallback = 'managed_persistent' | 'fail_closed';
4
+ export type BrowserNativeProduct = 'chrome' | 'vivaldi';
5
+ export type BrowserTabMatchReason = 'owned_token' | 'recovered_tab' | 'saved_url_title' | 'saved_url' | 'exact_url' | 'blank' | 'new_page';
6
+
7
+ export interface CdpAttachAttempt {
8
+ endpoint: string;
9
+ discoveredEndpoint?: string;
10
+ probeUrl?: string;
11
+ browserVersion?: string;
12
+ error?: string;
13
+ }
14
+
15
+ export interface BrowserNativeAttachAttempt {
16
+ product: BrowserNativeProduct;
17
+ appName: string;
18
+ bundleId: string;
19
+ status: 'selected' | 'available' | 'not_installed' | 'not_running' | 'unavailable';
20
+ frontmost?: boolean;
21
+ error?: string;
22
+ }
23
+
24
+ export interface BrowserSessionResumeDiagnostic {
25
+ sessionId: string;
26
+ status: 'matched' | 'stale_tab' | 'no_saved_tab';
27
+ reason: string;
28
+ savedTab?: Pick<BrowserTabResumeState, 'key' | 'url' | 'title' | 'index'>;
29
+ }
30
+
31
+ export interface BrowserConnectionFallback {
32
+ policy: BrowserCdpAttachFallback;
33
+ from: 'attach_preferred';
34
+ to: 'managed_persistent';
35
+ reason: string;
36
+ attempts: CdpAttachAttempt[];
37
+ nativeAttempts?: BrowserNativeAttachAttempt[];
38
+ }
39
+
40
+ export interface BrowserTabResumeState {
41
+ key: string;
42
+ index: number;
43
+ url: string;
44
+ title?: string;
45
+ matchedBy: BrowserTabMatchReason;
46
+ inventoryCount: number;
47
+ capturedAt: string;
48
+ ownership?: 'plugin_owned' | 'user_owned';
49
+ ownerToken?: string;
50
+ windowId?: string;
51
+ tabId?: string;
52
+ }
53
+
54
+ export interface BrowserSessionConnectionState {
55
+ mode: BrowserMode;
56
+ activeMode: BrowserMode;
57
+ provider: 'playwright-cdp' | 'playwright-persistent-context' | 'macos-apple-events';
58
+ endpoint?: string;
59
+ browserVersion?: string;
60
+ browserProduct?: BrowserNativeProduct;
61
+ nativeBrowserCandidates?: BrowserNativeProduct[];
62
+ fallback?: BrowserConnectionFallback;
63
+ tab?: BrowserTabResumeState;
64
+ sessionResume?: BrowserSessionResumeDiagnostic;
65
+ }
66
+
67
+ export interface BrowserSessionState {
68
+ schemaVersion: 1;
69
+ sessionId: string;
70
+ url: string;
71
+ title?: string;
72
+ createdAt: string;
73
+ updatedAt: string;
74
+ browser?: BrowserSessionConnectionState;
75
+ }
76
+
77
+ export type BrowserSessionLiveness = 'live' | 'unverified' | 'dead';
78
+ export type BrowserSessionLivenessEvidence =
79
+ | 'runtime_session_binding'
80
+ | 'runtime_owner_token'
81
+ | 'runtime_bound_page_missing'
82
+ | 'runtime_context_unavailable'
83
+ | 'runtime_owner_token_not_observed'
84
+ | 'provider_unverified'
85
+ | 'native_tab_live'
86
+ | 'native_tab_missing'
87
+ | 'native_tab_invalid'
88
+ | 'native_tab_invalid_closed'
89
+ | 'native_tab_invalid_close_failed'
90
+ | 'native_inventory_unavailable';
91
+
92
+ export interface BrowserSessionInventoryItem {
93
+ session: BrowserSessionState;
94
+ liveness: BrowserSessionLiveness;
95
+ evidence: BrowserSessionLivenessEvidence;
96
+ pruned?: boolean;
97
+ cleanupError?: string;
98
+ }
@@ -0,0 +1,354 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { existsSync, mkdirSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { controllerSystemRoot } from '../../cli/repositories/controller-home';
5
+ import { ControllerLockContentionError, withControllerLock } from '../../cli/repositories/locks';
6
+ import { readJsonFile, writeJsonAtomic } from '../shared/json-files';
7
+ import type { AssistantPluginActionRisk, AssistantPluginAuthorizationTarget } from './types';
8
+
9
+ export const DEFAULT_PLUGIN_CAPABILITY_GRANT_MINUTES = 30 * 24 * 60;
10
+ const MAX_PLUGIN_CAPABILITY_GRANT_MINUTES = 90 * 24 * 60;
11
+
12
+ export type PluginCapabilityAuthorizationGrantErrorCode =
13
+ | 'PLUGIN_CAPABILITY_GRANT_STORE_CORRUPT'
14
+ | 'PLUGIN_CAPABILITY_GRANT_STORE_BUSY'
15
+ | 'PLUGIN_CAPABILITY_GRANT_ARGUMENT_INVALID'
16
+ | 'PLUGIN_CAPABILITY_GRANT_DESTRUCTIVE_DENIED'
17
+ | 'PLUGIN_CAPABILITY_GRANT_NOT_FOUND'
18
+ | 'PLUGIN_CAPABILITY_GRANT_OWNER_MISMATCH';
19
+
20
+ export class PluginCapabilityAuthorizationGrantError extends Error {
21
+ constructor(
22
+ public readonly code: PluginCapabilityAuthorizationGrantErrorCode,
23
+ message: string,
24
+ ) {
25
+ super(message);
26
+ this.name = 'PluginCapabilityAuthorizationGrantError';
27
+ }
28
+ }
29
+
30
+ export interface PluginCapabilityAuthorizationGrant {
31
+ schemaVersion: 1;
32
+ grantId: string;
33
+ ownerScope: string;
34
+ repoId: string;
35
+ pluginId: string;
36
+ capabilityId: string;
37
+ target: AssistantPluginAuthorizationTarget;
38
+ scopes: string[];
39
+ riskCeiling: Exclude<AssistantPluginActionRisk, 'destructive'>;
40
+ createdAt: string;
41
+ updatedAt: string;
42
+ expiresAt: string;
43
+ revokedAt?: string;
44
+ revokedReason?: string;
45
+ }
46
+
47
+ interface PluginCapabilityAuthorizationGrantStore {
48
+ schemaVersion: 1;
49
+ grants: PluginCapabilityAuthorizationGrant[];
50
+ }
51
+
52
+ export interface PluginCapabilityAuthorizationQuery {
53
+ ownerScope: string;
54
+ repoId: string;
55
+ pluginId: string;
56
+ capabilityId: string;
57
+ target: AssistantPluginAuthorizationTarget;
58
+ scopes: readonly string[];
59
+ risk: AssistantPluginActionRisk;
60
+ at?: Date;
61
+ }
62
+
63
+ export interface RecordPluginCapabilityAuthorizationInput extends Omit<PluginCapabilityAuthorizationQuery, 'risk' | 'at'> {
64
+ riskCeiling: AssistantPluginActionRisk;
65
+ expiresInMinutes?: number;
66
+ now?: Date;
67
+ }
68
+
69
+ export interface RevokePluginCapabilityAuthorizationInput {
70
+ grantId: string;
71
+ ownerScope: string;
72
+ reason: string;
73
+ now?: Date;
74
+ }
75
+
76
+ const RISK_RANK: Record<AssistantPluginActionRisk, number> = {
77
+ readonly: 0,
78
+ workspace_write: 1,
79
+ remote_write: 2,
80
+ destructive: 3,
81
+ };
82
+
83
+ const GENERIC_PLUGIN_AUTHORIZATION_ACTORS = new Set(['', 'anonymous', 'plugin_action_execute']);
84
+
85
+ export function pluginCapabilityAuthorizationOwnerScope(origin: { surface: string; actor?: string }): string {
86
+ const actor = origin.actor?.trim() ?? '';
87
+ if (GENERIC_PLUGIN_AUTHORIZATION_ACTORS.has(actor)) return 'controller:shared';
88
+ return `${origin.surface}:${actor}`;
89
+ }
90
+
91
+ function required(value: string, label: string): string {
92
+ const normalized = value.trim();
93
+ if (!normalized) {
94
+ throw new PluginCapabilityAuthorizationGrantError(
95
+ 'PLUGIN_CAPABILITY_GRANT_ARGUMENT_INVALID',
96
+ `${label} is required.`,
97
+ );
98
+ }
99
+ return normalized;
100
+ }
101
+
102
+ function normalizeScopes(scopes: readonly string[]): string[] {
103
+ return [...new Set(scopes.map((scope) => scope.trim()).filter(Boolean))].sort();
104
+ }
105
+
106
+ function normalizeTarget(target: AssistantPluginAuthorizationTarget): AssistantPluginAuthorizationTarget {
107
+ const kind = required(target.kind, 'target.kind');
108
+ const id = required(target.id, 'target.id');
109
+ const identityFingerprint = target.identityFingerprint?.trim();
110
+ return {
111
+ kind,
112
+ id,
113
+ ...(identityFingerprint ? { identityFingerprint } : {}),
114
+ };
115
+ }
116
+
117
+ function validateRisk(value: unknown, index: number): Exclude<AssistantPluginActionRisk, 'destructive'> {
118
+ if (value === 'readonly' || value === 'workspace_write' || value === 'remote_write') return value;
119
+ throw new Error(`grants[${index}].riskCeiling is invalid`);
120
+ }
121
+
122
+ function validatePersistedGrant(value: unknown, index: number): PluginCapabilityAuthorizationGrant {
123
+ if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`grants[${index}] must be an object`);
124
+ const record = value as Record<string, unknown>;
125
+ const string = (field: string) => {
126
+ const current = record[field];
127
+ if (typeof current !== 'string' || !current.trim()) throw new Error(`grants[${index}].${field} is invalid`);
128
+ return current.trim();
129
+ };
130
+ const targetValue = record.target;
131
+ if (!targetValue || typeof targetValue !== 'object' || Array.isArray(targetValue)) throw new Error(`grants[${index}].target is invalid`);
132
+ const targetRecord = targetValue as Record<string, unknown>;
133
+ if (typeof targetRecord.kind !== 'string' || !targetRecord.kind.trim() || typeof targetRecord.id !== 'string' || !targetRecord.id.trim()) {
134
+ throw new Error(`grants[${index}].target identity is invalid`);
135
+ }
136
+ if (targetRecord.identityFingerprint !== undefined && typeof targetRecord.identityFingerprint !== 'string') {
137
+ throw new Error(`grants[${index}].target.identityFingerprint is invalid`);
138
+ }
139
+ if (!Array.isArray(record.scopes) || record.scopes.some((scope) => typeof scope !== 'string')) {
140
+ throw new Error(`grants[${index}].scopes is invalid`);
141
+ }
142
+ const createdAt = string('createdAt');
143
+ const updatedAt = string('updatedAt');
144
+ const expiresAt = string('expiresAt');
145
+ if (![createdAt, updatedAt, expiresAt].every((timestamp) => Number.isFinite(Date.parse(timestamp)))) {
146
+ throw new Error(`grants[${index}] has invalid timestamps`);
147
+ }
148
+ if (Date.parse(expiresAt) < Date.parse(createdAt)) throw new Error(`grants[${index}] expires before creation`);
149
+ const revokedAt = record.revokedAt;
150
+ const revokedReason = record.revokedReason;
151
+ if (revokedAt !== undefined && (typeof revokedAt !== 'string' || !Number.isFinite(Date.parse(revokedAt)))) {
152
+ throw new Error(`grants[${index}].revokedAt is invalid`);
153
+ }
154
+ if (revokedReason !== undefined && typeof revokedReason !== 'string') throw new Error(`grants[${index}].revokedReason is invalid`);
155
+ return {
156
+ schemaVersion: 1,
157
+ grantId: string('grantId'),
158
+ ownerScope: string('ownerScope'),
159
+ repoId: string('repoId'),
160
+ pluginId: string('pluginId'),
161
+ capabilityId: string('capabilityId'),
162
+ target: normalizeTarget({
163
+ kind: targetRecord.kind,
164
+ id: targetRecord.id,
165
+ ...(typeof targetRecord.identityFingerprint === 'string' && targetRecord.identityFingerprint.trim()
166
+ ? { identityFingerprint: targetRecord.identityFingerprint.trim() }
167
+ : {}),
168
+ }),
169
+ scopes: normalizeScopes(record.scopes as string[]),
170
+ riskCeiling: validateRisk(record.riskCeiling, index),
171
+ createdAt,
172
+ updatedAt,
173
+ expiresAt,
174
+ ...(typeof revokedAt === 'string' ? { revokedAt } : {}),
175
+ ...(typeof revokedReason === 'string' ? { revokedReason } : {}),
176
+ };
177
+ }
178
+
179
+ export function pluginCapabilityAuthorizationGrantStorePath(controllerHome: string): string {
180
+ return join(controllerSystemRoot(controllerHome), 'plugin-capability-authorizations', 'grants.json');
181
+ }
182
+
183
+ function loadStore(controllerHome: string): PluginCapabilityAuthorizationGrantStore {
184
+ const path = pluginCapabilityAuthorizationGrantStorePath(controllerHome);
185
+ if (!existsSync(path)) return { schemaVersion: 1, grants: [] };
186
+ try {
187
+ const raw = readJsonFile<unknown>(path);
188
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('store must be an object');
189
+ const record = raw as Record<string, unknown>;
190
+ if (record.schemaVersion !== 1 || !Array.isArray(record.grants)) throw new Error('schemaVersion/grants are invalid');
191
+ return { schemaVersion: 1, grants: record.grants.map(validatePersistedGrant) };
192
+ } catch (error) {
193
+ throw new PluginCapabilityAuthorizationGrantError(
194
+ 'PLUGIN_CAPABILITY_GRANT_STORE_CORRUPT',
195
+ `Plugin capability authorization store is corrupt: ${error instanceof Error ? error.message : String(error)}`,
196
+ );
197
+ }
198
+ }
199
+
200
+ function saveStore(controllerHome: string, store: PluginCapabilityAuthorizationGrantStore): void {
201
+ const path = pluginCapabilityAuthorizationGrantStorePath(controllerHome);
202
+ mkdirSync(join(controllerSystemRoot(controllerHome), 'plugin-capability-authorizations'), { recursive: true });
203
+ writeJsonAtomic(path, store);
204
+ }
205
+
206
+ function targetMatches(left: AssistantPluginAuthorizationTarget, right: AssistantPluginAuthorizationTarget): boolean {
207
+ return left.kind === right.kind
208
+ && left.id === right.id
209
+ && (left.identityFingerprint ?? '') === (right.identityFingerprint ?? '');
210
+ }
211
+
212
+ function scopesContain(granted: readonly string[], requested: readonly string[]): boolean {
213
+ const available = new Set(granted);
214
+ return requested.every((scope) => available.has(scope));
215
+ }
216
+
217
+ export function findActivePluginCapabilityAuthorization(
218
+ controllerHome: string,
219
+ query: PluginCapabilityAuthorizationQuery,
220
+ ): PluginCapabilityAuthorizationGrant | undefined {
221
+ if (query.risk === 'destructive') return undefined;
222
+ const ownerScope = required(query.ownerScope, 'ownerScope');
223
+ const repoId = required(query.repoId, 'repoId');
224
+ const pluginId = required(query.pluginId, 'pluginId');
225
+ const capabilityId = required(query.capabilityId, 'capabilityId');
226
+ const target = normalizeTarget(query.target);
227
+ const scopes = normalizeScopes(query.scopes);
228
+ const atMs = (query.at ?? new Date()).getTime();
229
+ return loadStore(controllerHome).grants
230
+ .filter((grant) => !grant.revokedAt && Date.parse(grant.expiresAt) > atMs)
231
+ .filter((grant) => grant.ownerScope === ownerScope
232
+ && grant.repoId === repoId
233
+ && grant.pluginId === pluginId
234
+ && grant.capabilityId === capabilityId
235
+ && targetMatches(grant.target, target)
236
+ && scopesContain(grant.scopes, scopes)
237
+ && RISK_RANK[grant.riskCeiling] >= RISK_RANK[query.risk])
238
+ .sort((left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt))[0];
239
+ }
240
+
241
+ export function recordPluginCapabilityAuthorization(
242
+ controllerHome: string,
243
+ input: RecordPluginCapabilityAuthorizationInput,
244
+ ): PluginCapabilityAuthorizationGrant {
245
+ if (input.riskCeiling === 'destructive') {
246
+ throw new PluginCapabilityAuthorizationGrantError(
247
+ 'PLUGIN_CAPABILITY_GRANT_DESTRUCTIVE_DENIED',
248
+ 'Destructive plugin actions can never establish reusable capability authorization.',
249
+ );
250
+ }
251
+ const now = input.now ?? new Date();
252
+ const ownerScope = required(input.ownerScope, 'ownerScope');
253
+ const repoId = required(input.repoId, 'repoId');
254
+ const pluginId = required(input.pluginId, 'pluginId');
255
+ const capabilityId = required(input.capabilityId, 'capabilityId');
256
+ const target = normalizeTarget(input.target);
257
+ const scopes = normalizeScopes(input.scopes);
258
+ const rawMinutes = input.expiresInMinutes ?? DEFAULT_PLUGIN_CAPABILITY_GRANT_MINUTES;
259
+ if (!Number.isFinite(rawMinutes) || rawMinutes <= 0) {
260
+ throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_ARGUMENT_INVALID', 'expiresInMinutes must be positive.');
261
+ }
262
+ const expiresInMinutes = Math.min(Math.max(1, Math.trunc(rawMinutes)), MAX_PLUGIN_CAPABILITY_GRANT_MINUTES);
263
+ const timestamp = now.toISOString();
264
+ const grant: PluginCapabilityAuthorizationGrant = {
265
+ schemaVersion: 1,
266
+ grantId: `plugin-grant-${randomUUID()}`,
267
+ ownerScope,
268
+ repoId,
269
+ pluginId,
270
+ capabilityId,
271
+ target,
272
+ scopes,
273
+ riskCeiling: input.riskCeiling,
274
+ createdAt: timestamp,
275
+ updatedAt: timestamp,
276
+ expiresAt: new Date(now.getTime() + expiresInMinutes * 60_000).toISOString(),
277
+ };
278
+ try {
279
+ return withControllerLock(
280
+ controllerHome,
281
+ { scope: 'global', resource: 'plugin-capability-authorization-grants' },
282
+ `plugin-capability-grant:${ownerScope}`,
283
+ () => {
284
+ const store = loadStore(controllerHome);
285
+ store.grants = store.grants.filter((entry) => !(entry.ownerScope === ownerScope
286
+ && entry.repoId === repoId
287
+ && entry.pluginId === pluginId
288
+ && entry.capabilityId === capabilityId
289
+ && entry.target.kind === target.kind
290
+ && entry.target.id === target.id));
291
+ store.grants.push(grant);
292
+ saveStore(controllerHome, store);
293
+ return grant;
294
+ },
295
+ 5_000,
296
+ );
297
+ } catch (error) {
298
+ if (error instanceof ControllerLockContentionError) {
299
+ throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_STORE_BUSY', error.message);
300
+ }
301
+ throw error;
302
+ }
303
+ }
304
+
305
+ export function revokePluginCapabilityAuthorization(
306
+ controllerHome: string,
307
+ input: RevokePluginCapabilityAuthorizationInput,
308
+ ): PluginCapabilityAuthorizationGrant {
309
+ const grantId = required(input.grantId, 'grantId');
310
+ const ownerScope = required(input.ownerScope, 'ownerScope');
311
+ const reason = required(input.reason, 'reason');
312
+ const now = input.now ?? new Date();
313
+ try {
314
+ return withControllerLock(
315
+ controllerHome,
316
+ { scope: 'global', resource: 'plugin-capability-authorization-grants' },
317
+ `plugin-capability-revoke:${ownerScope}`,
318
+ () => {
319
+ const store = loadStore(controllerHome);
320
+ const index = store.grants.findIndex((grant) => grant.grantId === grantId);
321
+ if (index < 0) throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_NOT_FOUND', `Grant ${grantId} was not found.`);
322
+ const current = store.grants[index]!;
323
+ if (current.ownerScope !== ownerScope) {
324
+ throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_OWNER_MISMATCH', `Grant ${grantId} belongs to another owner scope.`);
325
+ }
326
+ const revoked: PluginCapabilityAuthorizationGrant = {
327
+ ...current,
328
+ updatedAt: now.toISOString(),
329
+ revokedAt: now.toISOString(),
330
+ revokedReason: reason,
331
+ };
332
+ store.grants[index] = revoked;
333
+ saveStore(controllerHome, store);
334
+ return revoked;
335
+ },
336
+ 5_000,
337
+ );
338
+ } catch (error) {
339
+ if (error instanceof ControllerLockContentionError) {
340
+ throw new PluginCapabilityAuthorizationGrantError('PLUGIN_CAPABILITY_GRANT_STORE_BUSY', error.message);
341
+ }
342
+ throw error;
343
+ }
344
+ }
345
+
346
+ export function listPluginCapabilityAuthorizations(
347
+ controllerHome: string,
348
+ ownerScope?: string,
349
+ ): PluginCapabilityAuthorizationGrant[] {
350
+ const normalizedOwner = ownerScope?.trim();
351
+ return loadStore(controllerHome).grants
352
+ .filter((grant) => !normalizedOwner || grant.ownerScope === normalizedOwner)
353
+ .map((grant) => structuredClone(grant));
354
+ }
@@ -68,7 +68,7 @@ function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
68
68
  {
69
69
  actionId: 'desktop_session_open',
70
70
  title: 'Open desktop session',
71
- description: 'Launch or locate one application in the background and create a bounded interaction session without stealing foreground focus.',
71
+ description: 'Launch or locate one application and create a bounded interaction session; stays in the background by default, or explicitly activates the target when activate=true.',
72
72
  readOnly: false,
73
73
  risk: 'workspace_write',
74
74
  confirmation: 'authorization',
@@ -83,6 +83,7 @@ function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
83
83
  bundle_id: { type: 'string' },
84
84
  app_name: { type: 'string' },
85
85
  launch: { type: 'boolean' },
86
+ activate: { type: 'boolean', description: 'Explicitly activate the target application after launch/lookup. Defaults to false.' },
86
87
  },
87
88
  anyOf: [{ required: ['bundle_id'] }, { required: ['app_name'] }],
88
89
  additionalProperties: false,
@@ -118,7 +119,7 @@ function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
118
119
  {
119
120
  actionId: 'desktop_press',
120
121
  title: 'Press desktop element',
121
- description: 'Press one Accessibility element semantically in the background; pointer/coordinate fallback is intentionally unavailable.',
122
+ description: 'Perform one bounded Accessibility semantic action in the background, including one-page list scrolling; pointer/coordinate and raw input fallback are intentionally unavailable.',
122
123
  readOnly: false,
123
124
  risk: 'workspace_write',
124
125
  confirmation: 'authorization',
@@ -132,6 +133,11 @@ function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
132
133
  properties: {
133
134
  interaction_id: { type: 'string' },
134
135
  selector: SELECTOR_SCHEMA,
136
+ semantic_action: {
137
+ type: 'string',
138
+ enum: ['press', 'show_menu', 'pick', 'open', 'confirm', 'scroll_down_page', 'scroll_up_page'],
139
+ description: 'Bounded Accessibility action supported by the trusted Desktop Operator provider; scroll actions move exactly one page and default to press when omitted.',
140
+ },
135
141
  },
136
142
  required: ['interaction_id', 'selector'],
137
143
  additionalProperties: false,
@@ -164,7 +170,7 @@ function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
164
170
  {
165
171
  actionId: 'desktop_key',
166
172
  title: 'Press desktop keys',
167
- description: 'Send one bounded key chord only when the explicit target session is already foreground; the operator never activates it.',
173
+ description: 'Send one bounded key chord to the exact target session after Forge independently re-establishes and verifies that application as system-frontmost at the action boundary.',
168
174
  readOnly: false,
169
175
  risk: 'workspace_write',
170
176
  confirmation: 'authorization',
@@ -404,7 +410,7 @@ export function createDesktopOperatorRegistrationInput(
404
410
  { capabilityId: 'desktop.permissions', title: 'Desktop permissions', description: 'Request the official macOS permissions required by Desktop Operator capabilities.', scopes: ['desktop.permissions'], actions: ['desktop_permissions_request'] },
405
411
  { capabilityId: 'desktop.session', title: 'Desktop sessions', description: 'Create and close application interaction sessions.', scopes: ['desktop.session'], actions: ['desktop_session_open', 'desktop_session_close'] },
406
412
  { capabilityId: 'desktop.observe', title: 'Desktop observation', description: 'Read bounded Accessibility and window state.', scopes: ['desktop.observe'], actions: ['desktop_observe'] },
407
- { capabilityId: 'desktop.interact', title: 'Desktop interaction', description: 'Press, type, send keys, and open URLs.', scopes: ['desktop.interact'], actions: ['desktop_press', 'desktop_type_text', 'desktop_key', 'desktop_open_url'] },
413
+ { capabilityId: 'desktop.interact', title: 'Desktop interaction', description: 'Press controls, type text, send keys, and open URLs.', scopes: ['desktop.interact'], actions: ['desktop_press', 'desktop_type_text', 'desktop_key', 'desktop_open_url'] },
408
414
  { capabilityId: 'desktop.capture', title: 'Desktop capture', description: 'Capture authorized screenshots.', scopes: ['desktop.capture'], actions: ['desktop_screenshot'] },
409
415
  { capabilityId: 'desktop.clipboard', title: 'Desktop clipboard', description: 'Read or replace plain-text clipboard content and issue explicit copy/paste in a bound session.', scopes: ['desktop.clipboard'], actions: ['desktop_clipboard_read', 'desktop_clipboard_write', 'desktop_copy', 'desktop_paste'] },
410
416
  { capabilityId: 'desktop.batch', title: 'Desktop batch', description: 'Run bounded desktop action batches.', scopes: ['desktop.batch'], actions: ['desktop_batch'] },