@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
@@ -10,7 +10,7 @@ import {
10
10
  persistControllerAccessMode,
11
11
  resolveControllerAccessState,
12
12
  } from '../mcp/access-mode';
13
- import { listControllerChecks, runControllerCheck } from '../controller/check-runner';
13
+ import { listControllerChecks } from '../controller/check-runner';
14
14
  import { createMcpToolContext, type MultiRepositoryMcpToolContext } from '../mcp/multi-repository';
15
15
  import { readSchedulerHealthSnapshot } from '../../runtime/control-plane/global-scheduler/scheduler';
16
16
  import { observeRuntimeStatus } from '../../runtime/root/status';
@@ -27,7 +27,6 @@ import {
27
27
  buildFacadeResult,
28
28
  buildSyncOperationDigest,
29
29
  classifyUserFacingError,
30
- classifyVerificationOutcome,
31
30
  continueGoalWorkloop,
32
31
  delegateToCodexCerebellum,
33
32
  dismissHandoffItem,
@@ -44,7 +43,6 @@ import {
44
43
  stopGoalWorkloop,
45
44
  summarizeHandoffItem,
46
45
  summarizeWorkContract,
47
- verifyGoalWorkloop,
48
46
  type ExecutionModeSelectionInput,
49
47
  type FacadeResult,
50
48
  type HandoffItem,
@@ -80,7 +78,6 @@ import type {
80
78
  CommandCenterViewModel,
81
79
  ConnectorFreshnessViewModel,
82
80
  ConsoleErrorViewModel,
83
- GoalLoopStatusViewModel,
84
81
  HandoffCardViewModel,
85
82
  ModePreviewViewModel,
86
83
  PlainStatusTone,
@@ -94,35 +91,8 @@ import type {
94
91
  VerificationViewModel,
95
92
  WorkSummaryViewModel,
96
93
  } from './console-view-models';
97
- import {
98
- buildAutomationSettingsView,
99
- executorRoutePreviewWithConfig,
100
- executorRoutingConfigGet,
101
- executorRoutingConfigReset,
102
- executorRoutingConfigUpdate,
103
- goalLoopPolicyGet,
104
- goalLoopPolicyUpdate,
105
- goalStatus as goalLoopStatusSnapshot,
106
- localToolDisable,
107
- localToolEnable,
108
- localToolHealthCheck,
109
- localToolList,
110
- localToolConfigGet,
111
- localToolConfigUpdate,
112
- providerApiSettingsGet,
113
- providerApiSettingsUpdate,
114
- providerConfigGet,
115
- providerConfigUpdate,
116
- providerCredentialsStatus,
117
- providerDisable,
118
- providerEnable,
119
- providerHealthCheck,
120
- providerPriorityUpdate,
121
- providerResetDefaults,
122
- type ConfigFacadeContext,
123
- type GoalLoopContext,
124
- } from '../../runtime/control-plane/goal-loop';
125
94
  import { listActiveOccurrences, listSchedules } from '../../runtime/workflow/schedules/store';
95
+ import { executeWorkVerification } from '../../runtime/control-plane/execution/work-verification-service';
126
96
 
127
97
  export type ConsoleFacadeContext = {
128
98
  controllerHome: string;
@@ -995,7 +965,6 @@ export async function buildCommandCenter(
995
965
  const handoffs = listHandoffItems({ ...store(ctx), status: 'pending', limit: 20 }).map(mapHandoffCard);
996
966
  const plugins = listConsolePlugins(ctx);
997
967
  const pluginSummary = buildPluginSummary(plugins);
998
- const goalLoop = buildGoalLoopStatusView(ctx);
999
968
  const access = controllerAccessStateView(ctx);
1000
969
  const banner = readiness.connectorFreshness?.severity === 'warning' || readiness.connectorFreshness?.severity === 'error'
1001
970
  ? readiness.connectorFreshness.summary
@@ -1014,7 +983,6 @@ export async function buildCommandCenter(
1014
983
  currentWork: activeWork[0],
1015
984
  recentWork: allRecent,
1016
985
  handoffs,
1017
- goalLoop,
1018
986
  pluginSummary,
1019
987
  plugins,
1020
988
  modePreviewDefault: plainMode('direct_control'),
@@ -1031,192 +999,6 @@ export async function buildCommandCenter(
1031
999
  };
1032
1000
  }
1033
1001
 
1034
- function configCtx(ctx: ConsoleFacadeContext): ConfigFacadeContext {
1035
- return { controllerHome: ctx.controllerHome };
1036
- }
1037
-
1038
- export function buildGoalLoopStatusView(ctx: ConsoleFacadeContext): GoalLoopStatusViewModel {
1039
- const goalCtx: GoalLoopContext = {
1040
- goalStore: store(ctx),
1041
- packetStore: store(ctx),
1042
- repoId: ctx.repository.repoId,
1043
- configLocation: { controllerHome: ctx.controllerHome },
1044
- providerEnv: { configLocation: { controllerHome: ctx.controllerHome } },
1045
- };
1046
- const snapshot = goalLoopStatusSnapshot(goalCtx) as {
1047
- activeGoals?: Array<Record<string, unknown>>;
1048
- activeCount?: number;
1049
- invokableProviders?: string[];
1050
- handoffOnlyProviders?: string[];
1051
- providers?: Array<Record<string, unknown>>;
1052
- };
1053
- let automationSummary: string | undefined;
1054
- let liveEffective: boolean | undefined;
1055
- try {
1056
- const settings = buildAutomationSettingsView(configCtx(ctx));
1057
- automationSummary = settings.overview.plainLanguageSummary;
1058
- liveEffective = settings.overview.liveModelProvidersEffective;
1059
- } catch {
1060
- automationSummary = undefined;
1061
- }
1062
-
1063
- const goals = (snapshot.activeGoals ?? []).map((goal) => {
1064
- const stage = String(goal.stage ?? '');
1065
- const providerSelected = typeof goal.providerSelected === 'string' ? goal.providerSelected : undefined;
1066
- const waitingReason = typeof goal.waitingReason === 'string' ? goal.waitingReason : undefined;
1067
- const nextSafeAction = typeof goal.nextSafeAction === 'string' ? goal.nextSafeAction : undefined;
1068
- const handoffPacketAvailable = goal.handoffPacketAvailable === true;
1069
- return {
1070
- title: String(goal.title ?? ''),
1071
- stage,
1072
- currentStep: String(goal.currentStep ?? ''),
1073
- providerSelected,
1074
- waitingReason,
1075
- nextSafeAction,
1076
- handoffPacketAvailable,
1077
- approvalRequired: Boolean(waitingReason) || stage === 'waiting_for_user',
1078
- whyThisProvider: providerSelected
1079
- ? `Last selected provider: ${providerSelected}`
1080
- : 'No provider selected yet',
1081
- whatHappensNext: nextSafeAction
1082
- ?? (handoffPacketAvailable
1083
- ? 'Open handoff packet or configure a direct provider'
1084
- : 'Wait for next daemon tick or open Automation Settings'),
1085
- whatIsBlocked: waitingReason
1086
- ?? (stage === 'handoff_ready'
1087
- ? 'Waiting for handoff supervisor (ChatGPT is not auto-invokable)'
1088
- : undefined),
1089
- };
1090
- });
1091
- return {
1092
- activeCount: snapshot.activeCount ?? goals.length,
1093
- goals,
1094
- invokableProviders: snapshot.invokableProviders ?? [],
1095
- handoffOnlyProviders: snapshot.handoffOnlyProviders ?? [],
1096
- providerHealth: (snapshot.providers ?? []).map((provider) => ({
1097
- providerId: String(provider.providerId ?? ''),
1098
- status: String(provider.status ?? ''),
1099
- directDispatchAllowed: provider.directDispatchAllowed === true,
1100
- handoffOnly: provider.handoffOnly === true,
1101
- summary: String(provider.summary ?? ''),
1102
- })),
1103
- automationSummary,
1104
- liveModelProvidersEffective: liveEffective,
1105
- settingsPathHint: 'Model & Tool Providers',
1106
- nextTickHint: 'Daemon ticks active goals about every 5 seconds when the controller is running.',
1107
- };
1108
- }
1109
-
1110
- export function getAutomationSettings(ctx: ConsoleFacadeContext) {
1111
- return buildAutomationSettingsView(configCtx(ctx));
1112
- }
1113
-
1114
- export function consoleProviderConfigGet(ctx: ConsoleFacadeContext) {
1115
- return providerConfigGet(configCtx(ctx));
1116
- }
1117
-
1118
- export function consoleProviderConfigUpdate(ctx: ConsoleFacadeContext, body: Record<string, unknown>) {
1119
- return providerConfigUpdate(configCtx(ctx), body as unknown as Parameters<typeof providerConfigUpdate>[1]);
1120
- }
1121
-
1122
- export function consoleProviderEnable(ctx: ConsoleFacadeContext, providerId: string) {
1123
- return providerEnable(configCtx(ctx), providerId);
1124
- }
1125
-
1126
- export function consoleProviderDisable(ctx: ConsoleFacadeContext, providerId: string) {
1127
- return providerDisable(configCtx(ctx), providerId);
1128
- }
1129
-
1130
- export function consoleProviderPriority(ctx: ConsoleFacadeContext, providerId: string, direction: 'up' | 'down' | number) {
1131
- return providerPriorityUpdate(configCtx(ctx), providerId, direction);
1132
- }
1133
-
1134
- export function consoleProviderHealth(ctx: ConsoleFacadeContext, providerId?: string) {
1135
- return providerHealthCheck(configCtx(ctx), providerId);
1136
- }
1137
-
1138
- export function consoleProviderCredentials(ctx: ConsoleFacadeContext) {
1139
- return providerCredentialsStatus(configCtx(ctx));
1140
- }
1141
-
1142
- export function consoleProviderReset(ctx: ConsoleFacadeContext) {
1143
- return providerResetDefaults(configCtx(ctx));
1144
- }
1145
-
1146
- export function consoleProviderApiSettingsGet(ctx: ConsoleFacadeContext, providerId: string) {
1147
- return providerApiSettingsGet(configCtx(ctx), providerId);
1148
- }
1149
-
1150
- export function consoleProviderApiSettingsUpdate(
1151
- ctx: ConsoleFacadeContext,
1152
- providerId: string,
1153
- body: Record<string, unknown>,
1154
- ) {
1155
- return providerApiSettingsUpdate(configCtx(ctx), providerId, {
1156
- baseUrl: typeof body.baseUrl === 'string' ? body.baseUrl : typeof body.base_url === 'string' ? body.base_url : undefined,
1157
- model: typeof body.model === 'string' ? body.model : undefined,
1158
- apiKey: typeof body.apiKey === 'string'
1159
- ? body.apiKey
1160
- : typeof body.api_key === 'string'
1161
- ? body.api_key
1162
- : undefined,
1163
- clearApiKey: body.clearApiKey === true || body.clear_api_key === true,
1164
- });
1165
- }
1166
-
1167
- export function consoleLocalToolList(ctx: ConsoleFacadeContext) {
1168
- return localToolList(configCtx(ctx));
1169
- }
1170
-
1171
- export function consoleLocalToolEnable(ctx: ConsoleFacadeContext, toolId: string) {
1172
- return localToolEnable(configCtx(ctx), toolId);
1173
- }
1174
-
1175
- export function consoleLocalToolDisable(ctx: ConsoleFacadeContext, toolId: string) {
1176
- return localToolDisable(configCtx(ctx), toolId);
1177
- }
1178
-
1179
- export function consoleLocalToolHealth(ctx: ConsoleFacadeContext, toolId?: string) {
1180
- return localToolHealthCheck(configCtx(ctx), toolId);
1181
- }
1182
-
1183
- export function consoleLocalToolConfigGet(ctx: ConsoleFacadeContext) {
1184
- return localToolConfigGet(configCtx(ctx));
1185
- }
1186
-
1187
- export function consoleLocalToolConfigUpdate(ctx: ConsoleFacadeContext, body: Record<string, unknown>) {
1188
- return localToolConfigUpdate(configCtx(ctx), body as unknown as Parameters<typeof localToolConfigUpdate>[1]);
1189
- }
1190
-
1191
- export function consoleRoutingGet(ctx: ConsoleFacadeContext) {
1192
- return executorRoutingConfigGet(configCtx(ctx));
1193
- }
1194
-
1195
- export function consoleRoutingUpdate(ctx: ConsoleFacadeContext, body: Record<string, unknown>) {
1196
- return executorRoutingConfigUpdate(configCtx(ctx), body as unknown as Parameters<typeof executorRoutingConfigUpdate>[1]);
1197
- }
1198
-
1199
- export function consoleRoutingReset(ctx: ConsoleFacadeContext) {
1200
- return executorRoutingConfigReset(configCtx(ctx));
1201
- }
1202
-
1203
- export function consoleRoutePreview(ctx: ConsoleFacadeContext, body: Record<string, unknown> = {}) {
1204
- return executorRoutePreviewWithConfig(configCtx(ctx), {
1205
- taskIntent: typeof body.taskIntent === 'string' ? body.taskIntent as never : typeof body.task_intent === 'string' ? body.task_intent as never : undefined,
1206
- risk: typeof body.risk === 'string' ? body.risk as never : undefined,
1207
- objective: typeof body.objective === 'string' ? body.objective : undefined,
1208
- externalWrite: body.externalWrite === true || body.external_write === true,
1209
- });
1210
- }
1211
-
1212
- export function consoleGoalLoopPolicyGet(ctx: ConsoleFacadeContext) {
1213
- return goalLoopPolicyGet(configCtx(ctx));
1214
- }
1215
-
1216
- export function consoleGoalLoopPolicyUpdate(ctx: ConsoleFacadeContext, body: Record<string, unknown>) {
1217
- return goalLoopPolicyUpdate(configCtx(ctx), body as unknown as Parameters<typeof goalLoopPolicyUpdate>[1]);
1218
- }
1219
-
1220
1002
  export function getConsoleAccessPolicy(ctx: ConsoleFacadeContext) {
1221
1003
  const policy = readRepositoryAccessPolicy(ctx.controllerHome, ctx.repository.repoId);
1222
1004
  return {
@@ -1259,6 +1041,9 @@ export function startConsoleWork(
1259
1041
  requiresApproval?: boolean;
1260
1042
  destructive?: boolean;
1261
1043
  accessMode?: AccessMode;
1044
+ workspaceMode?: 'current' | 'isolated' | 'auto';
1045
+ requireWorktree?: boolean;
1046
+ directMainProhibited?: boolean;
1262
1047
  approvalConfirmed?: boolean;
1263
1048
  forceMode?: 'direct_control' | 'goal_workloop' | 'handoff_only';
1264
1049
  checkIds?: string[];
@@ -1278,7 +1063,17 @@ export function startConsoleWork(
1278
1063
  allowedPaths: input.allowedPaths,
1279
1064
  forbiddenPaths: input.forbiddenPaths,
1280
1065
  checks: input.checkIds,
1281
- constraints: input.accessMode ? { accessMode: input.accessMode } : undefined,
1066
+ constraints: input.accessMode !== undefined
1067
+ || input.workspaceMode !== undefined
1068
+ || input.requireWorktree !== undefined
1069
+ || input.directMainProhibited !== undefined
1070
+ ? {
1071
+ ...(input.accessMode !== undefined ? { accessMode: input.accessMode } : {}),
1072
+ ...(input.workspaceMode !== undefined ? { workspaceMode: input.workspaceMode } : {}),
1073
+ ...(input.requireWorktree !== undefined ? { requireWorktree: input.requireWorktree } : {}),
1074
+ ...(input.directMainProhibited !== undefined ? { directMainProhibited: input.directMainProhibited } : {}),
1075
+ }
1076
+ : undefined,
1282
1077
  modeInput: {
1283
1078
  objective: input.objective,
1284
1079
  expectedFiles: input.expectedFiles,
@@ -1309,51 +1104,24 @@ export function continueConsoleWork(ctx: ConsoleFacadeContext, workId: string, n
1309
1104
  );
1310
1105
  }
1311
1106
 
1312
- export function verifyConsoleWork(
1107
+ export async function verifyConsoleWork(
1313
1108
  ctx: ConsoleFacadeContext,
1314
1109
  input: { workId: string; checkId?: string; simulate?: boolean; checkFailed?: boolean; infrastructureFailed?: boolean },
1315
- ): FacadeResult {
1316
- const checks = listControllerChecks(ctx.repository.canonicalRoot);
1317
- const workloopCtx = {
1318
- workStore: store(ctx),
1319
- handoffStore: store(ctx),
1320
- repoId: ctx.repository.repoId,
1321
- availableChecks: checks,
1322
- };
1323
- const work = getWorkContract(store(ctx), input.workId);
1324
- const requested = input.checkId || work?.checks[0] || checks[0]?.id || '';
1325
- const classified = classifyVerificationOutcome({ checkId: requested, available: checks });
1326
- if (classified.outcome === 'invalid_check_id') {
1327
- return verifyGoalWorkloop(workloopCtx, { workId: input.workId, checkId: requested });
1328
- }
1329
- if (input.simulate) {
1330
- return verifyGoalWorkloop(workloopCtx, {
1331
- workId: input.workId,
1332
- checkId: classified.normalizedCheckId ?? requested,
1333
- checkFailed: input.checkFailed === true,
1334
- infrastructureFailed: input.infrastructureFailed === true,
1335
- });
1336
- }
1337
- try {
1338
- const executed = runControllerCheck(ctx.repository.canonicalRoot, classified.normalizedCheckId!);
1339
- return verifyGoalWorkloop(workloopCtx, {
1340
- workId: input.workId,
1341
- checkId: classified.normalizedCheckId!,
1342
- infrastructureFailed: executed.timedOut === true,
1343
- checkFailed: !executed.ok && !executed.timedOut,
1344
- });
1345
- } catch (error) {
1346
- const message = error instanceof Error ? error.message : String(error);
1347
- const facade = verifyGoalWorkloop(workloopCtx, {
1348
- workId: input.workId,
1349
- checkId: classified.normalizedCheckId ?? requested,
1350
- infrastructureFailed: true,
1351
- });
1352
- return {
1353
- ...facade,
1354
- warnings: [...facade.warnings, `环境执行检查失败:${message.slice(0, 160)}`],
1355
- };
1356
- }
1110
+ ): Promise<FacadeResult> {
1111
+ const verification = await executeWorkVerification({
1112
+ controllerHome: ctx.controllerHome,
1113
+ repository: ctx.repository,
1114
+ workId: input.workId,
1115
+ checkId: input.checkId,
1116
+ interactiveWaitMs: 0,
1117
+ simulate: input.simulate
1118
+ ? {
1119
+ checkFailed: input.checkFailed === true,
1120
+ infrastructureFailed: input.infrastructureFailed === true,
1121
+ }
1122
+ : undefined,
1123
+ });
1124
+ return verification.facade;
1357
1125
  }
1358
1126
 
1359
1127
  export function finalizeConsoleWork(ctx: ConsoleFacadeContext, workId: string): FacadeResult {
@@ -1493,6 +1261,11 @@ export function approveConsoleHandoff(ctx: ConsoleFacadeContext, handoffId: stri
1493
1261
  requiresApproval: payload.requiresApproval === true,
1494
1262
  destructive: payload.destructive === true,
1495
1263
  accessMode: isAccessMode(payload.accessMode) ? payload.accessMode : undefined,
1264
+ workspaceMode: payload.workspaceMode === 'current' || payload.workspaceMode === 'isolated' || payload.workspaceMode === 'auto'
1265
+ ? payload.workspaceMode
1266
+ : undefined,
1267
+ requireWorktree: typeof payload.requireWorktree === 'boolean' ? payload.requireWorktree : undefined,
1268
+ directMainProhibited: typeof payload.directMainProhibited === 'boolean' ? payload.directMainProhibited : undefined,
1496
1269
  approvalConfirmed: true,
1497
1270
  forceMode: 'goal_workloop',
1498
1271
  checkIds: strings(payload.checkIds),
@@ -1,10 +1,10 @@
1
- import{useCallback,useEffect,useState}from'react';import'./design/tokens.css';import'./styles.css';import type{AutomationView,ConsoleData,LocalToolView,ProviderView,RouteId}from'./types';import{api}from'./lib/api';import{routeFromHash}from'./lib/routes';import{AppShell}from'./shell/AppShell';import{OverviewView}from'./features/overview/OverviewView';import{AutomationsView}from'./features/automations/AutomationsView';import{WorkView}from'./features/work/WorkView';import{CapabilitiesView}from'./features/capabilities/CapabilitiesView';import{RepositoriesView}from'./features/repositories/RepositoriesView';import{SettingsView}from'./features/settings/SettingsView';import{SystemView}from'./features/system/SystemView';
2
- async function loadData():Promise<ConsoleData>{const[commandCenter,work,workPortfolio,automations,automationSettings,connector]=await Promise.all([api.commandCenter(),api.work(),api.workPortfolio(),api.automations(),api.automationSettings(),api.connector().catch(()=>undefined)]);return{commandCenter,work,workPortfolio,automations,automationSettings,connector,generatedAt:new Date().toISOString()}}
1
+ import{useCallback,useEffect,useState}from'react';import'./design/tokens.css';import'./styles.css';import type{AutomationView,ConsoleData,RouteId}from'./types';import{api}from'./lib/api';import{routeFromHash}from'./lib/routes';import{AppShell}from'./shell/AppShell';import{OverviewView}from'./features/overview/OverviewView';import{AutomationsView}from'./features/automations/AutomationsView';import{WorkView}from'./features/work/WorkView';import{CapabilitiesView}from'./features/capabilities/CapabilitiesView';import{RepositoriesView}from'./features/repositories/RepositoriesView';import{SystemView}from'./features/system/SystemView';
2
+ async function loadData():Promise<ConsoleData>{const[commandCenter,work,workPortfolio,automations,connector]=await Promise.all([api.commandCenter(),api.work(),api.workPortfolio(),api.automations(),api.connector().catch(()=>undefined)]);return{commandCenter,work,workPortfolio,automations,connector,generatedAt:new Date().toISOString()}}
3
3
  export default function App(){const[route,setRoute]=useState<RouteId>(routeFromHash());const[data,setData]=useState<ConsoleData>();const[busy,setBusy]=useState(false);const[error,setError]=useState('');
4
4
  const refresh=useCallback(async()=>{setBusy(true);setError('');try{setData(await loadData())}catch(e){setError(e instanceof Error?e.message:String(e))}finally{setBusy(false)}},[]);
5
5
  useEffect(()=>{void refresh();const onHash=()=>setRoute(routeFromHash());addEventListener('hashchange',onHash);return()=>removeEventListener('hashchange',onHash)},[refresh]);
6
6
  const mutate=useCallback(async(fn:()=>Promise<unknown>)=>{setBusy(true);try{await fn();setData(await loadData())}catch(e){setError(e instanceof Error?e.message:String(e))}finally{setBusy(false)}},[]);
7
7
  if(!data)return <div className="boot-state"><span className="brand-mark">F</span><strong>{error?'Forge console unavailable':'Loading Forge…'}</strong>{error&&<><p>{error}</p><button className="button" onClick={()=>void refresh()}>Retry</button></>}</div>;
8
8
  const common={data,busy,onRefresh:()=>void refresh()};let view;
9
- switch(route){case'automations':view=<AutomationsView {...common} onAction={(a:AutomationView,action:'run'|'pause'|'resume')=>mutate(()=>api.automationAction(a.source,a.repoId,a.id,action))}/>;break;case'work':view=<WorkView {...common}/>;break;case'capabilities':view=<CapabilitiesView {...common}/>;break;case'repositories':view=<RepositoriesView {...common} onRegister={(p,n)=>mutate(()=>api.registerRepository(p,n))} onRemove={id=>mutate(()=>api.removeRepository(id))}/>;break;case'settings':view=<SettingsView {...common} onProviderAction={(p:ProviderView,a:'enable'|'disable')=>mutate(()=>api.providerAction(p.providerId,a))} onProviderHealth={(p:ProviderView)=>mutate(()=>api.providerHealth(p.providerId))} onToolAction={(t:LocalToolView,a:'enable'|'disable')=>mutate(()=>api.localToolAction(t.toolId,a))} onToolHealth={(t:LocalToolView)=>mutate(()=>api.localToolHealth(t.toolId))}/>;break;case'system':view=<SystemView {...common}/>;break;default:view=<OverviewView {...common}/>}
9
+ switch(route){case'automations':view=<AutomationsView {...common} onAction={(a:AutomationView,action:'run'|'pause'|'resume')=>mutate(()=>api.automationAction(a.source,a.repoId,a.id,action))}/>;break;case'work':view=<WorkView {...common}/>;break;case'capabilities':view=<CapabilitiesView {...common}/>;break;case'repositories':view=<RepositoriesView {...common} onRegister={(p,n)=>mutate(()=>api.registerRepository(p,n))} onRemove={id=>mutate(()=>api.removeRepository(id))}/>;break;case'system':view=<SystemView {...common}/>;break;default:view=<OverviewView {...common}/>}
10
10
  return <AppShell route={route}>{error&&<div className="global-error"><strong>Last action failed</strong><span>{error}</span><button onClick={()=>setError('')}>×</button></div>}{view}</AppShell>}
@@ -7,12 +7,13 @@ import { StatusText } from '../../components/StatusText';
7
7
  import { Button } from '../../components/Button';
8
8
  import { formatDate, compact } from '../../lib/format';
9
9
 
10
- type Filter = 'enabled' | 'paused' | 'attention' | 'all';
10
+ type Filter = 'enabled' | 'paused' | 'attention' | 'completed' | 'all';
11
11
 
12
12
  function statusLabel(status: AutomationView['status']): string {
13
13
  if (status === 'enabled') return '运行中';
14
14
  if (status === 'paused') return '已暂停';
15
15
  if (status === 'attention') return '需要处理';
16
+ if (status === 'completed') return '已完成';
16
17
  return '已停用';
17
18
  }
18
19
 
@@ -20,6 +21,7 @@ function statusTone(status: AutomationView['status']): string {
20
21
  if (status === 'enabled') return 'success';
21
22
  if (status === 'attention') return 'danger';
22
23
  if (status === 'paused') return 'warning';
24
+ if (status === 'completed') return 'success';
23
25
  return 'neutral';
24
26
  }
25
27
 
@@ -50,10 +52,16 @@ function executionDetails(automation: AutomationView): Array<[string, string]> {
50
52
  if (!automation.agentModel) return [];
51
53
  return [
52
54
  ['执行模型', `${automation.agentModel} · ${reasoningLabel(automation.reasoningLevel)}推理`],
53
- ['浏览器会话', tabPolicyLabel(automation.tabPolicy)],
55
+ ['标签页策略', tabPolicyLabel(automation.tabPolicy)],
54
56
  ];
55
57
  }
56
58
 
59
+ function nextRunLabel(value?: string, completed = false): string {
60
+ if (completed) return '不会再次触发';
61
+ if (!value) return '等待下一次计划';
62
+ return Number.isFinite(Date.parse(value)) ? formatDate(value) : value;
63
+ }
64
+
57
65
  function historyTone(tone: AutomationHistoryView['tone']): string {
58
66
  if (tone === 'green') return 'success';
59
67
  if (tone === 'amber') return 'warning';
@@ -90,24 +98,25 @@ export function AutomationsView({ data, busy, onRefresh, onAction }: {
90
98
  const observation = selected ? observationLabel(selected.observationStatus) : undefined;
91
99
 
92
100
  return <>
93
- <CommandBar eyebrow="AUTOMATION" title="Automations" description="查看长期任务如何触发、当前是否正常,以及每一次实际执行发生了什么。" refreshedAt={data.automations.generatedAt} busy={busy} onRefresh={onRefresh} />
101
+ <CommandBar eyebrow="AUTOMATION" title="自动任务" description="查看哪些任务正在运行、何时再次执行、是否需要处理,以及最近实际发生了什么。" refreshedAt={data.automations.generatedAt} busy={busy} onRefresh={onRefresh} />
94
102
  <div className="toolbar automation-toolbar">
95
103
  <Segmented value={filter} onChange={setFilter} items={[
96
104
  { id: 'enabled', label: '运行中', count: all.filter((item) => item.status === 'enabled').length },
97
105
  { id: 'paused', label: '已暂停', count: all.filter((item) => item.status === 'paused' || item.status === 'disabled').length },
98
106
  { id: 'attention', label: '需要处理', count: all.filter((item) => item.status === 'attention').length },
107
+ { id: 'completed', label: '已完成', count: all.filter((item) => item.status === 'completed').length },
99
108
  { id: 'all', label: '全部', count: all.length },
100
109
  ]} />
101
110
  </div>
102
111
  <div className="split-workspace automation-layout">
103
112
  <div className="table-wrap">
104
113
  <table className="data-table automation-table">
105
- <thead><tr><th>Automation</th><th>触发</th><th>行为</th><th>状态</th><th>最近结果</th></tr></thead>
114
+ <thead><tr><th>自动任务</th><th>触发</th><th>行为</th><th>状态</th><th>最近结果</th></tr></thead>
106
115
  <tbody>{list.map((automation) => <tr key={key(automation)} className={selected && key(selected) === key(automation) ? 'selected' : ''} onClick={() => setSelectedKey(key(automation))}>
107
116
  <td><strong>{automation.name}</strong><small>{automation.repositoryName} · {automation.modeLabel}</small></td>
108
117
  <td><span>{automation.schedule}</span><small>{automation.timezone ?? '本地时区'}</small></td>
109
118
  <td><span>{automation.delivery ?? '本地执行'}</span>{automation.targetLabel && <small>{automation.targetLabel}</small>}</td>
110
- <td><StatusText label={statusLabel(automation.status)} tone={statusTone(automation.status)} />{automation.live !== undefined && <small>{automation.live ? 'Live' : 'Shadow'}</small>}</td>
119
+ <td><StatusText label={statusLabel(automation.status)} tone={statusTone(automation.status)} />{automation.live !== undefined && <small>{automation.live ? '实际执行' : '仅预演'}</small>}</td>
111
120
  <td><span>{compact(automation.lastResult, 26) || '—'}</span><small>{formatDate(automation.lastRunAt)}</small></td>
112
121
  </tr>)}</tbody>
113
122
  </table>
@@ -116,25 +125,26 @@ export function AutomationsView({ data, busy, onRefresh, onAction }: {
116
125
  <DetailPane title={selected?.name} subtitle={selected?.summary} empty="选择一个 Automation 查看配置与执行历史">
117
126
  {selected && <>
118
127
  <div className="automation-detail-status">
119
- <div><span className="eyebrow">CURRENT STATE</span><StatusText label={statusLabel(selected.status)} tone={statusTone(selected.status)} /></div>
128
+ <div><span className="eyebrow">当前状态</span><StatusText label={statusLabel(selected.status)} tone={statusTone(selected.status)} /></div>
120
129
  <div className="automation-result"><strong>{selected.lastResult ?? '尚未执行'}</strong><small>{formatDate(selected.observationAt ?? selected.lastRunAt)}</small></div>
121
130
  </div>
122
131
  <DefinitionList items={[
123
132
  ['类型', selected.modeLabel],
124
133
  ['触发计划', `${selected.schedule}${selected.timezone ? ` · ${selected.timezone}` : ''}`],
125
134
  ['触发后的行为', selected.delivery ?? '本地执行'],
135
+ ['下次执行', nextRunLabel(selected.nextRunHint, selected.status === 'completed')],
126
136
  ['观察目标', selected.targetLabel ?? '—'],
127
137
  ['观察状态', observation ?? '—'],
128
- ['绑定 Work', selected.boundWorkObjective ? compact(selected.boundWorkObjective, 96) : selected.boundWorkId ?? '—'],
129
- ['运行模式', selected.live === undefined ? '—' : selected.live ? 'Live · 会产生实际动作' : 'Shadow · 只记录预演'],
138
+ ['关联工作', selected.boundWorkObjective ? compact(selected.boundWorkObjective, 96) : selected.boundWorkId ?? '—'],
139
+ ['执行方式', selected.live === undefined ? '—' : selected.live ? '实际执行' : '仅预演'],
130
140
  ...executionDetails(selected),
131
- ['运行策略', selected.policySummary ?? '—'],
132
141
  ]} />
133
- {selected.pausedReason && <div className="detail-callout warning"><strong>暂停原因</strong><p>{selected.pausedReason}</p></div>}
134
- <div className="detail-button-row">{selected.actions.map((action) => <Button key={action} disabled={busy} className={action === 'pause' ? 'danger-text' : ''} onClick={() => void onAction(selected, action)}>{action === 'run' ? '立即运行' : action === 'pause' ? '暂停任务' : '开启任务'}</Button>)}</div>
135
- <div className="automation-section-head"><div><span className="eyebrow">EXECUTION HISTORY</span><h3>最近执行</h3></div><span>{selected.history.length} 条</span></div>
142
+ {selected.attentionMessage && <div className="detail-callout danger"><strong>需要处理</strong><p>{selected.attentionMessage}</p></div>}
143
+ {!selected.attentionMessage && selected.pausedReason && <div className={`detail-callout ${selected.status === 'completed' ? 'success' : 'warning'}`}><strong>{selected.status === 'completed' ? '任务已完成' : '暂停原因'}</strong><p>{selected.pausedReason}</p></div>}
144
+ <div className="detail-button-row">{selected.actions.map((action) => <Button key={action} disabled={busy} className={action === 'pause' ? 'danger-text' : ''} onClick={() => void onAction(selected, action)}>{action === 'run' ? '立即运行' : action === 'pause' ? '暂停任务' : '恢复任务'}</Button>)}</div>
145
+ <div className="automation-section-head"><div><span className="eyebrow">执行记录</span><h3>最近执行</h3></div><span>{selected.history.length} 条</span></div>
136
146
  <History items={selected.history} />
137
- <details className="advanced automation-advanced"><summary>技术信息</summary><pre>{JSON.stringify({ scheduleId: selected.source === 'schedule' ? selected.id : undefined, workId: selected.boundWorkId, source: selected.source, next: selected.nextRunHint, failureCount: selected.failureCount }, null, 2)}</pre></details>
147
+ <details className="advanced automation-advanced"><summary>技术信息</summary><pre>{JSON.stringify({ scheduleId: selected.source === 'schedule' ? selected.id : undefined, workId: selected.boundWorkId, source: selected.source, next: selected.nextRunHint, failureCount: selected.failureCount, policy: selected.policySummary }, null, 2)}</pre></details>
138
148
  <p className="detail-note">这里只展示配置、状态与执行摘要;邮件正文、浏览器 Cookie、登录凭据和 continuation prompt 不会复制到控制台。</p>
139
149
  </>}
140
150
  </DetailPane>
@@ -1,4 +1,37 @@
1
- import{useMemo,useState}from'react';import type{ConsoleData,PluginView}from'../../types';import{CommandBar}from'../../shell/CommandBar';import{Segmented}from'../../components/Segmented';import{DetailPane,DefinitionList}from'../../components/DetailPane';import{StatusText}from'../../components/StatusText';import{compact,pretty}from'../../lib/format';
2
- type Filter='all'|'extensions'|'services'|'execution'|'models';
3
- function category(p:PluginView):Exclude<Filter,'all'|'models'>{const s=`${p.name} ${p.provider} ${(p.capabilityLabels??[]).join(' ')}`.toLowerCase();if(/gmail|calendar|github|google task|notion/.test(s))return'services';if(/browser|desktop|ios|repository|codegraph|local/.test(s))return'execution';return'extensions'}
4
- export function CapabilitiesView({data,busy,onRefresh}:{data:ConsoleData;busy:boolean;onRefresh:()=>void}){const plugins=data.commandCenter.plugins??[],providers=data.automationSettings.providers??[];const[filter,setFilter]=useState<Filter>('all');const[selectedId,setSelectedId]=useState<string>();const filtered=useMemo(()=>plugins.filter(p=>filter==='all'||filter==='models'||category(p)===filter),[plugins,filter]);const selected=filtered.find(x=>x.id===selectedId)??filtered[0];return <><CommandBar eyebrow="CAPABILITY CATALOG" title="Capabilities" description="从“Forge 能做什么”查看扩展、服务、执行能力和模型,而不是浏览 MCP tool 清单。" refreshedAt={data.generatedAt} busy={busy} onRefresh={onRefresh}/><div className="toolbar"><Segmented value={filter} onChange={setFilter} items={[{id:'all',label:'All',count:plugins.length},{id:'extensions',label:'Extensions',count:plugins.filter(x=>category(x)==='extensions').length},{id:'services',label:'Services',count:plugins.filter(x=>category(x)==='services').length},{id:'execution',label:'Execution',count:plugins.filter(x=>category(x)==='execution').length},{id:'models',label:'Models',count:providers.length}]}/></div>{filter==='models'?<div className="single-list"><div className="scan-list">{providers.map(p=><div className="scan-row static" key={p.providerId}><div className="scan-main"><strong>{p.displayName}</strong><p>{compact(p.explanation??p.summary,110)}</p></div><StatusText label={p.statusLabel??p.status??'Unknown'} tone={p.status}/></div>)}</div></div>:<div className="split-workspace"><div className="scan-list">{filtered.map(p=><button key={p.id} className={`scan-row ${selected?.id===p.id?'selected':''}`} onClick={()=>setSelectedId(p.id)}><div className="scan-main"><span className="row-eyebrow">{category(p).toUpperCase()}</span><strong>{p.name}</strong><p>{compact(p.description,100)}</p></div><StatusText label={p.statusLabel??p.status??'Unknown'} tone={p.status??p.tone}/></button>)}</div><DetailPane title={selected?.name} subtitle={selected?.description}>{selected&&<><DefinitionList items={[["Status",<StatusText label={selected.statusLabel??selected.status??'Unknown'} tone={selected.status??selected.tone}/>],["Provider",selected.provider??'—'],["Health",selected.healthLabel??'—'],["Lifecycle",selected.lifecycleLabel??'—']]}/>{selected.nextStep&&<div className="detail-callout warning"><strong>Next step</strong><p>{selected.nextStep}</p></div>}{(selected.capabilityLabels??[]).length>0&&<div className="capability-lines">{selected.capabilityLabels!.map(x=><span key={x}>{x}</span>)}</div>}{(selected.warnings??[]).map(w=><div className="detail-callout warning" key={w}>{w}</div>)}<details className="advanced"><summary>Advanced · actions & protocol</summary><pre>{pretty({actions:selected.actions,advanced:selected.advanced})}</pre></details></>}</DetailPane></div>}</>}
1
+ import{useMemo,useState}from'react';
2
+ import type{ConsoleData,PluginView}from'../../types';
3
+ import{CommandBar}from'../../shell/CommandBar';
4
+ import{Segmented}from'../../components/Segmented';
5
+ import{DetailPane,DefinitionList}from'../../components/DetailPane';
6
+ import{StatusText}from'../../components/StatusText';
7
+ import{compact,pretty}from'../../lib/format';
8
+
9
+ type Filter='all'|'extensions'|'services'|'execution';
10
+
11
+ function category(plugin:PluginView):Exclude<Filter,'all'>{
12
+ const text=`${plugin.name} ${plugin.provider} ${(plugin.capabilityLabels??[]).join(' ')}`.toLowerCase();
13
+ if(/gmail|calendar|github|google task|notion/.test(text))return'services';
14
+ if(/browser|desktop|ios|repository|codegraph|local/.test(text))return'execution';
15
+ return'extensions';
16
+ }
17
+
18
+ export function CapabilitiesView({data,busy,onRefresh}:{data:ConsoleData;busy:boolean;onRefresh:()=>void}){
19
+ const plugins=data.commandCenter.plugins??[];
20
+ const[filter,setFilter]=useState<Filter>('all');
21
+ const[selectedId,setSelectedId]=useState<string>();
22
+ const filtered=useMemo(()=>plugins.filter(plugin=>filter==='all'||category(plugin)===filter),[plugins,filter]);
23
+ const selected=filtered.find(plugin=>plugin.id===selectedId)??filtered[0];
24
+ return <>
25
+ <CommandBar eyebrow="CAPABILITY CATALOG" title="Capabilities" description="从“Forge 能做什么”查看扩展、服务与执行能力,而不是浏览 MCP tool 清单。" refreshedAt={data.generatedAt} busy={busy} onRefresh={onRefresh}/>
26
+ <div className="toolbar"><Segmented value={filter} onChange={setFilter} items={[
27
+ {id:'all',label:'All',count:plugins.length},
28
+ {id:'extensions',label:'Extensions',count:plugins.filter(plugin=>category(plugin)==='extensions').length},
29
+ {id:'services',label:'Services',count:plugins.filter(plugin=>category(plugin)==='services').length},
30
+ {id:'execution',label:'Execution',count:plugins.filter(plugin=>category(plugin)==='execution').length},
31
+ ]}/></div>
32
+ <div className="split-workspace">
33
+ <div className="scan-list">{filtered.map(plugin=><button key={plugin.id} className={`scan-row ${selected?.id===plugin.id?'selected':''}`} onClick={()=>setSelectedId(plugin.id)}><div className="scan-main"><span className="row-eyebrow">{category(plugin).toUpperCase()}</span><strong>{plugin.name}</strong><p>{compact(plugin.description,100)}</p></div><StatusText label={plugin.statusLabel??plugin.status??'Unknown'} tone={plugin.status??plugin.tone}/></button>)}</div>
34
+ <DetailPane title={selected?.name} subtitle={selected?.description}>{selected&&<><DefinitionList items={[["Status",<StatusText label={selected.statusLabel??selected.status??'Unknown'} tone={selected.status??selected.tone}/>],["Provider",selected.provider??'—'],["Health",selected.healthLabel??'—'],["Lifecycle",selected.lifecycleLabel??'—']]}/>{selected.nextStep&&<div className="detail-callout warning"><strong>Next step</strong><p>{selected.nextStep}</p></div>}{(selected.capabilityLabels??[]).length>0&&<div className="capability-lines">{selected.capabilityLabels!.map(label=><span key={label}>{label}</span>)}</div>}{(selected.warnings??[]).map(warning=><div className="detail-callout warning" key={warning}>{warning}</div>)}<details className="advanced"><summary>Advanced · actions & protocol</summary><pre>{pretty({actions:selected.actions,advanced:selected.advanced})}</pre></details></>}</DetailPane>
35
+ </div>
36
+ </>;
37
+ }
@@ -88,7 +88,7 @@ export function OverviewView({ data, busy, onRefresh }: { data: ConsoleData; bus
88
88
  key: 'automations',
89
89
  source: 'Automations',
90
90
  title: `${automations.needsAttention} automation${automations.needsAttention === 1 ? '' : 's'} need attention`,
91
- summary: 'Inspect configured routines and schedules.',
91
+ summary: 'Inspect configured schedules.',
92
92
  statusLabel: 'Inspect',
93
93
  tone: 'warning',
94
94
  href: '#/automations',
@@ -117,10 +117,12 @@ export function OverviewView({ data, busy, onRefresh }: { data: ConsoleData; bus
117
117
  ? `${portfolio.summary.open} open · ${portfolio.summary.needsAttention} need attention`
118
118
  : `${portfolio.summary.open} open · no attention needed`;
119
119
  const automationSummary = automations.needsAttention
120
- ? `${automations.enabled} enabled · ${automations.needsAttention} need attention`
120
+ ? `${automations.enabled} 个运行中 · ${automations.needsAttention} 个需要处理`
121
121
  : automations.paused
122
- ? `${automations.enabled} enabled · ${automations.paused} paused`
123
- : `${automations.enabled} enabled · healthy`;
122
+ ? `${automations.enabled} 个运行中 · ${automations.paused} 个已暂停`
123
+ : (automations.completed ?? 0) > 0
124
+ ? `${automations.enabled} 个运行中 · ${automations.completed} 个已完成`
125
+ : `${automations.enabled} 个运行中 · 状态正常`;
124
126
  const capabilitySummary = (plugins.needsAttention ?? 0) > 0
125
127
  ? `${plugins.ready ?? 0} / ${capabilityTotal} ready · ${plugins.needsAttention} need attention`
126
128
  : `${plugins.ready ?? 0} / ${capabilityTotal} ready`;
@@ -1,4 +1,4 @@
1
- import type { AutomationSettingsView, AutomationsResponse, CommandCenterView, Dict, WorkPortfolioResponse, WorkResponse } from '../types';
1
+ import type { AutomationsResponse, CommandCenterView, Dict, WorkPortfolioResponse, WorkResponse } from '../types';
2
2
  export class ApiError extends Error { constructor(message:string, readonly status:number, readonly payload:unknown){super(message);} }
3
3
  const CONSOLE_REQUEST_TIMEOUT_MS=15_000;
4
4
  export async function requestJson<T>(path:string,init:RequestInit={}):Promise<T>{
@@ -22,14 +22,9 @@ export const api={
22
22
  work:()=>requestJson<WorkResponse>('/api/console/requirements'),
23
23
  workPortfolio:()=>requestJson<WorkPortfolioResponse>('/api/console/work-portfolio'),
24
24
  automations:()=>requestJson<AutomationsResponse>('/api/console/automations'),
25
- automationSettings:()=>requestJson<AutomationSettingsView>('/api/console/automation-settings'),
26
25
  connector:()=>requestJson<Dict>('/api/console/connector/status'),
27
26
  advanced:()=>requestJson<Dict>('/api/console/advanced'),
28
27
  automationAction:(source:string,repoId:string,id:string,action:string)=>requestJson<Dict>(`/api/console/automations/${encodeURIComponent(source)}/${encodeURIComponent(repoId)}/${encodeURIComponent(id)}/${encodeURIComponent(action)}`,{method:'POST',body:'{}'}),
29
- providerAction:(id:string,action:'enable'|'disable')=>requestJson<Dict>(`/api/console/providers/${encodeURIComponent(id)}/${action}`,{method:'POST',body:'{}'}),
30
- providerHealth:(id:string)=>requestJson<Dict>('/api/console/providers/health',{method:'POST',body:JSON.stringify({providerId:id})}),
31
- localToolAction:(id:string,action:'enable'|'disable')=>requestJson<Dict>(`/api/console/local-tools/${encodeURIComponent(id)}/${action}`,{method:'POST',body:'{}'}),
32
- localToolHealth:(id:string)=>requestJson<Dict>('/api/console/local-tools/health',{method:'POST',body:JSON.stringify({toolId:id})}),
33
28
  registerRepository:(path:string,displayName?:string)=>requestJson<Dict>('/api/repositories/register',{method:'POST',body:JSON.stringify({path,displayName})}),
34
29
  removeRepository:(id:string)=>requestJson<Dict>(`/api/repositories/${encodeURIComponent(id)}/remove`,{method:'POST',body:'{}'}),
35
30
  };
@@ -1,7 +1,7 @@
1
1
  import type { RouteId } from '../types';
2
2
  export const routes:{id:RouteId;label:string;group:'daily'|'manage'|'system'}[]=[
3
3
  {id:'overview',label:'Overview',group:'daily'}, {id:'automations',label:'Automations',group:'daily'}, {id:'work',label:'Work',group:'daily'},
4
- {id:'capabilities',label:'Capabilities',group:'manage'}, {id:'repositories',label:'Repositories',group:'manage'}, {id:'settings',label:'Settings',group:'manage'},
4
+ {id:'capabilities',label:'Capabilities',group:'manage'}, {id:'repositories',label:'Repositories',group:'manage'},
5
5
  {id:'system',label:'System',group:'system'},
6
6
  ];
7
7
  export function routeFromHash():RouteId{const id=location.hash.replace(/^#\/?/,'').split('/')[0] as RouteId;return routes.some(r=>r.id===id)?id:'overview';}
@@ -1,4 +1,4 @@
1
- import type{ComponentType,SVGProps}from'react';import type{RouteId}from'../types';import{routes}from'../lib/routes';import{AutomationIcon,CapabilityIcon,OverviewIcon,RepoIcon,SettingsIcon,SystemIcon,WorkIcon}from'../design/icons';
2
- const icons:Record<RouteId,ComponentType<SVGProps<SVGSVGElement>>>={overview:OverviewIcon,automations:AutomationIcon,work:WorkIcon,capabilities:CapabilityIcon,repositories:RepoIcon,settings:SettingsIcon,system:SystemIcon};
1
+ import type{ComponentType,SVGProps}from'react';import type{RouteId}from'../types';import{routes}from'../lib/routes';import{AutomationIcon,CapabilityIcon,OverviewIcon,RepoIcon,SystemIcon,WorkIcon}from'../design/icons';
2
+ const icons:Record<RouteId,ComponentType<SVGProps<SVGSVGElement>>>={overview:OverviewIcon,automations:AutomationIcon,work:WorkIcon,capabilities:CapabilityIcon,repositories:RepoIcon,system:SystemIcon};
3
3
  const groupLabels={daily:'Workspace',manage:'Configure',system:'System'} as const;
4
4
  export function Sidebar({route}:{route:RouteId}){let last='';return <aside className="sidebar"><div className="brand"><span className="brand-mark">F</span><div><strong>Forge</strong><small>Utility Console</small></div></div><nav>{routes.map(item=>{const Icon=icons[item.id];const first=item.group!==last;last=item.group;return <div key={item.id} className={first?'nav-group-start':'nav-item'}>{first&&<div className="nav-group-label">{groupLabels[item.group]}</div>}<a href={`#/${item.id}`} className={route===item.id?'active':''}><Icon/><span>{item.label}</span></a></div>})}</nav><div className="sidebar-foot"><span className="pulse-dot"/><span><strong>Runtime connected</strong><small>ChatGPT remains the primary workspace</small></span></div></aside>}