@moretea-labs/forge 1.6.0 → 1.7.0

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 (396) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +26 -0
  3. package/CLAUDE.md +2 -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/03-orchestration.partial.md +1 -1
  17. package/assets/plugin-registry.v1.json +1 -1
  18. package/assets/reference-configs/document-generation.md +1 -1
  19. package/assets/reference-configs/harness-overview.md +1 -1
  20. package/assets/reference-configs/sprint-contracts.md +3 -3
  21. package/assets/skill-version.json +2 -2
  22. package/assets/templates/contract.template.md +2 -7
  23. package/assets/templates/helpers/capture-plan.sh +2 -2
  24. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  25. package/assets/templates/helpers/contract-worktree.sh +1 -21
  26. package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
  27. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  28. package/assets/templates/helpers/new-plan.sh +1 -1
  29. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  30. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  31. package/assets/templates/helpers/verify-contract.sh +1 -111
  32. package/assets/templates/helpers/verify-sprint.sh +3 -180
  33. package/assets/templates/plan.template.md +1 -1
  34. package/assets/templates/review.template.md +9 -34
  35. package/assets/workflow-contract.v1.json +10 -19
  36. package/docs/README.md +10 -10
  37. package/docs/architecture/CURRENT.md +170 -0
  38. package/docs/architecture/EVOLUTION.md +42 -0
  39. package/docs/architecture/current/README.md +4 -156
  40. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  41. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  42. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  43. package/docs/architecture/history/README.md +7 -0
  44. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  45. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  46. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  47. package/docs/architecture/history.md +3 -34
  48. package/docs/architecture/index.md +15 -98
  49. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  50. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  51. package/docs/architecture/versions/1.6.md +38 -0
  52. package/docs/architecture/versions/1.7.md +41 -0
  53. package/docs/forge-chatgpt-browser-engine.md +2 -2
  54. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  55. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  56. package/docs/forge-github-issue-launcher.md +1 -1
  57. package/docs/forge-runtime-self-healing-loop.md +1 -1
  58. package/docs/operations/controller-browser-plugin.md +26 -6
  59. package/docs/operations/controller-performance-and-502.md +124 -0
  60. package/docs/operations/controller-reliability-runbook.md +1 -1
  61. package/docs/operations/features.md +2 -2
  62. package/docs/operations/github-repository.md +1 -1
  63. package/docs/operations/homebrew.md +2 -2
  64. package/docs/operations/mcp-tool-exposure.md +5 -3
  65. package/docs/wiki/Architecture.md +6 -6
  66. package/docs/wiki/Implementation.md +2 -2
  67. package/docs/wiki/Integrations.md +2 -2
  68. package/docs/wiki/Work-Lifecycle.md +1 -1
  69. package/package.json +29 -10
  70. package/scripts/activate-source-baseline.ts +17 -13
  71. package/scripts/benchmark-background-check-overlap.ts +228 -0
  72. package/scripts/benchmark-mcp-host.sh +117 -0
  73. package/scripts/benchmark-mcp-transport.ts +170 -0
  74. package/scripts/benchmark-quality-harness.ts +146 -0
  75. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  76. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  77. package/scripts/benchmark-typescript-navigation.ts +186 -0
  78. package/scripts/benchmark-work-efficiency.ts +334 -0
  79. package/scripts/capture-plan.sh +3 -3
  80. package/scripts/check-agent-tooling.sh +8 -35
  81. package/scripts/check-architecture-sync.sh +17 -86
  82. package/scripts/check-mcp-compatibility.ts +14 -0
  83. package/scripts/check-runtime-architecture.mjs +107 -64
  84. package/scripts/check-stable-baseline.ts +92 -0
  85. package/scripts/check-task-workflow.sh +4 -4
  86. package/scripts/contract-worktree.sh +1 -21
  87. package/scripts/ensure-task-workflow.sh +22 -55
  88. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  89. package/scripts/install-standalone-recovery.ts +24 -0
  90. package/scripts/lib/project-init-lib.sh +15 -44
  91. package/scripts/migrate-project-template.sh +23 -1179
  92. package/scripts/new-plan.sh +1 -1
  93. package/scripts/plan-to-todo.sh +11 -36
  94. package/scripts/run-governed-gate.ts +2 -1
  95. package/scripts/ship-worktrees.sh +2 -29
  96. package/scripts/smoke-ios-physical-device.ts +4 -2
  97. package/scripts/smoke-runtime-recovery.ts +1 -35
  98. package/scripts/smoke-schedule-engine.ts +1 -20
  99. package/scripts/verify-contract.sh +1 -111
  100. package/scripts/verify-forge-runtime.sh +0 -1
  101. package/scripts/verify-sprint.sh +3 -180
  102. package/scripts/workflow-contract.ts +1 -5
  103. package/src/cli/commands/init-hook.ts +3 -3
  104. package/src/cli/commands/mcp.ts +9 -5
  105. package/src/cli/commands/plugin.ts +1 -1
  106. package/src/cli/commands/recovery.ts +25 -3
  107. package/src/cli/commands/runtime.ts +55 -3
  108. package/src/cli/commands/security.ts +12 -1
  109. package/src/cli/commands/setup-profile.ts +31 -21
  110. package/src/cli/controller/check-runner.ts +106 -3
  111. package/src/cli/controller/composite-result.ts +1 -1
  112. package/src/cli/controller/context/focus.ts +51 -0
  113. package/src/cli/controller/context/instruction-context.ts +114 -0
  114. package/src/cli/controller/context/known-paths.ts +76 -0
  115. package/src/cli/controller/context/query-planning.ts +110 -0
  116. package/src/cli/controller/context/rule-resolution.ts +532 -0
  117. package/src/cli/controller/context/source-materializer.ts +278 -0
  118. package/src/cli/controller/context/structural.ts +16 -0
  119. package/src/cli/controller/context/types.ts +286 -0
  120. package/src/cli/controller/context-pack.ts +785 -469
  121. package/src/cli/controller/launch-agents.ts +77 -2
  122. package/src/cli/controller/operational-plan.ts +2 -2
  123. package/src/cli/controller/work-mode.ts +6 -4
  124. package/src/cli/editing/edit-session.ts +60 -7
  125. package/src/cli/github/github.ts +133 -0
  126. package/src/cli/installer/managed-entries.ts +15 -1
  127. package/src/cli/local-bridge/console-automations.ts +54 -78
  128. package/src/cli/local-bridge/console-view-models.ts +1 -35
  129. package/src/cli/local-bridge/facade-api.ts +0 -217
  130. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  131. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
  132. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  133. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
  134. package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
  135. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  136. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
  137. package/src/cli/local-bridge/frontend/src/styles.css +1 -1
  138. package/src/cli/local-bridge/frontend/src/types.ts +5 -8
  139. package/src/cli/local-bridge/job-store.ts +1 -490
  140. package/src/cli/local-bridge/server.ts +0 -513
  141. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  142. package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
  143. package/src/cli/mcp/auth.ts +5 -5
  144. package/src/cli/mcp/instructions.ts +3 -2
  145. package/src/cli/mcp/legacy-tool-service.ts +0 -189
  146. package/src/cli/mcp/multi-repository.ts +16 -5
  147. package/src/cli/mcp/oauth.ts +175 -26
  148. package/src/cli/mcp/repository-tools.ts +247 -107
  149. package/src/cli/mcp/server.ts +537 -111
  150. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  151. package/src/cli/mcp/toolset-selection.ts +1 -1
  152. package/src/cli/mcp/toolset.ts +42 -5
  153. package/src/cli/mcp/transports/http.ts +101 -14
  154. package/src/cli/mcp/transports/session-registry.ts +43 -5
  155. package/src/cli/mcp/types.ts +3 -3
  156. package/src/cli/repositories/command-classifier.ts +101 -19
  157. package/src/cli/repositories/command-executor.ts +55 -521
  158. package/src/cli/repositories/command-process.ts +108 -0
  159. package/src/cli/repositories/command-scope.ts +99 -41
  160. package/src/cli/repositories/controller-home.ts +7 -8
  161. package/src/cli/repositories/git-command-executor.ts +2 -0
  162. package/src/cli/repositories/locks.ts +53 -16
  163. package/src/cli/repositories/repository-snapshot.ts +121 -0
  164. package/src/cli/repositories/selected-path-actions.ts +17 -9
  165. package/src/cli/repositories/structured-git.ts +61 -3
  166. package/src/cli/repository/inspector.ts +553 -63
  167. package/src/cli/repository/session-cache.ts +58 -17
  168. package/src/cli/v81-entry.ts +1 -4
  169. package/src/effects/fs-transaction.ts +85 -17
  170. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  171. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  172. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  173. package/src/runtime/context/lsp-client.ts +283 -0
  174. package/src/runtime/context/semantic-navigation.ts +275 -0
  175. package/src/runtime/context/swift-navigation.ts +565 -0
  176. package/src/runtime/context/typescript-navigation.ts +226 -0
  177. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  178. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +47 -8
  179. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  180. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  181. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  182. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  183. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  184. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  185. package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
  186. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +143 -8
  187. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
  188. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +85 -8
  189. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  190. package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
  191. package/src/runtime/control-plane/facade/controller-session-store.ts +132 -1
  192. package/src/runtime/control-plane/facade/goal-workloop-access.ts +2 -0
  193. package/src/runtime/control-plane/facade/goal-workloop.ts +686 -129
  194. package/src/runtime/control-plane/facade/index.ts +1 -0
  195. package/src/runtime/control-plane/facade/plan-contract-store.ts +185 -20
  196. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  197. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  198. package/src/runtime/control-plane/facade/types.ts +22 -5
  199. package/src/runtime/control-plane/facade/work-contract-store.ts +175 -73
  200. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  201. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  202. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  203. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  204. package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
  205. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  206. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  207. package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
  208. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  209. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  210. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  211. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  212. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  213. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  214. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  215. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  216. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  217. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  218. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
  219. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +355 -116
  220. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
  221. package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
  222. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  223. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  224. package/src/runtime/control-plane/release-retention.ts +62 -2
  225. package/src/runtime/control-plane/routing/route-policy.ts +7 -16
  226. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  227. package/src/runtime/diagnostics/mcp-timing.ts +13 -0
  228. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  229. package/src/runtime/diagnostics/performance.ts +24 -1
  230. package/src/runtime/evidence/event-ledger.ts +1 -1
  231. package/src/runtime/execution/jobs/store.ts +58 -4
  232. package/src/runtime/execution/jobs/types.ts +1 -1
  233. package/src/runtime/execution/managed-workspace.ts +203 -1
  234. package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
  235. package/src/runtime/execution/process-runtime/check-result.ts +53 -0
  236. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  237. package/src/runtime/execution/process-runtime/command-facade.ts +345 -40
  238. package/src/runtime/execution/process-runtime/gc.ts +38 -6
  239. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
  240. package/src/runtime/execution/process-runtime/persisted-check.ts +47 -4
  241. package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
  242. package/src/runtime/execution/process-runtime/runtime.ts +43 -3
  243. package/src/runtime/execution/process-runtime/store.ts +1 -0
  244. package/src/runtime/execution/process-runtime/types.ts +2 -0
  245. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  246. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  247. package/src/runtime/execution/workers/executor.ts +0 -48
  248. package/src/runtime/gateway/mcp/execution-tools.ts +1192 -114
  249. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  250. package/src/runtime/gateway/mcp/router.ts +184 -82
  251. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
  252. package/src/runtime/gateway/mcp/runtime-tools.ts +2224 -1589
  253. package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
  254. package/src/runtime/plugins/browser-adapter.ts +2901 -241
  255. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  256. package/src/runtime/plugins/browser-handoff.ts +92 -2
  257. package/src/runtime/plugins/browser-macos-bridge.ts +582 -49
  258. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  259. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  260. package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
  261. package/src/runtime/plugins/browser-runtime.ts +183 -0
  262. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  263. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  264. package/src/runtime/plugins/desktop-operator-registration.ts +8 -2
  265. package/src/runtime/plugins/external-adapter.ts +324 -3
  266. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  267. package/src/runtime/plugins/first-party-registry.ts +2 -0
  268. package/src/runtime/plugins/github-adapter.ts +125 -0
  269. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  270. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  271. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  272. package/src/runtime/plugins/ios-adapter.ts +106 -16
  273. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  274. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  275. package/src/runtime/plugins/lightweight-action.ts +153 -0
  276. package/src/runtime/plugins/local-system-adapter.ts +123 -6
  277. package/src/runtime/plugins/macos-capability-broker.ts +55 -9
  278. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  279. package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
  280. package/src/runtime/plugins/resend-adapter.ts +1 -1
  281. package/src/runtime/plugins/store.ts +269 -29
  282. package/src/runtime/plugins/types.ts +35 -2
  283. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  284. package/src/runtime/projections/git-status-sampler.ts +16 -16
  285. package/src/runtime/projections/materialized-view.ts +28 -10
  286. package/src/runtime/recovery/maintenance-executor.ts +393 -28
  287. package/src/runtime/root/mcp-transport.ts +180 -10
  288. package/src/runtime/root/package-connector-service.ts +186 -8
  289. package/src/runtime/root/package-runtime-release.ts +143 -17
  290. package/src/runtime/root/package-runtime-service.ts +430 -22
  291. package/src/runtime/root/release-manifest.ts +7 -2
  292. package/src/runtime/root/release-materialize.ts +19 -0
  293. package/src/runtime/root/release-store.ts +48 -11
  294. package/src/runtime/root/runtime.ts +23 -5
  295. package/src/runtime/root/service.ts +100 -29
  296. package/src/runtime/root/types.ts +2 -0
  297. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  298. package/src/runtime/shared/trusted-executable.ts +62 -0
  299. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  300. package/src/runtime/standalone-recovery/core.ts +700 -92
  301. package/src/runtime/standalone-recovery/entry.ts +99 -23
  302. package/src/runtime/standalone-recovery/installer.ts +19 -3
  303. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  304. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  305. package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
  306. package/src/runtime/workflow/schedules/engine.ts +287 -151
  307. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  308. package/src/runtime/workflow/schedules/settlement.ts +48 -4
  309. package/src/runtime/workflow/schedules/store.ts +131 -10
  310. package/src/runtime/workflow/schedules/types.ts +2 -4
  311. package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
  312. package/src/testing/test-governance.ts +8 -40
  313. package/assets/reference-configs/heartbeat-triage.md +0 -57
  314. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  315. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  316. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  317. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  318. package/docs/architecture/current/architecture-invariants.md +0 -331
  319. package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
  320. package/docs/architecture/current/codegraph-context-provider.md +0 -238
  321. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  322. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  323. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
  324. package/docs/architecture/current/entity-model.md +0 -612
  325. package/docs/architecture/current/external-plugin-governance.md +0 -396
  326. package/docs/architecture/current/failure-recovery.md +0 -447
  327. package/docs/architecture/current/governance.md +0 -213
  328. package/docs/architecture/current/human-interaction-plane.md +0 -87
  329. package/docs/architecture/current/implementation-status.md +0 -128
  330. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  331. package/docs/architecture/current/legacy-governance.md +0 -58
  332. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  333. package/docs/architecture/current/migration-roadmap.md +0 -105
  334. package/docs/architecture/current/multi-repository-execution.md +0 -371
  335. package/docs/architecture/current/operations-runbook.md +0 -45
  336. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  337. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  338. package/docs/architecture/current/repository-access-modes.md +0 -102
  339. package/docs/architecture/current/route-policy.md +0 -15
  340. package/docs/architecture/current/route-session-concurrency.md +0 -85
  341. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  342. package/docs/architecture/current/runtime-directory-map.md +0 -49
  343. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  344. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  345. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  346. package/docs/architecture/current/system-overview.md +0 -169
  347. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  348. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  349. package/docs/architecture/current/thin-harness-v1.md +0 -321
  350. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  351. package/docs/forge-autonomous-goal-loop.md +0 -9
  352. package/docs/forge-provider-configuration.md +0 -7
  353. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
  354. package/docs/operations/gmail-assistant-routines.md +0 -186
  355. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  356. package/docs/operations/provider-configuration.md +0 -31
  357. package/scripts/harness-trace-grade.sh +0 -150
  358. package/scripts/heartbeat-triage.sh +0 -361
  359. package/scripts/maintenance-triage.sh +0 -167
  360. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  361. package/src/cli/repositories/goal-registry.ts +0 -239
  362. package/src/runtime/assistant/action-proposals.ts +0 -279
  363. package/src/runtime/assistant/intent.ts +0 -395
  364. package/src/runtime/assistant/model-provider.ts +0 -460
  365. package/src/runtime/assistant/openapi.ts +0 -223
  366. package/src/runtime/assistant/policy.ts +0 -89
  367. package/src/runtime/assistant/readiness.ts +0 -258
  368. package/src/runtime/assistant/routine-runtime.ts +0 -477
  369. package/src/runtime/assistant/schedule-binding.ts +0 -171
  370. package/src/runtime/assistant/standing-grants.ts +0 -375
  371. package/src/runtime/assistant/store.ts +0 -243
  372. package/src/runtime/assistant/types.ts +0 -135
  373. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  374. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  375. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  376. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  377. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  378. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  379. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  380. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  381. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  382. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  383. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  384. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  385. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  386. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  387. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  388. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  389. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  390. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  391. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  392. package/src/runtime/workflow/findings/store.ts +0 -204
  393. package/src/runtime/workflow/findings/types.ts +0 -58
  394. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  395. package/src/runtime/workflow/portfolio/store.ts +0 -185
  396. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -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,
