@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
@@ -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 }
@@ -3,7 +3,6 @@ import {
3
3
  appendFileSync,
4
4
  existsSync,
5
5
  mkdirSync,
6
- openSync,
7
6
  readFileSync,
8
7
  readdirSync,
9
8
  renameSync,
@@ -12,41 +11,29 @@ import {
12
11
  } from "fs";
13
12
  import { dirname, join, relative, resolve, sep } from "path";
14
13
  import { cancelAgentJob, getAgentJob } from "../agent-jobs/job-manager";
15
- import { getIssue, removeEphemeralIssue } from "../controller/issue-store";
14
+ import { removeEphemeralIssue } from "../controller/issue-store";
16
15
  import {
17
16
  currentControllerCheckRevision,
18
17
  releaseControllerCheckSubscription,
19
- runControllerCheckAsync,
20
- snapshotControllerCheck,
21
18
  } from "../controller/check-runner";
22
19
  import {
23
20
  DEFAULT_AGENT_TIMEOUT_MS,
24
21
  MAX_AGENT_TIMEOUT_MS,
25
22
  normalizeAgentTimeoutMs,
26
23
  } from "../controller/runtime-config";
27
- import { verifyEditSessionAsync } from "../editing/edit-session";
28
24
  import { loadMcpLocalConfig, loadMcpServiceLocalConfig } from "../mcp/auth";
29
- import {
30
- executeRepositoryCommandAsync,
31
- } from "../repositories/command-executor";
32
- import { registerRepository, resolveRepositorySelection } from "../repositories/registry";
33
25
  import type { ControllerTask } from "../controller/types";
34
26
  import { taskExecutionPolicy } from "../controller/execution-policy";
35
27
  import { tryAppendControllerWorklogEvent } from "../controller/worklog";
36
28
  import { resolveControllerHome, resolveRepoPreferredControllerHome } from "../repositories/controller-home";
37
- import { ensureRepositoryRuntimeStorage } from "../repositories/runtime-storage";
38
- import { commandValue, normalizeRepositoryCommand } from "../repositories/command-normalization";
39
29
  import { findExecutionJob } from "../../runtime/execution/jobs/store";
40
30
  import type {
41
- LaunchTaskPayload,
42
31
  LocalBridgeApproval,
43
32
  LocalBridgeConfig,
44
33
  LocalBridgeJob,
45
- LocalBridgeJobAction,
46
34
  LocalBridgeJobEvent,
47
35
  LocalBridgeJobRequest,
48
36
  RepositoryCommandPayload,
49
- QuickAgentSessionPayload,
50
37
  RunCheckPayload,
51
38
  VerifyEditSessionPayload,
52
39
  } from "./types";
@@ -276,24 +263,6 @@ function writeJson(path: string, value: unknown): void {
276
263
  }
277
264
  }
278
265
 
279
- function ensureJobLogFiles(repoRoot: string, jobId: string): void {
280
- mkdirSync(jobDir(repoRoot, jobId), { recursive: true });
281
- for (const path of [stdoutPath(repoRoot, jobId), stderrPath(repoRoot, jobId)]) {
282
- if (!existsSync(path)) writeFileSync(path, "", "utf-8");
283
- }
284
- }
285
-
286
- function appendJobOutput(
287
- repoRoot: string,
288
- jobId: string,
289
- stream: "stdout" | "stderr",
290
- chunk: string,
291
- ): void {
292
- const path = stream === "stdout" ? stdoutPath(repoRoot, jobId) : stderrPath(repoRoot, jobId);
293
- ensureJobLogFiles(repoRoot, jobId);
294
- appendFileSync(path, chunk, "utf-8");
295
- }
296
-
297
266
  function readJson<T>(path: string): T {
298
267
  return JSON.parse(readFileSync(path, "utf-8")) as T;
299
268
  }
@@ -384,149 +353,6 @@ function taskApproval(task: ControllerTask): LocalBridgeApproval {
384
353
  return taskExecutionPolicy(task).approval;
385
354
  }
