@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
@@ -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,212 @@ 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
+ async function independentlyEnsureExactFrontmostDesktopApplication(
252
+ bundleId: string,
253
+ appName: string,
254
+ dependencies: ExternalPluginAdapterDependencies,
255
+ ): Promise<void> {
256
+ const activateAndVerify = dependencies.activateAndVerifyFrontmostApplication ?? activateAndVerifyFrontmostApplication;
257
+ const proof = await activateAndVerify({ bundleId: bundleId || undefined, appName: appName || undefined });
258
+ const proofBundleId = typeof proof.bundleId === 'string' ? proof.bundleId.trim() : '';
259
+ const proofAppName = typeof proof.appName === 'string' ? proof.appName.trim() : '';
260
+ const proofMatches = bundleId ? proofBundleId === bundleId : proofAppName === appName;
261
+ if (proof.activated !== true || proof.verified !== true || !proofMatches) {
262
+ throw new AssistantPluginError(
263
+ 'DESKTOP_ACTIVATION_FALLBACK_IDENTITY_MISMATCH',
264
+ `Forge did not prove the exact requested application ${bundleId || appName} as frontmost.`,
265
+ { retryable: true, details: { target: { bundleId, appName }, observed: { bundleId: proofBundleId, appName: proofAppName } } },
266
+ );
267
+ }
268
+ }
269
+
270
+ async function openVerifiedDesktopSession(
271
+ registration: ExternalPluginRegistration,
272
+ requestId: string,
273
+ args: Record<string, unknown>,
274
+ timeoutMs: number | undefined,
275
+ signal: AbortSignal | undefined,
276
+ dependencies: ExternalPluginAdapterDependencies,
277
+ ): Promise<Record<string, unknown>> {
278
+ const bundleId = typeof args.bundle_id === 'string' ? args.bundle_id.trim() : '';
279
+ const appName = typeof args.app_name === 'string' ? args.app_name.trim() : '';
280
+ if (!bundleId && !appName) {
281
+ throw providerError('DESKTOP_ACTIVATION_TARGET_UNAVAILABLE', 'Activated desktop sessions require an exact bundle id or application name.');
282
+ }
283
+
284
+ let result: Record<string, unknown>;
285
+ let providerActivationError: AssistantPluginError | undefined;
286
+ try {
287
+ result = await callProvider(
288
+ registration,
289
+ requestId,
290
+ 'desktop_session_open',
291
+ args,
292
+ timeoutMs,
293
+ signal,
294
+ dependencies,
295
+ );
296
+ } catch (error) {
297
+ if (!(error instanceof AssistantPluginError) || error.code !== 'APP_ACTIVATION_FAILED') throw error;
298
+ providerActivationError = error;
299
+ result = await callProvider(
300
+ registration,
301
+ `${requestId}:fallback-session`,
302
+ 'desktop_session_open',
303
+ { ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: false },
304
+ timeoutMs,
305
+ signal,
306
+ dependencies,
307
+ );
308
+ }
309
+
310
+ try {
311
+ await independentlyEnsureExactFrontmostDesktopApplication(bundleId, appName, dependencies);
312
+ } catch (verificationError) {
313
+ const wrappedCode = providerActivationError ? 'DESKTOP_ACTIVATION_FALLBACK_FAILED' : 'DESKTOP_ACTIVATION_NOT_CONFIRMED';
314
+ const wrappedMessage = providerActivationError
315
+ ? `Desktop Operator activation failed and Forge could not independently verify ${bundleId || appName} as frontmost.`
316
+ : `Desktop Operator returned an activated session, but Forge could not independently verify ${bundleId || appName} as frontmost.`;
317
+ if (verificationError instanceof AssistantPluginError) {
318
+ throw new AssistantPluginError(wrappedCode, wrappedMessage, {
319
+ retryable: verificationError.retryable,
320
+ details: {
321
+ ...(providerActivationError ? { providerErrorCode: providerActivationError.code } : {}),
322
+ verificationErrorCode: verificationError.code,
323
+ verificationErrorMessage: verificationError.message,
324
+ target: bundleId || appName,
325
+ },
326
+ });
327
+ }
328
+ throw new AssistantPluginError(wrappedCode, wrappedMessage, {
329
+ retryable: true,
330
+ details: {
331
+ ...(providerActivationError ? { providerErrorCode: providerActivationError.code } : {}),
332
+ verificationErrorMessage: String(verificationError),
333
+ target: bundleId || appName,
334
+ },
335
+ });
336
+ }
337
+
338
+ return result;
339
+ }
340
+
341
+ async function resolveExternalAuthorizationContext(
342
+ registration: ExternalPluginRegistration,
343
+ input: Parameters<NonNullable<AssistantPluginAdapter['resolveAuthorizationContext']>>[0],
344
+ dependencies: ExternalPluginAdapterDependencies,
345
+ ): Promise<AssistantPluginAuthorizationContext | undefined> {
346
+ if (EXTERNAL_PROVIDER_LIFECYCLE_ACTIONS.has(input.actionId)) {
347
+ return externalProviderAuthorizationContext(registration);
348
+ }
349
+ if (registration.pluginId !== 'desktop_operator') return undefined;
350
+ if (input.actionId === 'desktop_permissions_request') {
351
+ return externalProviderAuthorizationContext(registration);
352
+ }
353
+ if (input.actionId === 'desktop_session_open') {
354
+ const bundleId = typeof input.args.bundle_id === 'string' ? input.args.bundle_id.trim() : '';
355
+ return bundleId ? desktopApplicationAuthorizationContext(registration, bundleId) : undefined;
356
+ }
357
+
358
+ const interactionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
359
+ if (!interactionId) return undefined;
360
+
361
+ const providerManifest = await callProvider(
362
+ registration,
363
+ `${input.requestId}:authorization-target:manifest`,
364
+ 'manifest',
365
+ {},
366
+ undefined,
367
+ input.signal,
368
+ dependencies,
369
+ );
370
+ parseProviderManifest(providerManifest, registration);
371
+ const status = await callProvider(
372
+ registration,
373
+ `${input.requestId}:authorization-target:desktop-status`,
374
+ 'desktop_status',
375
+ { limit: 500 },
376
+ input.timeoutMs,
377
+ input.signal,
378
+ dependencies,
379
+ );
380
+ const sessions = Array.isArray(status.sessions) ? status.sessions : [];
381
+ const session = sessions.find((entry) => {
382
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return false;
383
+ const record = entry as Record<string, unknown>;
384
+ const id = typeof record.interactionId === 'string' ? record.interactionId : typeof record.interaction_id === 'string' ? record.interaction_id : '';
385
+ return id === interactionId;
386
+ }) as Record<string, unknown> | undefined;
387
+ if (!session) {
388
+ throw providerError('EXTERNAL_PLUGIN_AUTHORIZATION_TARGET_UNAVAILABLE', `Desktop session ${interactionId} was not found while resolving its stable authorization target.`, false);
389
+ }
390
+ const bundleId = typeof session.bundleIdentifier === 'string' ? session.bundleIdentifier.trim()
391
+ : typeof session.bundle_identifier === 'string' ? session.bundle_identifier.trim()
392
+ : '';
393
+ const appName = typeof session.appName === 'string' ? session.appName.trim()
394
+ : typeof session.app_name === 'string' ? session.app_name.trim()
395
+ : '';
396
+ const stableApplicationId = bundleId || (appName ? `name:${appName.toLowerCase()}` : '');
397
+ if (!stableApplicationId) {
398
+ throw providerError('EXTERNAL_PLUGIN_AUTHORIZATION_TARGET_UNAVAILABLE', `Desktop session ${interactionId} has no stable application identity.`, false);
399
+ }
400
+ return desktopApplicationAuthorizationContext(registration, stableApplicationId);
401
+ }
402
+
192
403
  export function getExternalPluginAdapter(controllerHome: string, pluginId: string): AssistantPluginAdapter | undefined {
193
404
  const registration = getExternalPluginRegistration(controllerHome, pluginId);
194
405
  return registration ? createExternalPluginAdapter(registration) : undefined;
@@ -211,6 +422,7 @@ export function createExternalPluginAdapter(
211
422
  return {
212
423
  pluginId: registration.pluginId,
213
424
  scope: registration.scope,
425
+ resolveAuthorizationContext: (input) => resolveExternalAuthorizationContext(registration, input, dependencies),
214
426
  buildManifest(previousRevision = 0, previousUpdatedAt?: string): AssistantPluginManifest {
215
427
  const checkedAt = now().toISOString();
216
428
  if (!registration.enabled) {
@@ -305,6 +517,149 @@ export function createExternalPluginAdapter(
305
517
  );
306
518
  parseProviderManifest(providerManifest, registration);
307
519
  }
520
+ if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_foreground_pointer_click') {
521
+ const sourceInteractionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
522
+ const requestedWindowId = typeof input.args.window_id === 'number' && Number.isInteger(input.args.window_id) ? input.args.window_id : undefined;
523
+ const x = typeof input.args.x === 'number' && Number.isFinite(input.args.x) ? input.args.x : undefined;
524
+ const y = typeof input.args.y === 'number' && Number.isFinite(input.args.y) ? input.args.y : undefined;
525
+ if (!sourceInteractionId || !requestedWindowId || x === undefined || y === undefined) {
526
+ throw providerError('DESKTOP_FOREGROUND_POINTER_ARGUMENT_INVALID', 'desktop_foreground_pointer_click requires interaction_id, window_id, x, and y.');
527
+ }
528
+
529
+ const sourceStatus = await callProvider(
530
+ registration,
531
+ `${input.requestId}:source-status`,
532
+ 'desktop_status',
533
+ { limit: 500 },
534
+ input.timeoutMs,
535
+ input.signal,
536
+ dependencies,
537
+ );
538
+ const sourceSession = desktopSession(sourceStatus, sourceInteractionId);
539
+ if (!sourceSession) {
540
+ throw providerError('DESKTOP_FOREGROUND_POINTER_SESSION_NOT_FOUND', `Desktop session ${sourceInteractionId} is no longer available.`, true);
541
+ }
542
+ const bundleId = firstString(sourceSession, 'bundleIdentifier', 'bundle_id');
543
+ const appName = firstString(sourceSession, 'appName', 'app_name');
544
+ if (!bundleId && !appName) {
545
+ throw providerError('DESKTOP_FOREGROUND_POINTER_TARGET_UNAVAILABLE', `Desktop session ${sourceInteractionId} has no stable application identity.`);
546
+ }
547
+
548
+ const activation = await openVerifiedDesktopSession(
549
+ registration,
550
+ `${input.requestId}:activate`,
551
+ { ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: true },
552
+ input.timeoutMs,
553
+ input.signal,
554
+ dependencies,
555
+ );
556
+ const activationInteractionId = firstString(activation, 'interactionId', 'interaction_id');
557
+ if (!activationInteractionId) {
558
+ throw providerError('DESKTOP_ACTIVATION_SESSION_MISSING', 'Desktop Operator activated the application without returning a bound interaction session.', true);
559
+ }
560
+
561
+ const screenshot = await callProvider(
562
+ registration,
563
+ `${input.requestId}:screenshot`,
564
+ 'desktop_screenshot',
565
+ {
566
+ interaction_id: activationInteractionId,
567
+ scope: 'window',
568
+ window_id: requestedWindowId,
569
+ ...(typeof input.args.label === 'string' && input.args.label.trim() ? { label: input.args.label.trim() } : {}),
570
+ },
571
+ input.timeoutMs,
572
+ input.signal,
573
+ dependencies,
574
+ );
575
+ const visualRevision = firstNumber(screenshot, 'visual_revision', 'visualRevision');
576
+ const capturedWindowId = firstNumber(screenshot, 'windowId', 'window_id') ?? requestedWindowId;
577
+ if (!visualRevision || !capturedWindowId) {
578
+ throw providerError('DESKTOP_FOREGROUND_CAPTURE_INVALID', 'Desktop Operator did not return a fresh visual revision for the foreground window.', true);
579
+ }
580
+
581
+ const click = await callProvider(
582
+ registration,
583
+ `${input.requestId}:click`,
584
+ 'desktop_pointer_click',
585
+ {
586
+ interaction_id: activationInteractionId,
587
+ window_id: capturedWindowId,
588
+ visual_revision: visualRevision,
589
+ x,
590
+ y,
591
+ },
592
+ input.timeoutMs,
593
+ input.signal,
594
+ dependencies,
595
+ );
596
+ return {
597
+ interactionId: activationInteractionId,
598
+ activationVerified: true,
599
+ windowId: capturedWindowId,
600
+ visualRevision,
601
+ screenshot,
602
+ click,
603
+ };
604
+ }
605
+
606
+ if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_key') {
607
+ const sourceInteractionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
608
+ const keys = Array.isArray(input.args.keys) ? input.args.keys : [];
609
+ if (!sourceInteractionId || keys.length === 0) {
610
+ throw providerError('DESKTOP_FOREGROUND_KEY_ARGUMENT_INVALID', 'desktop_key requires interaction_id and at least one key.');
611
+ }
612
+ const sourceStatus = await callProvider(
613
+ registration,
614
+ `${input.requestId}:source-status`,
615
+ 'desktop_status',
616
+ { limit: 500 },
617
+ input.timeoutMs,
618
+ input.signal,
619
+ dependencies,
620
+ );
621
+ const sourceSession = desktopSession(sourceStatus, sourceInteractionId);
622
+ if (!sourceSession) {
623
+ throw providerError('DESKTOP_FOREGROUND_KEY_SESSION_NOT_FOUND', `Desktop session ${sourceInteractionId} is no longer available.`, true);
624
+ }
625
+ const bundleId = firstString(sourceSession, 'bundleIdentifier', 'bundle_id');
626
+ const appName = firstString(sourceSession, 'appName', 'app_name');
627
+ if (!bundleId && !appName) {
628
+ throw providerError('DESKTOP_FOREGROUND_KEY_TARGET_UNAVAILABLE', `Desktop session ${sourceInteractionId} has no stable application identity.`);
629
+ }
630
+ const activation = await openVerifiedDesktopSession(
631
+ registration,
632
+ `${input.requestId}:activate`,
633
+ { ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: true },
634
+ input.timeoutMs,
635
+ input.signal,
636
+ dependencies,
637
+ );
638
+ const activationInteractionId = firstString(activation, 'interactionId', 'interaction_id');
639
+ if (!activationInteractionId) {
640
+ throw providerError('DESKTOP_ACTIVATION_SESSION_MISSING', 'Desktop Operator activated the application without returning a bound interaction session.', true);
641
+ }
642
+ return await callProvider(
643
+ registration,
644
+ `${input.requestId}:key`,
645
+ 'desktop_key',
646
+ { interaction_id: activationInteractionId, keys },
647
+ input.timeoutMs,
648
+ input.signal,
649
+ dependencies,
650
+ );
651
+ }
652
+
653
+ if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_session_open' && input.args.activate === true) {
654
+ return await openVerifiedDesktopSession(
655
+ registration,
656
+ input.requestId,
657
+ input.args,
658
+ input.timeoutMs,
659
+ input.signal,
660
+ dependencies,
661
+ );
662
+ }
308
663
  return await callProvider(
309
664
  registration,
310
665
  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;