@moretea-labs/forge 1.7.2 → 1.8.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 (900) hide show
  1. package/AGENTS.md +121 -62
  2. package/CHANGELOG.md +40 -0
  3. package/CLAUDE.md +57 -62
  4. package/CONTRIBUTING.md +3 -2
  5. package/README.md +2 -2
  6. package/SKILL.md +0 -1
  7. package/THIRD_PARTY_NOTICES.md +5 -2
  8. package/adapters/browser/index.ts +2 -0
  9. package/adapters/chatgpt/browser-delivery-host.ts +77 -0
  10. package/adapters/chatgpt/browser-delivery-runtime.ts +1256 -0
  11. package/adapters/chatgpt/controller-binding-store.ts +134 -0
  12. package/adapters/chatgpt/controller-round-host.ts +68 -0
  13. package/adapters/chatgpt/controller-round-settlement-store.ts +99 -0
  14. package/adapters/chatgpt/provider-delivery.ts +340 -0
  15. package/adapters/chatgpt/work-conversation-binding-store.ts +218 -0
  16. package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
  17. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  18. package/adapters/computer/chatgpt-target-router.ts +103 -0
  19. package/adapters/computer/chrome-extension/background.js +385 -0
  20. package/adapters/computer/chrome-extension/content.js +378 -0
  21. package/adapters/computer/chrome-extension/core.js +24 -0
  22. package/adapters/computer/chrome-extension/manifest.json +30 -0
  23. package/adapters/computer/desktop-operator-contract.ts +7 -0
  24. package/adapters/computer/desktop-operator-discovery.ts +181 -0
  25. package/adapters/computer/desktop-operator-negotiation.ts +174 -0
  26. package/adapters/computer/desktop-operator-provider.ts +312 -0
  27. package/adapters/computer/index.ts +1 -0
  28. package/adapters/computer/interaction-target-authority.ts +1068 -0
  29. package/adapters/controller-process/binding-store.ts +34 -0
  30. package/adapters/controller-process/controller-host.ts +26 -0
  31. package/adapters/mcp/access-mode.ts +132 -0
  32. package/adapters/mcp/audit.ts +32 -0
  33. package/adapters/mcp/auth.ts +406 -0
  34. package/adapters/mcp/instructions.ts +37 -0
  35. package/adapters/mcp/legacy-context.ts +18 -0
  36. package/adapters/mcp/multi-repository.ts +421 -0
  37. package/adapters/mcp/oauth.ts +464 -0
  38. package/adapters/mcp/paths.ts +143 -0
  39. package/adapters/mcp/policy.ts +232 -0
  40. package/adapters/mcp/proxy-env.ts +62 -0
  41. package/adapters/mcp/readiness-projection.ts +24 -0
  42. package/adapters/mcp/redaction.ts +21 -0
  43. package/adapters/mcp/repo.ts +24 -0
  44. package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
  45. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  46. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  47. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  48. package/adapters/mcp/runtime-gateway/context-adapter.ts +1167 -0
  49. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  50. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +206 -0
  51. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  52. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +130 -0
  53. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  54. package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
  55. package/adapters/mcp/runtime-gateway/execution-tools.ts +173 -0
  56. package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
  57. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +412 -0
  58. package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
  59. package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
  60. package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
  61. package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
  62. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +380 -0
  63. package/adapters/mcp/runtime-gateway/process-tools.ts +457 -0
  64. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +88 -0
  65. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +285 -0
  66. package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
  67. package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
  68. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +79 -0
  69. package/adapters/mcp/runtime-gateway/result-adapter.ts +114 -0
  70. package/adapters/mcp/runtime-gateway/router.ts +242 -0
  71. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  72. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1200 -0
  73. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  74. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +574 -0
  75. package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
  76. package/adapters/mcp/runtime-gateway/runtime-tools.ts +78 -0
  77. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +187 -0
  78. package/adapters/mcp/runtime-gateway/shared-adapter.ts +45 -0
  79. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +962 -0
  80. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  81. package/adapters/mcp/runtime-gateway/work-adapter.ts +325 -0
  82. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  83. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  84. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  85. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  86. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  87. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  88. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  89. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  90. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  91. package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
  92. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  93. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  94. package/adapters/mcp/server.ts +1092 -0
  95. package/adapters/mcp/setup.ts +789 -0
  96. package/adapters/mcp/tool-capability-cache.ts +87 -0
  97. package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
  98. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5139 -0
  99. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +145 -0
  100. package/adapters/mcp/tool-mapping/repository-tools.ts +1682 -0
  101. package/adapters/mcp/tool-mapping/tools.ts +9 -0
  102. package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
  103. package/adapters/mcp/toolset-names.ts +79 -0
  104. package/adapters/mcp/toolset-selection.ts +41 -0
  105. package/adapters/mcp/toolset.ts +337 -0
  106. package/adapters/mcp/transports/http-observation.ts +365 -0
  107. package/adapters/mcp/transports/http.ts +933 -0
  108. package/adapters/mcp/transports/oauth-http.ts +322 -0
  109. package/adapters/mcp/transports/session-registry.ts +519 -0
  110. package/adapters/mcp/transports/stdio.ts +8 -0
  111. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +223 -0
  112. package/adapters/mcp/types.ts +41 -0
  113. package/assets/AGENTS.md +2 -16
  114. package/assets/CLAUDE.md +2 -16
  115. package/assets/hooks/AGENTS.md +3 -14
  116. package/assets/hooks/CLAUDE.md +3 -14
  117. package/assets/hooks/hook-input.sh +9 -2
  118. package/assets/hooks/lib/workflow-state.sh +28 -10
  119. package/assets/hooks/prompt-guard.sh +63 -37
  120. package/assets/hooks/security-sentinel.sh +2 -1
  121. package/assets/hooks/session-start-context.sh +7 -5
  122. package/assets/hooks/stop-orchestrator.sh +13 -3
  123. package/assets/initializer-question-pack.v4.json +11 -7
  124. package/assets/partials/05-workflow.partial.md +18 -73
  125. package/assets/partials/07-footer.partial.md +1 -1
  126. package/assets/partials-agents/02-operating-mode.partial.md +1 -2
  127. package/assets/partials-agents/04-task-protocol.partial.md +14 -59
  128. package/assets/partials-agents/06-quality-safety.partial.md +11 -16
  129. package/assets/partials-agents/08-deep-docs.partial.md +1 -2
  130. package/assets/plan-map.json +11 -11
  131. package/assets/plugin-registry.v1.json +11 -3
  132. package/assets/plugin-trust-policy.v1.json +6 -0
  133. package/assets/recovery/ForgeRecovery.ps1 +100 -0
  134. package/assets/recovery/forge-wsl-rescue +271 -0
  135. package/assets/reference-configs/agentic-development-flow.md +25 -0
  136. package/assets/reference-configs/development-protocol.md +11 -15
  137. package/assets/reference-configs/document-generation.md +1 -1
  138. package/assets/reference-configs/global-working-rules.md +28 -1
  139. package/assets/reference-configs/harness-overview.md +22 -112
  140. package/assets/reference-configs/hook-operations.md +1 -1
  141. package/assets/reference-configs/sprint-contracts.md +2 -2
  142. package/assets/skill-version.json +2 -2
  143. package/assets/templates/helpers/architecture-event.ts +3 -34
  144. package/assets/templates/helpers/architecture-queue.sh +61 -10
  145. package/assets/templates/helpers/archive-workflow.sh +90 -180
  146. package/assets/templates/helpers/capability-config.ts +8 -11
  147. package/assets/templates/helpers/capability-resolver.ts +37 -19
  148. package/assets/templates/helpers/capture-plan.sh +2 -2
  149. package/assets/templates/helpers/check-architecture-sync.sh +1 -9
  150. package/assets/templates/helpers/check-task-sync.sh +82 -11
  151. package/assets/templates/helpers/check-task-workflow.sh +1 -3
  152. package/assets/templates/helpers/context-contract-sync.sh +1 -12
  153. package/assets/templates/helpers/contract-worktree.sh +26 -24
  154. package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
  155. package/assets/templates/helpers/inspect-project-state.ts +1 -1
  156. package/assets/templates/helpers/migrate-project-template.sh +1 -1
  157. package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
  158. package/assets/templates/helpers/new-plan.sh +2 -2
  159. package/assets/templates/helpers/plan-to-todo.sh +3 -31
  160. package/assets/templates/helpers/sprint-backlog.sh +1 -1
  161. package/assets/templates/helpers/switch-plan.sh +1 -1
  162. package/assets/templates/helpers/workflow-contract.ts +1 -0
  163. package/assets/workflow-contract.v1.json +63 -171
  164. package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
  165. package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
  166. package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
  167. package/docs/architecture/CURRENT.md +233 -28
  168. package/docs/architecture/EVOLUTION.md +13 -0
  169. package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
  170. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  171. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  172. package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
  173. package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
  174. package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
  175. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +37 -0
  176. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +311 -0
  177. package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
  178. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  179. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  180. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  181. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  182. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  183. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  184. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  185. package/docs/architecture/domains/verification.md +8 -0
  186. package/docs/architecture/domains/workflow-engine.md +7 -1
  187. package/docs/architecture/index.md +3 -3
  188. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
  189. package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
  190. package/docs/forge-chatgpt-mcp-setup.md +5 -3
  191. package/docs/forge-plugin-management.md +20 -4
  192. package/docs/forge-runtime-self-healing-loop.md +2 -0
  193. package/docs/operations/benchmark-cross-version-freeze.md +38 -0
  194. package/docs/operations/controller-browser-plugin.md +3 -1
  195. package/docs/operations/controller-performance-and-502.md +17 -0
  196. package/docs/operations/controller-reliability-runbook.md +2 -2
  197. package/docs/operations/features.md +1 -1
  198. package/docs/operations/features.zh-CN.md +1 -1
  199. package/docs/operations/homebrew.md +2 -2
  200. package/docs/operations/mcp-tool-exposure.md +2 -0
  201. package/docs/operations/platform-support.md +16 -8
  202. package/docs/operations/platform-support.zh-CN.md +2 -2
  203. package/docs/operations/releasing.md +2 -0
  204. package/docs/operations/standalone-disaster-recovery.md +38 -5
  205. package/docs/operations/uu-remote-rescue.md +41 -0
  206. package/docs/operations/windows-wsl-host-rescue.md +133 -0
  207. package/docs/public-usage-guide.md +1 -1
  208. package/docs/public-usage-guide.zh-CN.md +1 -1
  209. package/docs/tutorials/01-install-and-start.md +1 -1
  210. package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
  211. package/docs/tutorials/02-connect-chatgpt.md +4 -4
  212. package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
  213. package/docs/wiki/Implementation.md +1 -1
  214. package/package.json +46 -26
  215. package/packages/kernel/cognition/api/index.ts +6 -0
  216. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  217. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  218. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  219. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  220. package/packages/kernel/cognition/domain/learning.ts +106 -0
  221. package/packages/kernel/cognition/domain/memory.ts +254 -0
  222. package/packages/kernel/controller/api/index.ts +3 -0
  223. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  224. package/packages/kernel/controller/application/controller-round-service.ts +41 -0
  225. package/packages/kernel/controller/application/controller-service.ts +30 -0
  226. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +529 -0
  227. package/packages/kernel/controller/domain/controller-round.ts +110 -0
  228. package/packages/kernel/controller/domain/execution-quality.ts +135 -0
  229. package/packages/kernel/controller/domain/types.ts +56 -0
  230. package/packages/kernel/controller/index.ts +1 -0
  231. package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
  232. package/packages/kernel/controller/infrastructure/controller-round-store.ts +1970 -0
  233. package/packages/kernel/controller/infrastructure/controller-session-store.ts +804 -0
  234. package/packages/kernel/controller/ports/controller-host.ts +18 -0
  235. package/packages/kernel/goal/api/index.ts +1 -0
  236. package/packages/kernel/goal/domain/types.ts +40 -0
  237. package/packages/kernel/goal/index.ts +1 -0
  238. package/packages/kernel/identity/api/index.ts +15 -0
  239. package/packages/kernel/identity/application/identity-service.ts +67 -0
  240. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  241. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  242. package/packages/kernel/identity/domain/grant.ts +72 -0
  243. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  244. package/packages/kernel/identity/domain/scope.ts +63 -0
  245. package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
  246. package/packages/kernel/identity/domain/types.ts +44 -0
  247. package/packages/kernel/identity/domain/user-request.ts +93 -0
  248. package/packages/kernel/identity/domain/workspace.ts +56 -0
  249. package/packages/kernel/identity/index.ts +1 -0
  250. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  251. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  252. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  253. package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
  254. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  255. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  256. package/packages/kernel/memory/api/index.ts +5 -0
  257. package/packages/kernel/memory/application/experience-service.ts +118 -0
  258. package/packages/kernel/memory/application/outcome-service.ts +77 -0
  259. package/packages/kernel/memory/domain/experience.ts +103 -0
  260. package/packages/kernel/memory/domain/operational-prior.ts +92 -0
  261. package/packages/kernel/memory/index.ts +1 -0
  262. package/packages/kernel/scheduler/api/index.ts +4 -0
  263. package/packages/kernel/scheduler/application/eligibility.ts +252 -0
  264. package/packages/kernel/scheduler/application/schedule-service.ts +27 -0
  265. package/packages/kernel/scheduler/application/settlement.ts +182 -0
  266. package/packages/kernel/scheduler/domain/schedule.ts +236 -0
  267. package/packages/kernel/scheduler/index.ts +1 -0
  268. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +805 -0
  269. package/packages/kernel/work/api/index.ts +16 -0
  270. package/packages/kernel/work/application/work-service.ts +123 -0
  271. package/packages/kernel/work/domain/check-receipt.ts +43 -0
  272. package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
  273. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  274. package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
  275. package/packages/kernel/work/domain/engineering-design.ts +286 -0
  276. package/packages/kernel/work/domain/engineering-profile.ts +238 -0
  277. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  278. package/packages/kernel/work/domain/execution-concurrency.ts +247 -0
  279. package/packages/kernel/work/domain/execution-snapshot.ts +2 -0
  280. package/packages/kernel/work/domain/implementation-review.ts +193 -0
  281. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  282. package/packages/kernel/work/domain/project-engineering-contract.ts +224 -0
  283. package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
  284. package/{src/runtime/control-plane/facade/work-state-machine.ts → packages/kernel/work/domain/state-machine.ts} +37 -66
  285. package/packages/kernel/work/domain/types.ts +534 -0
  286. package/packages/kernel/work/index.ts +1 -0
  287. package/packages/kernel/work/infrastructure/work-contract-store.ts +1967 -0
  288. package/packages/kernel/work/ports/work-contract-store.ts +21 -0
  289. package/packages/plugin-runtime/browser/index.ts +3 -0
  290. package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
  291. package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
  292. package/packages/plugin-runtime/browser/session-authority.ts +62 -0
  293. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  294. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  295. package/packages/plugin-runtime/computer/index.ts +8 -0
  296. package/packages/plugin-runtime/computer/provider-error.ts +26 -0
  297. package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
  298. package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
  299. package/packages/plugin-runtime/computer/provider.ts +19 -0
  300. package/packages/plugin-runtime/computer/target-authority.ts +215 -0
  301. package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
  302. package/packages/plugin-runtime/external/index.ts +1 -0
  303. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +581 -0
  304. package/packages/plugin-runtime/index.ts +3 -0
  305. package/packages/protocols/browser/index.ts +1 -0
  306. package/packages/protocols/browser/session.ts +98 -0
  307. package/packages/protocols/computer/contract.ts +225 -0
  308. package/packages/protocols/computer/index.ts +1 -0
  309. package/packages/protocols/failure/contract.ts +158 -0
  310. package/packages/protocols/failure/index.ts +1 -0
  311. package/packages/protocols/handoff/index.ts +1 -0
  312. package/packages/protocols/handoff/status.ts +22 -0
  313. package/packages/protocols/mcp/execution-context.ts +11 -0
  314. package/packages/protocols/mcp/index.ts +2 -0
  315. package/packages/protocols/mcp/tool-contract.ts +42 -0
  316. package/packages/workflow-runtime/api/index.ts +2 -0
  317. package/packages/workflow-runtime/application/interpreter.ts +342 -0
  318. package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
  319. package/packages/workflow-runtime/index.ts +1 -0
  320. package/scripts/activate-source-baseline.ts +7 -9
  321. package/scripts/assemble-template.ts +1 -1
  322. package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
  323. package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
  324. package/scripts/canary-controller-semantic-wait.ts +183 -0
  325. package/scripts/canary-global-hook.sh +2 -2
  326. package/scripts/check-mcp-compatibility.ts +85 -7
  327. package/scripts/check-platform-support.mjs +28 -2
  328. package/scripts/check-public-docs.sh +1 -1
  329. package/scripts/check-repository-hygiene.mjs +92 -0
  330. package/scripts/check-runtime-architecture.mjs +1643 -127
  331. package/scripts/check-source-duplication.mjs +9 -1
  332. package/scripts/controller-ngrok-rotation.sh +5 -4
  333. package/scripts/create-project-dirs.sh +10 -74
  334. package/scripts/forge-local-recovery-helper.mjs +282 -0
  335. package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
  336. package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
  337. package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
  338. package/scripts/hook-shim.sh +2 -2
  339. package/scripts/init-project.sh +12 -70
  340. package/scripts/install-desktop-operator-registration.ts +4 -2
  341. package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
  342. package/scripts/install-standalone-recovery.ts +122 -10
  343. package/scripts/install-uu-remote-rescue-registration.ts +74 -0
  344. package/scripts/install-windows-host-recovery-registration.ts +22 -0
  345. package/scripts/lib/controller-home-env.sh +6 -3
  346. package/scripts/lib/project-init-lib.sh +42 -582
  347. package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
  348. package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
  349. package/scripts/open-source-audit-allowlist.txt +11 -1
  350. package/scripts/portability-bindings.mjs +70 -0
  351. package/scripts/run-bounded-command.mjs +60 -0
  352. package/scripts/run-bun-test-file.ts +22 -6
  353. package/scripts/run-governed-gate.ts +4 -2
  354. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  355. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  356. package/scripts/smoke-mcp-http-runtime.ts +6 -1
  357. package/scripts/smoke-runtime-recovery.ts +13 -11
  358. package/scripts/smoke-schedule-engine.ts +24 -16
  359. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  360. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  361. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  362. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  363. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  364. package/scripts/smoke-workflow-supervisor.ts +103 -0
  365. package/scripts/test-governance.ts +51 -2
  366. package/scripts/verify-forge-runtime.sh +2 -1
  367. package/src/cli/agent-jobs/executor-health.ts +11 -34
  368. package/src/cli/agent-jobs/integration.ts +18 -49
  369. package/src/cli/agent-jobs/job-manager.ts +17 -4
  370. package/src/cli/chatgpt-browser/bind-server.ts +2 -1
  371. package/src/cli/chatgpt-browser/binding.ts +20 -10
  372. package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
  373. package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
  374. package/src/cli/chatgpt-browser/engine.ts +10 -11
  375. package/src/cli/chatgpt-browser/native-provider.ts +24 -83
  376. package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
  377. package/src/cli/chatgpt-browser/types.ts +1 -0
  378. package/src/cli/commands/bootstrap-control.ts +334 -0
  379. package/src/cli/commands/brain-assistant.ts +52 -0
  380. package/src/cli/commands/brain.ts +191 -40
  381. package/src/cli/commands/chatgpt.ts +32 -67
  382. package/src/cli/commands/computer.ts +437 -0
  383. package/src/cli/commands/doctor.ts +18 -1
  384. package/src/cli/commands/init-hook.ts +71 -61
  385. package/src/cli/commands/init.ts +3 -1
  386. package/src/cli/commands/mcp.ts +16 -10
  387. package/src/cli/commands/plugin.ts +38 -12
  388. package/src/cli/commands/recovery.ts +507 -80
  389. package/src/cli/commands/runtime.ts +12 -7
  390. package/src/cli/commands/setup-profile.ts +97 -39
  391. package/src/cli/commands/status.ts +2 -1
  392. package/src/cli/controller/check-runner.ts +500 -100
  393. package/src/cli/controller/completion-backlog.ts +3 -3
  394. package/src/cli/controller/completion-orchestrator.ts +4 -43
  395. package/src/cli/controller/completion-target.ts +3 -72
  396. package/src/cli/controller/context/source-materializer.ts +81 -100
  397. package/src/cli/controller/context/types.ts +7 -1
  398. package/src/cli/controller/context-pack.ts +28 -6
  399. package/src/cli/controller/execution-completion.ts +4 -7
  400. package/src/cli/controller/execution-policy.ts +36 -153
  401. package/src/cli/controller/governance.ts +2 -3
  402. package/src/cli/controller/issue-store.ts +4 -99
  403. package/src/cli/controller/launch-agents.ts +59 -18
  404. package/src/cli/controller/operational-plan.ts +24 -51
  405. package/src/cli/controller/runtime-config.ts +5 -1
  406. package/src/cli/controller/stuck-state-migration.ts +2 -3
  407. package/src/cli/controller/systemd-user.ts +148 -0
  408. package/src/cli/controller/types.ts +10 -70
  409. package/src/cli/controller/worklog.ts +67 -13
  410. package/src/cli/editing/edit-operation-contract.ts +92 -0
  411. package/src/cli/editing/edit-session.ts +290 -20
  412. package/src/cli/github/plugin.ts +17 -12
  413. package/src/cli/hook/route-registry.ts +3 -5
  414. package/src/cli/hook/runtime.ts +49 -3
  415. package/src/cli/index.ts +3 -0
  416. package/src/cli/local-bridge/connector-freshness.ts +2 -2
  417. package/src/cli/local-bridge/console-automations.ts +20 -15
  418. package/src/cli/local-bridge/console-view-models.ts +3 -12
  419. package/src/cli/local-bridge/facade-api.ts +105 -205
  420. package/src/cli/local-bridge/job-store.ts +1 -1
  421. package/src/cli/local-bridge/server.ts +48 -174
  422. package/src/cli/local-bridge/types.ts +0 -1
  423. package/src/cli/mcp/access-mode.ts +2 -132
  424. package/src/cli/mcp/access-tools.ts +2 -387
  425. package/src/cli/mcp/audit.ts +2 -32
  426. package/src/cli/mcp/auth.ts +2 -404
  427. package/src/cli/mcp/instructions.ts +2 -34
  428. package/src/cli/mcp/legacy-context.ts +2 -16
  429. package/src/cli/mcp/legacy-tool-service.ts +2 -5308
  430. package/src/cli/mcp/multi-repository.ts +2 -436
  431. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  432. package/src/cli/mcp/oauth.ts +2 -375
  433. package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
  434. package/src/cli/mcp/paths.ts +2 -140
  435. package/src/cli/mcp/policy.ts +2 -232
  436. package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
  437. package/src/cli/mcp/proxy-env.ts +2 -62
  438. package/src/cli/mcp/readiness-projection.ts +2 -24
  439. package/src/cli/mcp/redaction.ts +2 -21
  440. package/src/cli/mcp/repo.ts +2 -24
  441. package/src/cli/mcp/repository-tools.ts +2 -1613
  442. package/src/cli/mcp/server.ts +2 -951
  443. package/src/cli/mcp/setup.ts +2 -737
  444. package/src/cli/mcp/tool-capability-cache.ts +2 -87
  445. package/src/cli/mcp/tool-contract.ts +2 -14
  446. package/src/cli/mcp/tools.ts +2 -9
  447. package/src/cli/mcp/toolset-names.ts +2 -70
  448. package/src/cli/mcp/toolset-selection.ts +2 -41
  449. package/src/cli/mcp/toolset.ts +2 -336
  450. package/src/cli/mcp/transports/AGENTS.md +1 -10
  451. package/src/cli/mcp/transports/CLAUDE.md +1 -10
  452. package/src/cli/mcp/transports/http.ts +2 -1414
  453. package/src/cli/mcp/transports/session-registry.ts +2 -490
  454. package/src/cli/mcp/transports/stdio.ts +2 -8
  455. package/src/cli/mcp/types.ts +2 -41
  456. package/src/cli/mcp/umbrella-tools.ts +2 -117
  457. package/src/cli/repositories/command-executor.ts +91 -39
  458. package/src/cli/repositories/command-scope.ts +139 -4
  459. package/src/cli/repositories/controller-home.ts +167 -1
  460. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  461. package/src/cli/repositories/git-command-executor.ts +2 -2
  462. package/src/cli/repositories/identity.ts +13 -0
  463. package/src/cli/repositories/registry.ts +145 -60
  464. package/src/cli/repositories/repository-snapshot.ts +53 -7
  465. package/src/cli/repositories/runtime-storage.ts +27 -2
  466. package/src/cli/repositories/safe-patch.ts +34 -38
  467. package/src/cli/repositories/selected-path-actions.ts +22 -2
  468. package/src/cli/repositories/structured-git.ts +167 -27
  469. package/src/cli/repository/session-cache.ts +92 -6
  470. package/src/cli/runtime/helper-runner.ts +7 -0
  471. package/src/cli/runtime-invocation.ts +8 -1
  472. package/src/cli/tools/codegraph.ts +44 -25
  473. package/src/core/adoption/manifest-templates.ts +1 -1
  474. package/src/core/adoption/plan.ts +3 -26
  475. package/src/core/adoption/workflow-contract-plan.ts +17 -9
  476. package/src/effects/process-runner.ts +8 -14
  477. package/src/runtime/context/assistant-context.ts +167 -0
  478. package/src/runtime/context/assistant-work-context.ts +209 -0
  479. package/src/runtime/context/automatic-learning.ts +565 -0
  480. package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
  481. package/src/runtime/context/codegraph-read-provider.ts +55 -22
  482. package/src/runtime/context/codegraph-sidecar.cjs +8 -1
  483. package/src/runtime/context/cognitive-attention.ts +173 -0
  484. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  485. package/src/runtime/context/context-closure.ts +305 -0
  486. package/src/runtime/context/context-pack-process.ts +103 -0
  487. package/src/runtime/context/context-plane.ts +203 -0
  488. package/src/runtime/context/direct-controller-learning.ts +298 -0
  489. package/src/runtime/context/project-engineering-contract.ts +60 -0
  490. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  491. package/src/runtime/context/semantic-navigation.ts +6 -34
  492. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  493. package/src/runtime/context/typescript-navigation.ts +89 -3
  494. package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
  495. package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
  496. package/src/runtime/control-plane/bootstrap/index.ts +5 -0
  497. package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
  498. package/src/runtime/control-plane/bootstrap/store.ts +21 -0
  499. package/src/runtime/control-plane/bootstrap/types.ts +87 -0
  500. package/src/runtime/control-plane/cleanup-artifact-retention.ts +531 -0
  501. package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
  502. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +282 -0
  503. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +380 -0
  504. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +113 -16
  505. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  506. package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
  507. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  508. package/src/runtime/control-plane/execution/retained-work-resume.ts +439 -102
  509. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  510. package/src/runtime/control-plane/execution/validation.ts +34 -11
  511. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +87 -0
  512. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  513. package/src/runtime/control-plane/execution/work-completion-authority.ts +31 -44
  514. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  515. package/src/runtime/control-plane/execution/work-evidence-policy.ts +46 -53
  516. package/src/runtime/control-plane/execution/work-execution-support.ts +85 -164
  517. package/src/runtime/control-plane/execution/work-handle-authority.ts +349 -73
  518. package/src/runtime/control-plane/execution/work-handle-store.ts +55 -2
  519. package/src/runtime/control-plane/execution/work-head-settlement.ts +108 -0
  520. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +173 -28
  521. package/src/runtime/control-plane/execution/work-operation-service.ts +92 -40
  522. package/src/runtime/control-plane/execution/work-preparation-service.ts +145 -269
  523. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  524. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  525. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +543 -225
  526. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +59 -45
  527. package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
  528. package/src/runtime/control-plane/execution/work-verification-service.ts +662 -52
  529. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +205 -16
  530. package/src/runtime/control-plane/facade/capability-registry.ts +380 -44
  531. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  532. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  533. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  534. package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
  535. package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -22
  536. package/src/runtime/control-plane/facade/goal-workloop.ts +565 -1202
  537. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +145 -0
  538. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +266 -52
  539. package/src/runtime/control-plane/facade/index.ts +4 -3
  540. package/src/runtime/control-plane/facade/operation-digest.ts +34 -73
  541. package/src/runtime/control-plane/facade/plan-contract-store.ts +671 -245
  542. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  543. package/src/runtime/control-plane/facade/repository-work-admission.ts +31 -23
  544. package/src/runtime/control-plane/facade/requirement-authority.ts +121 -0
  545. package/src/runtime/control-plane/facade/requirement-board.ts +9 -4
  546. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +85 -0
  547. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  548. package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
  549. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -15
  550. package/src/runtime/control-plane/facade/types.ts +218 -620
  551. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  552. package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
  553. package/src/runtime/control-plane/generated-cache-retention.ts +336 -19
  554. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  555. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +13 -2
  556. package/src/runtime/control-plane/global-scheduler/maintenance.ts +274 -84
  557. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
  558. package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
  559. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -2
  560. package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
  561. package/src/runtime/control-plane/global-scheduler/scheduler.ts +227 -109
  562. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  563. package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
  564. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  565. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  566. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +160 -0
  567. package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
  568. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +139 -670
  569. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  570. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +25 -6
  571. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -194
  572. package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
  573. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  574. package/src/runtime/control-plane/persistence/experience-store.ts +302 -0
  575. package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
  576. package/src/runtime/control-plane/persistence/requirement-store.ts +230 -80
  577. package/src/runtime/control-plane/persistence/sqlite-store.ts +654 -78
  578. package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
  579. package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
  580. package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
  581. package/src/runtime/control-plane/release-retention.ts +154 -26
  582. package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
  583. package/src/runtime/control-plane/runtime-cleanup.ts +844 -38
  584. package/src/runtime/control-plane/runtime-generation.ts +6 -0
  585. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  586. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +479 -0
  587. package/src/runtime/control-plane/workspace/workspace-store.ts +249 -0
  588. package/src/runtime/diagnostics/incident-repair.ts +573 -0
  589. package/src/runtime/diagnostics/mcp-timing.ts +239 -6
  590. package/src/runtime/diagnostics/performance.ts +6 -14
  591. package/src/runtime/diagnostics/read-only-tool.ts +1 -1
  592. package/src/runtime/evidence/artifact-store.ts +216 -35
  593. package/src/runtime/evidence/evidence-store.ts +112 -8
  594. package/src/runtime/evidence/operational-shadow.ts +38 -0
  595. package/src/runtime/evidence/output-handle-index.ts +225 -0
  596. package/src/runtime/evidence/process-check-receipt.ts +5 -43
  597. package/src/runtime/evidence/result-store.ts +158 -44
  598. package/src/runtime/evidence/sensitive-output.ts +4 -4
  599. package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
  600. package/src/runtime/execution/jobs/store.ts +124 -6
  601. package/src/runtime/execution/managed-workspace.ts +112 -5
  602. package/src/runtime/execution/process-runtime/canary.ts +19 -5
  603. package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
  604. package/src/runtime/execution/process-runtime/check-facade.ts +24 -10
  605. package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
  606. package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
  607. package/src/runtime/execution/process-runtime/check-result.ts +177 -2
  608. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +58 -9
  609. package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
  610. package/src/runtime/execution/process-runtime/command-facade.ts +117 -114
  611. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  612. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  613. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  614. package/src/runtime/execution/process-runtime/index.ts +4 -0
  615. package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
  616. package/src/runtime/execution/process-runtime/lightweight-managed.ts +283 -73
  617. package/src/runtime/execution/process-runtime/persisted-check.ts +130 -23
  618. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  619. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  620. package/src/runtime/execution/process-runtime/resource-claims.ts +125 -64
  621. package/src/runtime/execution/process-runtime/runtime.ts +167 -17
  622. package/src/runtime/execution/process-runtime/store.ts +30 -2
  623. package/src/runtime/execution/process-runtime/types.ts +27 -0
  624. package/src/runtime/execution/workers/executor.ts +18 -19
  625. package/src/runtime/execution/workers/worker-entry.ts +1 -1
  626. package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
  627. package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
  628. package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
  629. package/src/runtime/gateway/mcp/process-tools.ts +2 -289
  630. package/src/runtime/gateway/mcp/router.ts +2 -1125
  631. package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
  632. package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
  633. package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
  634. package/src/runtime/maintenance/cleanup.ts +38 -24
  635. package/src/runtime/platform/browser-product-discovery.ts +174 -0
  636. package/src/runtime/platform/computer-platform.ts +14 -0
  637. package/src/runtime/platform/executable-discovery.ts +54 -0
  638. package/src/runtime/platform/fetch-http-server.ts +90 -0
  639. package/src/runtime/platform/service-inventory.ts +130 -0
  640. package/src/runtime/platform/service-manager.ts +146 -0
  641. package/src/runtime/platform/windows-host-discovery.ts +118 -0
  642. package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
  643. package/src/runtime/plugins/action-application.ts +192 -0
  644. package/src/runtime/plugins/app-store-connect-adapter.ts +47 -35
  645. package/src/runtime/plugins/browser-adapter.ts +898 -135
  646. package/src/runtime/plugins/browser-automation-service.ts +33 -34
  647. package/src/runtime/plugins/browser-macos-bridge.ts +386 -46
  648. package/src/runtime/plugins/browser-manifest-surface.ts +75 -17
  649. package/src/runtime/plugins/browser-native-session-service.ts +64 -14
  650. package/src/runtime/plugins/browser-provider-registry.ts +2 -109
  651. package/src/runtime/plugins/browser-registration.ts +32 -0
  652. package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
  653. package/src/runtime/plugins/browser-runtime.ts +55 -10
  654. package/src/runtime/plugins/browser-session-authority.ts +101 -291
  655. package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
  656. package/src/runtime/plugins/browser-session-store.ts +243 -80
  657. package/src/runtime/plugins/browser-session-types.ts +2 -98
  658. package/src/runtime/plugins/capability-authorization-grants.ts +272 -59
  659. package/src/runtime/plugins/catalog-trust.ts +82 -0
  660. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  661. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  662. package/src/runtime/plugins/computer-registration.ts +1050 -0
  663. package/src/runtime/plugins/config-store.ts +119 -0
  664. package/src/runtime/plugins/desktop-operator-external-policy.ts +964 -0
  665. package/src/runtime/plugins/desktop-operator-registration.ts +123 -12
  666. package/src/runtime/plugins/errors.ts +8 -1
  667. package/src/runtime/plugins/external-adapter.ts +82 -323
  668. package/src/runtime/plugins/external-provider-policy.ts +48 -0
  669. package/src/runtime/plugins/external-registration.ts +30 -2
  670. package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
  671. package/src/runtime/plugins/external-unix-socket.ts +64 -193
  672. package/src/runtime/plugins/first-party-external-registration.ts +163 -0
  673. package/src/runtime/plugins/first-party-registry.ts +3 -1
  674. package/src/runtime/plugins/github-adapter.ts +1 -2
  675. package/src/runtime/plugins/gmail-adapter.ts +29 -8
  676. package/src/runtime/plugins/google-calendar-adapter.ts +8 -8
  677. package/src/runtime/plugins/google-shared.ts +45 -53
  678. package/src/runtime/plugins/google-tasks-adapter.ts +8 -8
  679. package/src/runtime/plugins/ios-adapter.ts +2 -3
  680. package/src/runtime/plugins/lightweight-action.ts +208 -2
  681. package/src/runtime/plugins/local-system-adapter.ts +192 -2
  682. package/src/runtime/plugins/macos-capability-broker.ts +15 -105
  683. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  684. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  685. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  686. package/src/runtime/plugins/resend-adapter.ts +15 -24
  687. package/src/runtime/plugins/store.ts +1003 -387
  688. package/src/runtime/plugins/types.ts +28 -1
  689. package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
  690. package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
  691. package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
  692. package/src/runtime/plugins/xiaohongshu-publish.ts +102 -430
  693. package/src/runtime/projections/controller-context.ts +12 -6
  694. package/src/runtime/projections/git-status-sampler.ts +73 -22
  695. package/src/runtime/projections/invalidation.ts +7 -3
  696. package/src/runtime/projections/materialized-view.ts +93 -43
  697. package/src/runtime/recovery/actions.ts +3 -3
  698. package/src/runtime/recovery/capability-action-application.ts +229 -0
  699. package/src/runtime/recovery/index.ts +3 -0
  700. package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
  701. package/src/runtime/recovery/local-jobs-repair.ts +14 -14
  702. package/src/runtime/recovery/maintenance-executor.ts +701 -168
  703. package/src/runtime/recovery/quarantine-retention.ts +256 -0
  704. package/src/runtime/recovery/store.ts +29 -11
  705. package/src/runtime/release/identity.ts +6 -0
  706. package/src/runtime/release/release-coordinator.ts +296 -0
  707. package/src/runtime/release/release-session.ts +716 -0
  708. package/src/runtime/release/release-state-migration.ts +25 -0
  709. package/src/runtime/resources/leases/store.ts +56 -25
  710. package/src/runtime/root/active-execution-power-assertion.ts +139 -0
  711. package/src/runtime/root/assistant-learning-loop.ts +45 -0
  712. package/src/runtime/root/browser-session-composition.ts +59 -0
  713. package/src/runtime/root/computer-composition.ts +376 -0
  714. package/src/runtime/root/computer-target-composition.ts +16 -0
  715. package/src/runtime/root/computer-target-persistence.ts +39 -0
  716. package/src/runtime/root/controller-progression-composition.ts +192 -0
  717. package/src/runtime/root/controller-round-composition.ts +126 -0
  718. package/src/runtime/root/controller-services.ts +2 -0
  719. package/src/runtime/root/deployment-topology.ts +106 -0
  720. package/src/runtime/root/entry.ts +8 -6
  721. package/src/runtime/root/gateway-adapter.ts +3 -3
  722. package/src/runtime/root/known-good-recovery.ts +184 -0
  723. package/src/runtime/root/local-bridge.ts +5 -3
  724. package/src/runtime/root/mcp-transport.ts +116 -23
  725. package/src/runtime/root/ownership.ts +261 -9
  726. package/src/runtime/root/package-connector-service.ts +212 -74
  727. package/src/runtime/root/package-runtime-release.ts +199 -33
  728. package/src/runtime/root/package-runtime-service.ts +77 -108
  729. package/src/runtime/root/release-execution-canary.ts +103 -0
  730. package/src/runtime/root/release-loader.ts +150 -0
  731. package/src/runtime/root/release-manifest.ts +185 -7
  732. package/src/runtime/root/release-materialize.ts +474 -31
  733. package/src/runtime/root/release-store.ts +425 -37
  734. package/src/runtime/root/runtime-lane.ts +191 -0
  735. package/src/runtime/root/runtime.ts +379 -32
  736. package/src/runtime/root/scheduled-controller-composition.ts +76 -0
  737. package/src/runtime/root/scheduler.ts +12 -4
  738. package/src/runtime/root/service-runner.ts +3 -3
  739. package/src/runtime/root/service.ts +73 -45
  740. package/src/runtime/root/status.ts +49 -0
  741. package/src/runtime/root/types.ts +55 -3
  742. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  743. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  744. package/src/runtime/root/write-fence.ts +50 -2
  745. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  746. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  747. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  748. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  749. package/src/runtime/shared/local-bridge-surface.ts +1 -1
  750. package/src/runtime/shared/process-environment.ts +36 -10
  751. package/src/runtime/shared/response-budget.ts +1 -3
  752. package/src/runtime/shared/storage-capacity.ts +68 -0
  753. package/src/runtime/standalone-recovery/controller-home-migration.ts +1108 -0
  754. package/src/runtime/standalone-recovery/core.ts +4609 -495
  755. package/src/runtime/standalone-recovery/entry.ts +642 -81
  756. package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
  757. package/src/runtime/standalone-recovery/installer.ts +399 -177
  758. package/src/runtime/standalone-recovery/mcp-server.ts +79 -0
  759. package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
  760. package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
  761. package/src/runtime/standalone-recovery/performance.ts +173 -0
  762. package/src/runtime/standalone-recovery/release.ts +58 -5
  763. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  764. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  765. package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
  766. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  767. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -4
  768. package/src/runtime/workflow/schedules/engine.ts +298 -484
  769. package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
  770. package/src/runtime/workflow/schedules/settlement.ts +2 -191
  771. package/src/runtime/workflow/schedules/store.ts +2 -607
  772. package/src/runtime/workflow/schedules/types.ts +2 -127
  773. package/src/runtime/workflow/schedules/work-continuation.ts +220 -16
  774. package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
  775. package/src/runtime/workflows/runtime.ts +482 -0
  776. package/src/testing/test-governance.ts +95 -30
  777. package/supervisor/chatgpt-conversation.ts +23 -0
  778. package/supervisor/client.ts +201 -0
  779. package/supervisor/control-plane.ts +868 -0
  780. package/supervisor/entry.ts +15 -0
  781. package/supervisor/forge-validators.ts +80 -0
  782. package/supervisor/index.ts +5 -0
  783. package/supervisor/native-browser-adapter.ts +786 -0
  784. package/supervisor/native-messaging/host.ts +39 -0
  785. package/supervisor/native-messaging/manifest.ts +26 -0
  786. package/supervisor/native-messaging/protocol.ts +27 -0
  787. package/supervisor/paths.ts +18 -0
  788. package/supervisor/protocol.ts +202 -0
  789. package/supervisor/server.ts +404 -0
  790. package/supervisor/store.ts +1451 -0
  791. package/supervisor/tsconfig.json +8 -0
  792. package/supervisor/types.ts +255 -0
  793. package/assets/templates/helpers/archive-architecture-request.sh +0 -244
  794. package/docs/architecture/history/README.md +0 -7
  795. package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
  796. package/docs/architecture/history/global-hook-runtime.md +0 -166
  797. package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
  798. package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  799. package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
  800. package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
  801. package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
  802. package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
  803. package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  804. package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  805. package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  806. package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
  807. package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
  808. package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  809. package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  810. package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
  811. package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  812. package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  813. package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  814. package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  815. package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
  816. package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
  817. package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
  818. package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
  819. package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
  820. package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  821. package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  822. package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
  823. package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
  824. package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
  825. package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
  826. package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
  827. package/docs/architecture/requests/archive/2026/root.md +0 -68
  828. package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
  829. package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
  830. package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
  831. package/scripts/archive-architecture-request.sh +0 -4
  832. package/scripts/benchmark-background-check-overlap.ts +0 -228
  833. package/scripts/benchmark-controller-hotpath.ts +0 -212
  834. package/scripts/benchmark-controller-round2.ts +0 -139
  835. package/scripts/benchmark-ios-agent-device.ts +0 -514
  836. package/scripts/benchmark-mcp-host.sh +0 -117
  837. package/scripts/benchmark-mcp-transport.ts +0 -170
  838. package/scripts/benchmark-quality-harness.ts +0 -146
  839. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  840. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  841. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  842. package/scripts/benchmark-thin-harness.ts +0 -251
  843. package/scripts/benchmark-typescript-navigation.ts +0 -186
  844. package/scripts/benchmark-work-efficiency.ts +0 -334
  845. package/scripts/build-controller-ui.ts +0 -28
  846. package/scripts/check-npm-release.sh +0 -32
  847. package/scripts/check-public-release-surface.sh +0 -19
  848. package/scripts/check-release-published.sh +0 -57
  849. package/scripts/check-release-readiness.sh +0 -37
  850. package/scripts/check-release-version.mjs +0 -74
  851. package/scripts/check-tarball-install-smoke.sh +0 -67
  852. package/scripts/package-source-archive.sh +0 -147
  853. package/scripts/public-release-files.txt +0 -39
  854. package/scripts/public-release.ts +0 -174
  855. package/scripts/publish-release-tarball.sh +0 -27
  856. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  857. package/scripts/run-skill-evals.ts +0 -1022
  858. package/scripts/stage-runtime-release.ts +0 -39
  859. package/src/cli/controller/progress.ts +0 -656
  860. package/src/cli/controller/work-mode.ts +0 -181
  861. package/src/cli/local-bridge/console-assets.ts +0 -17
  862. package/src/cli/local-bridge/dashboard.ts +0 -17
  863. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  864. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  865. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  866. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  867. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  868. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  869. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  870. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  871. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  872. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  873. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  874. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  875. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  876. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  877. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  878. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  879. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  880. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  881. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  882. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  883. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  884. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  885. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  886. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  887. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  888. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  889. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  890. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  891. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -385
  892. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -1913
  893. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  894. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -449
  895. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -1118
  896. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -93
  897. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  898. package/src/runtime/control-plane/routing/index.ts +0 -1
  899. package/src/runtime/control-plane/routing/route-policy.ts +0 -382
  900. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -1,5 +1,6 @@
