@moretea-labs/forge 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +26 -0
  3. package/CLAUDE.md +2 -0
  4. package/README.md +2 -2
  5. package/README.zh-CN.md +1 -1
  6. package/SKILL.md +2 -2
  7. package/THIRD_PARTY_NOTICES.md +1 -1
  8. package/agents/openai.yaml +1 -1
  9. package/assets/hooks/hook-input.sh +11 -8
  10. package/assets/hooks/lib/session-state.sh +10 -7
  11. package/assets/hooks/lib/workflow-state.sh +13 -177
  12. package/assets/hooks/post-tool-observer.sh +8 -2
  13. package/assets/hooks/prompt-guard.sh +5 -81
  14. package/assets/hooks/session-start-context.sh +56 -1
  15. package/assets/partials/05-workflow.partial.md +1 -1
  16. package/assets/partials-agents/03-orchestration.partial.md +1 -1
  17. package/assets/plugin-registry.v1.json +1 -1
  18. package/assets/reference-configs/document-generation.md +1 -1
  19. package/assets/reference-configs/harness-overview.md +1 -1
  20. package/assets/reference-configs/sprint-contracts.md +3 -3
  21. package/assets/skill-version.json +2 -2
  22. package/assets/templates/contract.template.md +2 -7
  23. package/assets/templates/helpers/capture-plan.sh +2 -2
  24. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  25. package/assets/templates/helpers/contract-worktree.sh +1 -21
  26. package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
  27. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  28. package/assets/templates/helpers/new-plan.sh +1 -1
  29. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  30. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  31. package/assets/templates/helpers/verify-contract.sh +1 -111
  32. package/assets/templates/helpers/verify-sprint.sh +3 -180
  33. package/assets/templates/plan.template.md +1 -1
  34. package/assets/templates/review.template.md +9 -34
  35. package/assets/workflow-contract.v1.json +10 -19
  36. package/docs/README.md +10 -10
  37. package/docs/architecture/CURRENT.md +170 -0
  38. package/docs/architecture/EVOLUTION.md +42 -0
  39. package/docs/architecture/current/README.md +4 -156
  40. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  41. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  42. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  43. package/docs/architecture/history/README.md +7 -0
  44. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  45. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  46. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  47. package/docs/architecture/history.md +3 -34
  48. package/docs/architecture/index.md +15 -98
  49. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  50. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  51. package/docs/architecture/versions/1.6.md +38 -0
  52. package/docs/architecture/versions/1.7.md +41 -0
  53. package/docs/forge-chatgpt-browser-engine.md +2 -2
  54. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  55. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  56. package/docs/forge-github-issue-launcher.md +1 -1
  57. package/docs/forge-runtime-self-healing-loop.md +1 -1
  58. package/docs/operations/controller-browser-plugin.md +26 -6
  59. package/docs/operations/controller-performance-and-502.md +124 -0
  60. package/docs/operations/controller-reliability-runbook.md +1 -1
  61. package/docs/operations/features.md +2 -2
  62. package/docs/operations/github-repository.md +1 -1
  63. package/docs/operations/homebrew.md +2 -2
  64. package/docs/operations/mcp-tool-exposure.md +5 -3
  65. package/docs/wiki/Architecture.md +6 -6
  66. package/docs/wiki/Implementation.md +2 -2
  67. package/docs/wiki/Integrations.md +2 -2
  68. package/docs/wiki/Work-Lifecycle.md +1 -1
  69. package/package.json +29 -10
  70. package/scripts/activate-source-baseline.ts +17 -13
  71. package/scripts/benchmark-background-check-overlap.ts +228 -0
  72. package/scripts/benchmark-mcp-host.sh +117 -0
  73. package/scripts/benchmark-mcp-transport.ts +170 -0
  74. package/scripts/benchmark-quality-harness.ts +146 -0
  75. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  76. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  77. package/scripts/benchmark-typescript-navigation.ts +186 -0
  78. package/scripts/benchmark-work-efficiency.ts +334 -0
  79. package/scripts/capture-plan.sh +3 -3
  80. package/scripts/check-agent-tooling.sh +8 -35
  81. package/scripts/check-architecture-sync.sh +17 -86
  82. package/scripts/check-mcp-compatibility.ts +14 -0
  83. package/scripts/check-runtime-architecture.mjs +107 -64
  84. package/scripts/check-stable-baseline.ts +92 -0
  85. package/scripts/check-task-workflow.sh +4 -4
  86. package/scripts/contract-worktree.sh +1 -21
  87. package/scripts/ensure-task-workflow.sh +22 -55
  88. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  89. package/scripts/install-standalone-recovery.ts +24 -0
  90. package/scripts/lib/project-init-lib.sh +15 -44
  91. package/scripts/migrate-project-template.sh +23 -1179
  92. package/scripts/new-plan.sh +1 -1
  93. package/scripts/plan-to-todo.sh +11 -36
  94. package/scripts/run-governed-gate.ts +2 -1
  95. package/scripts/ship-worktrees.sh +2 -29
  96. package/scripts/smoke-ios-physical-device.ts +4 -2
  97. package/scripts/smoke-runtime-recovery.ts +1 -35
  98. package/scripts/smoke-schedule-engine.ts +1 -20
  99. package/scripts/verify-contract.sh +1 -111
  100. package/scripts/verify-forge-runtime.sh +0 -1
  101. package/scripts/verify-sprint.sh +3 -180
  102. package/scripts/workflow-contract.ts +1 -5
  103. package/src/cli/commands/init-hook.ts +3 -3
  104. package/src/cli/commands/mcp.ts +9 -5
  105. package/src/cli/commands/plugin.ts +1 -1
  106. package/src/cli/commands/recovery.ts +25 -3
  107. package/src/cli/commands/runtime.ts +55 -3
  108. package/src/cli/commands/security.ts +12 -1
  109. package/src/cli/commands/setup-profile.ts +31 -21
  110. package/src/cli/controller/check-runner.ts +106 -3
  111. package/src/cli/controller/composite-result.ts +1 -1
  112. package/src/cli/controller/context/focus.ts +51 -0
  113. package/src/cli/controller/context/instruction-context.ts +114 -0
  114. package/src/cli/controller/context/known-paths.ts +76 -0
  115. package/src/cli/controller/context/query-planning.ts +110 -0
  116. package/src/cli/controller/context/rule-resolution.ts +532 -0
  117. package/src/cli/controller/context/source-materializer.ts +278 -0
  118. package/src/cli/controller/context/structural.ts +16 -0
  119. package/src/cli/controller/context/types.ts +286 -0
  120. package/src/cli/controller/context-pack.ts +785 -469
  121. package/src/cli/controller/launch-agents.ts +77 -2
  122. package/src/cli/controller/operational-plan.ts +2 -2
  123. package/src/cli/controller/work-mode.ts +6 -4
  124. package/src/cli/editing/edit-session.ts +60 -7
  125. package/src/cli/github/github.ts +133 -0
  126. package/src/cli/installer/managed-entries.ts +15 -1
  127. package/src/cli/local-bridge/console-automations.ts +54 -78
  128. package/src/cli/local-bridge/console-view-models.ts +1 -35
  129. package/src/cli/local-bridge/facade-api.ts +0 -217
  130. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  131. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
  132. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  133. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
  134. package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
  135. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  136. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
  137. package/src/cli/local-bridge/frontend/src/styles.css +1 -1
  138. package/src/cli/local-bridge/frontend/src/types.ts +5 -8
  139. package/src/cli/local-bridge/job-store.ts +1 -490
  140. package/src/cli/local-bridge/server.ts +0 -513
  141. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  142. package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
  143. package/src/cli/mcp/auth.ts +5 -5
  144. package/src/cli/mcp/instructions.ts +3 -2
  145. package/src/cli/mcp/legacy-tool-service.ts +0 -189
  146. package/src/cli/mcp/multi-repository.ts +16 -5
  147. package/src/cli/mcp/oauth.ts +175 -26
  148. package/src/cli/mcp/repository-tools.ts +247 -107
  149. package/src/cli/mcp/server.ts +537 -111
  150. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  151. package/src/cli/mcp/toolset-selection.ts +1 -1
  152. package/src/cli/mcp/toolset.ts +42 -5
  153. package/src/cli/mcp/transports/http.ts +101 -14
  154. package/src/cli/mcp/transports/session-registry.ts +43 -5
  155. package/src/cli/mcp/types.ts +3 -3
  156. package/src/cli/repositories/command-classifier.ts +101 -19
  157. package/src/cli/repositories/command-executor.ts +55 -521
  158. package/src/cli/repositories/command-process.ts +108 -0
  159. package/src/cli/repositories/command-scope.ts +99 -41
  160. package/src/cli/repositories/controller-home.ts +7 -8
  161. package/src/cli/repositories/git-command-executor.ts +2 -0
  162. package/src/cli/repositories/locks.ts +53 -16
  163. package/src/cli/repositories/repository-snapshot.ts +121 -0
  164. package/src/cli/repositories/selected-path-actions.ts +17 -9
  165. package/src/cli/repositories/structured-git.ts +61 -3
  166. package/src/cli/repository/inspector.ts +553 -63
  167. package/src/cli/repository/session-cache.ts +58 -17
  168. package/src/cli/v81-entry.ts +1 -4
  169. package/src/effects/fs-transaction.ts +85 -17
  170. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  171. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  172. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  173. package/src/runtime/context/lsp-client.ts +283 -0
  174. package/src/runtime/context/semantic-navigation.ts +275 -0
  175. package/src/runtime/context/swift-navigation.ts +565 -0
  176. package/src/runtime/context/typescript-navigation.ts +226 -0
  177. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  178. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +47 -8
  179. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  180. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  181. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  182. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  183. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  184. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  185. package/src/runtime/control-plane/execution/work-task-receipt.ts +54 -11
  186. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +143 -8
  187. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
  188. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +85 -8
  189. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  190. package/src/runtime/control-plane/facade/controller-round-relay.ts +991 -0
  191. package/src/runtime/control-plane/facade/controller-session-store.ts +132 -1
  192. package/src/runtime/control-plane/facade/goal-workloop-access.ts +2 -0
  193. package/src/runtime/control-plane/facade/goal-workloop.ts +686 -129
  194. package/src/runtime/control-plane/facade/index.ts +1 -0
  195. package/src/runtime/control-plane/facade/plan-contract-store.ts +185 -20
  196. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  197. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  198. package/src/runtime/control-plane/facade/types.ts +22 -5
  199. package/src/runtime/control-plane/facade/work-contract-store.ts +175 -73
  200. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  201. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  202. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  203. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  204. package/src/runtime/control-plane/global-scheduler/maintenance.ts +145 -0
  205. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  206. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  207. package/src/runtime/control-plane/global-scheduler/scheduler.ts +273 -542
  208. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  209. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  210. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  211. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  212. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  213. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  214. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  215. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  216. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  217. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  218. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +50 -0
  219. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +355 -116
  220. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +40 -0
  221. package/src/runtime/control-plane/launcher/thin-launcher.ts +194 -10
  222. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  223. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  224. package/src/runtime/control-plane/release-retention.ts +62 -2
  225. package/src/runtime/control-plane/routing/route-policy.ts +7 -16
  226. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  227. package/src/runtime/diagnostics/mcp-timing.ts +13 -0
  228. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  229. package/src/runtime/diagnostics/performance.ts +24 -1
  230. package/src/runtime/evidence/event-ledger.ts +1 -1
  231. package/src/runtime/execution/jobs/store.ts +58 -4
  232. package/src/runtime/execution/jobs/types.ts +1 -1
  233. package/src/runtime/execution/managed-workspace.ts +203 -1
  234. package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
  235. package/src/runtime/execution/process-runtime/check-result.ts +53 -0
  236. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  237. package/src/runtime/execution/process-runtime/command-facade.ts +345 -40
  238. package/src/runtime/execution/process-runtime/gc.ts +38 -6
  239. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1184 -0
  240. package/src/runtime/execution/process-runtime/persisted-check.ts +47 -4
  241. package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
  242. package/src/runtime/execution/process-runtime/runtime.ts +43 -3
  243. package/src/runtime/execution/process-runtime/store.ts +1 -0
  244. package/src/runtime/execution/process-runtime/types.ts +2 -0
  245. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  246. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  247. package/src/runtime/execution/workers/executor.ts +0 -48
  248. package/src/runtime/gateway/mcp/execution-tools.ts +1192 -114
  249. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  250. package/src/runtime/gateway/mcp/router.ts +184 -82
  251. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +546 -0
  252. package/src/runtime/gateway/mcp/runtime-tools.ts +2224 -1589
  253. package/src/runtime/plugins/app-store-connect-adapter.ts +123 -19
  254. package/src/runtime/plugins/browser-adapter.ts +2901 -241
  255. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  256. package/src/runtime/plugins/browser-handoff.ts +92 -2
  257. package/src/runtime/plugins/browser-macos-bridge.ts +582 -49
  258. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  259. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  260. package/src/runtime/plugins/browser-runtime-contract.ts +152 -0
  261. package/src/runtime/plugins/browser-runtime.ts +183 -0
  262. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  263. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  264. package/src/runtime/plugins/desktop-operator-registration.ts +8 -2
  265. package/src/runtime/plugins/external-adapter.ts +324 -3
  266. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  267. package/src/runtime/plugins/first-party-registry.ts +2 -0
  268. package/src/runtime/plugins/github-adapter.ts +125 -0
  269. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  270. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  271. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  272. package/src/runtime/plugins/ios-adapter.ts +106 -16
  273. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  274. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  275. package/src/runtime/plugins/lightweight-action.ts +153 -0
  276. package/src/runtime/plugins/local-system-adapter.ts +123 -6
  277. package/src/runtime/plugins/macos-capability-broker.ts +55 -9
  278. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  279. package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
  280. package/src/runtime/plugins/resend-adapter.ts +1 -1
  281. package/src/runtime/plugins/store.ts +269 -29
  282. package/src/runtime/plugins/types.ts +35 -2
  283. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  284. package/src/runtime/projections/git-status-sampler.ts +16 -16
  285. package/src/runtime/projections/materialized-view.ts +28 -10
  286. package/src/runtime/recovery/maintenance-executor.ts +393 -28
  287. package/src/runtime/root/mcp-transport.ts +180 -10
  288. package/src/runtime/root/package-connector-service.ts +186 -8
  289. package/src/runtime/root/package-runtime-release.ts +143 -17
  290. package/src/runtime/root/package-runtime-service.ts +430 -22
  291. package/src/runtime/root/release-manifest.ts +7 -2
  292. package/src/runtime/root/release-materialize.ts +19 -0
  293. package/src/runtime/root/release-store.ts +48 -11
  294. package/src/runtime/root/runtime.ts +23 -5
  295. package/src/runtime/root/service.ts +100 -29
  296. package/src/runtime/root/types.ts +2 -0
  297. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  298. package/src/runtime/shared/trusted-executable.ts +62 -0
  299. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  300. package/src/runtime/standalone-recovery/core.ts +700 -92
  301. package/src/runtime/standalone-recovery/entry.ts +99 -23
  302. package/src/runtime/standalone-recovery/installer.ts +19 -3
  303. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  304. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  305. package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
  306. package/src/runtime/workflow/schedules/engine.ts +287 -151
  307. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  308. package/src/runtime/workflow/schedules/settlement.ts +48 -4
  309. package/src/runtime/workflow/schedules/store.ts +131 -10
  310. package/src/runtime/workflow/schedules/types.ts +2 -4
  311. package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
  312. package/src/testing/test-governance.ts +8 -40
  313. package/assets/reference-configs/heartbeat-triage.md +0 -57
  314. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  315. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  316. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  317. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  318. package/docs/architecture/current/architecture-invariants.md +0 -331
  319. package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
  320. package/docs/architecture/current/codegraph-context-provider.md +0 -238
  321. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  322. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  323. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
  324. package/docs/architecture/current/entity-model.md +0 -612
  325. package/docs/architecture/current/external-plugin-governance.md +0 -396
  326. package/docs/architecture/current/failure-recovery.md +0 -447
  327. package/docs/architecture/current/governance.md +0 -213
  328. package/docs/architecture/current/human-interaction-plane.md +0 -87
  329. package/docs/architecture/current/implementation-status.md +0 -128
  330. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  331. package/docs/architecture/current/legacy-governance.md +0 -58
  332. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  333. package/docs/architecture/current/migration-roadmap.md +0 -105
  334. package/docs/architecture/current/multi-repository-execution.md +0 -371
  335. package/docs/architecture/current/operations-runbook.md +0 -45
  336. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  337. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  338. package/docs/architecture/current/repository-access-modes.md +0 -102
  339. package/docs/architecture/current/route-policy.md +0 -15
  340. package/docs/architecture/current/route-session-concurrency.md +0 -85
  341. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  342. package/docs/architecture/current/runtime-directory-map.md +0 -49
  343. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  344. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  345. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  346. package/docs/architecture/current/system-overview.md +0 -169
  347. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  348. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  349. package/docs/architecture/current/thin-harness-v1.md +0 -321
  350. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  351. package/docs/forge-autonomous-goal-loop.md +0 -9
  352. package/docs/forge-provider-configuration.md +0 -7
  353. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
  354. package/docs/operations/gmail-assistant-routines.md +0 -186
  355. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  356. package/docs/operations/provider-configuration.md +0 -31
  357. package/scripts/harness-trace-grade.sh +0 -150
  358. package/scripts/heartbeat-triage.sh +0 -361
  359. package/scripts/maintenance-triage.sh +0 -167
  360. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  361. package/src/cli/repositories/goal-registry.ts +0 -239
  362. package/src/runtime/assistant/action-proposals.ts +0 -279
  363. package/src/runtime/assistant/intent.ts +0 -395
  364. package/src/runtime/assistant/model-provider.ts +0 -460
  365. package/src/runtime/assistant/openapi.ts +0 -223
  366. package/src/runtime/assistant/policy.ts +0 -89
  367. package/src/runtime/assistant/readiness.ts +0 -258
  368. package/src/runtime/assistant/routine-runtime.ts +0 -477
  369. package/src/runtime/assistant/schedule-binding.ts +0 -171
  370. package/src/runtime/assistant/standing-grants.ts +0 -375
  371. package/src/runtime/assistant/store.ts +0 -243
  372. package/src/runtime/assistant/types.ts +0 -135
  373. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  374. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  375. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  376. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  377. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  378. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  379. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  380. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  381. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  382. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  383. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  384. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  385. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  386. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  387. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  388. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  389. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  390. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  391. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  392. package/src/runtime/workflow/findings/store.ts +0 -204
  393. package/src/runtime/workflow/findings/types.ts +0 -58
  394. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  395. package/src/runtime/workflow/portfolio/store.ts +0 -185
  396. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -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>}
