@moretea-labs/forge 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (469) hide show
  1. package/AGENTS.md +4 -0
  2. package/CHANGELOG.md +39 -0
  3. package/CLAUDE.md +4 -0
  4. package/README.md +2 -2
  5. package/README.zh-CN.md +1 -1
  6. package/SKILL.md +2 -2
  7. package/THIRD_PARTY_NOTICES.md +1 -1
  8. package/agents/openai.yaml +1 -1
  9. package/assets/hooks/hook-input.sh +11 -8
  10. package/assets/hooks/lib/session-state.sh +10 -7
  11. package/assets/hooks/lib/workflow-state.sh +13 -177
  12. package/assets/hooks/post-tool-observer.sh +8 -2
  13. package/assets/hooks/prompt-guard.sh +5 -81
  14. package/assets/hooks/session-start-context.sh +56 -1
  15. package/assets/partials/05-workflow.partial.md +1 -1
  16. package/assets/partials-agents/02-operating-mode.partial.md +2 -0
  17. package/assets/partials-agents/03-orchestration.partial.md +1 -1
  18. package/assets/plugin-registry.v1.json +3 -3
  19. package/assets/reference-configs/document-generation.md +1 -1
  20. package/assets/reference-configs/harness-overview.md +1 -1
  21. package/assets/reference-configs/sprint-contracts.md +3 -3
  22. package/assets/skill-version.json +2 -2
  23. package/assets/templates/contract.template.md +2 -7
  24. package/assets/templates/helpers/capture-plan.sh +2 -2
  25. package/assets/templates/helpers/check-architecture-sync.sh +17 -0
  26. package/assets/templates/helpers/check-task-workflow.sh +4 -4
  27. package/assets/templates/helpers/contract-worktree.sh +1 -21
  28. package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
  29. package/assets/templates/helpers/inspect-project-state.ts +8 -6
  30. package/assets/templates/helpers/migrate-project-template.sh +22 -45
  31. package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
  32. package/assets/templates/helpers/new-plan.sh +1 -1
  33. package/assets/templates/helpers/plan-to-todo.sh +12 -37
  34. package/assets/templates/helpers/ship-worktrees.sh +2 -29
  35. package/assets/templates/helpers/verify-contract.sh +1 -111
  36. package/assets/templates/helpers/verify-sprint.sh +3 -180
  37. package/assets/templates/helpers/workflow-contract.ts +5 -1
  38. package/assets/templates/plan.template.md +1 -1
  39. package/assets/templates/review.template.md +9 -34
  40. package/assets/workflow-contract.v1.json +10 -19
  41. package/docs/README.md +10 -10
  42. package/docs/architecture/CURRENT.md +178 -0
  43. package/docs/architecture/EVOLUTION.md +42 -0
  44. package/docs/architecture/current/README.md +4 -156
  45. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
  46. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
  47. package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
  48. package/docs/architecture/history/README.md +7 -0
  49. package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
  50. package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
  51. package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
  52. package/docs/architecture/history.md +3 -34
  53. package/docs/architecture/index.md +15 -98
  54. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  55. package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
  56. package/docs/architecture/versions/1.6.md +38 -0
  57. package/docs/architecture/versions/1.7.md +41 -0
  58. package/docs/forge-chatgpt-browser-engine.md +2 -2
  59. package/docs/forge-chatgpt-mcp-setup.md +4 -28
  60. package/docs/forge-chatgpt-supervised-automation.md +3 -3
  61. package/docs/forge-github-issue-launcher.md +1 -1
  62. package/docs/forge-plugin-management.md +1 -1
  63. package/docs/forge-runtime-self-healing-loop.md +1 -1
  64. package/docs/operations/controller-browser-plugin.md +26 -6
  65. package/docs/operations/controller-performance-and-502.md +143 -0
  66. package/docs/operations/controller-reliability-runbook.md +1 -1
  67. package/docs/operations/features.md +2 -2
  68. package/docs/operations/github-repository.md +1 -1
  69. package/docs/operations/homebrew.md +2 -2
  70. package/docs/operations/mcp-tool-exposure.md +5 -3
  71. package/docs/wiki/Architecture.md +6 -6
  72. package/docs/wiki/Implementation.md +2 -2
  73. package/docs/wiki/Integrations.md +2 -2
  74. package/docs/wiki/Work-Lifecycle.md +1 -1
  75. package/package.json +33 -11
  76. package/scripts/activate-source-baseline.ts +17 -13
  77. package/scripts/architecture-event.ts +2 -820
  78. package/scripts/architecture-queue.sh +2 -645
  79. package/scripts/archive-architecture-request.sh +2 -242
  80. package/scripts/archive-workflow.sh +1 -291
  81. package/scripts/benchmark-background-check-overlap.ts +228 -0
  82. package/scripts/benchmark-mcp-host.sh +117 -0
  83. package/scripts/benchmark-mcp-transport.ts +170 -0
  84. package/scripts/benchmark-quality-harness.ts +146 -0
  85. package/scripts/benchmark-route-session-concurrency.ts +207 -6
  86. package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
  87. package/scripts/benchmark-typescript-navigation.ts +186 -0
  88. package/scripts/benchmark-work-efficiency.ts +334 -0
  89. package/scripts/capability-config.ts +2 -392
  90. package/scripts/capability-resolver.ts +2 -503
  91. package/scripts/capture-plan.sh +1 -332
  92. package/scripts/check-agent-tooling.sh +2 -1558
  93. package/scripts/check-architecture-sync.sh +2 -371
  94. package/scripts/check-brain-manifest.sh +2 -253
  95. package/scripts/check-context-files.sh +2 -47
  96. package/scripts/check-deploy-sql-order.sh +2 -115
  97. package/scripts/check-mcp-compatibility.ts +14 -0
  98. package/scripts/check-runtime-architecture.mjs +349 -79
  99. package/scripts/check-skill-version.ts +3 -191
  100. package/scripts/check-source-duplication.mjs +61 -0
  101. package/scripts/check-stable-baseline.ts +92 -0
  102. package/scripts/check-task-sync.sh +2 -63
  103. package/scripts/check-task-workflow.sh +2 -1000
  104. package/scripts/codex-handoff-resume.sh +2 -267
  105. package/scripts/context-contract-sync.sh +2 -514
  106. package/scripts/contract-run.ts +2 -463
  107. package/scripts/contract-worktree.sh +1 -722
  108. package/scripts/ensure-task-workflow.sh +1 -1225
  109. package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
  110. package/scripts/inspect-project-state.ts +4 -279
  111. package/scripts/install-standalone-recovery.ts +24 -0
  112. package/scripts/lib/project-init-lib.sh +22 -46
  113. package/scripts/lib/run-forge-helper.sh +19 -0
  114. package/scripts/lib/run-forge-helper.ts +26 -0
  115. package/scripts/migrate-project-template.sh +1 -1189
  116. package/scripts/migrate-workflow-docs.ts +4 -412
  117. package/scripts/new-plan.sh +1 -180
  118. package/scripts/new-spec.sh +1 -47
  119. package/scripts/new-sprint.sh +1 -46
  120. package/scripts/plan-to-todo.sh +1 -796
  121. package/scripts/prepare-codex-handoff.sh +2 -201
  122. package/scripts/prepare-handoff.sh +1 -78
  123. package/scripts/refresh-current-status.sh +2 -467
  124. package/scripts/run-governed-gate.ts +5 -1
  125. package/scripts/select-agent-context-blocks.sh +2 -64
  126. package/scripts/ship-worktrees.sh +1 -558
  127. package/scripts/smoke-ios-physical-device.ts +4 -2
  128. package/scripts/smoke-runtime-recovery.ts +1 -35
  129. package/scripts/smoke-schedule-engine.ts +1 -20
  130. package/scripts/sprint-backlog.sh +1 -834
  131. package/scripts/stage-runtime-release.ts +2 -1
  132. package/scripts/summarize-failures.sh +2 -123
  133. package/scripts/switch-plan.sh +1 -150
  134. package/scripts/sync-brain-docs.sh +2 -379
  135. package/scripts/sync-generated-authority.mjs +175 -0
  136. package/scripts/verify-contract.sh +2 -703
  137. package/scripts/verify-forge-runtime.sh +0 -1
  138. package/scripts/verify-sprint.sh +1 -677
  139. package/scripts/workflow-contract.ts +4 -205
  140. package/scripts/workstream-sync.sh +2 -261
  141. package/src/cli/agent-jobs/executor-health.ts +1 -1
  142. package/src/cli/commands/init-hook.ts +3 -3
  143. package/src/cli/commands/mcp.ts +9 -5
  144. package/src/cli/commands/plugin.ts +12 -3
  145. package/src/cli/commands/recovery.ts +25 -3
  146. package/src/cli/commands/runtime.ts +55 -3
  147. package/src/cli/commands/security.ts +12 -1
  148. package/src/cli/commands/setup-profile.ts +31 -21
  149. package/src/cli/controller/check-runner.ts +113 -5
  150. package/src/cli/controller/composite-result.ts +1 -1
  151. package/src/cli/controller/context/focus.ts +51 -0
  152. package/src/cli/controller/context/instruction-context.ts +114 -0
  153. package/src/cli/controller/context/known-paths.ts +76 -0
  154. package/src/cli/controller/context/query-planning.ts +110 -0
  155. package/src/cli/controller/context/rule-resolution.ts +532 -0
  156. package/src/cli/controller/context/source-materializer.ts +278 -0
  157. package/src/cli/controller/context/structural.ts +16 -0
  158. package/src/cli/controller/context/types.ts +286 -0
  159. package/src/cli/controller/context-pack.ts +828 -487
  160. package/src/cli/controller/launch-agents.ts +77 -2
  161. package/src/cli/controller/operational-plan.ts +2 -2
  162. package/src/cli/controller/work-mode.ts +6 -4
  163. package/src/cli/editing/edit-session.ts +60 -7
  164. package/src/cli/github/contracts.ts +16 -0
  165. package/src/cli/github/github.ts +135 -16
  166. package/src/cli/github/session.ts +2 -1
  167. package/src/cli/installer/managed-entries.ts +15 -1
  168. package/src/cli/local-bridge/console-automations.ts +54 -78
  169. package/src/cli/local-bridge/console-view-models.ts +1 -35
  170. package/src/cli/local-bridge/facade-api.ts +37 -264
  171. package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
  172. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
  173. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
  174. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
  175. package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
  176. package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
  177. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
  178. package/src/cli/local-bridge/frontend/src/styles.css +1 -1
  179. package/src/cli/local-bridge/frontend/src/types.ts +5 -8
  180. package/src/cli/local-bridge/job-store.ts +1 -490
  181. package/src/cli/local-bridge/server.ts +2 -515
  182. package/src/cli/local-bridge/ui-dist/app.css +1 -1
  183. package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
  184. package/src/cli/mcp/auth.ts +5 -5
  185. package/src/cli/mcp/instructions.ts +3 -2
  186. package/src/cli/mcp/legacy-tool-service.ts +10 -222
  187. package/src/cli/mcp/multi-repository.ts +16 -5
  188. package/src/cli/mcp/oauth.ts +175 -26
  189. package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
  190. package/src/cli/mcp/repository-tools.ts +282 -146
  191. package/src/cli/mcp/server.ts +586 -116
  192. package/src/cli/mcp/tool-capability-cache.ts +1 -1
  193. package/src/cli/mcp/tool-contract.ts +14 -0
  194. package/src/cli/mcp/toolset-selection.ts +1 -1
  195. package/src/cli/mcp/toolset.ts +44 -7
  196. package/src/cli/mcp/transports/http.ts +124 -14
  197. package/src/cli/mcp/transports/session-registry.ts +43 -5
  198. package/src/cli/mcp/types.ts +3 -3
  199. package/src/cli/repositories/command-classifier.ts +103 -21
  200. package/src/cli/repositories/command-executor.ts +78 -526
  201. package/src/cli/repositories/command-process.ts +108 -0
  202. package/src/cli/repositories/command-scope.ts +99 -41
  203. package/src/cli/repositories/controller-home.ts +7 -8
  204. package/src/cli/repositories/git-command-executor.ts +2 -0
  205. package/src/cli/repositories/locks.ts +53 -16
  206. package/src/cli/repositories/repository-snapshot.ts +124 -0
  207. package/src/cli/repositories/selected-path-actions.ts +17 -9
  208. package/src/cli/repositories/structured-git.ts +118 -6
  209. package/src/cli/repository/inspector.ts +563 -65
  210. package/src/cli/repository/session-cache.ts +58 -17
  211. package/src/cli/v81-entry.ts +1 -4
  212. package/src/effects/fs-transaction.ts +85 -17
  213. package/src/runtime/context/codegraph-read-provider.ts +233 -2
  214. package/src/runtime/context/codegraph-sidecar.cjs +74 -40
  215. package/src/runtime/context/generic-lsp-provider.ts +355 -0
  216. package/src/runtime/context/lsp-client.ts +283 -0
  217. package/src/runtime/context/semantic-navigation-contract.ts +61 -0
  218. package/src/runtime/context/semantic-navigation.ts +223 -0
  219. package/src/runtime/context/swift-navigation.ts +565 -0
  220. package/src/runtime/context/typescript-navigation.ts +226 -0
  221. package/src/runtime/control-plane/dispatch-priority.ts +28 -0
  222. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +48 -16
  223. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
  224. package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
  225. package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
  226. package/src/runtime/control-plane/execution/session-store.ts +18 -0
  227. package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
  228. package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
  229. package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
  230. package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
  231. package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
  232. package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
  233. package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
  234. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
  235. package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
  236. package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
  237. package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
  238. package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
  239. package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
  240. package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
  241. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
  242. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
  243. package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
  244. package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
  245. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
  246. package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
  247. package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
  248. package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
  249. package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
  250. package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
  251. package/src/runtime/control-plane/facade/index.ts +3 -0
  252. package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
  253. package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
  254. package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
  255. package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
  256. package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
  257. package/src/runtime/control-plane/facade/types.ts +90 -10
  258. package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
  259. package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
  260. package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
  261. package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
  262. package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
  263. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
  264. package/src/runtime/control-plane/global-scheduler/maintenance.ts +152 -0
  265. package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
  266. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
  267. package/src/runtime/control-plane/global-scheduler/scheduler.ts +278 -543
  268. package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
  269. package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
  270. package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
  271. package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
  272. package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
  273. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
  274. package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
  275. package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
  276. package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
  277. package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
  278. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +63 -0
  279. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
  280. package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
  281. package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
  282. package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
  283. package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
  284. package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
  285. package/src/runtime/control-plane/release-retention.ts +62 -2
  286. package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
  287. package/src/runtime/control-plane/routing/route-policy.ts +24 -21
  288. package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
  289. package/src/runtime/control-plane/runtime-status-client.ts +0 -2
  290. package/src/runtime/diagnostics/mcp-timing.ts +13 -0
  291. package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
  292. package/src/runtime/diagnostics/performance.ts +24 -1
  293. package/src/runtime/evidence/event-ledger.ts +1 -1
  294. package/src/runtime/evidence/process-check-execution.ts +18 -0
  295. package/src/runtime/execution/jobs/child-reference.ts +6 -2
  296. package/src/runtime/execution/jobs/store.ts +58 -4
  297. package/src/runtime/execution/jobs/types.ts +1 -1
  298. package/src/runtime/execution/managed-workspace.ts +203 -1
  299. package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
  300. package/src/runtime/execution/process-runtime/check-result.ts +88 -0
  301. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
  302. package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
  303. package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
  304. package/src/runtime/execution/process-runtime/gc.ts +38 -6
  305. package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
  306. package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
  307. package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
  308. package/src/runtime/execution/process-runtime/runtime.ts +53 -3
  309. package/src/runtime/execution/process-runtime/store.ts +1 -0
  310. package/src/runtime/execution/process-runtime/types.ts +4 -12
  311. package/src/runtime/execution/thin-harness/async-process.ts +12 -2
  312. package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
  313. package/src/runtime/execution/work-activity.ts +21 -0
  314. package/src/runtime/execution/workers/executor.ts +18 -61
  315. package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
  316. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
  317. package/src/runtime/gateway/mcp/process-tools.ts +83 -37
  318. package/src/runtime/gateway/mcp/router.ts +186 -84
  319. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
  320. package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
  321. package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
  322. package/src/runtime/plugins/browser-adapter.ts +2662 -829
  323. package/src/runtime/plugins/browser-automation-service.ts +10 -0
  324. package/src/runtime/plugins/browser-handoff-host.ts +2 -25
  325. package/src/runtime/plugins/browser-handoff.ts +110 -5
  326. package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
  327. package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
  328. package/src/runtime/plugins/browser-native-session-service.ts +222 -0
  329. package/src/runtime/plugins/browser-node-bridge.ts +6 -34
  330. package/src/runtime/plugins/browser-provider-registry.ts +109 -0
  331. package/src/runtime/plugins/browser-runtime-contract.ts +154 -0
  332. package/src/runtime/plugins/browser-runtime.ts +193 -0
  333. package/src/runtime/plugins/browser-session-authority.ts +332 -0
  334. package/src/runtime/plugins/browser-session-store.ts +121 -0
  335. package/src/runtime/plugins/browser-session-types.ts +98 -0
  336. package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
  337. package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
  338. package/src/runtime/plugins/external-adapter.ts +358 -3
  339. package/src/runtime/plugins/external-unix-socket.ts +7 -1
  340. package/src/runtime/plugins/first-party-registry.ts +2 -0
  341. package/src/runtime/plugins/github-adapter.ts +125 -0
  342. package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
  343. package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
  344. package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
  345. package/src/runtime/plugins/ios-adapter.ts +106 -16
  346. package/src/runtime/plugins/ios-agent-device.ts +234 -64
  347. package/src/runtime/plugins/ios-physical-device.ts +1143 -392
  348. package/src/runtime/plugins/lightweight-action.ts +153 -0
  349. package/src/runtime/plugins/local-system-adapter.ts +123 -6
  350. package/src/runtime/plugins/macos-capability-broker.ts +47 -9
  351. package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
  352. package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
  353. package/src/runtime/plugins/resend-adapter.ts +1 -1
  354. package/src/runtime/plugins/store.ts +330 -33
  355. package/src/runtime/plugins/types.ts +38 -3
  356. package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
  357. package/src/runtime/projections/git-status-sampler.ts +16 -16
  358. package/src/runtime/projections/materialized-view.ts +28 -10
  359. package/src/runtime/recovery/maintenance-executor.ts +426 -25
  360. package/src/runtime/root/mcp-transport.ts +180 -10
  361. package/src/runtime/root/package-connector-service.ts +230 -10
  362. package/src/runtime/root/package-runtime-release.ts +143 -17
  363. package/src/runtime/root/package-runtime-service.ts +461 -22
  364. package/src/runtime/root/release-manifest.ts +144 -18
  365. package/src/runtime/root/release-materialize.ts +125 -32
  366. package/src/runtime/root/release-store.ts +48 -11
  367. package/src/runtime/root/runtime.ts +23 -5
  368. package/src/runtime/root/service.ts +100 -29
  369. package/src/runtime/root/types.ts +12 -0
  370. package/src/runtime/safe-tooling/ios-development.ts +321 -63
  371. package/src/runtime/shared/trusted-executable.ts +62 -0
  372. package/src/runtime/shared/trusted-node-executable.ts +48 -0
  373. package/src/runtime/standalone-recovery/core.ts +1079 -240
  374. package/src/runtime/standalone-recovery/entry.ts +100 -24
  375. package/src/runtime/standalone-recovery/installer.ts +20 -4
  376. package/src/runtime/standalone-recovery/service-labels.ts +2 -0
  377. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
  378. package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
  379. package/src/runtime/workflow/schedules/engine.ts +364 -202
  380. package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
  381. package/src/runtime/workflow/schedules/settlement.ts +64 -17
  382. package/src/runtime/workflow/schedules/store.ts +209 -19
  383. package/src/runtime/workflow/schedules/types.ts +2 -4
  384. package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
  385. package/src/testing/test-governance.ts +8 -40
  386. package/assets/reference-configs/heartbeat-triage.md +0 -57
  387. package/assets/templates/helpers/harness-trace-grade.sh +0 -150
  388. package/assets/templates/helpers/heartbeat-triage.sh +0 -361
  389. package/assets/templates/helpers/maintenance-triage.sh +0 -167
  390. package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
  391. package/docs/architecture/current/architecture-invariants.md +0 -331
  392. package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
  393. package/docs/architecture/current/codegraph-context-provider.md +0 -238
  394. package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
  395. package/docs/architecture/current/controller-repository-decoupling.md +0 -148
  396. package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
  397. package/docs/architecture/current/entity-model.md +0 -612
  398. package/docs/architecture/current/external-plugin-governance.md +0 -396
  399. package/docs/architecture/current/failure-recovery.md +0 -447
  400. package/docs/architecture/current/governance.md +0 -213
  401. package/docs/architecture/current/human-interaction-plane.md +0 -87
  402. package/docs/architecture/current/implementation-status.md +0 -128
  403. package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
  404. package/docs/architecture/current/legacy-governance.md +0 -58
  405. package/docs/architecture/current/local-workspace-target-grants.md +0 -70
  406. package/docs/architecture/current/migration-roadmap.md +0 -105
  407. package/docs/architecture/current/multi-repository-execution.md +0 -371
  408. package/docs/architecture/current/operations-runbook.md +0 -45
  409. package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
  410. package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
  411. package/docs/architecture/current/repository-access-modes.md +0 -102
  412. package/docs/architecture/current/route-policy.md +0 -15
  413. package/docs/architecture/current/route-session-concurrency.md +0 -85
  414. package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
  415. package/docs/architecture/current/runtime-directory-map.md +0 -49
  416. package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
  417. package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
  418. package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
  419. package/docs/architecture/current/system-overview.md +0 -169
  420. package/docs/architecture/current/target-requirements-traceability.md +0 -202
  421. package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
  422. package/docs/architecture/current/thin-harness-v1.md +0 -321
  423. package/docs/architecture/current/verification-and-release-gates.md +0 -391
  424. package/docs/forge-autonomous-goal-loop.md +0 -9
  425. package/docs/forge-provider-configuration.md +0 -7
  426. package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
  427. package/docs/operations/gmail-assistant-routines.md +0 -186
  428. package/docs/operations/personal-assistant-operator-guide.md +0 -61
  429. package/docs/operations/provider-configuration.md +0 -31
  430. package/scripts/harness-trace-grade.sh +0 -150
  431. package/scripts/heartbeat-triage.sh +0 -361
  432. package/scripts/maintenance-triage.sh +0 -167
  433. package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
  434. package/src/cli/repositories/goal-registry.ts +0 -239
  435. package/src/runtime/assistant/action-proposals.ts +0 -279
  436. package/src/runtime/assistant/intent.ts +0 -395
  437. package/src/runtime/assistant/model-provider.ts +0 -460
  438. package/src/runtime/assistant/openapi.ts +0 -223
  439. package/src/runtime/assistant/policy.ts +0 -89
  440. package/src/runtime/assistant/readiness.ts +0 -258
  441. package/src/runtime/assistant/routine-runtime.ts +0 -477
  442. package/src/runtime/assistant/schedule-binding.ts +0 -171
  443. package/src/runtime/assistant/standing-grants.ts +0 -375
  444. package/src/runtime/assistant/store.ts +0 -243
  445. package/src/runtime/assistant/types.ts +0 -135
  446. package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
  447. package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
  448. package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
  449. package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
  450. package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
  451. package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
  452. package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
  453. package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
  454. package/src/runtime/control-plane/goal-loop/index.ts +0 -13
  455. package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
  456. package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
  457. package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
  458. package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
  459. package/src/runtime/control-plane/goal-loop/types.ts +0 -378
  460. package/src/runtime/control-plane/startup-recovery.ts +0 -198
  461. package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
  462. package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
  463. package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
  464. package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
  465. package/src/runtime/workflow/findings/store.ts +0 -204
  466. package/src/runtime/workflow/findings/types.ts +0 -58
  467. package/src/runtime/workflow/portfolio/engine.ts +0 -20
  468. package/src/runtime/workflow/portfolio/store.ts +0 -185
  469. package/src/runtime/workflow/portfolio/types.ts +0 -29