1
- import { createHash } from 'crypto';
1
+ import { createHash, randomUUID } from 'crypto';
2
2
  import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync } from 'fs';
3
+ import { tmpdir } from 'os';
3
4
  import { basename, dirname, join, normalize, relative, resolve } from 'path';
4
5
  import {
5
6
  capProcessOutput,
@@ -12,6 +13,21 @@ import { runBoundedChild } from '../../runtime/shared/bounded-child-supervisor';
12
13
  import { signalProcessTree } from '../../runtime/shared/process-tree';
13
14
  import { repositoryChildProcessEnvironment, resolveBunExecutable } from '../../runtime/shared/process-environment';
14
15
  import { materializeManagedWorkspaceCheckDependencies } from '../../runtime/execution/managed-workspace';
16
+ import {
17
+ isStructuredCheckFailureEvidence,
18
+ STRUCTURED_CHECK_RESULT_PATH_ENV,
19
+ type StructuredCheckFailureEvidence,
20
+ } from '../../runtime/execution/process-runtime/check-result';
21
+ import { readRuntimeReleaseAuthority } from '../../runtime/root/release-store';
22
+ import { observeRuntimeStatus } from '../../runtime/root/status';
23
+ import { readCurrentRecoveryRelease } from '../../runtime/standalone-recovery/release';
24
+ import { acquireRecoveryOperationLock, recoveryOperationLockPath } from '../../runtime/standalone-recovery/operation-lock';
25
+ import {
26
+ ensureRepositoryCheckStorage,
27
+ resolveRepositoryCheckStorage,
28
+ type RepositoryCheckStorageAuthority,
29
+ type ResolvedRepositoryCheckStorage,
30
+ } from '../../runtime/execution/process-runtime/check-storage';
15
31
 
16
32
  export interface ControllerCheckEffects {
17
33
  /** Repository-relative read scopes. Use [\".\"] for the whole checkout. */
@@ -29,6 +45,7 @@ export interface ControllerCheckEffects {
29
45
  export type ControllerCheckCostClass = 'L0' | 'L1' | 'L2' | 'L3' | 'L4';
30
46
  export type ControllerCheckRiskFloor = 'readonly' | 'low' | 'medium' | 'high' | 'destructive';
31
47
  export type ControllerCheckPhase = 'pre_edit' | 'post_edit' | 'pre_finalize' | 'release';
48
+ export type ControllerCheckExecutionAuthority = 'isolated_controller_home' | 'live_controller_home';
32
49
 
33
50
  export interface ControllerCheckSelection {
34
51
  /** Execution cost only; it does not lower severity or automatically run the check. */
@@ -45,6 +62,8 @@ export interface ControllerCheck {
45
62
  cwd: string;
46
63
  timeoutMs: number;
47
64
  source: 'repo-config' | 'package-script';
65
+ /** Where authority-sensitive child state is resolved. Ordinary checks stay isolated. */
66
+ executionAuthority?: ControllerCheckExecutionAuthority;
48
67
  effects?: ControllerCheckEffects;
49
68
  /** Selection/preflight metadata; intentionally excluded from physical execution identity. */
50
69
  selection?: ControllerCheckSelection;
@@ -89,8 +108,8 @@ interface CheckConfig {
89
108
 
90
109
  const CHECK_CONFIG = '.forge/checks.json';
91
110
  const LEGACY_TRACKED_CHECK_CONFIG = '.repo-harness/checks.json';
92
- const CHECK_EVIDENCE_ROOT = '.ai/harness/checks/controller';
93
- const HEAVY_CHECK_LOCK = '.ai/harness/controller/heavy-check.lock';
111
+ const CHECK_EVIDENCE_SUBDIR = 'controller';
112
+ const HEAVY_CHECK_LOCK = 'heavy-check.lock';
94
113
  const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
95
114
  const MAX_TIMEOUT_MS = 30 * 60 * 1000;
96
115
  const SAFE_PACKAGE_SCRIPT = /^(test(?::|$)|check(?::|$)|lint(?::|$)|typecheck(?::|$)|format:check$)/;
@@ -253,8 +272,27 @@ export function controllerCheckSelection(check: Pick<ControllerCheck, 'id' | 'se
253
272
 
254
273
  function inferredPackageCheckEffects(name: string): ControllerCheckEffects | undefined {
255
274
  const normalized = name.trim().toLowerCase();
256
- const staticAnalysis = /(?:^|:)(?:type|typecheck|lint|format:check|runtime-architecture|mcp-compatibility|forge-runtime)$/.test(normalized);
257
- if (staticAnalysis) return { reads: ['.'], cache: 'write' };
275
+ if (normalized === 'check:stable-baseline') {
276
+ return { reads: ['.'], hostServices: ['canonical-runtime', 'forge-recovery'] };
277
+ }
278
+ if (normalized === 'check:task' || normalized === 'check:main') {
279
+ // Governed gates reject any candidate workspace mutation after every step
280
+ // and persist only content-bound receipts/caches outside repository source.
281
+ return { reads: ['.'], cache: 'write', temp: 'isolated', git: 'read' };
282
+ }
283
+ if (normalized === 'check:type' || normalized === 'check:runtime-architecture') {
284
+ // These canonical gates are source readers: TypeScript runs with --noEmit,
285
+ // while runtime-architecture only inspects source/AST structure. Neither
286
+ // owns the shared repository build cache.
287
+ return { reads: ['.'] };
288
+ }
289
+ if (normalized === 'check:architecture-sync') {
290
+ // Architecture sync runs the queue in --check mode and inspects Git state.
291
+ // Its scratch space is check-local; it never mutates repository source.
292
+ return { reads: ['.'], temp: 'isolated', git: 'read' };
293
+ }
294
+ const cachedStaticAnalysis = /(?:^|:)(?:typecheck|lint|format:check|mcp-compatibility|forge-runtime)$/.test(normalized);
295
+ if (cachedStaticAnalysis) return { reads: ['.'], cache: 'write' };
258
296
  const isolatedReadOnlyCheck = /(?:^|:)(?:quality-harness|evaluation-framework|background-check-overlap|typescript-navigation|check-scheduling|bootstrap-files)$/.test(normalized);
259
297
  if (isolatedReadOnlyCheck) return { reads: ['.'], temp: 'isolated', git: 'read' };
260
298
  const browserLive = /(?:^|:)browser-live$/.test(normalized);
@@ -312,6 +350,9 @@ function packageChecks(repoRoot: string): ControllerCheck[] {
312
350
  cwd: '.',
313
351
  timeoutMs: packageScriptTimeoutMs(name),
314
352
  source: 'package-script' as const,
353
+ executionAuthority: name.trim().toLowerCase() === 'check:stable-baseline'
354
+ ? 'live_controller_home' as const
355
+ : 'isolated_controller_home' as const,
315
356
  effects: inferredPackageCheckEffects(name),
316
357
  selection: inferredCheckSelection(name),
317
358
  }];
@@ -340,8 +381,9 @@ export interface ControllerCheckResult {
340
381
  validatedRevision?: string;
341
382
  /** Original process execution timestamp; retained when a result is served from cache. */
342
383
  originalExecutedAt?: string;
343
- /** A non-zero check result is acceptance failure; runtime/process defects are infrastructure. */
384
+ /** Non-zero repository failures are acceptance failures unless bounded infrastructure evidence proves otherwise. */
344
385
  failureClass?: 'acceptance_failure' | 'infrastructure_failure';
386
+ failureEvidence?: StructuredCheckFailureEvidence;
345
387
  }
346
388
 
347
389
  export interface ControllerCheckEvidence {
@@ -365,54 +407,190 @@ export interface ControllerCheckEvidence {
365
407
  validatedRevision?: string;
366
408
  originalExecutedAt?: string;
367
409
  failureClass?: 'acceptance_failure' | 'infrastructure_failure';
410
+ failureEvidence?: StructuredCheckFailureEvidence;
411
+ }
412
+
413
+ const STRONG_TRANSPORT_FAILURE_PATTERNS = [
414
+ /\bjava\.net\.(?:SocketTimeoutException|UnknownHostException|ConnectException|NoRouteToHostException)\b/i,
415
+ /\b(?:EAI_AGAIN|ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENETUNREACH|EHOSTUNREACH)\b/i,
416
+ /\bCould not resolve host\b/i,
417
+ /\b(?:connection|connect|read) timed out\b/i,
418
+ /\bNetwork is unreachable\b/i,
419
+ /\b(?:SSLHandshakeException|TLS handshake (?:failed|timeout|timed out)|CERTIFICATE_VERIFY_FAILED)\b/i,
420
+ ] as const;
421
+
422
+ function classifyControllerCheckFailure(input: {
423
+ ok: boolean;
424
+ stale?: boolean;
425
+ timedOut: boolean;
426
+ runtimeFailure: boolean;
427
+ stdout: string;
428
+ stderr: string;
429
+ }): 'acceptance_failure' | 'infrastructure_failure' | undefined {
430
+ if (input.ok && !input.stale) return undefined;
431
+ if (input.stale || input.timedOut || input.runtimeFailure) return 'infrastructure_failure';
432
+ const output = `${input.stdout}\n${input.stderr}`;
433
+ if (STRONG_TRANSPORT_FAILURE_PATTERNS.some((pattern) => pattern.test(output))) return 'infrastructure_failure';
434
+ return 'acceptance_failure';
435
+ }
436
+
437
+ const GOVERNED_TEST_GATES = new Map<string, string>([
438
+ ['package:test', 'affected'],
439
+ ['package:test:core', 'core'],
440
+ ['package:test:integration', 'integration'],
441
+ ['package:test:infrastructure', 'infrastructure'],
442
+ ['package:test:fault', 'fault'],
443
+ ['package:test:full', 'full'],
444
+ ['package:test:bun', 'full'],
445
+ ]);
446
+ const MAX_STRUCTURED_CHECK_RESULT_BYTES = 64 * 1024;
447
+
448
+ interface StructuredCheckObservation {
449
+ evidence?: StructuredCheckFailureEvidence;
450
+ error?: string;
451
+ }
452
+
453
+ function structuredCheckResultPath(check: ControllerCheck): string | undefined {
454
+ if (!GOVERNED_TEST_GATES.has(check.id)) return undefined;
455
+ return join(tmpdir(), `forge-check-result-${process.pid}-${randomUUID()}.json`);
456
+ }
457
+
458
+ function readStructuredCheckObservation(check: ControllerCheck, path: string | undefined): StructuredCheckObservation {
459
+ const expectedGate = GOVERNED_TEST_GATES.get(check.id);
460
+ if (!expectedGate) return {};
461
+ if (!path || !existsSync(path)) return { error: 'CHECK_STRUCTURED_RESULT_MISSING' };
462
+ try {
463
+ const bytes = readFileSync(path);
464
+ if (bytes.byteLength > MAX_STRUCTURED_CHECK_RESULT_BYTES) return { error: 'CHECK_STRUCTURED_RESULT_TOO_LARGE' };
465
+ const value = JSON.parse(bytes.toString('utf8')) as unknown;
466
+ if (!isStructuredCheckFailureEvidence(value) || value.gate !== expectedGate) return { error: 'CHECK_STRUCTURED_RESULT_INVALID' };
467
+ return { evidence: value };
468
+ } catch {
469
+ return { error: 'CHECK_STRUCTURED_RESULT_INVALID' };
470
+ }
471
+ }
472
+
473
+ function consumeStructuredCheckObservation(check: ControllerCheck, path: string | undefined): StructuredCheckObservation {
474
+ try {
475
+ return readStructuredCheckObservation(check, path);
476
+ } finally {
477
+ if (path) rmSync(path, { force: true });
478
+ }
479
+ }
480
+
481
+ function applyStructuredCheckObservation(processOk: boolean, observation: StructuredCheckObservation): {
482
+ ok: boolean;
483
+ failureClass?: 'acceptance_failure' | 'infrastructure_failure';
484
+ failureEvidence?: StructuredCheckFailureEvidence;
485
+ error?: string;
486
+ } {
487
+ if (!observation.error && !observation.evidence) return { ok: processOk };
488
+ if (observation.error) return { ok: false, failureClass: 'infrastructure_failure', error: observation.error };
489
+ const evidence = observation.evidence!;
490
+ const reportOk = evidence.status === 'passed';
491
+ if (reportOk !== processOk) {
492
+ return { ok: false, failureClass: 'infrastructure_failure', failureEvidence: evidence, error: 'CHECK_STRUCTURED_RESULT_STATUS_MISMATCH' };
493
+ }
494
+ if (reportOk) return { ok: true, failureEvidence: evidence };
495
+ const sourceOnly = evidence.failureClasses.length > 0 && evidence.failureClasses.every((entry) => entry === 'source');
496
+ return {
497
+ ok: false,
498
+ failureClass: sourceOnly ? 'acceptance_failure' : 'infrastructure_failure',
499
+ failureEvidence: evidence,
500
+ };
368
501
  }
369
502
 
370
503
  function artifactSlug(id: string): string {
371
504
  return id.toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'check';
372
505
  }
373
506
 
374
- function evidencePath(repoRoot: string, id: string): string {
375
- return join(repoRoot, CHECK_EVIDENCE_ROOT, `latest-${artifactSlug(id)}.json`);
507
+ function evidencePath(storage: ResolvedRepositoryCheckStorage, id: string): string {
508
+ return join(storage.physicalRoot, CHECK_EVIDENCE_SUBDIR, `latest-${artifactSlug(id)}.json`);
509
+ }
510
+
511
+ function historicalEvidencePath(storage: ResolvedRepositoryCheckStorage, id: string, cacheKey: string): string {
512
+ return join(storage.physicalRoot, CHECK_EVIDENCE_SUBDIR, artifactSlug(id), `${cacheKey}.json`);
376
513
  }
377
514
 
378
- function historicalEvidencePath(repoRoot: string, id: string, cacheKey: string): string {
379
- return join(repoRoot, CHECK_EVIDENCE_ROOT, artifactSlug(id), `${cacheKey}.json`);
515
+ function logicalEvidenceArtifactPath(id: string): string {
516
+ return `controller-home://checks/controller/latest-${artifactSlug(id)}.json`;
380
517
  }
381
518
 
382
519
  const CHECK_REVISION_EXCLUDES = [
383
- '.ai/harness/jobs/**',
384
- '.ai/harness/local-jobs/**',
385
- '.ai/harness/checks/controller/**',
386
- '.ai/harness/edit-sessions/**',
387
- '.ai/harness/worktrees/**',
388
- '.ai/harness/controller/**',
389
- '.ai/harness/artifacts/**',
390
- '.ai/harness/local-bridge/**',
391
- '.ai/harness/ephemeral-issues/**',
520
+ // `.ai/harness` is Forge runtime/check state, not repository source. Checks
521
+ // are allowed to materialize artifacts such as design-system audit reports
522
+ // there; hashing those outputs would make a stable check invalidate itself.
523
+ '.ai/harness/**',
392
524
  ];
393
525
 
394
526
  function checkRevisionPathspecs(): string[] {
395
527
  return ['.', ...CHECK_REVISION_EXCLUDES.map((path) => `:(exclude)${path}`)];
396
528
  }
397
529
 
398
- export function currentControllerCheckRevision(repoRoot: string): string {
530
+ interface ControllerCheckContentObservation {
531
+ revision: string;
532
+ fileDigests?: Map<string, string>;
533
+ listingAvailable: boolean;
534
+ }
535
+
536
+ function observeControllerCheckContent(
537
+ repoRoot: string,
538
+ options: { captureFileDigests?: boolean } = {},
539
+ ): ControllerCheckContentObservation {
399
540
  const files = runProcess('git', ['ls-files', '--cached', '--others', '--exclude-standard', '-z', '--', ...checkRevisionPathspecs()], {
400
541
  cwd: repoRoot,
401
542
  timeoutMs: 10_000,
402
543
  maxOutputBytes: 8 * 1024 * 1024,
403
544
  });
404
545
  const revision = createHash('sha256').update('controller-check-content-v2\n');
405
- if (!files.ok) return revision.update(`git-error:${files.error || files.stderr}`).digest('hex').slice(0, 24);
546
+ const fileDigests = options.captureFileDigests ? new Map<string, string>() : undefined;
547
+ if (!files.ok) {
548
+ return {
549
+ revision: revision.update(`git-error:${files.error || files.stderr}`).digest('hex').slice(0, 24),
550
+ ...(fileDigests ? { fileDigests } : {}),
551
+ listingAvailable: false,
552
+ };
553
+ }
406
554
  for (const relativePath of files.stdout.split('\0').filter(Boolean).sort()) {
407
555
  if (relativePath.startsWith('tasks/') || relativePath.startsWith('plans/')) continue;
408
556
  revision.update(`${relativePath}\0`);
409
557
  try {
410
- revision.update(readFileSync(resolve(repoRoot, relativePath)));
558
+ const content = readFileSync(resolve(repoRoot, relativePath));
559
+ revision.update(content);
560
+ fileDigests?.set(relativePath, createHash('sha256').update(content).digest('hex'));
411
561
  } catch (_error) {
412
562
  revision.update('missing');
563
+ fileDigests?.set(relativePath, 'missing');
413
564
  }
414
565
  }
415
- return revision.digest('hex').slice(0, 24);
566
+ return {
567
+ revision: revision.digest('hex').slice(0, 24),
568
+ ...(fileDigests ? { fileDigests } : {}),
569
+ listingAvailable: true,
570
+ };
571
+ }
572
+
573
+ export function currentControllerCheckRevision(repoRoot: string): string {
574
+ return observeControllerCheckContent(repoRoot).revision;
575
+ }
576
+
577
+ function controllerCheckWriteScopeContainsPath(scope: string, relativePath: string): boolean {
578
+ return scope === '.' || relativePath === scope || relativePath.startsWith(`${scope}/`);
579
+ }
580
+
581
+ function controllerCheckInputIntegrityChanged(
582
+ check: ControllerCheck,
583
+ input: ControllerCheckContentObservation,
584
+ completed: ControllerCheckContentObservation,
585
+ ): boolean {
586
+ if (!input.listingAvailable || !completed.listingAvailable || !input.fileDigests || !completed.fileDigests) return true;
587
+ const writeScopes = check.effects?.writes ?? [];
588
+ const observedPaths = new Set([...input.fileDigests.keys(), ...completed.fileDigests.keys()]);
589
+ for (const relativePath of observedPaths) {
590
+ if (writeScopes.some((scope) => controllerCheckWriteScopeContainsPath(scope, relativePath))) continue;
591
+ if (input.fileDigests.get(relativePath) !== completed.fileDigests.get(relativePath)) return true;
592
+ }
593
+ return false;
416
594
  }
417
595
 
418
596
  function checkDefinitionDigest(check: ControllerCheck): string {
@@ -423,6 +601,7 @@ function checkDefinitionDigest(check: ControllerCheck): string {
423
601
  cwd: check.cwd,
424
602
  timeoutMs: check.timeoutMs,
425
603
  source: check.source,
604
+ executionAuthority: check.executionAuthority ?? 'isolated_controller_home',
426
605
  effects: check.effects,
427
606
  })).digest('hex');
428
607
  }
@@ -450,6 +629,7 @@ function validateControllerCheckSnapshot(repoRoot: string, snapshot: ControllerC
450
629
  cwd: normalizeCwd(repoRoot, snapshot.cwd),
451
630
  timeoutMs: boundedTimeout(snapshot.timeoutMs),
452
631
  source: snapshot.source,
632
+ executionAuthority: snapshot.executionAuthority ?? 'isolated_controller_home',
453
633
  effects: normalizeCheckEffects(repoRoot, snapshot.effects),
454
634
  selection: normalizeCheckSelection(snapshot.selection, snapshot.id),
455
635
  };
@@ -457,7 +637,72 @@ function validateControllerCheckSnapshot(repoRoot: string, snapshot: ControllerC
457
637
 
458
638
  const CONTROLLER_CHECK_EXECUTION_IDENTITY_VERSION = 'controller-check-execution-v2';
459
639
 
460
- function checkEnvironmentFingerprint(check: ControllerCheck): string {
640
+ /**
641
+ * Bounded live-state identity for certification checks. This is read-only
642
+ * evidence, not lifecycle authority. It includes current release authority and
643
+ * observed Runtime liveness so a dead/replaced Runtime cannot reuse a prior
644
+ * green Stable Baseline receipt merely because its status file remained.
645
+ */
646
+ export function controllerCheckLiveExecutionStateFingerprint(controllerHome: string, recoveryFenceInstanceId?: string): string {
647
+ const mutationLockPath = recoveryOperationLockPath(controllerHome);
648
+ try {
649
+ const raw = readFileSync(mutationLockPath, 'utf8');
650
+ if (recoveryFenceInstanceId?.trim()) {
651
+ try {
652
+ const owner = JSON.parse(raw) as { instanceId?: unknown };
653
+ if (owner?.instanceId === recoveryFenceInstanceId.trim()) {
654
+ // This check owns the real Recovery mutation fence; its own lock is not drift.
655
+ } else {
656
+ throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
657
+ }
658
+ } catch (error) {
659
+ if (error instanceof Error && error.message === 'LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS') throw error;
660
+ throw new Error('LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE');
661
+ }
662
+ } else {
663
+ throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
664
+ }
665
+ } catch (error) {
666
+ if (error instanceof Error && (
667
+ error.message === 'LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS'
668
+ || error.message === 'LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE'
669
+ )) throw error;
670
+ if ((error as NodeJS.ErrnoException)?.code !== 'ENOENT') {
671
+ throw new Error('LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE');
672
+ }
673
+ }
674
+ const release = readRuntimeReleaseAuthority(controllerHome);
675
+ const recoveryRelease = readCurrentRecoveryRelease(controllerHome);
676
+ const runtime = observeRuntimeStatus(controllerHome);
677
+ return createHash('sha256')
678
+ .update(JSON.stringify({
679
+ release: release ? {
680
+ revision: release.revision,
681
+ releaseId: release.active.releaseId,
682
+ artifactIdentity: release.active.artifactIdentity,
683
+ manifestSha256: release.active.manifestSha256,
684
+ } : null,
685
+ recoveryRelease: recoveryRelease ? {
686
+ releaseRevision: recoveryRelease.releaseRevision,
687
+ sourceCommit: recoveryRelease.sourceCommit,
688
+ manifestSha256: recoveryRelease.manifestSha256,
689
+ } : null,
690
+ runtime: {
691
+ running: runtime.running,
692
+ ready: runtime.ready,
693
+ stale: runtime.stale,
694
+ reasonCodes: [...runtime.reasonCodes].sort(),
695
+ runtimeInstanceId: runtime.snapshot?.runtimeInstanceId ?? null,
696
+ pid: runtime.snapshot?.pid ?? null,
697
+ releaseId: runtime.snapshot?.releaseId ?? null,
698
+ artifactIdentity: runtime.snapshot?.artifactIdentity ?? null,
699
+ },
700
+ }))
701
+ .digest('hex')
702
+ .slice(0, 24);
703
+ }
704
+
705
+ export function controllerCheckEnvironmentFingerprint(check: ControllerCheck, executionStateFingerprint?: string): string {
461
706
  const env = repositoryChildProcessEnvironment(process.env);
462
707
  return createHash('sha256')
463
708
  .update(JSON.stringify({
@@ -470,6 +715,8 @@ function checkEnvironmentFingerprint(check: ControllerCheck): string {
470
715
  // for the parent and forge-check-runner for the sidecar; process.execPath
471
716
  // therefore differs even though both execute the exact same check/toolchain.
472
717
  commandExecutable: check.command[0],
718
+ executionAuthority: check.executionAuthority ?? 'isolated_controller_home',
719
+ executionStateFingerprint: executionStateFingerprint?.trim() || '',
473
720
  path: env.PATH ?? '',
474
721
  home: env.HOME ?? env.USERPROFILE ?? '',
475
722
  bunInstall: env.BUN_INSTALL ?? '',
@@ -514,7 +761,7 @@ function buildCheckCacheKey(
514
761
  timeoutMs: number,
515
762
  revision: string,
516
763
  definitionDigest = checkDefinitionDigest(check),
517
- environmentFingerprint = checkEnvironmentFingerprint(check),
764
+ environmentFingerprint = controllerCheckEnvironmentFingerprint(check),
518
765
  ): string {
519
766
  return createHash('sha256')
520
767
  .update(JSON.stringify({
@@ -531,11 +778,13 @@ function buildCheckCacheKey(
531
778
  .slice(0, 24);
532
779
  }
533
780
 
534
- export function controllerCheckExecutionIdentity(
781
+ function controllerCheckExecutionIdentityForRevision(
535
782
  repoRoot: string,
536
783
  id: string,
784
+ revision: string,
537
785
  requestedTimeoutMs?: number,
538
786
  snapshot?: ControllerCheckSnapshot,
787
+ executionStateFingerprint?: string,
539
788
  ): ControllerCheckExecutionIdentity {
540
789
  const check = snapshot
541
790
  ? validateControllerCheckSnapshot(repoRoot, snapshot)
@@ -544,9 +793,8 @@ export function controllerCheckExecutionIdentity(
544
793
  const timeoutMs = requestedTimeoutMs === undefined
545
794
  ? check.timeoutMs
546
795
  : Math.min(check.timeoutMs, boundedTimeout(requestedTimeoutMs));
547
- const revision = currentControllerCheckRevision(repoRoot);
548
796
  const definitionDigest = checkDefinitionDigest(check);
549
- const environmentFingerprint = checkEnvironmentFingerprint(check);
797
+ const environmentFingerprint = controllerCheckEnvironmentFingerprint(check, executionStateFingerprint);
550
798
  const checkoutClean = checkWorkspaceClean(repoRoot);
551
799
  const crossCheckoutReusable = checkoutClean
552
800
  && checkEffectsAllowCrossCheckoutReuse(check)
@@ -565,8 +813,25 @@ export function controllerCheckExecutionIdentity(
565
813
  };
566
814
  }
567
815
 
568
- function persistCheckEvidence(
816
+ export function controllerCheckExecutionIdentity(
569
817
  repoRoot: string,
818
+ id: string,
819
+ requestedTimeoutMs?: number,
820
+ snapshot?: ControllerCheckSnapshot,
821
+ executionStateFingerprint?: string,
822
+ ): ControllerCheckExecutionIdentity {
823
+ return controllerCheckExecutionIdentityForRevision(
824
+ repoRoot,
825
+ id,
826
+ currentControllerCheckRevision(repoRoot),
827
+ requestedTimeoutMs,
828
+ snapshot,
829
+ executionStateFingerprint,
830
+ );
831
+ }
832
+
833
+ function persistCheckEvidence(
834
+ storage: ResolvedRepositoryCheckStorage,
570
835
  result: Omit<ControllerCheckResult, 'artifactPath'>,
571
836
  meta: {
572
837
  revision?: string;
@@ -577,7 +842,7 @@ function persistCheckEvidence(
577
842
  validatedRevision?: string;
578
843
  } = {},
579
844
  ): string {
580
- const path = evidencePath(repoRoot, result.check.id);
845
+ const path = evidencePath(storage, result.check.id);
581
846
  mkdirSync(dirname(path), { recursive: true });
582
847
  const evidence: ControllerCheckEvidence = {
583
848
  schemaVersion: 2,
@@ -600,30 +865,40 @@ function persistCheckEvidence(
600
865
  validatedRevision: meta.validatedRevision,
601
866
  originalExecutedAt: result.originalExecutedAt ?? result.executedAt,
602
867
  failureClass: result.failureClass,
868
+ failureEvidence: result.failureEvidence,
603
869
  };
604
870
  const serialized = `${JSON.stringify(evidence, null, 2)}\n`;
605
871
  atomicWriteFileSync(path, serialized);
606
872
  if (meta.cacheKey) {
607
- const historicalPath = historicalEvidencePath(repoRoot, result.check.id, meta.cacheKey);
873
+ const historicalPath = historicalEvidencePath(storage, result.check.id, meta.cacheKey);
608
874
  mkdirSync(dirname(historicalPath), { recursive: true });
609
875
  atomicWriteFileSync(historicalPath, serialized);
610
876
  }
611
- return relative(repoRoot, path).replace(/\\/g, '/');
877
+ return logicalEvidenceArtifactPath(result.check.id);
612
878
  }
613
879
 
614
- export function readLatestControllerCheckEvidence(repoRoot: string, id: string): ControllerCheckEvidence | undefined {
615
- const path = evidencePath(repoRoot, id);
880
+ export function readLatestControllerCheckEvidence(
881
+ repoRoot: string,
882
+ id: string,
883
+ storageAuthority?: RepositoryCheckStorageAuthority | ResolvedRepositoryCheckStorage,
884
+ ): ControllerCheckEvidence | undefined {
885
+ const storage = storageAuthority && 'physicalRoot' in storageAuthority
886
+ ? storageAuthority as ResolvedRepositoryCheckStorage
887
+ : resolveRepositoryCheckStorage(repoRoot, storageAuthority as RepositoryCheckStorageAuthority | undefined);
888
+ const path = evidencePath(storage, id);
616
889
  if (!existsSync(path)) return undefined;
617
890
  try {
618
891
  const value = JSON.parse(readFileSync(path, 'utf-8')) as ControllerCheckEvidence;
619
- return value.schemaVersion === 2 && value.checkId === id ? value : undefined;
892
+ if (value.schemaVersion !== 2 || value.checkId !== id) return undefined;
893
+ if (value.failureEvidence !== undefined && !isStructuredCheckFailureEvidence(value.failureEvidence)) return undefined;
894
+ return value;
620
895
  } catch (_error) {
621
896
  return undefined;
622
897
  }
623
898
  }
624
899
 
625
- function readControllerCheckEvidenceByKey(repoRoot: string, id: string, cacheKey: string): ControllerCheckEvidence | undefined {
626
- const path = historicalEvidencePath(repoRoot, id, cacheKey);
900
+ function readControllerCheckEvidenceByKey(storage: ResolvedRepositoryCheckStorage, id: string, cacheKey: string): ControllerCheckEvidence | undefined {
901
+ const path = historicalEvidencePath(storage, id, cacheKey);
627
902
  if (!existsSync(path)) return undefined;
628
903
  try {
629
904
  const value = JSON.parse(readFileSync(path, 'utf-8')) as ControllerCheckEvidence;
@@ -638,16 +913,27 @@ function prepareControllerCheckDependencies(repoRoot: string, check: ControllerC
638
913
  materializeManagedWorkspaceCheckDependencies(repoRoot);
639
914
  }
640
915
 
641
- export function runControllerCheck(repoRoot: string, id: string, requestedTimeoutMs?: number, snapshot?: ControllerCheckSnapshot): ControllerCheckResult {
916
+ export function runControllerCheck(
917
+ repoRoot: string,
918
+ id: string,
919
+ requestedTimeoutMs?: number,
920
+ snapshot?: ControllerCheckSnapshot,
921
+ storageAuthority?: RepositoryCheckStorageAuthority,
922
+ ): ControllerCheckResult {
642
923
  const check = snapshot ? validateControllerCheckSnapshot(repoRoot, snapshot) : listControllerChecks(repoRoot).find((entry) => entry.id === id);
643
924
  if (!check || check.id !== id) throw new Error(`check not found: ${id}`);
925
+ if (check.executionAuthority === 'live_controller_home') {
926
+ throw new Error('LIVE_CHECK_DURABLE_EXECUTION_REQUIRED');
927
+ }
928
+ const storage = ensureRepositoryCheckStorage(repoRoot, storageAuthority);
644
929
  prepareControllerCheckDependencies(repoRoot, check);
645
- const identity = controllerCheckExecutionIdentity(repoRoot, id, requestedTimeoutMs, snapshot);
930
+ const inputIntegrity = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
931
+ const identity = controllerCheckExecutionIdentityForRevision(repoRoot, id, inputIntegrity.revision, requestedTimeoutMs, snapshot);
646
932
  const timeoutMs = identity.timeoutMs;
647
933
  const revision = identity.revision;
648
934
  const cacheKey = identity.cacheKey;
649
- const cached = readControllerCheckEvidenceByKey(repoRoot, id, cacheKey)
650
- ?? readLatestControllerCheckEvidence(repoRoot, id);
935
+ const cached = readControllerCheckEvidenceByKey(storage, id, cacheKey)
936
+ ?? readLatestControllerCheckEvidence(repoRoot, id, storage);
651
937
  if (cached?.cacheKey === cacheKey && cached.ok) {
652
938
  return {
653
939
  check,
@@ -658,20 +944,23 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
658
944
  stderr: cached.stderr,
659
945
  command: cached.command,
660
946
  executedAt: cached.executedAt,
661
- artifactPath: relative(repoRoot, evidencePath(repoRoot, id)).replace(/\\/g, '/'),
947
+ artifactPath: logicalEvidenceArtifactPath(id),
662
948
  cacheHit: true,
663
949
  validatedRevision: cached.validatedRevision ?? cached.completedRevision ?? cached.revision ?? revision,
664
950
  originalExecutedAt: cached.originalExecutedAt ?? cached.executedAt,
665
951
  failureClass: cached.failureClass,
952
+ failureEvidence: cached.failureEvidence,
666
953
  };
667
954
  }
668
955
  const heavy = controllerCheckConcurrencyClass(id) === 'heavy';
669
- const lease = heavy ? tryAcquireHeavyCheckLock(repoRoot, id) : undefined;
956
+ const lease = heavy ? tryAcquireHeavyCheckLock(storage, id) : undefined;
670
957
  if (heavy && !lease) throw new Error(`heavy check already running for repository: ${id}`);
958
+ const structuredResultPath = structuredCheckResultPath(check);
671
959
  let result: ProcessRunResult;
672
960
  try {
673
961
  const bridgeRuntime = resolveSyncSupervisorBridgeRuntime();
674
962
  const childEnvironment = repositoryChildProcessEnvironment();
963
+ if (structuredResultPath) childEnvironment[STRUCTURED_CHECK_RESULT_PATH_ENV] = structuredResultPath;
675
964
  delete childEnvironment[CHECK_BRIDGE_RUNTIME_ENV];
676
965
  childEnvironment.FORGE_SUPERVISED_REQUEST = Buffer.from(JSON.stringify({
677
966
  command: check.command[0],
@@ -736,17 +1025,23 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
736
1025
  } finally {
737
1026
  lease?.release();
738
1027
  }
739
- const completedRevision = currentControllerCheckRevision(repoRoot);
740
- const stale = completedRevision !== revision;
1028
+ const structuredObservation = consumeStructuredCheckObservation(check, structuredResultPath);
1029
+ const structuredDecision = applyStructuredCheckObservation(result.ok, structuredObservation);
1030
+ const completedContent = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
1031
+ const completedRevision = completedContent.revision;
1032
+ const stale = controllerCheckInputIntegrityChanged(check, inputIntegrity, completedContent);
741
1033
  const executedAt = new Date().toISOString();
1034
+ const effectiveOk = structuredDecision.ok && !stale;
1035
+ const hardInfrastructureFailure = stale || result.timedOut || Boolean(result.error) || Boolean(result.signal);
742
1036
  const withoutPath = {
743
1037
  check,
744
- ok: result.ok && !stale,
745
- status: stale ? 1 : result.status,
1038
+ ok: effectiveOk,
1039
+ status: stale || (!structuredDecision.ok && result.status === 0) ? 1 : result.status,
746
1040
  timedOut: result.timedOut,
747
1041
  stdout: result.stdout,
748
1042
  stderr: [
749
1043
  result.stderr || result.error,
1044
+ structuredDecision.error,
750
1045
  stale ? 'repository revision changed while the check was running; evidence is stale and the check must be rerun' : '',
751
1046
  ].filter(Boolean).join('\n'),
752
1047
  command: result.command,
@@ -754,13 +1049,21 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
754
1049
  cacheHit: false,
755
1050
  validatedRevision: stale ? completedRevision : revision,
756
1051
  originalExecutedAt: executedAt,
757
- failureClass: stale || result.timedOut || Boolean(result.error) || Boolean(result.signal)
1052
+ failureClass: hardInfrastructureFailure
758
1053
  ? 'infrastructure_failure' as const
759
- : result.ok ? undefined : 'acceptance_failure' as const,
1054
+ : structuredDecision.failureClass ?? classifyControllerCheckFailure({
1055
+ ok: effectiveOk,
1056
+ stale,
1057
+ timedOut: result.timedOut,
1058
+ runtimeFailure: Boolean(result.error) || Boolean(result.signal),
1059
+ stdout: result.stdout,
1060
+ stderr: [result.stderr, result.error, structuredDecision.error].filter(Boolean).join('\n'),
1061
+ }),
1062
+ failureEvidence: structuredDecision.failureEvidence,
760
1063
  };
761
1064
  return {
762
1065
  ...withoutPath,
763
- artifactPath: persistCheckEvidence(repoRoot, withoutPath, {
1066
+ artifactPath: persistCheckEvidence(storage, withoutPath, {
764
1067
  revision,
765
1068
  completedRevision,
766
1069
  stale,
@@ -773,6 +1076,11 @@ export function runControllerCheck(repoRoot: string, id: string, requestedTimeou
773
1076
 
774
1077
  export interface AsyncControllerCheckOptions {
775
1078
  snapshot?: ControllerCheckSnapshot;
1079
+ /** Exact live-state identity supplied by the persisted Work verifier for live certification checks. */
1080
+ executionStateFingerprint?: string;
1081
+ /** Explicit installed Controller Home; never inferred from ambient child environment. */
1082
+ liveControllerHome?: string;
1083
+ storageAuthority?: RepositoryCheckStorageAuthority;
776
1084
  /** Explicit isolated authority for Candidate verification child processes. */
777
1085
  isolatedControllerHome?: string;
778
1086
  requestedTimeoutMs?: number;
@@ -823,8 +1131,8 @@ interface HeavyCheckLease {
823
1131
  release(): void;
824
1132
  }
825
1133
 
826
- function tryAcquireHeavyCheckLock(repoRoot: string, checkId: string): HeavyCheckLease | undefined {
827
- const path = join(repoRoot, HEAVY_CHECK_LOCK);
1134
+ function tryAcquireHeavyCheckLock(storage: ResolvedRepositoryCheckStorage, checkId: string): HeavyCheckLease | undefined {
1135
+ const path = join(storage.lockRoot, HEAVY_CHECK_LOCK);
828
1136
  mkdirSync(dirname(path), { recursive: true });
829
1137
  const lockId = `${process.pid}:${Date.now()}:${checkId}`;
830
1138
  const record: HeavyCheckLockRecord = {
@@ -851,7 +1159,7 @@ function tryAcquireHeavyCheckLock(repoRoot: string, checkId: string): HeavyCheck
851
1159
  const orphaned = !isProcessAlive(existing?.controllerPid ?? existing?.pid) && !isProcessAlive(existing?.childPid);
852
1160
  if (!existing || orphaned) {
853
1161
  rmSync(path, { force: true });
854
- return tryAcquireHeavyCheckLock(repoRoot, checkId);
1162
+ return tryAcquireHeavyCheckLock(storage, checkId);
855
1163
  }
856
1164
  return undefined;
857
1165
  }
@@ -873,10 +1181,10 @@ function tryAcquireHeavyCheckLock(repoRoot: string, checkId: string): HeavyCheck
873
1181
  };
874
1182
  }
875
1183
 
876
- async function acquireHeavyCheckLock(repoRoot: string, checkId: string): Promise<HeavyCheckLease> {
1184
+ async function acquireHeavyCheckLock(storage: ResolvedRepositoryCheckStorage, checkId: string): Promise<HeavyCheckLease> {
877
1185
  const deadline = Date.now() + MAX_TIMEOUT_MS * 2;
878
1186
  while (true) {
879
- const lease = tryAcquireHeavyCheckLock(repoRoot, checkId);
1187
+ const lease = tryAcquireHeavyCheckLock(storage, checkId);
880
1188
  if (lease) return lease;
881
1189
  if (Date.now() >= deadline) throw new Error(`timed out waiting for repository heavy-check lock before ${checkId}`);
882
1190
  await new Promise((resolvePromise) => setTimeout(resolvePromise, 50));
@@ -913,13 +1221,19 @@ async function executeControllerCheckAsync(
913
1221
  repoRoot: string,
914
1222
  check: ControllerCheck,
915
1223
  timeoutMs: number,
1224
+ storage: ResolvedRepositoryCheckStorage,
916
1225
  onSpawn?: (pid: number) => void,
917
1226
  isolatedControllerHome?: string,
1227
+ liveControllerHome?: string,
918
1228
  ): Promise<ControllerCheckResult> {
919
1229
  const maxOutputBytes = 256 * 1024;
920
1230
  const command = [check.command[0], ...check.command.slice(1)];
921
1231
  const childEnvironment = repositoryChildProcessEnvironment();
922
- if (isolatedControllerHome?.trim()) childEnvironment.FORGE_CONTROLLER_HOME = resolve(isolatedControllerHome);
1232
+ const structuredResultPath = structuredCheckResultPath(check);
1233
+ if (structuredResultPath) childEnvironment[STRUCTURED_CHECK_RESULT_PATH_ENV] = structuredResultPath;
1234
+ if (isolatedControllerHome?.trim() && liveControllerHome?.trim()) throw new Error('CHECK_CONTROLLER_HOME_AUTHORITY_CONFLICT');
1235
+ if (liveControllerHome?.trim()) childEnvironment.FORGE_CONTROLLER_HOME = resolve(liveControllerHome);
1236
+ else if (isolatedControllerHome?.trim()) childEnvironment.FORGE_CONTROLLER_HOME = resolve(isolatedControllerHome);
923
1237
  const supervised = await runBoundedChild(check.command[0], check.command.slice(1), {
924
1238
  cwd: resolve(repoRoot, check.cwd),
925
1239
  env: childEnvironment,
@@ -935,19 +1249,34 @@ async function executeControllerCheckAsync(
935
1249
  const timeoutMessage = supervised.timedOut
936
1250
  ? `process timed out after ${timeoutMs}ms: ${command.join(' ')}`
937
1251
  : '';
1252
+ const processOk = supervised.status === 0 && !supervised.failureCode;
1253
+ const structuredObservation = consumeStructuredCheckObservation(check, structuredResultPath);
1254
+ const structuredDecision = applyStructuredCheckObservation(processOk, structuredObservation);
1255
+ const hardInfrastructureFailure = supervised.timedOut
1256
+ || Boolean(supervised.failureCode)
1257
+ || Boolean(supervised.error)
1258
+ || Boolean(supervised.signal);
938
1259
  const result = {
939
- ok: supervised.status === 0 && !supervised.failureCode,
940
- status: supervised.status,
1260
+ ok: structuredDecision.ok,
1261
+ status: !structuredDecision.ok && supervised.status === 0 ? 1 : supervised.status,
941
1262
  timedOut: supervised.timedOut,
942
1263
  stdout: capProcessOutput(redactProcessOutput(supervised.stdout), maxOutputBytes),
943
1264
  stderr: capProcessOutput(redactProcessOutput([
944
1265
  supervised.stderr,
945
1266
  timeoutMessage || supervised.error || '',
946
1267
  processTreeError,
1268
+ structuredDecision.error,
947
1269
  ].filter(Boolean).join('\n')), maxOutputBytes),
948
- failureClass: supervised.failureCode
1270
+ failureClass: hardInfrastructureFailure
949
1271
  ? 'infrastructure_failure' as const
950
- : supervised.status === 0 ? undefined : 'acceptance_failure' as const,
1272
+ : structuredDecision.failureClass ?? classifyControllerCheckFailure({
1273
+ ok: structuredDecision.ok,
1274
+ timedOut: supervised.timedOut,
1275
+ runtimeFailure: Boolean(supervised.failureCode) || Boolean(supervised.error) || Boolean(supervised.signal),
1276
+ stdout: supervised.stdout,
1277
+ stderr: [supervised.stderr, timeoutMessage, supervised.error, processTreeError, structuredDecision.error].filter(Boolean).join('\n'),
1278
+ }),
1279
+ failureEvidence: structuredDecision.failureEvidence,
951
1280
  };
952
1281
 
953
1282
  const executedAt = new Date().toISOString();
@@ -964,8 +1293,9 @@ async function executeControllerCheckAsync(
964
1293
  validatedRevision: undefined,
965
1294
  originalExecutedAt: executedAt,
966
1295
  failureClass: result.failureClass,
1296
+ failureEvidence: result.failureEvidence,
967
1297
  };
968
- return { ...withoutPath, artifactPath: relative(repoRoot, evidencePath(repoRoot, check.id)).replace(/\\/g, '/') };
1298
+ return { ...withoutPath, artifactPath: logicalEvidenceArtifactPath(check.id) };
969
1299
  }
970
1300
 
971
1301
  export function runControllerCheckAsync(
@@ -980,19 +1310,68 @@ export function runControllerCheckAsync(
980
1310
  return Promise.reject(error);
981
1311
  }
982
1312
  if (!check || check.id !== id) return Promise.reject(new Error(`check not found: ${id}`));
1313
+ const liveCertification = check.executionAuthority === 'live_controller_home';
1314
+ const liveControllerHome = options.liveControllerHome?.trim();
1315
+ const expectedLiveState = options.executionStateFingerprint?.trim();
1316
+ if (liveCertification) {
1317
+ if (!liveControllerHome || !expectedLiveState) {
1318
+ return Promise.reject(new Error('LIVE_CHECK_EXPLICIT_AUTHORITY_REQUIRED'));
1319
+ }
1320
+ } else if (liveControllerHome) {
1321
+ return Promise.reject(new Error('LIVE_CHECK_AUTHORITY_NOT_DECLARED'));
1322
+ }
1323
+ let storage: ResolvedRepositoryCheckStorage;
983
1324
  try {
1325
+ storage = ensureRepositoryCheckStorage(repoRoot, options.storageAuthority);
984
1326
  prepareControllerCheckDependencies(repoRoot, check);
985
1327
  } catch (error) {
986
1328
  return Promise.reject(error);
987
1329
  }
988
- const identity = controllerCheckExecutionIdentity(repoRoot, id, options.requestedTimeoutMs, options.snapshot);
1330
+ const inputIntegrity = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
1331
+ const identity = controllerCheckExecutionIdentityForRevision(
1332
+ repoRoot,
1333
+ id,
1334
+ inputIntegrity.revision,
1335
+ options.requestedTimeoutMs,
1336
+ options.snapshot,
1337
+ options.executionStateFingerprint,
1338
+ );
989
1339
  const timeoutMs = identity.timeoutMs;
990
1340
  const revision = identity.revision;
991
1341
  const cacheKey = identity.cacheKey;
992
- const cached = readControllerCheckEvidenceByKey(repoRoot, id, cacheKey)
993
- ?? readLatestControllerCheckEvidence(repoRoot, id);
1342
+ const cached = readControllerCheckEvidenceByKey(storage, id, cacheKey)
1343
+ ?? readLatestControllerCheckEvidence(repoRoot, id, storage);
1344
+ const withLiveRecoveryFence = async <T>(action: (recoveryFenceInstanceId?: string) => Promise<T> | T): Promise<T> => {
1345
+ if (!liveCertification) return await action(undefined);
1346
+ let attempt;
1347
+ try {
1348
+ attempt = acquireRecoveryOperationLock({
1349
+ controllerHome: liveControllerHome!,
1350
+ action: 'certify_stable_baseline',
1351
+ requestId: `check:${id}:${cacheKey}`,
1352
+ instanceIdPrefix: 'live-certification-',
1353
+ });
1354
+ } catch (error) {
1355
+ const message = error instanceof Error ? error.message : String(error);
1356
+ if (message === 'RECOVERY_OPERATION_LOCK_BUSY') throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
1357
+ throw new Error(`LIVE_CHECK_RECOVERY_MUTATION_STATE_UNREADABLE: ${message}`);
1358
+ }
1359
+ if (!attempt.acquired) throw new Error('LIVE_CHECK_RECOVERY_MUTATION_IN_PROGRESS');
1360
+ try {
1361
+ const observedLiveState = controllerCheckLiveExecutionStateFingerprint(
1362
+ liveControllerHome!,
1363
+ attempt.handle.record.instanceId,
1364
+ );
1365
+ if (observedLiveState !== expectedLiveState) {
1366
+ throw new Error('LIVE_CHECK_STATE_CHANGED_BEFORE_EXECUTION');
1367
+ }
1368
+ return await action(attempt.handle.record.instanceId);
1369
+ } finally {
1370
+ attempt.handle.close();
1371
+ }
1372
+ };
994
1373
  if (cached?.cacheKey === cacheKey && cached.ok) {
995
- return Promise.resolve({
1374
+ return withLiveRecoveryFence(() => ({
996
1375
  check,
997
1376
  ok: cached.ok,
998
1377
  status: cached.status,
@@ -1001,12 +1380,12 @@ export function runControllerCheckAsync(
1001
1380
  stderr: cached.stderr,
1002
1381
  command: cached.command,
1003
1382
  executedAt: cached.executedAt,
1004
- artifactPath: relative(repoRoot, evidencePath(repoRoot, id)).replace(/\\/g, '/'),
1383
+ artifactPath: logicalEvidenceArtifactPath(id),
1005
1384
  cacheHit: true,
1006
1385
  validatedRevision: cached.validatedRevision ?? cached.completedRevision ?? cached.revision ?? revision,
1007
1386
  originalExecutedAt: cached.originalExecutedAt ?? cached.executedAt,
1008
1387
  failureClass: cached.failureClass,
1009
- });
1388
+ }));
1010
1389
  }
1011
1390
  const key = `${resolve(repoRoot)}\u0000${id}\u0000${cacheKey}`;
1012
1391
  const existing = activeAsyncChecks.get(key);
@@ -1052,48 +1431,69 @@ export function runControllerCheckAsync(
1052
1431
  };
1053
1432
  const execute = async (lease?: HeavyCheckLease) => {
1054
1433
  assertExecutionStillRequested();
1055
- const result = await executeControllerCheckAsync(repoRoot, check, timeoutMs, (pid) => {
1056
- lease?.setChildPid(pid);
1057
- notifySpawn(pid);
1058
- }, options.isolatedControllerHome);
1059
- const completedRevision = currentControllerCheckRevision(repoRoot);
1060
- const stale = completedRevision !== revision;
1061
- const finalized = {
1062
- ...result,
1063
- ...(stale ? {
1064
- ok: false,
1065
- status: 1,
1066
- stderr: [
1067
- result.stderr,
1068
- 'repository revision changed while the check was running; evidence is stale and the check must be rerun',
1069
- ].filter(Boolean).join('\n'),
1070
- failureClass: 'infrastructure_failure' as const,
1071
- } : {}),
1072
- cacheHit: false,
1073
- validatedRevision: stale ? completedRevision : revision,
1074
- };
1075
- const { artifactPath: _artifactPath, ...withoutPath } = finalized;
1076
- const artifactPath = persistCheckEvidence(repoRoot, withoutPath, {
1077
- revision,
1078
- completedRevision,
1079
- stale,
1080
- cacheKey: stale ? undefined : cacheKey,
1081
- cacheHit: false,
1082
- validatedRevision: stale ? completedRevision : revision,
1434
+ return withLiveRecoveryFence(async (recoveryFenceInstanceId) => {
1435
+ assertExecutionStillRequested();
1436
+ const result = await executeControllerCheckAsync(repoRoot, check, timeoutMs, storage, (pid) => {
1437
+ lease?.setChildPid(pid);
1438
+ notifySpawn(pid);
1439
+ }, options.isolatedControllerHome, options.liveControllerHome);
1440
+ const completedContent = observeControllerCheckContent(repoRoot, { captureFileDigests: true });
1441
+ const completedRevision = completedContent.revision;
1442
+ let liveStateStale = false;
1443
+ if (liveCertification) {
1444
+ try {
1445
+ liveStateStale = controllerCheckLiveExecutionStateFingerprint(
1446
+ liveControllerHome!,
1447
+ recoveryFenceInstanceId,
1448
+ ) !== expectedLiveState;
1449
+ } catch {
1450
+ liveStateStale = true;
1451
+ }
1452
+ }
1453
+ const repositoryStale = controllerCheckInputIntegrityChanged(check, inputIntegrity, completedContent);
1454
+ const stale = repositoryStale || liveStateStale;
1455
+ const finalized = {
1456
+ ...result,
1457
+ ...(stale ? {
1458
+ ok: false,
1459
+ status: 1,
1460
+ stderr: [
1461
+ result.stderr,
1462
+ repositoryStale
1463
+ ? 'repository revision changed while the check was running; evidence is stale and the check must be rerun'
1464
+ : '',
1465
+ liveStateStale
1466
+ ? 'live Runtime/Recovery authority changed while the check was running; evidence is stale and the check must be rerun'
1467
+ : '',
1468
+ ].filter(Boolean).join('\n'),
1469
+ failureClass: 'infrastructure_failure' as const,
1470
+ } : {}),
1471
+ cacheHit: false,
1472
+ validatedRevision: stale ? completedRevision : revision,
1473
+ };
1474
+ const { artifactPath: _artifactPath, ...withoutPath } = finalized;
1475
+ const artifactPath = persistCheckEvidence(storage, withoutPath, {
1476
+ revision,
1477
+ completedRevision,
1478
+ stale,
1479
+ cacheKey: stale ? undefined : cacheKey,
1480
+ cacheHit: false,
1481
+ validatedRevision: stale ? completedRevision : revision,
1482
+ });
1483
+ return { ...finalized, artifactPath };
1083
1484
  });
1084
- return { ...finalized, artifactPath };
1085
1485
  };
1086
1486
  const executeHeavy = async (): Promise<ControllerCheckResult> => {
1087
1487
  assertExecutionStillRequested();
1088
- const lease = await acquireHeavyCheckLock(repoRoot, id);
1488
+ const lease = await acquireHeavyCheckLock(storage, id);
1089
1489
  try {
1090
1490
  assertExecutionStillRequested();
1091
1491
  const currentRevision = currentControllerCheckRevision(repoRoot);
1092
1492
  if (currentRevision !== revision) {
1093
1493
  throw new Error(`repository revision changed while heavy check ${id} was queued; resubmit the check`);
1094
1494
  }
1095
- const refreshed = readControllerCheckEvidenceByKey(repoRoot, id, cacheKey)
1096
- ?? readLatestControllerCheckEvidence(repoRoot, id);
1495
+ const refreshed = readControllerCheckEvidenceByKey(storage, id, cacheKey)
1496
+ ?? readLatestControllerCheckEvidence(repoRoot, id, storage);
1097
1497
  if (refreshed?.cacheKey === cacheKey && refreshed.ok) {
1098
1498
  return {
1099
1499
  check,
@@ -1104,7 +1504,7 @@ export function runControllerCheckAsync(
1104
1504
  stderr: refreshed.stderr,
1105
1505
  command: refreshed.command,
1106
1506
  executedAt: refreshed.executedAt,
1107
- artifactPath: relative(repoRoot, evidencePath(repoRoot, id)).replace(/\\/g, '/'),
1507
+ artifactPath: logicalEvidenceArtifactPath(id),
1108
1508
  cacheHit: true,
1109
1509
  validatedRevision: refreshed.validatedRevision ?? refreshed.completedRevision ?? refreshed.revision ?? revision,
1110
1510
  originalExecutedAt: refreshed.originalExecutedAt ?? refreshed.executedAt,