386
355
 
387
- function executionApproval(
388
- repoRoot: string,
389
- action: LocalBridgeJobAction,
390
- payload: LocalBridgeJobRequest["payload"],
391
- ): LocalBridgeApproval {
392
- if (action === "run-check" || action === "verify-edit-session" || action === "repository-command") return "auto";
393
- if (action === "launch-task") {
394
- const input = payload as LaunchTaskPayload;
395
- const issue = getIssue(repoRoot, input.issueId);
396
- const task = issue.tasks.find((entry) => entry.id === input.taskId);
397
- if (!task)
398
- throw new Error(`task not found: ${input.issueId}/${input.taskId}`);
399
- return taskApproval(task);
400
- }
401
- const input = payload as QuickAgentSessionPayload;
402
- const synthetic: ControllerTask = {
403
- id: "QUICK",
404
- title: input.title || "Quick Agent",
405
- objective: input.objective || "Execute a quick agent session.",
406
- status: "ready",
407
- dependsOn: [],
408
- allowedPaths: normalizeStringList(input.allowedPaths),
409
- forbiddenPaths: normalizeStringList(input.forbiddenPaths),
410
- checks: normalizeStringList(input.checks),
411
- acceptanceCriteria: normalizeStringList(input.acceptanceCriteria),
412
- risk: input.risk ?? "low",
413
- recommendedAgent: input.agent,
414
- notes: [],
415
- runIds: [],
416
- createdAt: now(),
417
- updatedAt: now(),
418
- };
419
- return taskApproval(synthetic);
420
- }
421
-
422
- function findExistingLaunchJob(
423
- repoRoot: string,
424
- payload: LaunchTaskPayload,
425
- ): LocalBridgeJob | undefined {
426
- const jobs = readStoredJobs(repoRoot, 500);
427
- const requestId = payload.requestId?.trim();
428
- if (requestId) {
429
- return jobs.find((entry) =>
430
- entry.action === "launch-task" &&
431
- typeof (entry.payload as LaunchTaskPayload).requestId === "string" &&
432
- (entry.payload as LaunchTaskPayload).requestId === requestId,
433
- );
434
- }
435
- return jobs.find((entry) =>
436
- entry.action === "launch-task" &&
437
- ["approved", "running", "dispatched"].includes(entry.status) &&
438
- entry.issueId === payload.issueId &&
439
- entry.taskId === payload.taskId,
440
- );
441
- }
442
-
443
- function findExistingQuickSessionJob(
444
- repoRoot: string,
445
- payload: QuickAgentSessionPayload,
446
- ): LocalBridgeJob | undefined {
447
- const jobs = readStoredJobs(repoRoot, 500);
448
- const requestId = payload.requestId?.trim();
449
- if (requestId) {
450
- return jobs.find((entry) =>
451
- entry.action === "quick-agent-session" &&
452
- typeof (entry.payload as QuickAgentSessionPayload).requestId === "string" &&
453
- (entry.payload as QuickAgentSessionPayload).requestId === requestId,
454
- );
455
- }
456
- return undefined;
457
- }
458
-
459
- function findExistingRunCheckJob(
460
- repoRoot: string,
461
- payload: RunCheckPayload,
462
- revision: string,
463
- ): LocalBridgeJob | undefined {
464
- const requestId = payload.requestId?.trim();
465
- if (requestId) {
466
- const duplicate = readStoredJobs(repoRoot, 500).find((entry) =>
467
- entry.action === "run-check" &&
468
- typeof (entry.payload as RunCheckPayload).requestId === "string" &&
469
- (entry.payload as RunCheckPayload).requestId === requestId,
470
- );
471
- if (duplicate) return duplicate;
472
- }
473
- const candidate = readActiveLocalBridgeJobs(repoRoot).find((entry) =>
474
- entry.action === "run-check" &&
475
- (entry.payload as RunCheckPayload).checkId === payload.checkId &&
476
- entry.revision === revision
477
- );
478
- return candidate ? refreshLocalBridgeJob(repoRoot, candidate, revision) : undefined;
479
- }
480
-
481
- function findExistingVerifyEditSessionJob(
482
- repoRoot: string,
483
- payload: VerifyEditSessionPayload,
484
- ): LocalBridgeJob | undefined {
485
- const jobs = readStoredJobs(repoRoot, 500);
486
- const requestId = payload.requestId?.trim();
487
- if (requestId) {
488
- return jobs.find((entry) =>
489
- entry.action === "verify-edit-session" &&
490
- typeof (entry.payload as VerifyEditSessionPayload).requestId === "string" &&
491
- (entry.payload as VerifyEditSessionPayload).requestId === requestId,
492
- );
493
- }
494
- return jobs.find((entry) =>
495
- entry.action === "verify-edit-session" &&
496
- ["approved", "running"].includes(entry.status) &&
497
- (entry.payload as VerifyEditSessionPayload).sessionId === payload.sessionId &&
498
- (entry.payload as VerifyEditSessionPayload).revision === payload.revision &&
499
- JSON.stringify((entry.payload as VerifyEditSessionPayload).checkIds ?? []) === JSON.stringify(payload.checkIds ?? []),
500
- );
501
- }
502
-
503
- function findExistingRepositoryCommandJob(
504
- repoRoot: string,
505
- payload: RepositoryCommandPayload,
506
- ): LocalBridgeJob | undefined {
507
- const jobs = readStoredJobs(repoRoot, 500);
508
- const requestId = payload.requestId?.trim();
509
- if (requestId) {
510
- return jobs.find((entry) =>
511
- entry.action === "repository-command" &&
512
- typeof (entry.payload as RepositoryCommandPayload).requestId === "string" &&
513
- (entry.payload as RepositoryCommandPayload).requestId === requestId,
514
- );
515
- }
516
- const candidate = jobs.find((entry) =>
517
- entry.action === "repository-command" &&
518
- ["approved", "running"].includes(entry.status) &&
519
- (entry.payload as RepositoryCommandPayload).repoId === payload.repoId &&
520
- (entry.payload as RepositoryCommandPayload).checkoutId === payload.checkoutId &&
521
- JSON.stringify((entry.payload as RepositoryCommandPayload).command) === JSON.stringify(payload.command) &&
522
- (entry.payload as RepositoryCommandPayload).cwd === payload.cwd &&
523
- (entry.payload as RepositoryCommandPayload).approvalToken === payload.approvalToken,
524
- );
525
- if (!candidate) return undefined;
526
- const refreshed = refreshLocalBridgeJob(repoRoot, candidate);
527
- return ["approved", "running"].includes(refreshed.status) ? refreshed : undefined;
528
- }
529
-
530
356
  export function submitLocalBridgeJob(
531
357
  _repoRoot: string,
532
358
  _request: LocalBridgeJobRequest,
@@ -542,14 +368,6 @@ function readLocalBridgeJob(repoRoot: string, jobId: string): LocalBridgeJob {
542
368
  return readJson<LocalBridgeJob>(path);
543
369
  }
544
370
 
545
- function tryReadLocalBridgeJob(repoRoot: string, jobId: string): LocalBridgeJob | undefined {
546
- try {
547
- return readLocalBridgeJob(repoRoot, jobId);
548
- } catch (_error) {
549
- return undefined;
550
- }
551
- }
552
-
553
371
  function cleanupEphemeralJob(repoRoot: string, job: LocalBridgeJob): void {
554
372
  if (!job.ephemeral || !job.issueId || job.cleanupAt || job.status !== "succeeded") return;
555
373
  const runStatus = job.result && typeof job.result === "object"
@@ -622,17 +440,6 @@ function markJobTerminal(
622
440
  return saveJob(repoRoot, job);
623
441
  }
624
442
 
625
- export function failLocalBridgeJob(
626
- repoRoot: string,
627
- jobId: string,
628
- message: string,
629
- data?: Record<string, unknown>,
630
- ): LocalBridgeJob {
631
- const job = readLocalBridgeJob(repoRoot, jobId);
632
- if (["succeeded", "failed", "timed_out", "orphaned", "stale", "cancelled"].includes(job.status)) return job;
633
- return markJobTerminal(repoRoot, job, "failed", message, data);
634
- }
635
-
636
443
  function projectedExecutionJobId(job: LocalBridgeJob): string | undefined {
637
444
  const result = job.result;
638
445
  return result && typeof result.executionJobId === "string" ? result.executionJobId : undefined;
@@ -1091,39 +898,6 @@ export function readLocalBridgeJobOutput(
1091
898
  return readLocalBridgeJobOutputSnapshot(repoRoot, jobId, input);
1092
899
  }
1093
900
 
1094
- export function buildLocalBridgeJobHandoff(
1095
- repoRoot: string,
1096
- jobId: string,
1097
- input: { maxBytes?: number } = {},
1098
- ): LocalBridgeJobHandoff {
1099
- const snapshot = getLocalBridgeJobSnapshot(repoRoot, jobId);
1100
- if (snapshot.status !== "ok" || !snapshot.job) {
1101
- return {
1102
- jobId: snapshot.jobId,
1103
- status: snapshot.status === "ok" ? "not_found" : snapshot.status,
1104
- error: snapshot.error,
1105
- };
1106
- }
1107
- const maxBytes = boundedOutputBytes(input.maxBytes);
1108
- const stdout = readLocalBridgeJobOutputSnapshot(repoRoot, snapshot.job.jobId, { stream: "stdout", maxBytes });
1109
- const stderr = readLocalBridgeJobOutputSnapshot(repoRoot, snapshot.job.jobId, { stream: "stderr", maxBytes });
1110
- const result = snapshot.job.result ?? {};
1111
- return {
1112
- jobId: snapshot.job.jobId,
1113
- status: snapshot.job.status,
1114
- stdoutPath: stdout.path,
1115
- stderrPath: stderr.path,
1116
- stdout: typeof result.stdout === "string" ? result.stdout : undefined,
1117
- stderr: typeof result.stderr === "string" ? result.stderr : undefined,
1118
- outputStatus: {
1119
- stdout: stdout.status,
1120
- stderr: stderr.status,
1121
- },
1122
- changedPaths: snapshot.job.outcome?.policy?.changedPaths,
1123
- nextLocalCommand: `tail -n 120 ${relativeOutputPath(snapshot.job.jobId, "stdout")} ${relativeOutputPath(snapshot.job.jobId, "stderr")}`,
1124
- };
1125
- }
1126
-
1127
901
  function saveJob(repoRoot: string, job: LocalBridgeJob): LocalBridgeJob {
1128
902
  job.updatedAt = now();
1129
903
  writeJson(metaPath(repoRoot, job.jobId), job);
@@ -1155,269 +929,6 @@ export function cancelLocalBridgeJob(
1155
929
  return saveJob(repoRoot, job);
1156
930
  }
1157
931
 
1158
- async function executeRunCheck(
1159
- repoRoot: string,
1160
- jobId: string,
1161
- payload: RunCheckPayload,
1162
- ): Promise<void> {
1163
- let job = tryReadLocalBridgeJob(repoRoot, jobId);
1164
- if (!job || job.status !== "running") return;
1165
- job.ownerPid = process.pid;
1166
- saveJob(repoRoot, job);
1167
- try {
1168
- const timeoutMs = resolvedJobTimeout(repoRoot, payload.timeoutMs);
1169
- const result = await runControllerCheckAsync(repoRoot, payload.checkId, {
1170
- snapshot: payload.checkSnapshot,
1171
- requestedTimeoutMs: timeoutMs,
1172
- onSpawn: (pid) => {
1173
- const current = tryReadLocalBridgeJob(repoRoot, jobId);
1174
- if (!current || current.status !== "running") {
1175
- releaseControllerCheckSubscription(checkSubscriberId(jobId));
1176
- return;
1177
- }
1178
- current.workerPid = pid;
1179
- current.ownerPid = process.pid;
1180
- current.deadlineAt = new Date(Date.now() + timeoutMs + 5_000).toISOString();
1181
- saveJob(repoRoot, current);
1182
- },
1183
- subscriberId: checkSubscriberId(jobId),
1184
- });
1185
- job = tryReadLocalBridgeJob(repoRoot, jobId);
1186
- if (!job || job.status !== "running") return;
1187
- job.status = result.ok ? "succeeded" : "failed";
1188
- job.finishedAt = now();
1189
- job.result = result as unknown as Record<string, unknown>;
1190
- const failureClass = result.failureClass ?? (result.ok ? undefined : "infrastructure_failure");
1191
- const failureMessage = result.stderr || `check failed: ${payload.checkId}`;
1192
- job.outcome = {
1193
- process: { exitCode: result.status, timedOut: result.timedOut },
1194
- failureClass,
1195
- acceptanceFailure: failureClass === "acceptance_failure"
1196
- ? { code: "CHECK_FAILED", message: failureMessage }
1197
- : undefined,
1198
- infrastructureError: failureClass === "infrastructure_failure"
1199
- ? {
1200
- code: result.timedOut ? "CHECK_TIMED_OUT" : "CHECK_EXECUTION_FAILED",
1201
- message: failureMessage,
1202
- }
1203
- : undefined,
1204
- };
1205
- job.workerPid = undefined;
1206
- if (!result.ok) job.error = failureMessage;
1207
- appendEvent(repoRoot, job.jobId, {
1208
- type: result.ok ? "job_succeeded" : "job_failed",
1209
- message: result.ok
1210
- ? `Check ${payload.checkId} passed.`
1211
- : `Check ${payload.checkId} failed.`,
1212
- data: { timedOut: result.timedOut, artifactPath: result.artifactPath },
1213
- });
1214
- saveJob(repoRoot, job);
1215
- } catch (error) {
1216
- job = tryReadLocalBridgeJob(repoRoot, jobId);
1217
- if (!job || job.status !== "running") return;
1218
- job.status = "failed";
1219
- job.finishedAt = now();
1220
- job.workerPid = undefined;
1221
- const message = error instanceof Error ? error.message : String(error);
1222
- job.error = message;
1223
- job.outcome = {
1224
- failureClass: "infrastructure_failure",
1225
- infrastructureError: { code: "CHECK_EXECUTION_FAILED", message },
1226
- };
1227
- appendEvent(repoRoot, job.jobId, {
1228
- type: "job_failed",
1229
- message: job.error,
1230
- });
1231
- saveJob(repoRoot, job);
1232
- }
1233
- }
1234
-
1235
- async function executeVerifyEditSession(
1236
- repoRoot: string,
1237
- jobId: string,
1238
- payload: VerifyEditSessionPayload,
1239
- ): Promise<void> {
1240
- let job = tryReadLocalBridgeJob(repoRoot, jobId);
1241
- if (!job || job.status !== "running") return;
1242
- const timeoutMs = resolvedJobTimeout(repoRoot, undefined);
1243
- job.ownerPid = process.pid;
1244
- job.deadlineAt = new Date(Date.now() + timeoutMs + 5_000).toISOString();
1245
- saveJob(repoRoot, job);
1246
- appendEvent(repoRoot, job.jobId, {
1247
- type: "job_progress",
1248
- message: `Verifying edit session ${payload.sessionId}.`,
1249
- data: { sessionId: payload.sessionId, revision: payload.revision },
1250
- });
1251
- try {
1252
- const session = await verifyEditSessionAsync(repoRoot, payload.sessionId, {
1253
- checkIds: payload.checkIds,
1254
- reviewer: payload.reviewer,
1255
- note: payload.note,
1256
- }, {
1257
- onCheckSpawn: (checkId, pid) => {
1258
- const current = tryReadLocalBridgeJob(repoRoot, jobId);
1259
- if (!current || current.status !== "running") {
1260
- releaseControllerCheckSubscription(checkSubscriberId(jobId));
1261
- return;
1262
- }
1263
- current.workerPid = pid;
1264
- current.ownerPid = process.pid;
1265
- current.heartbeatAt = now();
1266
- saveJob(repoRoot, current);
1267
- appendEvent(repoRoot, current.jobId, {
1268
- type: "job_progress",
1269
- message: `Running check ${checkId}.`,
1270
- data: { checkId, pid },
1271
- });
1272
- },
1273
- subscriberId: checkSubscriberId(jobId),
1274
- });
1275
- job = tryReadLocalBridgeJob(repoRoot, jobId);
1276
- if (!job || job.status !== "running") return;
1277
- job.status = session.status === "checked" ? "succeeded" : "failed";
1278
- job.finishedAt = now();
1279
- job.workerPid = undefined;
1280
- job.result = {
1281
- sessionId: session.sessionId,
1282
- status: session.status,
1283
- verifiedAt: session.verifiedAt,
1284
- checkResults: session.checkResults,
1285
- diffPath: session.diffPath,
1286
- };
1287
- if (job.status !== "succeeded") job.error = session.checkResults.find((entry) => !entry.ok)?.summary ?? "edit session verification failed";
1288
- appendEvent(repoRoot, job.jobId, {
1289
- type: job.status === "succeeded" ? "job_succeeded" : "job_failed",
1290
- message: job.status === "succeeded"
1291
- ? `Edit session ${payload.sessionId} verified.`
1292
- : `Edit session ${payload.sessionId} verification failed.`,
1293
- data: { sessionId: payload.sessionId, revision: payload.revision },
1294
- });
1295
- saveJob(repoRoot, job);
1296
- } catch (error) {
1297
- job = tryReadLocalBridgeJob(repoRoot, jobId);
1298
- if (!job || job.status !== "running") return;
1299
- markJobTerminal(repoRoot, job, "failed", error instanceof Error ? error.message : String(error));
1300
- }
1301
- }
1302
-
1303
- async function executeRepositoryCommand(
1304
- repoRoot: string,
1305
- jobId: string,
1306
- payload: RepositoryCommandPayload,
1307
- ): Promise<void> {
1308
- let job = tryReadLocalBridgeJob(repoRoot, jobId);
1309
- if (!job || job.status !== "running") return;
1310
- const timeoutMs = resolvedJobTimeout(repoRoot, payload.timeoutMs);
1311
- job.ownerPid = process.pid;
1312
- job.deadlineAt = new Date(Date.now() + timeoutMs + 5_000).toISOString();
1313
- saveJob(repoRoot, job);
1314
- appendEvent(repoRoot, job.jobId, {
1315
- type: "job_progress",
1316
- message: `Executing repository command for ${payload.repoId}.`,
1317
- data: { repoId: payload.repoId, checkoutId: payload.checkoutId },
1318
- });
1319
- try {
1320
- const repository = resolveRepositorySelection({
1321
- repoId: payload.repoId,
1322
- checkoutId: payload.checkoutId,
1323
- controllerHome: payload.controllerHome,
1324
- allowSoleRepository: true,
1325
- });
1326
- // Durable Execution Jobs already hold repository-scoped leases for the
1327
- // command lifetime. Holding the controller repository lock here as well
1328
- // blocks the owning worker from renewing those leases and turns any
1329
- // command longer than the renewal interval into a false LOCK_HELD failure.
1330
- const execution = await executeRepositoryCommandAsync(payload.controllerHome, repository, {
1331
- command: payload.command,
1332
- cwd: payload.cwd,
1333
- authorization: "confirmed_plan",
1334
- approvalToken: payload.approvalToken,
1335
- approvalRequestId: payload.approvalRequestId,
1336
- timeoutMs: payload.timeoutMs,
1337
- maxOutputBytes: payload.maxOutputBytes,
1338
- }, {
1339
- onSpawn: (pid) => {
1340
- const current = tryReadLocalBridgeJob(repoRoot, jobId);
1341
- if (!current || current.status !== "running") {
1342
- signalWorker(pid, "SIGTERM");
1343
- return;
1344
- }
1345
- current.workerPid = pid;
1346
- current.ownerPid = process.pid;
1347
- current.heartbeatAt = now();
1348
- saveJob(repoRoot, current);
1349
- },
1350
- onStdout: (chunk) => {
1351
- appendJobOutput(repoRoot, jobId, "stdout", chunk);
1352
- const current = tryReadLocalBridgeJob(repoRoot, jobId);
1353
- if (!current || current.status !== "running") return;
1354
- current.heartbeatAt = now();
1355
- saveJob(repoRoot, current);
1356
- },
1357
- onStderr: (chunk) => {
1358
- appendJobOutput(repoRoot, jobId, "stderr", chunk);
1359
- const current = tryReadLocalBridgeJob(repoRoot, jobId);
1360
- if (!current || current.status !== "running") return;
1361
- current.heartbeatAt = now();
1362
- saveJob(repoRoot, current);
1363
- },
1364
- });
1365
- job = tryReadLocalBridgeJob(repoRoot, jobId);
1366
- if (!job || job.status !== "running") return;
1367
- const stdoutPath = `.ai/harness/local-jobs/${job.jobId}/stdout.log`;
1368
- const stderrPath = `.ai/harness/local-jobs/${job.jobId}/stderr.log`;
1369
- job.workerPid = undefined;
1370
- job.ownerPid = undefined;
1371
- job.result = {
1372
- ...(execution as unknown as Record<string, unknown>),
1373
- stdoutPath,
1374
- stderrPath,
1375
- };
1376
- job.outcome = {
1377
- process: { exitCode: execution.exitCode, timedOut: execution.timedOut, stdoutPath, stderrPath },
1378
- policy: {
1379
- decision: execution.status === "approval_required" ? "approval_required" : "allowed",
1380
- repositoryChanged: execution.repositoryChanged,
1381
- changedPaths: execution.changedPaths,
1382
- },
1383
- infrastructureError: execution.infrastructureError,
1384
- };
1385
- if (execution.status === "approval_required") {
1386
- job.status = "pending_approval";
1387
- job.finishedAt = undefined;
1388
- job.error = undefined;
1389
- appendEvent(repoRoot, job.jobId, {
1390
- type: "job_approval_required",
1391
- message: `Repository command is waiting for approval for ${payload.repoId}.`,
1392
- data: {
1393
- repoId: payload.repoId,
1394
- approvalRequestId: execution.approvalRequestId,
1395
- authorizationDecision: execution.authorizationDecision,
1396
- },
1397
- });
1398
- saveJob(repoRoot, job);
1399
- return;
1400
- }
1401
- job.status = execution.ok ? "succeeded" : execution.timedOut ? "timed_out" : "failed";
1402
- job.finishedAt = now();
1403
- job.error = execution.ok ? undefined : execution.infrastructureError?.message
1404
- ?? execution.stderr
1405
- ?? `repository command exited with ${String(execution.exitCode ?? 1)}`;
1406
- appendEvent(repoRoot, job.jobId, {
1407
- type: job.status === "succeeded" ? "job_succeeded" : "job_failed",
1408
- message: job.status === "succeeded"
1409
- ? `Repository command completed for ${payload.repoId}.`
1410
- : `Repository command failed for ${payload.repoId}.`,
1411
- data: { repoId: payload.repoId, exitCode: execution.exitCode, timedOut: execution.timedOut },
1412
- });
1413
- saveJob(repoRoot, job);
1414
- } catch (error) {
1415
- job = tryReadLocalBridgeJob(repoRoot, jobId);
1416
- if (!job || job.status !== "running") return;
1417
- markJobTerminal(repoRoot, job, "failed", error instanceof Error ? error.message : String(error));
1418
- }
1419
- }
1420
-
1421
932
  export function executeLocalBridgeJobInline(
1422
933
  repoRoot: string,
1423
934
  jobId: string,