@@ -5,7 +5,7 @@
5
5
  .overview-hero{margin-top:10px;min-height:190px;display:grid;grid-template-columns:minmax(0,1.7fr) minmax(300px,.8fr);gap:26px;align-items:stretch;padding:28px 30px;border-radius:var(--r-lg);background:linear-gradient(135deg,var(--accent-soft),#FCFCFB 60%,#F1F1EE);box-shadow:inset 0 0 0 1px rgba(94,84,232,.09)}.overview-posture{align-self:center;max-width:760px}.overview-posture-title{display:flex;align-items:center;gap:14px;margin-top:7px}.overview-posture h2{font-size:25px;line-height:1.18;letter-spacing:-.03em;margin:0;font-weight:670}.overview-posture p{margin:10px 0 0;color:var(--muted);font-size:13px;line-height:1.6}.overview-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;align-self:stretch}.overview-action{min-width:0;border-radius:11px;background:rgba(255,255,255,.68);padding:17px;display:flex;flex-direction:column;justify-content:flex-end;box-shadow:inset 0 0 0 1px rgba(34,34,39,.06)}a.overview-action:hover{background:#FFF;box-shadow:inset 0 0 0 1px rgba(34,34,39,.08);transform:translateY(-1px)}.overview-action.primary{background:var(--ink);color:white;box-shadow:none}.overview-action.primary:hover{background:#2B2B30}.overview-action.calm{background:rgba(255,255,255,.5)}.overview-action span{font-size:10px;color:var(--faint)}.overview-action.primary span,.overview-action.primary small{color:#B9B9C0}.overview-action strong{font-size:28px;line-height:1;margin-top:10px;letter-spacing:-.04em}.overview-action small{font-size:10px;color:var(--muted);margin-top:8px}.signal-strip{margin-top:18px;display:grid;grid-template-columns:repeat(4,1fr);gap:4px;padding:0 4px}.signal-strip a{padding:14px 16px;border-radius:9px;min-width:0;position:relative}.signal-strip a:not(:last-child):after{content:"";position:absolute;right:-2px;top:17px;bottom:17px;width:1px;background:var(--border)}.signal-strip a:hover{background:rgba(255,255,255,.72)}.signal-strip span{display:block;color:var(--muted);font-size:10px}.signal-strip strong{display:block;font-size:19px;letter-spacing:-.02em;margin-top:5px;text-transform:capitalize}.signal-strip strong i{font-style:normal;font-size:12px;color:var(--faint);font-weight:550}.signal-strip small{display:block;color:var(--faint);font-size:10px;margin-top:3px}.page-section{margin-top:34px}.section-header{height:32px;display:flex;align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--border)}.section-header>div:first-child{display:flex;align-items:baseline;gap:10px}.section-header h2{font-size:15px;margin:0;font-weight:650}.section-header span{font-size:11px;color:var(--faint)}
6
6
  .attention-list,.compact-work-list{border-bottom:1px solid var(--border)}.attention-section .attention-list{margin-top:4px}.attention-row{display:grid;grid-template-columns:42px minmax(0,1fr) auto;align-items:center;gap:12px;min-height:66px;padding:10px 8px;border-bottom:1px solid var(--border);border-radius:8px}.attention-row:hover{background:rgba(255,255,255,.7)}.attention-row:last-child{border-bottom:0}.attention-index{font-family:var(--font-mono);font-size:10px;color:var(--faint)}.attention-row strong,.compact-work-list strong{font-size:13px}.attention-row p,.compact-work-list p{margin:3px 0 0;color:var(--muted);font-size:12px}.compact-work-list a>div{min-width:0}.compact-work-list p{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-work-list a{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:16px;align-items:center;min-height:54px;padding:8px 4px;border-bottom:1px solid var(--border)}.compact-work-list a:last-child{border-bottom:0}.compact-work-list a:hover strong{color:var(--accent)}.quiet-empty{padding:30px 8px;color:var(--muted)}.success-empty{padding:24px 8px;border-radius:10px;background:linear-gradient(90deg,var(--success-soft),transparent 72%)}.quiet-empty p{margin:6px 0 0}.status-text{display:inline-flex;align-items:center;gap:7px;white-space:nowrap;font-size:11px;color:var(--muted)}.status-dot{width:7px;height:7px;border-radius:50%;background:var(--faint)}.status-dot.success{background:var(--success)}.status-dot.warning{background:var(--warning)}.status-dot.danger{background:var(--danger)}.status-dot.info{background:var(--info)}
7
7
  .toolbar{min-height:58px;display:flex;align-items:center;border-bottom:1px solid var(--border);position:sticky;top:0;z-index:4;background:rgba(245,245,243,.92);backdrop-filter:blur(12px)}.work-toolbar{justify-content:space-between;gap:18px}.repository-filter{display:flex;align-items:center;gap:8px;color:var(--faint);font-size:10px}.repository-filter select{height:30px;max-width:220px;border:1px solid var(--border-strong);border-radius:var(--r-sm);background:var(--surface);color:var(--ink);padding:0 28px 0 9px;font:inherit}.work-row .row-eyebrow{color:var(--accent);letter-spacing:.06em;text-transform:none}.segmented{display:inline-flex;padding:2px;background:var(--surface-strong);border-radius:7px;gap:1px}.segmented button{border:0;background:transparent;color:var(--muted);border-radius:5px;height:28px;padding:0 9px;cursor:pointer;font-size:11px}.segmented button.selected{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.05)}.segmented button span{margin-left:5px;color:var(--faint);font-size:10px}.split-workspace{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(310px,.85fr);gap:22px;min-height:520px;padding-top:16px}.automation-layout{grid-template-columns:minmax(0,2.1fr) minmax(320px,.9fr)}.scan-list{min-width:0}.scan-row{width:100%;min-height:68px;border:0;border-bottom:1px solid var(--border);border-radius:9px;background:transparent;text-align:left;padding:11px 12px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:18px;align-items:center;cursor:pointer;color:var(--ink)}.scan-row.static{cursor:default}.scan-row:hover{background:rgba(255,255,255,.72)}.scan-row.selected{background:var(--accent-soft);box-shadow:inset 0 0 0 1px rgba(94,84,232,.12)}.scan-main{min-width:0}.scan-main strong{display:block;font-size:13px;font-weight:620;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.scan-main p{margin:4px 0 0;color:var(--muted);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row-eyebrow{display:block;margin-bottom:3px}.scan-meta{text-align:right;display:grid;justify-items:end;gap:5px;color:var(--faint);font-size:10px}
8
- .detail-pane{border:1px solid var(--border);border-radius:12px;background:var(--surface);min-width:0;align-self:start;position:sticky;top:18px;overflow:hidden}.detail-head{padding:19px 20px 16px;border-bottom:1px solid var(--border);display:flex;gap:12px;justify-content:space-between}.detail-head h2{font-size:16px;margin:4px 0 5px;line-height:1.3}.detail-head p{margin:0;color:var(--muted);font-size:12px;line-height:1.5}.detail-body{padding:18px}.detail-empty{display:grid;place-items:center;min-height:260px;color:var(--faint);font-size:12px}.definition-list{margin:0}.definition-list>div{display:grid;grid-template-columns:100px minmax(0,1fr);gap:10px;padding:8px 0;border-bottom:1px solid var(--border)}.definition-list dt{color:var(--faint);font-size:11px}.definition-list dd{margin:0;min-width:0;overflow-wrap:anywhere}.definition-list code{font-size:10px;color:var(--muted)}.detail-callout{margin-top:16px;border-left:2px solid var(--warning);padding:4px 0 4px 12px}.detail-callout.danger{border-color:var(--danger)}.detail-callout p{margin:5px 0 0;color:var(--muted);line-height:1.5}.detail-note{margin-top:18px;color:var(--faint);font-size:11px;line-height:1.55}.detail-button-row{display:flex;gap:7px;margin-top:18px;flex-wrap:wrap}.danger-text{color:var(--danger)}
8
+ .detail-pane{border:1px solid var(--border);border-radius:12px;background:var(--surface);min-width:0;align-self:start;position:sticky;top:18px;overflow:hidden}.detail-head{padding:19px 20px 16px;border-bottom:1px solid var(--border);display:flex;gap:12px;justify-content:space-between}.detail-head h2{font-size:16px;margin:4px 0 5px;line-height:1.3}.detail-head p{margin:0;color:var(--muted);font-size:12px;line-height:1.5}.detail-body{padding:18px}.detail-empty{display:grid;place-items:center;min-height:260px;color:var(--faint);font-size:12px}.definition-list{margin:0}.definition-list>div{display:grid;grid-template-columns:100px minmax(0,1fr);gap:10px;padding:8px 0;border-bottom:1px solid var(--border)}.definition-list dt{color:var(--faint);font-size:11px}.definition-list dd{margin:0;min-width:0;overflow-wrap:anywhere}.definition-list code{font-size:10px;color:var(--muted)}.detail-callout{margin-top:16px;border-left:2px solid var(--warning);padding:4px 0 4px 12px}.detail-callout.danger{border-color:var(--danger)}.detail-callout.success{border-color:var(--success)}.detail-callout p{margin:5px 0 0;color:var(--muted);line-height:1.5}.detail-note{margin-top:18px;color:var(--faint);font-size:11px;line-height:1.55}.detail-button-row{display:flex;gap:7px;margin-top:18px;flex-wrap:wrap}.danger-text{color:var(--danger)}
9
9
  .table-wrap{min-width:0;overflow:auto}.data-table{width:100%;border-collapse:collapse;font-size:12px}.data-table th{text-align:left;height:38px;color:var(--faint);font-size:10px;font-weight:650;letter-spacing:.03em;border-bottom:1px solid var(--border);padding:0 10px;position:sticky;top:58px;background:rgba(245,245,243,.96);backdrop-filter:blur(10px);z-index:2}.data-table td{height:62px;border-bottom:1px solid var(--border);padding:9px 10px;vertical-align:middle}.data-table tbody tr{cursor:pointer}.data-table tbody tr:hover{background:rgba(255,255,255,.72)}.data-table tbody tr.selected{background:var(--accent-soft);box-shadow:inset 3px 0 var(--accent)}.data-table td:first-child{max-width:280px}.data-table td strong{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.data-table td small{display:block;color:var(--faint);margin-top:3px}.capability-lines{display:flex;flex-wrap:wrap;gap:6px;margin-top:16px}.capability-lines span{font-size:10px;color:var(--muted);border:1px solid var(--border);border-radius:5px;padding:4px 6px;background:var(--surface)}.advanced{margin-top:18px;border-top:1px solid var(--border);padding-top:12px}.advanced summary{cursor:pointer;color:var(--muted);font-size:11px}.advanced pre{white-space:pre-wrap;word-break:break-word;background:var(--surface-subtle);border-radius:6px;padding:10px;font-size:10px;max-height:420px;overflow:auto}
10
10
  .repository-tools{min-height:58px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:14px;justify-content:space-between}.repository-count{color:var(--faint);font-size:10px}.repository-tools input,.search-field input,.repository-add-panel input{height:34px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);padding:0 10px;color:var(--ink);min-width:170px}.search-field{display:flex;align-items:center;position:relative}.search-field svg{position:absolute;left:10px;width:14px;color:var(--faint)}.search-field input{padding-left:31px;width:250px}.repository-add-panel{margin:14px 0 2px;padding:18px 20px;border-radius:11px;background:var(--surface);border:1px solid var(--border)}.repository-add-fields{display:grid;grid-template-columns:minmax(260px,1.4fr) minmax(180px,.8fr) auto;gap:10px;align-items:end}.repository-add-fields label{display:grid;gap:6px}.repository-add-fields label>span{font-size:10px;color:var(--faint);font-weight:650}.repository-add-fields input{width:100%}.repository-add-panel p{margin:11px 0 0;color:var(--faint);font-size:10px}.repository-workspace{padding-top:14px}.settings-column{max-width:900px;padding-top:12px}.settings-column section{margin-top:26px}.settings-list{border-top:1px solid var(--border)}.settings-row{display:grid;grid-template-columns:minmax(0,1fr) 130px auto;gap:20px;align-items:center;min-height:68px;border-bottom:1px solid var(--border);padding:9px 0}.settings-row strong{font-size:13px}.settings-row p{margin:3px 0 0;color:var(--muted);font-size:12px}.settings-actions{display:flex;gap:6px}.system-layout{max-width:900px;padding-top:26px}.system-summary{border-bottom:1px solid var(--border);padding-bottom:20px}.system-posture{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;margin-bottom:12px}.system-posture h2{font-size:18px;margin:4px 0}.system-posture p{margin:0;color:var(--muted)}.system-layout>section+section{margin-top:24px}.boot-state{min-height:100vh;display:grid;place-content:center;justify-items:center;gap:10px;background:var(--canvas);color:var(--muted)}.boot-state .brand-mark{width:34px;height:34px}.boot-state p{max-width:460px;text-align:center}.single-list{max-width:900px}
11
11
  @media(max-width:1080px){.workspace{padding-left:28px;padding-right:28px}.command-bar{align-items:flex-start;flex-direction:column}.command-actions{width:100%;justify-content:flex-start}.command-meta{justify-items:start}.overview-hero{grid-template-columns:1fr}.overview-actions{min-height:130px}.signal-strip{grid-template-columns:repeat(2,1fr)}.signal-strip a:nth-child(2):after{display:none}.split-workspace,.automation-layout{grid-template-columns:1fr}.detail-pane{position:static;border:1px solid var(--border);margin-bottom:20px}.data-table{min-width:760px}}
@@ -1,18 +1,15 @@
1
- export type RouteId = 'overview' | 'automations' | 'work' | 'capabilities' | 'repositories' | 'settings' | 'system';
1
+ export type RouteId = 'overview' | 'automations' | 'work' | 'capabilities' | 'repositories' | 'system';
2
2
  export type Dict = Record<string, unknown>;
3
3
  export interface RepositoryView { id:string; name:string; path?:string; branchLabel?:string; dirtyLabel?:string; readinessLabel?:string; statusLabel?:string; current?:boolean; advanced?:Dict }
4
4
  export interface PluginActionView { id:string; title?:string; description?:string; risk?:string; riskLabel?:string; readOnly?:boolean; canPreview?:boolean; confirmationLabel?:string }
5
5
  export interface PluginView { id:string; name:string; description?:string; status?:string; statusLabel?:string; tone?:string; nextStep?:string; provider?:string; healthLabel?:string; lifecycleLabel?:string; capabilityLabels?:string[]; actions?:PluginActionView[]; warnings?:string[]; advanced?:Dict }
6
- export interface ProviderView { providerId:string; displayName:string; status?:string; statusLabel?:string; kindLabel?:string; summary?:string; explanation?:string; directDispatch?:boolean; handoffOnly?:boolean; enabled?:boolean; priority?:number; capabilities?:string[]; lastErrorSummary?:string }
7
- export interface LocalToolView { toolId:string; displayName:string; status?:string; summary?:string; enabled?:boolean; executablePath?:string; version?:string; usedByWorkflows?:string[] }
8
- export interface AutomationSettingsView { schemaVersion?:number; overview?:Dict; providers?:ProviderView[]; localTools?:LocalToolView[]; credentials?:Dict[]; routing?:{orders?:Record<string,string[]>}; warnings?:string[] }
9
6
  export interface CommandCenterView { readiness?:Dict; repositories?:RepositoryView[]; handoffs?:Dict[]; plugins?:PluginView[]; pluginSummary?:{total?:number;ready?:number;needsAttention?:number}; warnings?:string[] }
10
- export type AutomationMode='browser_watch'|'browser_keepalive'|'continuation'|'routine'|'schedule';
7
+ export type AutomationMode='browser_watch'|'browser_keepalive'|'continuation'|'schedule';
11
8
  export interface AutomationHistoryView { id:string; at:string; result:string; tone:'green'|'amber'|'red'|'blue'|'gray'; reason?:string; trigger?:string }
12
- export interface AutomationView { id:string; source:'schedule'|'routine'; repoId:string; repositoryName:string; name:string; summary?:string; status:'enabled'|'paused'|'attention'|'disabled'; schedule:string; timezone?:string; delivery?:string; mode:AutomationMode; modeLabel:string; live?:boolean; targetLabel?:string; boundWorkId?:string; boundWorkObjective?:string; observationStatus?:'baseline'|'unchanged'|'changed'|'keepalive'|'auth_required'; observationAt?:string; failureCount?:number; policySummary?:string; agentModel?:string; reasoningLevel?:string; tabPolicy?:string; lastRunAt?:string; lastResult?:string; nextRunHint?:string; pausedReason?:string; history:AutomationHistoryView[]; actions:Array<'run'|'pause'|'resume'> }
13
- export interface AutomationsResponse { schemaVersion:1; generatedAt:string; summary:{total:number;enabled:number;paused:number;needsAttention:number}; automations:AutomationView[] }
9
+ export interface AutomationView { id:string; source:'schedule'; repoId:string; repositoryName:string; name:string; summary?:string; status:'enabled'|'paused'|'attention'|'completed'|'disabled'; schedule:string; timezone?:string; delivery?:string; mode:AutomationMode; modeLabel:string; live?:boolean; targetLabel?:string; boundWorkId?:string; boundWorkObjective?:string; observationStatus?:'baseline'|'unchanged'|'changed'|'keepalive'|'auth_required'; observationAt?:string; failureCount?:number; policySummary?:string; agentModel?:string; reasoningLevel?:string; tabPolicy?:string; lastRunAt?:string; lastResult?:string; nextRunHint?:string; pausedReason?:string; attentionMessage?:string; history:AutomationHistoryView[]; actions:Array<'run'|'pause'|'resume'> }
10
+ export interface AutomationsResponse { schemaVersion:1; generatedAt:string; summary:{total:number;enabled:number;paused:number;completed:number;needsAttention:number}; automations:AutomationView[] }
14
11
  export interface TrackedWorkView { requirementId:string; title:string; outcome?:string; state:'planned'|'active'|'waiting_for_user'|'done'|'cancelled'; needsAttention?:boolean; blocker?:string; requiredUserDecision?:string; updatedAt?:string }
15
12
  export interface WorkResponse { schemaVersion?:number; requirementCount?:number; activeRequirementCount?:number; waitingForUserCount?:number; needsAttentionCount?:number; requirements?:TrackedWorkView[]; requirementTruncatedCount?:number }
16
13
  export interface WorkPortfolioItem { id:string; repoId:string; repositoryName:string; updatedAt:string; title:string; objective:string; modeLabel:string; statusLabel:string; tone?:string; phase:string; phaseLabel:string; nextAction:string; latestSummary:string; latestVerification?:Dict; changedFiles?:Dict; advanced?:{workId:string;status:string;checkIds:string[];handoffRefs:string[]} }
17
14
  export interface WorkPortfolioResponse { schemaVersion:1; generatedAt:string; summary:{total:number;open:number;needsAttention:number;completed:number}; repositories:Array<{repoId:string;repositoryName:string}>; items:WorkPortfolioItem[] }
18
- export interface ConsoleData { commandCenter:CommandCenterView; work:WorkResponse; workPortfolio:WorkPortfolioResponse; automations:AutomationsResponse; automationSettings:AutomationSettingsView; connector?:Dict; generatedAt:string }
15
+ export interface ConsoleData { commandCenter:CommandCenterView; work:WorkResponse; workPortfolio:WorkPortfolioResponse; automations:AutomationsResponse; connector?:Dict; generatedAt:string }