@@ -1,5 +1,5 @@
1
1
  import { createHash } from 'crypto';
2
- import { existsSync, mkdirSync, realpathSync } from 'fs';
2
+ import { existsSync, mkdirSync, readFileSync, realpathSync, symlinkSync } from 'fs';
3
3
  import { dirname, join, resolve } from 'path';
4
4
  import { repositoryControllerRoot } from '../../cli/repositories/controller-home';
5
5
  import type { RepositoryRecord } from '../../cli/repositories/types';
@@ -14,6 +14,7 @@ import { branchSlugSegment, validateBranchName } from '../../cli/repositories/br
14
14
  import { withControllerLock } from '../../cli/repositories/locks';
15
15
  import { resolveGitExecutable } from '../../effects/git-executable';
16
16
  import { runProcess } from '../../effects/process-runner';
17
+ import { repositoryChildProcessEnvironment, resolveBunExecutable } from '../shared/process-environment';
17
18
  import { readJsonFile, writeJsonAtomic } from '../shared/json-files';
18
19
 
19
20
  export interface EnsureManagedWorkspaceInput {
@@ -21,6 +22,24 @@ export interface EnsureManagedWorkspaceInput {
21
22
  title: string;
22
23
  baseRef?: string;
23
24
  branchName?: string;
25
+ /** Explicitly materialize lockfile-backed Node dependencies in this isolated worktree. */
26
+ prepareDependencies?: boolean;
27
+ }
28
+
29
+ export interface ManagedWorkspaceDependencyBootstrap {
30
+ packageManager: 'bun' | 'pnpm' | 'npm' | 'yarn';
31
+ lockfile: string;
32
+ command: string[];
33
+ }
34
+
35
+ export interface ManagedWorkspaceDependencyPreparation {
36
+ mode: 'already_ready' | 'canonical_reuse' | 'installed';
37
+ nodeModulesRoot: string;
38
+ canonicalRoot?: string;
39
+ }
40
+
41
+ export interface ManagedWorkspaceDependencies {
42
+ materializeDependencies?: (workspaceRoot: string) => void;
24
43
  }
25
44
 
26
45
  export interface ManagedWorkspace {
@@ -73,6 +92,180 @@ function assertBranch(root: string, branch: string): string {
73
92
  return normalized;
74
93
  }
75
94
 
95
+ export function managedWorkspaceDependencyBootstrap(repoRoot: string): ManagedWorkspaceDependencyBootstrap | undefined {
96
+ if (!existsSync(join(repoRoot, 'package.json')) || existsSync(join(repoRoot, 'node_modules'))) return undefined;
97
+ const lockCandidates = [
98
+ ['bun', 'bun.lock', ['bun', 'install', '--frozen-lockfile']],
99
+ ['bun', 'bun.lockb', ['bun', 'install', '--frozen-lockfile']],
100
+ ['pnpm', 'pnpm-lock.yaml', ['pnpm', 'install', '--frozen-lockfile']],
101
+ ['npm', 'package-lock.json', ['npm', 'ci']],
102
+ ['yarn', 'yarn.lock', ['yarn', 'install', '--frozen-lockfile']],
103
+ ] as const;
104
+ const detected = lockCandidates.find(([, lockfile]) => existsSync(join(repoRoot, lockfile)));
105
+ if (!detected) return undefined;
106
+ return { packageManager: detected[0], lockfile: detected[1], command: [...detected[2]] };
107
+ }
108
+
109
+ const DEPENDENCY_REUSE_CONFIG_PATHS = [
110
+ '.npmrc',
111
+ 'bunfig.toml',
112
+ 'pnpm-workspace.yaml',
113
+ '.yarnrc.yml',
114
+ ] as const;
115
+
116
+ function dependencyInputMatches(leftRoot: string, rightRoot: string, path: string): boolean {
117
+ const left = join(leftRoot, path);
118
+ const right = join(rightRoot, path);
119
+ const leftExists = existsSync(left);
120
+ const rightExists = existsSync(right);
121
+ if (leftExists !== rightExists) return false;
122
+ return !leftExists || readFileSync(left).equals(readFileSync(right));
123
+ }
124
+
125
+ function linkedWorkspaceCanonicalRoot(repoRoot: string): string | undefined {
126
+ const common = runProcess(resolveGitExecutable(), ['-C', repoRoot, 'rev-parse', '--path-format=absolute', '--git-common-dir'], {
127
+ timeoutMs: 15_000,
128
+ maxOutputBytes: 8 * 1024,
129
+ });
130
+ if (!common.ok || !common.stdout.trim()) return undefined;
131
+ const canonicalRoot = dirname(resolve(common.stdout.trim()));
132
+ if (!existsSync(canonicalRoot)) return undefined;
133
+ try {
134
+ if (realpathSync(canonicalRoot) === realpathSync(repoRoot)) return undefined;
135
+ } catch {
136
+ return undefined;
137
+ }
138
+ const topLevel = runProcess(resolveGitExecutable(), ['-C', canonicalRoot, 'rev-parse', '--show-toplevel'], {
139
+ timeoutMs: 15_000,
140
+ maxOutputBytes: 8 * 1024,
141
+ });
142
+ if (!topLevel.ok || !topLevel.stdout.trim()) return undefined;
143
+ try {
144
+ return realpathSync(topLevel.stdout.trim()) === realpathSync(canonicalRoot) ? canonicalRoot : undefined;
145
+ } catch {
146
+ return undefined;
147
+ }
148
+ }
149
+
150
+ export function resolveManagedWorkspaceCanonicalDependencies(repoRoot: string): {
151
+ canonicalRoot: string;
152
+ nodeModulesRoot: string;
153
+ } | undefined {
154
+ const bootstrap = managedWorkspaceDependencyBootstrap(repoRoot);
155
+ if (!bootstrap) return undefined;
156
+ const canonicalRoot = linkedWorkspaceCanonicalRoot(repoRoot);
157
+ if (!canonicalRoot) return undefined;
158
+ const nodeModulesRoot = join(canonicalRoot, 'node_modules');
159
+ if (!existsSync(nodeModulesRoot)) return undefined;
160
+ const dependencyInputs = ['package.json', bootstrap.lockfile, ...DEPENDENCY_REUSE_CONFIG_PATHS];
161
+ if (!dependencyInputs.every((path) => dependencyInputMatches(repoRoot, canonicalRoot, path))) return undefined;
162
+ return { canonicalRoot, nodeModulesRoot: realpathSync(nodeModulesRoot) };
163
+ }
164
+
165
+ function packageManifestRequiresDependencyMaterialization(repoRoot: string): boolean {
166
+ const packagePath = join(repoRoot, 'package.json');
167
+ if (!existsSync(packagePath)) return false;
168
+ let manifest: Record<string, unknown>;
169
+ try {
170
+ const parsed = JSON.parse(readFileSync(packagePath, 'utf8')) as unknown;
171
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return true;
172
+ manifest = parsed as Record<string, unknown>;
173
+ } catch {
174
+ // Preserve fail-closed dependency preparation for malformed manifests. The
175
+ // package manager remains the authority for the concrete parse error once a
176
+ // supported frozen lockfile is present.
177
+ return true;
178
+ }
179
+
180
+ const dependencyFields = [
181
+ 'dependencies',
182
+ 'devDependencies',
183
+ 'optionalDependencies',
184
+ 'peerDependencies',
185
+ 'bundleDependencies',
186
+ 'bundledDependencies',
187
+ ] as const;
188
+ if (dependencyFields.some((field) => {
189
+ const value = manifest[field];
190
+ return Array.isArray(value)
191
+ ? value.length > 0
192
+ : Boolean(value && typeof value === 'object' && Object.keys(value as Record<string, unknown>).length > 0);
193
+ })) return true;
194
+
195
+ const workspaces = manifest.workspaces;
196
+ if (Array.isArray(workspaces)) return workspaces.length > 0;
197
+ if (workspaces && typeof workspaces === 'object') {
198
+ const packages = (workspaces as Record<string, unknown>).packages;
199
+ if (Array.isArray(packages)) return packages.length > 0;
200
+ return Object.keys(workspaces as Record<string, unknown>).length > 0;
201
+ }
202
+ return false;
203
+ }
204
+
205
+ function reuseManagedWorkspaceCanonicalDependencies(repoRoot: string): ManagedWorkspaceDependencyPreparation | undefined {
206
+ const nodeModulesRoot = join(repoRoot, 'node_modules');
207
+ const reusable = resolveManagedWorkspaceCanonicalDependencies(repoRoot);
208
+ if (!reusable) return undefined;
209
+ try {
210
+ symlinkSync(reusable.nodeModulesRoot, nodeModulesRoot, process.platform === 'win32' ? 'junction' : 'dir');
211
+ } catch (error) {
212
+ if (!existsSync(nodeModulesRoot)) {
213
+ const detail = error instanceof Error ? error.message : String(error);
214
+ throw new Error(`MANAGED_WORKSPACE_DEPENDENCY_REUSE_FAILED: ${detail}`);
215
+ }
216
+ }
217
+ return {
218
+ mode: 'canonical_reuse',
219
+ nodeModulesRoot: realpathSync(nodeModulesRoot),
220
+ canonicalRoot: reusable.canonicalRoot,
221
+ };
222
+ }
223
+
224
+ export function materializeManagedWorkspaceDependencies(repoRoot: string): ManagedWorkspaceDependencyPreparation | undefined {
225
+ if (!existsSync(join(repoRoot, 'package.json'))) return undefined;
226
+ const nodeModulesRoot = join(repoRoot, 'node_modules');
227
+ if (existsSync(nodeModulesRoot)) {
228
+ return { mode: 'already_ready', nodeModulesRoot: realpathSync(nodeModulesRoot) };
229
+ }
230
+ // A linked worktree may safely reuse canonical dependencies even when the
231
+ // package manifest itself declares no dependencies. The supported lockfile
232
+ // and dependency-reuse inputs remain the authority for proving equivalence.
233
+ const reused = reuseManagedWorkspaceCanonicalDependencies(repoRoot);
234
+ if (reused) return reused;
235
+ // A package manifest can define dependency-free scripts (for example a
236
+ // built-in `node -e` check). Such checks do not need node_modules and must not
237
+ // be rejected merely because the repository intentionally has no lockfile.
238
+ if (!packageManifestRequiresDependencyMaterialization(repoRoot)) return undefined;
239
+ const bootstrap = managedWorkspaceDependencyBootstrap(repoRoot);
240
+ if (!bootstrap) {
241
+ throw new Error('MANAGED_WORKSPACE_DEPENDENCY_LOCK_REQUIRED: package.json declares dependencies but no supported lockfile was found');
242
+ }
243
+ const childEnv = repositoryChildProcessEnvironment();
244
+ const executable = bootstrap.packageManager === 'bun'
245
+ ? resolveBunExecutable(process.execPath, childEnv)
246
+ : bootstrap.command[0]!;
247
+ const result = runProcess(executable, bootstrap.command.slice(1), {
248
+ cwd: repoRoot,
249
+ env: childEnv,
250
+ timeoutMs: 10 * 60_000,
251
+ maxOutputBytes: 4 * 1024 * 1024,
252
+ });
253
+ if (!result.ok) {
254
+ const detail = result.stderr || result.error || `exit ${result.status}`;
255
+ throw new Error(`MANAGED_WORKSPACE_DEPENDENCY_INSTALL_FAILED: ${bootstrap.command.join(' ')}: ${detail}`);
256
+ }
257
+ if (!existsSync(nodeModulesRoot)) {
258
+ throw new Error(`MANAGED_WORKSPACE_DEPENDENCY_INSTALL_INCOMPLETE: ${bootstrap.command.join(' ')} completed without node_modules`);
259
+ }
260
+ return { mode: 'installed', nodeModulesRoot: realpathSync(nodeModulesRoot) };
261
+ }
262
+
263
+ export function materializeManagedWorkspaceCheckDependencies(repoRoot: string): ManagedWorkspaceDependencyPreparation | undefined {
264
+ if (!existsSync(join(repoRoot, 'package.json')) || existsSync(join(repoRoot, 'node_modules'))) return undefined;
265
+ if (!linkedWorkspaceCanonicalRoot(repoRoot)) return undefined;
266
+ return materializeManagedWorkspaceDependencies(repoRoot);
267
+ }
268
+
76
269
  function existingWorkspace(path: string, branch: string): boolean {
77
270
  if (!existsSync(path)) return false;
78
271
  const root = runProcess(resolveGitExecutable(), ['-C', path, 'rev-parse', '--show-toplevel'], {
@@ -109,6 +302,7 @@ export function ensureManagedWorkspace(
109
302
  controllerHome: string,
110
303
  repository: RepositoryRecord,
111
304
  input: EnsureManagedWorkspaceInput,
305
+ dependencies: ManagedWorkspaceDependencies = {},
112
306
  ): ManagedWorkspace {
113
307
  const requestId = input.requestId.trim();
114
308
  if (!requestId) throw new Error('MANAGED_WORKSPACE_REQUEST_ID_REQUIRED');
@@ -159,6 +353,14 @@ export function ensureManagedWorkspace(
159
353
  if (!repositoryCheckoutRootMatches(repository, path)) {
160
354
  throw new Error(`MANAGED_WORKSPACE_REPOSITORY_MISMATCH: ${path}`);
161
355
  }
356
+ if (input.prepareDependencies === true) {
357
+ (dependencies.materializeDependencies ?? materializeManagedWorkspaceDependencies)(path);
358
+ } else {
359
+ // Reusing a byte-equivalent canonical dependency tree is cheap and
360
+ // deterministic, so isolated Work checkouts should get it even when a
361
+ // full package-manager install was not explicitly requested.
362
+ reuseManagedWorkspaceCanonicalDependencies(path);
363
+ }
162
364
 
163
365
  const record = addRepositoryCheckout({
164
366
  repoId: repository.repoId,
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Lightweight run_check facade.
3
3
  *
4
- * Short checks complete via Process Runtime and return results directly.
5
- * Long checks return a Managed Process handle for the same OS process.
4
+ * Ordinary checks execute through an in-memory lightweight handle and return
5
+ * within the interactive budget without creating Process/Lease state. Checks
6
+ * with real Work/Edit/verification consumers keep persisted Process receipts.
6
7
  * Multi-phase and release checks require explicit external Controller handling.
7
8
  */
8
9
 
@@ -15,6 +16,12 @@ import {
15
16
  } from '../../../cli/controller/check-runner';
16
17
  import { claimsForCheck, scopeResourceClaims, toProcessClaims } from './resource-claims';
17
18
  import { spawnManagedProcess, waitForProcess, getProcessHandle } from './runtime';
19
+ import {
20
+ getLightweightProcessHandle,
21
+ isLightweightProcessId,
22
+ startLightweightControllerCheck,
23
+ waitForLightweightProcess,
24
+ } from './lightweight-managed';
18
25
  import type { ProcessHandle } from './types';
19
26
  import { DEFAULT_INTERACTIVE_WAIT_MS } from './types';
20
27
  import { durationAwareInteractiveWaitMs } from './interactive-admission';
@@ -37,10 +44,14 @@ export interface RunCheckFacadeInput {
37
44
  */
38
45
  leaseWaitMs?: number;
39
46
  requestId?: string;
47
+ /** Stable caller-owned semantic identity for safely reattaching the same request before rebuilding ephemeral execution inputs. */
48
+ requestSemanticFingerprint?: string;
40
49
  workId?: string;
41
50
  commandId?: string;
42
51
  /** Force durable workflow (release / multi-phase). */
43
52
  forceDurable?: boolean;
53
+ /** Internal-only: allow an already-authorized external Work Controller to execute a durable-class check through persisted Process Runtime. */
54
+ allowDurableCheckExecution?: boolean;
44
55
  signal?: AbortSignal;
45
56
  /** Immutable resolved identity — required; never inferred from main/active/cwd. */
46
57
  executionIdentity: ResolvedExecutionIdentity;
@@ -143,8 +154,9 @@ export async function runCheckViaProcessRuntime(
143
154
  };
144
155
  }
145
156
 
146
- // Most checks are builds/tests; return their existing Process handle at once.
147
- // Only predictable shell primitives keep a short synchronous admission.
157
+ // The wait budget is an interaction preference, not a persistence reason.
158
+ // Ordinary checks stay in memory; only a real durable evidence consumer may
159
+ // allocate Process/Lease state.
148
160
  const interactiveWaitMs = durationAwareInteractiveWaitMs(
149
161
  check.command,
150
162
  input.interactiveWaitMs,
@@ -156,6 +168,14 @@ export async function runCheckViaProcessRuntime(
156
168
  ? Math.max(1_000, Math.trunc(input.timeoutMs))
157
169
  : check.timeoutMs,
158
170
  );
171
+ const durableVerificationBinding = Boolean(
172
+ input.workId
173
+ || input.verificationSnapshot
174
+ || input.verificationBinding?.executionSessionId
175
+ || input.verificationBinding?.editSessionId
176
+ || input.verificationBinding?.issueId
177
+ || input.verificationBinding?.taskId,
178
+ );
159
179
  if (!input.executionIdentity) {
160
180
  throw new Error('EXECUTION_IDENTITY_REQUIRED: run_check requires an immutable executionIdentity');
161
181
  }
@@ -170,6 +190,27 @@ export async function runCheckViaProcessRuntime(
170
190
  `CHECKOUT_ROUTE_MISMATCH: check checkout ${input.checkoutId} differs from identity ${executionIdentity.checkoutId}`,
171
191
  );
172
192
  }
193
+ if (!durableVerificationBinding) {
194
+ const lightweight = await startLightweightControllerCheck({
195
+ controllerHome: input.controllerHome,
196
+ repoId: input.repoId,
197
+ repoRoot: input.repoRoot,
198
+ checkId: input.checkId,
199
+ interactiveWaitMs,
200
+ timeoutMs,
201
+ workId: input.workId,
202
+ commandId: input.commandId ?? input.requestId,
203
+ });
204
+ const handle = lightweight.handle;
205
+ return {
206
+ mode: handle.completed ? 'direct' : 'managed',
207
+ checkId: input.checkId,
208
+ check,
209
+ process: handle,
210
+ ok: handle.completed ? handle.ok : undefined,
211
+ durableSideEffects: emptyEffects,
212
+ };
213
+ }
173
214
  const claims = scopeResourceClaims(
174
215
  claimsForCheck(
175
216
  input.checkId,
@@ -252,6 +293,9 @@ export async function waitForCheckProcess(
252
293
  processId: string,
253
294
  timeoutMs?: number,
254
295
  ): Promise<ProcessHandle> {
296
+ if (isLightweightProcessId(processId)) {
297
+ return waitForLightweightProcess(controllerHome, repoId, processId, { timeoutMs });
298
+ }
255
299
  return waitForProcess(controllerHome, repoId, processId, { timeoutMs });
256
300
  }
257
301
 
@@ -260,6 +304,9 @@ export function getCheckProcessHandle(
260
304
  repoId: string,
261
305
  processId: string,
262
306
  ): ProcessHandle | undefined {
307
+ if (isLightweightProcessId(processId)) {
308
+ return getLightweightProcessHandle(controllerHome, repoId, processId);
309
+ }
263
310
  return getProcessHandle(controllerHome, repoId, processId);
264
311
  }
265
312
 
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from 'crypto';
2
2
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
3
3
  import { dirname, join } from 'path';
4
4
  import { processLogDir } from './store';
5
+ import type { ManagedProcessRecord } from './types';
5
6
 
6
7
  export interface PersistedCheckResultReceipt {
7
8
  schemaVersion: 1;
@@ -51,3 +52,90 @@ export function readPersistedCheckResultReceipt(path: string | undefined): Persi
51
52
  return undefined;
52
53
  }
53
54
  }
55
+
56
+ export type PersistedCheckTerminalEvidenceState =
57
+ | 'matched'
58
+ | 'process_runtime_failed_before_result'
59
+ | 'missing'
60
+ | 'mismatch';
61
+
62
+ export interface PersistedCheckTerminalEvidence {
63
+ state: PersistedCheckTerminalEvidenceState;
64
+ failureClass?: PersistedCheckResultReceipt['failureClass'];
65
+ warning?: string;
66
+ infrastructureReason?: string;
67
+ }
68
+
69
+ export interface TerminalCheckEvidenceClassificationInput {
70
+ processError?: { code: string; message: string };
71
+ structuredPresent: boolean;
72
+ structuredMatches: boolean;
73
+ legacyPresent: boolean;
74
+ legacyMatches: boolean;
75
+ }
76
+
77
+ /**
78
+ * Compatibility-level classifier for terminal Check evidence. Keep this pure so
79
+ * legacy/public callers and the Process Runtime record adapter share one semantic
80
+ * authority instead of carrying duplicate decision trees.
81
+ */
82
+ export function classifyTerminalCheckEvidence(
83
+ input: TerminalCheckEvidenceClassificationInput,
84
+ ): PersistedCheckTerminalEvidence {
85
+ if (input.structuredMatches || input.legacyMatches) return { state: 'matched' };
86
+ if (!input.structuredPresent && !input.legacyPresent && input.processError?.message?.trim()) {
87
+ const reason = input.processError.message.trim().slice(0, 512);
88
+ return {
89
+ state: 'process_runtime_failed_before_result',
90
+ warning: `check process failed before structured result receipt: ${reason}`,
91
+ infrastructureReason: reason,
92
+ };
93
+ }
94
+ if (input.structuredPresent || input.legacyPresent) {
95
+ return { state: 'mismatch', warning: 'check result receipt did not match the terminal Process semantic identity' };
96
+ }
97
+ return { state: 'missing', warning: 'check result receipt is missing for the terminal Check Process' };
98
+ }
99
+
100
+ /**
101
+ * Classify one terminal Check Process using the structured result emitted by
102
+ * the check-runner sidecar. A Process Runtime/admission failure can terminate
103
+ * before that result exists (for example PROCESS_LEASE_CONFLICT); such a
104
+ * Process is infrastructure failure, never evidence that repository checks
105
+ * rejected the candidate. Missing/mismatched result identity also fails closed
106
+ * as infrastructure rather than manufacturing acceptance evidence.
107
+ */
108
+ export interface LegacyCheckEvidenceLike {
109
+ cacheKey?: string;
110
+ failureClass?: PersistedCheckResultReceipt['failureClass'];
111
+ }
112
+
113
+ export function classifyPersistedCheckTerminalEvidence(
114
+ record: ManagedProcessRecord,
115
+ expectedCheckId: string,
116
+ options: { legacyEvidence?: LegacyCheckEvidenceLike } = {},
117
+ ): PersistedCheckTerminalEvidence {
118
+ const structured = readPersistedCheckResultReceipt(record.origin?.checkResultReceiptPath);
119
+ const structuredMatches = Boolean(
120
+ structured
121
+ && record.checkExecution
122
+ && structured.checkId === expectedCheckId
123
+ && structured.cacheKey === record.checkExecution.cacheKey,
124
+ );
125
+ const legacy = options.legacyEvidence;
126
+ const legacyMatches = Boolean(
127
+ legacy?.cacheKey
128
+ && record.checkExecution?.cacheKey
129
+ && legacy.cacheKey === record.checkExecution.cacheKey,
130
+ );
131
+ const classified = classifyTerminalCheckEvidence({
132
+ processError: record.error,
133
+ structuredPresent: Boolean(structured),
134
+ structuredMatches,
135
+ legacyPresent: Boolean(legacy),
136
+ legacyMatches,
137
+ });
138
+ return classified.state === 'matched'
139
+ ? { ...classified, failureClass: structuredMatches ? structured?.failureClass : legacy?.failureClass }
140
+ : classified;
141
+ }
@@ -16,6 +16,7 @@ interface ParsedArgs {
16
16
  expectedCheckFingerprint: string;
17
17
  resultReceiptPath?: string;
18
18
  cleanupRoot?: string;
19
+ isolatedControllerHome?: string;
19
20
  }
20
21
 
21
22
  function requiredValue(argv: string[], flag: string): string {
@@ -38,6 +39,7 @@ function parseArgs(argv: string[]): ParsedArgs {
38
39
  expectedCheckFingerprint: requiredValue(argv, '--expected-check-fingerprint'),
39
40
  resultReceiptPath: argv.includes('--result-receipt') ? requiredValue(argv, '--result-receipt') : undefined,
40
41
  cleanupRoot: argv.includes('--cleanup-root') ? requiredValue(argv, '--cleanup-root') : undefined,
42
+ isolatedControllerHome: argv.includes('--isolated-controller-home') ? requiredValue(argv, '--isolated-controller-home') : undefined,
41
43
  };
42
44
  }
43
45
 
@@ -51,7 +53,11 @@ export async function runPersistedCheckSidecar(argv = process.argv.slice(2)): Pr
51
53
  throw new Error('CHECK_SNAPSHOT_CHANGED: registered check changed before Process Runtime execution');
52
54
  }
53
55
  const identity = controllerCheckExecutionIdentity(root, args.checkId, args.timeoutMs, snapshot);
54
- const result = await runControllerCheckAsync(root, args.checkId, { requestedTimeoutMs: args.timeoutMs, snapshot });
56
+ const result = await runControllerCheckAsync(root, args.checkId, {
57
+ requestedTimeoutMs: args.timeoutMs,
58
+ snapshot,
59
+ isolatedControllerHome: args.isolatedControllerHome,
60
+ });
55
61
  if (args.resultReceiptPath) {
56
62
  writePersistedCheckResultReceipt(args.resultReceiptPath, {
57
63
  checkId: args.checkId,
@@ -0,0 +1,114 @@
1
+ import type { ControllerCheck } from '../../../cli/controller/check-runner';
2
+ import type { ResourceClaimSpec } from '../jobs/types';
3
+ import { resourceClaimsConflict } from '../../resources/claims/conflicts';
4
+ import { claimsForCheck } from './resource-claims';
5
+
6
+ export interface CheckExecutionWave {
7
+ wave: number;
8
+ checkIds: string[];
9
+ parallelSafe: boolean;
10
+ }
11
+
12
+ export interface CheckExecutionConflict {
13
+ leftCheckId: string;
14
+ rightCheckId: string;
15
+ resources: Array<{
16
+ left: Pick<ResourceClaimSpec, 'resourceKey' | 'mode'>;
17
+ right: Pick<ResourceClaimSpec, 'resourceKey' | 'mode'>;
18
+ }>;
19
+ }
20
+
21
+ interface ScheduledCheck {
22
+ check: ControllerCheck;
23
+ claims: ResourceClaimSpec[];
24
+ }
25
+
26
+ function conflictingResources(left: ScheduledCheck, right: ScheduledCheck): CheckExecutionConflict['resources'] {
27
+ const conflicts: CheckExecutionConflict['resources'] = [];
28
+ for (const leftClaim of left.claims) {
29
+ for (const rightClaim of right.claims) {
30
+ if (!resourceClaimsConflict(leftClaim, rightClaim)) continue;
31
+ conflicts.push({
32
+ left: { resourceKey: leftClaim.resourceKey, mode: leftClaim.mode },
33
+ right: { resourceKey: rightClaim.resourceKey, mode: rightClaim.mode },
34
+ });
35
+ }
36
+ }
37
+ return conflicts;
38
+ }
39
+
40
+ /**
41
+ * Produce deterministic execution waves from the exact same resource-claim model
42
+ * used by Process Runtime. Checks in one wave may overlap; waves run in order.
43
+ * This is advisory scheduling metadata, not a second lease authority.
44
+ */
45
+ export function buildCheckExecutionSchedule(input: {
46
+ checks: ControllerCheck[];
47
+ requestedCheckIds: string[];
48
+ repoId: string;
49
+ checkoutId?: string;
50
+ }): {
51
+ waves: CheckExecutionWave[];
52
+ conflicts: CheckExecutionConflict[];
53
+ invalidCheckIds: string[];
54
+ maxParallel: number;
55
+ guidance: string[];
56
+ claimsByCheck: Array<{ checkId: string; claims: Array<Pick<ResourceClaimSpec, 'resourceKey' | 'mode'>> }>;
57
+ } {
58
+ const byId = new Map(input.checks.map((check) => [check.id, check]));
59
+ const requested = [...new Set(input.requestedCheckIds.filter(Boolean))];
60
+ const invalidCheckIds = requested.filter((checkId) => !byId.has(checkId));
61
+ const scheduled: ScheduledCheck[] = requested.flatMap((checkId) => {
62
+ const check = byId.get(checkId);
63
+ if (!check) return [];
64
+ return [{
65
+ check,
66
+ claims: claimsForCheck(check.id, check.command, input.repoId, input.checkoutId, check.effects),
67
+ }];
68
+ });
69
+
70
+ const conflicts: CheckExecutionConflict[] = [];
71
+ for (let leftIndex = 0; leftIndex < scheduled.length; leftIndex += 1) {
72
+ for (let rightIndex = leftIndex + 1; rightIndex < scheduled.length; rightIndex += 1) {
73
+ const left = scheduled[leftIndex]!;
74
+ const right = scheduled[rightIndex]!;
75
+ const resources = conflictingResources(left, right);
76
+ if (resources.length === 0) continue;
77
+ conflicts.push({ leftCheckId: left.check.id, rightCheckId: right.check.id, resources });
78
+ }
79
+ }
80
+
81
+ const waves: ScheduledCheck[][] = [];
82
+ for (const entry of scheduled) {
83
+ const compatible = waves.find((wave) => wave.every((other) => conflictingResources(entry, other).length === 0));
84
+ if (compatible) compatible.push(entry);
85
+ else waves.push([entry]);
86
+ }
87
+
88
+ const projectedWaves = waves.map((wave, index) => ({
89
+ wave: index + 1,
90
+ checkIds: wave.map((entry) => entry.check.id),
91
+ parallelSafe: wave.length > 1,
92
+ }));
93
+ const maxParallel = projectedWaves.reduce((max, wave) => Math.max(max, wave.checkIds.length), 0);
94
+ const guidance: string[] = [];
95
+ if (projectedWaves.length > 1) {
96
+ guidance.push('Run check waves in order; only checks within the same wave are resource-compatible for overlap.');
97
+ } else if (maxParallel > 1) {
98
+ guidance.push('Requested checks are resource-compatible and may run concurrently for this checkout.');
99
+ } else if (maxParallel === 1) {
100
+ guidance.push('Run the requested check as one focused verification unit.');
101
+ }
102
+
103
+ return {
104
+ waves: projectedWaves,
105
+ conflicts,
106
+ invalidCheckIds,
107
+ maxParallel,
108
+ guidance,
109
+ claimsByCheck: scheduled.map((entry) => ({
110
+ checkId: entry.check.id,
111
+ claims: entry.claims.map((claim) => ({ resourceKey: claim.resourceKey, mode: claim.mode })),
112
+ })),
113
+ };
114
+ }