@@ -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'],
139
+ description: 'Bounded Accessibility action supported by the trusted Desktop Operator provider; defaults to press when omitted.',
140
+ },
135
141
  },
136
142
  required: ['interaction_id', 'selector'],
137
143
  additionalProperties: false,
@@ -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'] },
@@ -1,9 +1,10 @@
1
+ import { createHash } from 'crypto';
1
2
  import { AssistantPluginError } from './errors';
2
3
  import { getExternalPluginRegistration, listExternalPluginRegistrations, type ExternalPluginRegistration } from './external-registration';
3
4
  import { callExternalUnixSocket, probeExternalUnixSocketSync, type ExternalUnixSocketCallOptions } from './external-unix-socket';
4
5
  import { executeManagedPluginProcess, executeManagedPluginProcessSync, type ManagedPluginProcessSpec } from './managed-process-adapter';
5
- import { restartVerifiedUserLaunchAgent, startVerifiedUserLaunchAgent, stopVerifiedUserLaunchAgent } from './local-system-adapter';
6
- import type { AssistantPluginActionDescriptor, AssistantPluginAdapter, AssistantPluginCapability, AssistantPluginHealth, AssistantPluginManifest, AssistantPluginPermissionScope } from './types';
6
+ import { activateAndVerifyFrontmostApplication, restartVerifiedUserLaunchAgent, startVerifiedUserLaunchAgent, stopVerifiedUserLaunchAgent } from './local-system-adapter';
7
+ import type { AssistantPluginActionDescriptor, AssistantPluginAdapter, AssistantPluginAuthorizationContext, AssistantPluginCapability, AssistantPluginHealth, AssistantPluginManifest, AssistantPluginPermissionScope } from './types';
7
8
 
8
9
  interface ProviderManifest {
9
10
  id: string;
@@ -31,6 +32,7 @@ export interface ExternalPluginAdapterDependencies {
31
32
  startVerifiedUserLaunchAgent?: (label: unknown, expectedProgram: unknown) => Record<string, unknown>;
32
33
  stopVerifiedUserLaunchAgent?: (label: unknown, expectedProgram: unknown) => Record<string, unknown>;
33
34
  restartVerifiedUserLaunchAgent?: (label: unknown, expectedProgram: unknown) => Record<string, unknown>;
35
+ activateAndVerifyFrontmostApplication?: typeof activateAndVerifyFrontmostApplication;
34
36
  now?: () => Date;
35
37
  }
36
38
 
@@ -59,7 +61,10 @@ function parseProviderManifest(value: Record<string, unknown>, registration: Ext
59
61
  if (manifest.protocolVersion !== registration.protocolVersion) throw providerError('EXTERNAL_PLUGIN_PROTOCOL_MISMATCH', `Expected provider protocol ${registration.protocolVersion}, received ${manifest.protocolVersion || 'unknown'}.`);
60
62
  if (manifest.scope !== registration.scope) throw providerError('EXTERNAL_PLUGIN_SCOPE_MISMATCH', `Expected provider scope ${registration.scope}, received ${manifest.scope || 'unknown'}.`);
61
63
  if (manifest.provider !== registration.provider) throw providerError('EXTERNAL_PLUGIN_PROVIDER_MISMATCH', `Expected provider ${registration.provider}, received ${manifest.provider || 'unknown'}.`);
62
- const missingActions = registration.actions.map((action) => action.actionId).filter((actionId) => !manifest.actions.includes(actionId));
64
+ const missingActions = registration.actions
65
+ .map((action) => action.actionId)
66
+ .filter((actionId) => !(registration.pluginId === 'desktop_operator' && ['desktop_pointer_click', 'desktop_foreground_pointer_click'].includes(actionId)))
67
+ .filter((actionId) => !manifest.actions.includes(actionId));
63
68
  if (missingActions.length > 0) throw providerError('EXTERNAL_PLUGIN_ACTION_MISMATCH', `Provider is missing registered actions: ${missingActions.join(', ')}.`);
64
69
  return manifest;
65
70
  }
@@ -189,6 +194,225 @@ async function callProvider(
189
194
  });
190
195
  }
191
196
 
197
+ function externalProviderAuthorizationContext(registration: ExternalPluginRegistration): AssistantPluginAuthorizationContext {
198
+ return {
199
+ target: {
200
+ kind: 'external-provider',
201
+ id: registration.pluginId,
202
+ identityFingerprint: registration.registrationFingerprint,
203
+ },
204
+ expiresInMinutes: 30 * 24 * 60,
205
+ };
206
+ }
207
+
208
+ function desktopApplicationAuthorizationContext(
209
+ registration: ExternalPluginRegistration,
210
+ stableApplicationId: string,
211
+ ): AssistantPluginAuthorizationContext {
212
+ const normalized = stableApplicationId.trim();
213
+ return {
214
+ target: {
215
+ kind: 'desktop-application',
216
+ id: normalized,
217
+ identityFingerprint: createHash('sha256')
218
+ .update(`${registration.registrationFingerprint}\0${normalized}`)
219
+ .digest('hex'),
220
+ },
221
+ expiresInMinutes: 30 * 24 * 60,
222
+ };
223
+ }
224
+
225
+ function recordArray(value: unknown): Record<string, unknown>[] {
226
+ return Array.isArray(value)
227
+ ? value.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry))
228
+ : [];
229
+ }
230
+
231
+ function firstString(record: Record<string, unknown>, ...keys: string[]): string {
232
+ for (const key of keys) {
233
+ const value = record[key];
234
+ if (typeof value === 'string' && value.trim()) return value.trim();
235
+ }
236
+ return '';
237
+ }
238
+
239
+ function firstNumber(record: Record<string, unknown>, ...keys: string[]): number | undefined {
240
+ for (const key of keys) {
241
+ const value = record[key];
242
+ if (typeof value === 'number' && Number.isFinite(value)) return value;
243
+ }
244
+ return undefined;
245
+ }
246
+
247
+ function desktopSession(status: Record<string, unknown>, interactionId: string): Record<string, unknown> | undefined {
248
+ return recordArray(status.sessions).find((session) => firstString(session, 'interactionId', 'interaction_id') === interactionId);
249
+ }
250
+
251
+ function desktopApplicationIsActive(status: Record<string, unknown>, bundleId: string, appName: string): boolean {
252
+ return recordArray(status.applications).some((application) => {
253
+ if (application.active !== true || application.terminated === true) return false;
254
+ const candidateBundleId = firstString(application, 'bundle_id', 'bundleIdentifier');
255
+ const candidateName = firstString(application, 'name', 'appName');
256
+ return bundleId ? candidateBundleId === bundleId : Boolean(appName) && candidateName === appName;
257
+ });
258
+ }
259
+
260
+ async function openVerifiedDesktopSession(
261
+ registration: ExternalPluginRegistration,
262
+ requestId: string,
263
+ args: Record<string, unknown>,
264
+ timeoutMs: number | undefined,
265
+ signal: AbortSignal | undefined,
266
+ dependencies: ExternalPluginAdapterDependencies,
267
+ ): Promise<Record<string, unknown>> {
268
+ const bundleId = typeof args.bundle_id === 'string' ? args.bundle_id.trim() : '';
269
+ const appName = typeof args.app_name === 'string' ? args.app_name.trim() : '';
270
+ if (!bundleId && !appName) {
271
+ throw providerError('DESKTOP_ACTIVATION_TARGET_UNAVAILABLE', 'Activated desktop sessions require an exact bundle id or application name.');
272
+ }
273
+
274
+ let result: Record<string, unknown>;
275
+ let fallbackVerified = false;
276
+ try {
277
+ result = await callProvider(
278
+ registration,
279
+ requestId,
280
+ 'desktop_session_open',
281
+ args,
282
+ timeoutMs,
283
+ signal,
284
+ dependencies,
285
+ );
286
+ } catch (error) {
287
+ if (!(error instanceof AssistantPluginError) || error.code !== 'APP_ACTIVATION_FAILED') throw error;
288
+
289
+ result = await callProvider(
290
+ registration,
291
+ `${requestId}:fallback-session`,
292
+ 'desktop_session_open',
293
+ { ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: false },
294
+ timeoutMs,
295
+ signal,
296
+ dependencies,
297
+ );
298
+
299
+ const activateFallback = dependencies.activateAndVerifyFrontmostApplication ?? activateAndVerifyFrontmostApplication;
300
+ try {
301
+ const fallbackProof = await activateFallback({ bundleId: bundleId || undefined, appName: appName || undefined });
302
+ const proofBundleId = typeof fallbackProof.bundleId === 'string' ? fallbackProof.bundleId.trim() : '';
303
+ const proofAppName = typeof fallbackProof.appName === 'string' ? fallbackProof.appName.trim() : '';
304
+ const proofMatches = bundleId ? proofBundleId === bundleId : proofAppName === appName;
305
+ if (fallbackProof.activated !== true || fallbackProof.verified !== true || !proofMatches) {
306
+ throw new AssistantPluginError(
307
+ 'DESKTOP_ACTIVATION_FALLBACK_IDENTITY_MISMATCH',
308
+ `Forge fallback did not prove the exact requested application ${bundleId || appName} as frontmost.`,
309
+ { retryable: true, details: { target: { bundleId, appName }, observed: { bundleId: proofBundleId, appName: proofAppName } } },
310
+ );
311
+ }
312
+ fallbackVerified = true;
313
+ } catch (fallbackError) {
314
+ if (fallbackError instanceof AssistantPluginError) {
315
+ throw new AssistantPluginError(
316
+ 'DESKTOP_ACTIVATION_FALLBACK_FAILED',
317
+ `Desktop Operator activation failed and Forge could not independently verify ${bundleId || appName} as frontmost.`,
318
+ {
319
+ retryable: fallbackError.retryable,
320
+ details: {
321
+ providerErrorCode: error.code,
322
+ fallbackErrorCode: fallbackError.code,
323
+ fallbackErrorMessage: fallbackError.message,
324
+ target: bundleId || appName,
325
+ },
326
+ },
327
+ );
328
+ }
329
+ throw new AssistantPluginError(
330
+ 'DESKTOP_ACTIVATION_FALLBACK_FAILED',
331
+ `Desktop Operator activation failed and Forge fallback failed for ${bundleId || appName}.`,
332
+ { retryable: true, details: { providerErrorCode: error.code, fallbackErrorMessage: String(fallbackError), target: bundleId || appName } },
333
+ );
334
+ }
335
+ }
336
+
337
+ if (!fallbackVerified) {
338
+ const activeStatus = await callProvider(
339
+ registration,
340
+ `${requestId}:active-status`,
341
+ 'desktop_status',
342
+ { limit: 500 },
343
+ timeoutMs,
344
+ signal,
345
+ dependencies,
346
+ );
347
+ if (!desktopApplicationIsActive(activeStatus, bundleId, appName)) {
348
+ throw providerError('DESKTOP_ACTIVATION_NOT_CONFIRMED', `Desktop Operator did not confirm ${bundleId || appName} as the frontmost application after activation.`, true);
349
+ }
350
+ }
351
+ return result;
352
+ }
353
+
354
+ async function resolveExternalAuthorizationContext(
355
+ registration: ExternalPluginRegistration,
356
+ input: Parameters<NonNullable<AssistantPluginAdapter['resolveAuthorizationContext']>>[0],
357
+ dependencies: ExternalPluginAdapterDependencies,
358
+ ): Promise<AssistantPluginAuthorizationContext | undefined> {
359
+ if (EXTERNAL_PROVIDER_LIFECYCLE_ACTIONS.has(input.actionId)) {
360
+ return externalProviderAuthorizationContext(registration);
361
+ }
362
+ if (registration.pluginId !== 'desktop_operator') return undefined;
363
+ if (input.actionId === 'desktop_permissions_request') {
364
+ return externalProviderAuthorizationContext(registration);
365
+ }
366
+ if (input.actionId === 'desktop_session_open') {
367
+ const bundleId = typeof input.args.bundle_id === 'string' ? input.args.bundle_id.trim() : '';
368
+ return bundleId ? desktopApplicationAuthorizationContext(registration, bundleId) : undefined;
369
+ }
370
+
371
+ const interactionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
372
+ if (!interactionId) return undefined;
373
+
374
+ const providerManifest = await callProvider(
375
+ registration,
376
+ `${input.requestId}:authorization-target:manifest`,
377
+ 'manifest',
378
+ {},
379
+ undefined,
380
+ input.signal,
381
+ dependencies,
382
+ );
383
+ parseProviderManifest(providerManifest, registration);
384
+ const status = await callProvider(
385
+ registration,
386
+ `${input.requestId}:authorization-target:desktop-status`,
387
+ 'desktop_status',
388
+ { limit: 500 },
389
+ input.timeoutMs,
390
+ input.signal,
391
+ dependencies,
392
+ );
393
+ const sessions = Array.isArray(status.sessions) ? status.sessions : [];
394
+ const session = sessions.find((entry) => {
395
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return false;
396
+ const record = entry as Record<string, unknown>;
397
+ const id = typeof record.interactionId === 'string' ? record.interactionId : typeof record.interaction_id === 'string' ? record.interaction_id : '';
398
+ return id === interactionId;
399
+ }) as Record<string, unknown> | undefined;
400
+ if (!session) {
401
+ throw providerError('EXTERNAL_PLUGIN_AUTHORIZATION_TARGET_UNAVAILABLE', `Desktop session ${interactionId} was not found while resolving its stable authorization target.`, false);
402
+ }
403
+ const bundleId = typeof session.bundleIdentifier === 'string' ? session.bundleIdentifier.trim()
404
+ : typeof session.bundle_identifier === 'string' ? session.bundle_identifier.trim()
405
+ : '';
406
+ const appName = typeof session.appName === 'string' ? session.appName.trim()
407
+ : typeof session.app_name === 'string' ? session.app_name.trim()
408
+ : '';
409
+ const stableApplicationId = bundleId || (appName ? `name:${appName.toLowerCase()}` : '');
410
+ if (!stableApplicationId) {
411
+ throw providerError('EXTERNAL_PLUGIN_AUTHORIZATION_TARGET_UNAVAILABLE', `Desktop session ${interactionId} has no stable application identity.`, false);
412
+ }
413
+ return desktopApplicationAuthorizationContext(registration, stableApplicationId);
414
+ }
415
+
192
416
  export function getExternalPluginAdapter(controllerHome: string, pluginId: string): AssistantPluginAdapter | undefined {
193
417
  const registration = getExternalPluginRegistration(controllerHome, pluginId);
194
418
  return registration ? createExternalPluginAdapter(registration) : undefined;
@@ -211,6 +435,7 @@ export function createExternalPluginAdapter(
211
435
  return {
212
436
  pluginId: registration.pluginId,
213
437
  scope: registration.scope,
438
+ resolveAuthorizationContext: (input) => resolveExternalAuthorizationContext(registration, input, dependencies),
214
439
  buildManifest(previousRevision = 0, previousUpdatedAt?: string): AssistantPluginManifest {
215
440
  const checkedAt = now().toISOString();
216
441
  if (!registration.enabled) {
@@ -305,6 +530,102 @@ export function createExternalPluginAdapter(
305
530
  );
306
531
  parseProviderManifest(providerManifest, registration);
307
532
  }
533
+ if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_foreground_pointer_click') {
534
+ const sourceInteractionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
535
+ const requestedWindowId = typeof input.args.window_id === 'number' && Number.isInteger(input.args.window_id) ? input.args.window_id : undefined;
536
+ const x = typeof input.args.x === 'number' && Number.isFinite(input.args.x) ? input.args.x : undefined;
537
+ const y = typeof input.args.y === 'number' && Number.isFinite(input.args.y) ? input.args.y : undefined;
538
+ if (!sourceInteractionId || !requestedWindowId || x === undefined || y === undefined) {
539
+ throw providerError('DESKTOP_FOREGROUND_POINTER_ARGUMENT_INVALID', 'desktop_foreground_pointer_click requires interaction_id, window_id, x, and y.');
540
+ }
541
+
542
+ const sourceStatus = await callProvider(
543
+ registration,
544
+ `${input.requestId}:source-status`,
545
+ 'desktop_status',
546
+ { limit: 500 },
547
+ input.timeoutMs,
548
+ input.signal,
549
+ dependencies,
550
+ );
551
+ const sourceSession = desktopSession(sourceStatus, sourceInteractionId);
552
+ if (!sourceSession) {
553
+ throw providerError('DESKTOP_FOREGROUND_POINTER_SESSION_NOT_FOUND', `Desktop session ${sourceInteractionId} is no longer available.`, true);
554
+ }
555
+ const bundleId = firstString(sourceSession, 'bundleIdentifier', 'bundle_id');
556
+ const appName = firstString(sourceSession, 'appName', 'app_name');
557
+ if (!bundleId && !appName) {
558
+ throw providerError('DESKTOP_FOREGROUND_POINTER_TARGET_UNAVAILABLE', `Desktop session ${sourceInteractionId} has no stable application identity.`);
559
+ }
560
+
561
+ const activation = await openVerifiedDesktopSession(
562
+ registration,
563
+ `${input.requestId}:activate`,
564
+ { ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: true },
565
+ input.timeoutMs,
566
+ input.signal,
567
+ dependencies,
568
+ );
569
+ const activationInteractionId = firstString(activation, 'interactionId', 'interaction_id');
570
+ if (!activationInteractionId) {
571
+ throw providerError('DESKTOP_ACTIVATION_SESSION_MISSING', 'Desktop Operator activated the application without returning a bound interaction session.', true);
572
+ }
573
+
574
+ const screenshot = await callProvider(
575
+ registration,
576
+ `${input.requestId}:screenshot`,
577
+ 'desktop_screenshot',
578
+ {
579
+ interaction_id: activationInteractionId,
580
+ scope: 'window',
581
+ window_id: requestedWindowId,
582
+ ...(typeof input.args.label === 'string' && input.args.label.trim() ? { label: input.args.label.trim() } : {}),
583
+ },
584
+ input.timeoutMs,
585
+ input.signal,
586
+ dependencies,
587
+ );
588
+ const visualRevision = firstNumber(screenshot, 'visual_revision', 'visualRevision');
589
+ const capturedWindowId = firstNumber(screenshot, 'windowId', 'window_id') ?? requestedWindowId;
590
+ if (!visualRevision || !capturedWindowId) {
591
+ throw providerError('DESKTOP_FOREGROUND_CAPTURE_INVALID', 'Desktop Operator did not return a fresh visual revision for the foreground window.', true);
592
+ }
593
+
594
+ const click = await callProvider(
595
+ registration,
596
+ `${input.requestId}:click`,
597
+ 'desktop_pointer_click',
598
+ {
599
+ interaction_id: activationInteractionId,
600
+ window_id: capturedWindowId,
601
+ visual_revision: visualRevision,
602
+ x,
603
+ y,
604
+ },
605
+ input.timeoutMs,
606
+ input.signal,
607
+ dependencies,
608
+ );
609
+ return {
610
+ interactionId: activationInteractionId,
611
+ activationVerified: true,
612
+ windowId: capturedWindowId,
613
+ visualRevision,
614
+ screenshot,
615
+ click,
616
+ };
617
+ }
618
+
619
+ if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_session_open' && input.args.activate === true) {
620
+ return await openVerifiedDesktopSession(
621
+ registration,
622
+ input.requestId,
623
+ input.args,
624
+ input.timeoutMs,
625
+ input.signal,
626
+ dependencies,
627
+ );
628
+ }
308
629
  return await callProvider(
309
630
  registration,
310
631
  input.requestId,
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from 'child_process';
2
2
  import { existsSync } from 'fs';
3
3
  import { createConnection, type Socket } from 'net';
4
- import { dirname, isAbsolute, join } from 'path';
4
+ import { dirname, isAbsolute, join, resolve } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { resolveBunExecutable } from '../shared/process-environment';
7
7
  import { AssistantPluginError } from './errors';
@@ -178,7 +178,13 @@ export async function callExternalUnixSocket(
178
178
  export function resolveExternalPluginProbeSidecarPath(
179
179
  execPath: string = process.execPath,
180
180
  moduleUrl: string = import.meta.url,
181
+ env: NodeJS.ProcessEnv = process.env,
181
182
  ): string {
183
+ const configuredReleaseRoot = env.FORGE_RELEASE_PATH?.trim();
184
+ if (configuredReleaseRoot) {
185
+ const releaseSidecar = join(resolve(configuredReleaseRoot), 'external-unix-socket-probe.cjs');
186
+ if (existsSync(releaseSidecar)) return releaseSidecar;
187
+ }
182
188
  const releaseSibling = join(dirname(execPath), 'external-unix-socket-probe.cjs');
183
189
  if (existsSync(releaseSibling)) return releaseSibling;
184
190
  const moduleSibling = fileURLToPath(new URL('./external-unix-socket-probe.cjs', moduleUrl));
@@ -8,6 +8,7 @@ import { iosPluginAdapter } from './ios-adapter';
8
8
  import { localSystemPluginAdapter } from './local-system-adapter';
9
9
  import { pluginManagementAdapter } from './plugin-management-adapter';
10
10
  import { resendPluginAdapter } from './resend-adapter';
11
+ import { xiaohongshuPluginAdapter } from './xiaohongshu-publish';
11
12
  import type { AssistantPluginAdapter } from './types';
12
13
 
13
14
  const FIRST_PARTY_PLUGIN_ADAPTERS: readonly AssistantPluginAdapter[] = [
@@ -19,6 +20,7 @@ const FIRST_PARTY_PLUGIN_ADAPTERS: readonly AssistantPluginAdapter[] = [
19
20
  googleCalendarPluginAdapter,
20
21
  googleTasksPluginAdapter,
21
22
  resendPluginAdapter,
23
+ xiaohongshuPluginAdapter,
22
24
  localSystemPluginAdapter,
23
25
  pluginManagementAdapter,
24
26
  ];
@@ -7,6 +7,11 @@ import {
7
7
  refreshIssueWithGitHubPlugin,
8
8
  saveGitHubPluginConfig,
9
9
  } from '../../cli/github/plugin';
10
+ import {
11
+ dispatchGitHubWorkflow,
12
+ listGitHubWorkflowRuns,
13
+ listGitHubWorkflows,
14
+ } from '../../cli/github/github';
10
15
  import type {
11
16
  AssistantPluginActionDescriptor,
12
17
  AssistantPluginActionExecutionInput,
@@ -37,6 +42,20 @@ function githubPermissions(ready: boolean, projectConfigured: boolean): Assistan
37
42
  granted: ready && projectConfigured,
38
43
  required: projectConfigured,
39
44
  },
45
+ {
46
+ scope: 'github:actions:read',
47
+ mode: 'read',
48
+ description: 'List GitHub Actions workflows and recent workflow runs.',
49
+ granted: ready,
50
+ required: false,
51
+ },
52
+ {
53
+ scope: 'github:actions:write',
54
+ mode: 'write',
55
+ description: 'Dispatch an explicitly named workflow_dispatch workflow.',
56
+ granted: ready,
57
+ required: false,
58
+ },
40
59
  {
41
60
  scope: 'controller:issues:write',
42
61
  mode: 'write',
@@ -63,6 +82,13 @@ function githubCapabilities(): AssistantPluginCapability[] {
63
82
  scopes: ['github:projects:write'],
64
83
  actions: ['configure', 'publish_issue'],
65
84
  },
85
+ {
86
+ capabilityId: 'actions-ci',
87
+ title: 'GitHub Actions CI',
88
+ description: 'List workflow definitions and runs, and dispatch an explicitly named workflow_dispatch workflow.',
89
+ scopes: ['github:actions:read', 'github:actions:write'],
90
+ actions: ['list_workflows', 'list_workflow_runs', 'dispatch_workflow'],
91
+ },
66
92
  ];
67
93
  }
68
94
 
@@ -144,6 +170,74 @@ function githubActions(): AssistantPluginActionDescriptor[] {
144
170
  additionalProperties: false,
145
171
  },
146
172
  },
173
+ {
174
+ actionId: 'list_workflows',
175
+ title: 'List GitHub Actions workflows',
176
+ description: 'List workflow definitions for the configured GitHub repository.',
177
+ readOnly: true,
178
+ risk: 'readonly',
179
+ confirmation: 'none',
180
+ defaultTimeoutMs: 30_000,
181
+ cancellable: true,
182
+ idempotent: true,
183
+ scopes: ['github:actions:read'],
184
+ resourceClaims: [{ resource: 'remote', mode: 'read' }],
185
+ argumentsSchema: {
186
+ type: 'object',
187
+ properties: {
188
+ limit: { type: 'number', minimum: 1, maximum: 100 },
189
+ include_disabled: { type: 'boolean' },
190
+ },
191
+ additionalProperties: false,
192
+ },
193
+ },
194
+ {
195
+ actionId: 'list_workflow_runs',
196
+ title: 'List GitHub Actions runs',
197
+ description: 'List recent GitHub Actions workflow runs with optional workflow, branch, and status filters.',
198
+ readOnly: true,
199
+ risk: 'readonly',
200
+ confirmation: 'none',
201
+ defaultTimeoutMs: 30_000,
202
+ cancellable: true,
203
+ idempotent: true,
204
+ scopes: ['github:actions:read'],
205
+ resourceClaims: [{ resource: 'remote', mode: 'read' }],
206
+ argumentsSchema: {
207
+ type: 'object',
208
+ properties: {
209
+ workflow: { type: 'string' },
210
+ branch: { type: 'string' },
211
+ status: { type: 'string' },
212
+ limit: { type: 'number', minimum: 1, maximum: 100 },
213
+ include_disabled: { type: 'boolean' },
214
+ },
215
+ additionalProperties: false,
216
+ },
217
+ },
218
+ {
219
+ actionId: 'dispatch_workflow',
220
+ title: 'Dispatch GitHub Actions workflow',
221
+ description: 'Create a workflow_dispatch event for one explicitly named workflow.',
222
+ readOnly: false,
223
+ risk: 'remote_write',
224
+ confirmation: 'authorization',
225
+ defaultTimeoutMs: 60_000,
226
+ cancellable: true,
227
+ idempotent: false,
228
+ scopes: ['github:actions:write'],
229
+ resourceClaims: [{ resource: 'remote', mode: 'exclusive' }],
230
+ argumentsSchema: {
231
+ type: 'object',
232
+ properties: {
233
+ workflow: { type: 'string' },
234
+ ref: { type: 'string' },
235
+ inputs: { type: 'object', additionalProperties: { type: ['string', 'number', 'boolean'] } },
236
+ },
237
+ required: ['workflow'],
238
+ additionalProperties: false,
239
+ },
240
+ },
147
241
  {
148
242
  actionId: 'close_issue',
149
243
  title: 'Close linked GitHub issue',
@@ -252,6 +346,37 @@ export async function executeGitHubPluginAction(input: AssistantPluginActionExec
252
346
  return { issue: publishIssueWithGitHubPlugin(input.repoRoot, String(input.args.issue_id ?? '').trim()) };
253
347
  case 'refresh_issue':
254
348
  return refreshIssueWithGitHubPlugin(input.repoRoot, String(input.args.issue_id ?? '').trim()) as Record<string, unknown>;
349
+ case 'list_workflows': {
350
+ const config = loadGitHubPluginConfig(input.repoRoot);
351
+ return {
352
+ workflows: listGitHubWorkflows(input.repoRoot, config.repository, {
353
+ limit: typeof input.args.limit === 'number' ? input.args.limit : undefined,
354
+ includeDisabled: input.args.include_disabled === true,
355
+ }),
356
+ };
357
+ }
358
+ case 'list_workflow_runs': {
359
+ const config = loadGitHubPluginConfig(input.repoRoot);
360
+ return {
361
+ runs: listGitHubWorkflowRuns(input.repoRoot, config.repository, {
362
+ workflow: typeof input.args.workflow === 'string' ? input.args.workflow : undefined,
363
+ branch: typeof input.args.branch === 'string' ? input.args.branch : undefined,
364
+ status: typeof input.args.status === 'string' ? input.args.status : undefined,
365
+ limit: typeof input.args.limit === 'number' ? input.args.limit : undefined,
366
+ includeDisabled: input.args.include_disabled === true,
367
+ }),
368
+ };
369
+ }
370
+ case 'dispatch_workflow': {
371
+ const config = loadGitHubPluginConfig(input.repoRoot);
372
+ return dispatchGitHubWorkflow(input.repoRoot, config.repository, {
373
+ workflow: String(input.args.workflow ?? ''),
374
+ ref: typeof input.args.ref === 'string' ? input.args.ref : undefined,
375
+ inputs: input.args.inputs && typeof input.args.inputs === 'object' && !Array.isArray(input.args.inputs)
376
+ ? input.args.inputs as Record<string, string | number | boolean>
377
+ : undefined,
378
+ });
379
+ }
255
380
  case 'close_issue':
256
381
  return { issue: closeIssueWithGitHubPlugin(input.repoRoot, String(input.args.issue_id ?? '').trim()) };
257
382
  default:
@@ -14,7 +14,7 @@ export interface AgentDeviceProviderIdentity {
14
14
  export interface AgentDeviceSessionContext {
15
15
  stateDir: string;
16
16
  session: string;
17
- device: string;
17
+ device?: string;
18
18
  platform: 'ios';
19
19
  requestId: string;
20
20
  cwd: string;