@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
@@ -0,0 +1,79 @@
1
+ import type { IncomingMessage, ServerResponse } from 'http';
2
+ import { createMcpHandler, Server, type Tool } from '@modelcontextprotocol/server';
3
+ import { toNodeHandler } from '@modelcontextprotocol/node';
4
+ import { FORGE_VERSION } from '../../version';
5
+
6
+ export interface RecoveryMcpRequestContext {
7
+ remoteAddress: string;
8
+ }
9
+
10
+ export interface RecoveryMcpServerOptions {
11
+ tools: readonly Tool[];
12
+ dispatchTool(name: string, args: Record<string, unknown>, context: RecoveryMcpRequestContext): Promise<unknown>;
13
+ }
14
+
15
+ /**
16
+ * Standalone Recovery owns durable recovery/release authority, never MCP
17
+ * transport-session authority. Both MCP 2026-07-28 and the bounded 2025-era
18
+ * compatibility protocol are served statelessly so a Gateway process
19
+ * replacement cannot invalidate the Recovery control path.
20
+ */
21
+ export class RecoveryMcpServer {
22
+ constructor(private readonly options: RecoveryMcpServerOptions) {}
23
+
24
+ async close(): Promise<void> {
25
+ // Stateless handlers retain no cross-request transport resources.
26
+ }
27
+
28
+ async handle(request: IncomingMessage, response: ServerResponse, body?: unknown): Promise<void> {
29
+ if (request.method !== 'POST') {
30
+ response.statusCode = 405;
31
+ response.setHeader('allow', 'POST');
32
+ response.end();
33
+ return;
34
+ }
35
+
36
+ const context: RecoveryMcpRequestContext = {
37
+ remoteAddress: request.socket.remoteAddress ?? 'unknown',
38
+ };
39
+ const handler = createMcpHandler(async () => this.createServer(context), {
40
+ legacy: 'stateless',
41
+ responseMode: 'auto',
42
+ });
43
+ try {
44
+ await toNodeHandler(handler)(request, response, body);
45
+ } finally {
46
+ await handler.close();
47
+ }
48
+ }
49
+
50
+ private createServer(context: RecoveryMcpRequestContext): Server {
51
+ const server = new Server(
52
+ { name: 'forge-standalone-recovery', version: FORGE_VERSION },
53
+ { capabilities: { tools: {} } },
54
+ );
55
+ server.setRequestHandler('tools/list', async () => ({ tools: [...this.options.tools] }));
56
+ server.setRequestHandler('tools/call', async (request) => {
57
+ const name = request.params.name;
58
+ const args = request.params.arguments && typeof request.params.arguments === 'object' && !Array.isArray(request.params.arguments)
59
+ ? request.params.arguments as Record<string, unknown>
60
+ : {};
61
+ try {
62
+ const payload = await this.options.dispatchTool(name, args, context);
63
+ const structuredContent = payload && typeof payload === 'object' && !Array.isArray(payload)
64
+ ? payload as Record<string, unknown>
65
+ : { value: payload };
66
+ return {
67
+ content: [{ type: 'text' as const, text: JSON.stringify(payload) }],
68
+ structuredContent,
69
+ };
70
+ } catch (error) {
71
+ return {
72
+ isError: true,
73
+ content: [{ type: 'text' as const, text: error instanceof Error ? error.message : 'Recovery request rejected' }],
74
+ };
75
+ }
76
+ });
77
+ return server;
78
+ }
79
+ }
@@ -0,0 +1,21 @@
1
+ /** Canonical external mutation identity contract for Standalone Recovery.
2
+ *
3
+ * Both the runtime fencing implementation and the MCP tool schema derive from
4
+ * this single authority. Keep target-identity field names and validation shape
5
+ * here so an upgraded Recovery cannot require fields that its own connector
6
+ * schema forgot to expose.
7
+ */
8
+ export const RECOVERY_MUTATION_IDENTITY_CONTRACT = {
9
+ expected_host: { type: 'string', minLength: 1, maxLength: 255 },
10
+ expected_platform: { type: 'string', minLength: 1, maxLength: 64 },
11
+ expected_controller_home: { type: 'string', minLength: 1, maxLength: 2048 },
12
+ expected_recovery_release: { type: 'string', minLength: 1, maxLength: 256 },
13
+ expected_target_runtime: { type: 'string', minLength: 1, maxLength: 1024 },
14
+ } as const;
15
+
16
+ export const RECOVERY_MUTATION_IDENTITY_FIELDS = Object.freeze(
17
+ Object.keys(RECOVERY_MUTATION_IDENTITY_CONTRACT),
18
+ ) as readonly (keyof typeof RECOVERY_MUTATION_IDENTITY_CONTRACT)[];
19
+
20
+ export type RecoveryMutationIdentityField = (typeof RECOVERY_MUTATION_IDENTITY_FIELDS)[number];
21
+ export type RecoveryMutationIdentityArguments = Record<RecoveryMutationIdentityField, string>;
@@ -0,0 +1,160 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { spawnSync } from 'child_process';
3
+ import { closeSync, mkdirSync, openSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'fs';
4
+ import { dirname, join, resolve } from 'path';
5
+ import { isProcessAlive } from '../shared/process-tree';
6
+
7
+ export interface RecoveryOperationLockRecord {
8
+ schemaVersion?: 1;
9
+ pid: number;
10
+ instanceId: string;
11
+ processStartTime?: string;
12
+ acquiredAt: string;
13
+ action?: string;
14
+ requestId?: string;
15
+ }
16
+
17
+ export interface RecoveryOperationLockHandle {
18
+ path: string;
19
+ record: RecoveryOperationLockRecord;
20
+ close: () => void;
21
+ }
22
+
23
+ export type RecoveryOperationLockAttempt =
24
+ | { acquired: true; handle: RecoveryOperationLockHandle }
25
+ | { acquired: false; owner: RecoveryOperationLockRecord };
26
+
27
+ function processStartTime(pid: number): string | undefined {
28
+ const result = spawnSync('/bin/ps', ['-o', 'lstart=', '-p', String(pid)], {
29
+ encoding: 'utf8',
30
+ timeout: 2_000,
31
+ maxBuffer: 4_096,
32
+ });
33
+ if (result.status !== 0 || typeof result.stdout !== 'string') return undefined;
34
+ return result.stdout.trim() || undefined;
35
+ }
36
+
37
+ function readRecoveryOperationLockPath(path: string): RecoveryOperationLockRecord | undefined {
38
+ let raw: string;
39
+ try {
40
+ raw = readFileSync(path, 'utf8');
41
+ } catch (error) {
42
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;
43
+ throw error;
44
+ }
45
+ try {
46
+ const parsed = JSON.parse(raw) as RecoveryOperationLockRecord;
47
+ if (!Number.isInteger(parsed.pid) || parsed.pid <= 0) return undefined;
48
+ if (typeof parsed.instanceId !== 'string' || !parsed.instanceId.trim()) return undefined;
49
+ if (typeof parsed.acquiredAt !== 'string' || !parsed.acquiredAt.trim()) return undefined;
50
+ return parsed;
51
+ } catch {
52
+ return undefined;
53
+ }
54
+ }
55
+
56
+ export function recoveryOperationLockPath(controllerHome: string): string {
57
+ const resolved = resolve(controllerHome);
58
+ let canonical = resolved;
59
+ try {
60
+ canonical = realpathSync(resolved);
61
+ } catch (error) {
62
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
63
+ }
64
+ return join(canonical, 'recovery', 'locks', 'operation.lock');
65
+ }
66
+
67
+ export function readRecoveryOperationLock(controllerHome: string): RecoveryOperationLockRecord | undefined {
68
+ return readRecoveryOperationLockPath(recoveryOperationLockPath(controllerHome));
69
+ }
70
+
71
+ export function recoveryOperationLockOwnerAlive(lock: RecoveryOperationLockRecord): boolean {
72
+ if (!isProcessAlive(lock.pid)) return false;
73
+ if (!lock.processStartTime) return true;
74
+ const observed = processStartTime(lock.pid);
75
+ return observed === lock.processStartTime;
76
+ }
77
+
78
+ export function acquireRecoveryOperationLock(input: {
79
+ controllerHome: string;
80
+ action: string;
81
+ requestId?: string;
82
+ instanceIdPrefix?: string;
83
+ }, dependencies: {
84
+ writeRecord?: (fd: number, content: string) => void;
85
+ } = {}): RecoveryOperationLockAttempt {
86
+ const path = recoveryOperationLockPath(input.controllerHome);
87
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
88
+ const instanceId = `${input.instanceIdPrefix ?? 'recovery-operation-'}${randomUUID()}`;
89
+ const requestId = input.requestId?.trim() || `internal:${input.action}:${instanceId}`;
90
+ const record: RecoveryOperationLockRecord = {
91
+ schemaVersion: 1,
92
+ pid: process.pid,
93
+ instanceId,
94
+ processStartTime: processStartTime(process.pid),
95
+ acquiredAt: new Date().toISOString(),
96
+ action: input.action,
97
+ requestId,
98
+ };
99
+
100
+ for (let attempt = 0; attempt < 2; attempt += 1) {
101
+ let fd: number | undefined;
102
+ try {
103
+ try {
104
+ fd = openSync(path, 'wx', 0o600);
105
+ try {
106
+ (dependencies.writeRecord ?? ((targetFd: number, content: string) => writeFileSync(targetFd, content)))(fd, JSON.stringify(record));
107
+ } catch (error) {
108
+ // O_EXCL proved this process created this exact path. A partial or failed
109
+ // owner-record write must never leave an unreadable lock that poisons
110
+ // every later Recovery/certification attempt.
111
+ try { rmSync(path, { force: true }); } finally {
112
+ try { closeSync(fd); } catch { /* best effort */ }
113
+ fd = undefined;
114
+ }
115
+ throw error;
116
+ }
117
+ } catch (error) {
118
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
119
+ const existing = readRecoveryOperationLockPath(path);
120
+ if (!existing) throw new Error('RECOVERY_OPERATION_LOCK_UNCERTAIN');
121
+ if (recoveryOperationLockOwnerAlive(existing)) return { acquired: false, owner: existing };
122
+ const latest = readRecoveryOperationLockPath(path);
123
+ if (!latest || latest.instanceId !== existing.instanceId) {
124
+ if (attempt === 1) {
125
+ if (latest && recoveryOperationLockOwnerAlive(latest)) return { acquired: false, owner: latest };
126
+ throw new Error('RECOVERY_OPERATION_LOCK_RACE');
127
+ }
128
+ continue;
129
+ }
130
+ if (recoveryOperationLockOwnerAlive(latest)) return { acquired: false, owner: latest };
131
+ try { writeFileSync(`${path}.stale-${Date.now()}-${existing.instanceId}`, readFileSync(path)); } catch { /* evidence best effort */ }
132
+ rmSync(path, { force: true });
133
+ continue;
134
+ }
135
+
136
+ if (fd === undefined) throw new Error('RECOVERY_OPERATION_LOCK_BUSY');
137
+ let closed = false;
138
+ return {
139
+ acquired: true,
140
+ handle: {
141
+ path,
142
+ record,
143
+ close: () => {
144
+ if (closed) return;
145
+ closed = true;
146
+ closeSync(fd!);
147
+ const current = readRecoveryOperationLockPath(path);
148
+ if (current?.instanceId === instanceId) rmSync(path, { force: true });
149
+ },
150
+ },
151
+ };
152
+ } catch (error) {
153
+ if (fd !== undefined) {
154
+ try { closeSync(fd); } catch { /* best effort */ }
155
+ }
156
+ throw error;
157
+ }
158
+ }
159
+ throw new Error('RECOVERY_OPERATION_LOCK_BUSY');
160
+ }
@@ -0,0 +1,173 @@
1
+ import { spawnSync } from 'node:child_process';
2
+
3
+ /** Release acceptance evidence, never a readiness/liveness or watchdog input. */
4
+ export interface RuntimePerformanceIdentity {
5
+ releaseId: string;
6
+ authorityRevision: number;
7
+ runtimeInstanceId: string;
8
+ pid: number;
9
+ startedAt: string;
10
+ }
11
+
12
+ export interface RuntimePerformanceEvidence extends RuntimePerformanceIdentity {
13
+ policy: 'runaway-cpu-v4';
14
+ measuredFrom: string;
15
+ measuredUntil: string;
16
+ warmupMs: number;
17
+ durationMs: number;
18
+ sampleCount: number;
19
+ meanCpuPercent: number;
20
+ p95CpuPercent: number;
21
+ /** Windows whose CPU consumption reached the per-window runaway ceiling. */
22
+ sustainedHighWindowCount: number;
23
+ }
24
+
25
+ export interface RuntimeCpuReading { cpuMs: number; processStartTime: string }
26
+
27
+ const PERFORMANCE_WINDOW_MS = 2_500;
28
+ const PERFORMANCE_MAX_WINDOW_MS = 3_750;
29
+ const PERFORMANCE_WARMUP_WINDOWS = 4;
30
+ const PERFORMANCE_SAMPLE_WINDOWS = 20;
31
+ const PERFORMANCE_WARMUP_MS = PERFORMANCE_WINDOW_MS * PERFORMANCE_WARMUP_WINDOWS;
32
+ const PERFORMANCE_DURATION_MS = PERFORMANCE_WINDOW_MS * PERFORMANCE_SAMPLE_WINDOWS;
33
+
34
+ // Recovery known-good is a runaway safety gate, not the comparative release benchmark.
35
+ // The v4 sampler keeps the same 60-second budget, the same twenty 2.5-second windows
36
+ // and the same 25%/50% ceilings as v2/v3, but decides runaway from *sustained*
37
+ // consumption instead of from nearest-rank p95.
38
+ //
39
+ // Why p95 cannot be the decision rule: the Canonical Runtime performs bounded,
40
+ // scheduled maintenance (the release-fenced periodic cleanup child and the in-process
41
+ // scheduler/recovery passes). Such a pass lasts several seconds and recurs about once
42
+ // per minute, so in any 50-second observation at least two windows necessarily land
43
+ // inside it. nearest-rank p95 is exactly the second-highest window, so a healthy
44
+ // Runtime with an ~11% mean was deterministically rejected (live evidence:
45
+ // mean=12.60% p95=65.05% and mean=11.41% p95=65.13%, both rolled back within minutes
46
+ // of cutover) and every automatic release progression converged on rollback.
47
+ //
48
+ // A watchdog duty must distinguish "unbounded spin" from "bounded periodic work", so
49
+ // v4 rejects a sample only when the process is high for at least half of the observed
50
+ // windows (sustainedHighWindowCount * 2 >= sampleCount) or when the mean exceeds the
51
+ // ceiling. The historical runaway population (mean >= 90.64%, p95 >= 104.72%) fails
52
+ // both tests by a wide margin, while a once-per-minute bounded pass (<= 4 of 20
53
+ // windows) can no longer be mistaken for runaway. p95 stays in the evidence for audit.
54
+ // Relative <=10% regression remains Benchmark/Release Evaluation authority.
55
+ export const RECOVERY_RUNAWAY_MEAN_CPU_PERCENT = 25;
56
+ export const RECOVERY_RUNAWAY_P95_CPU_PERCENT = 50;
57
+
58
+ /** Dependencies are in-process test seams; no transport accepts evidence or threshold overrides. */
59
+ export interface RuntimePerformanceDependencies {
60
+ readCpu?: (pid: number) => RuntimeCpuReading;
61
+ monotonicNow?: () => number;
62
+ wallNow?: () => number;
63
+ sleep?: (ms: number) => Promise<void>;
64
+ }
65
+
66
+ export function readRuntimeCpu(pid: number): RuntimeCpuReading {
67
+ const result = spawnSync('/bin/ps', ['-p', String(pid), '-o', 'time=', '-o', 'lstart='], {
68
+ encoding: 'utf8', timeout: 2_000, maxBuffer: 4_096, env: { ...process.env, LC_ALL: 'C' },
69
+ });
70
+ const match = result.status === 0
71
+ ? result.stdout.trim().match(/^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+(?:\.\d+)?)\s+(.+)$/)
72
+ : undefined;
73
+ if (!match) throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: process CPU measurement unavailable');
74
+ const cpuMs = (Number(match[1] ?? 0) * 86400 + Number(match[2] ?? 0) * 3600
75
+ + Number(match[3]) * 60 + Number(match[4])) * 1000;
76
+ return { cpuMs, processStartTime: match[5]! };
77
+ }
78
+
79
+ export function samePerformanceIdentity(a: RuntimePerformanceIdentity, b: RuntimePerformanceIdentity): boolean {
80
+ return a.releaseId === b.releaseId && a.authorityRevision === b.authorityRevision
81
+ && a.runtimeInstanceId === b.runtimeInstanceId && a.pid === b.pid && a.startedAt === b.startedAt;
82
+ }
83
+
84
+ export function assertRuntimePerformanceEvidence(
85
+ evidence: RuntimePerformanceEvidence,
86
+ identity: RuntimePerformanceIdentity,
87
+ now = Date.now(),
88
+ ): void {
89
+ const age = now - Date.parse(evidence.measuredUntil);
90
+ if (evidence.policy !== 'runaway-cpu-v4' || !samePerformanceIdentity(evidence, identity)
91
+ || !Number.isFinite(age) || age < 0 || age > 60_000
92
+ || evidence.warmupMs < PERFORMANCE_WARMUP_MS || evidence.warmupMs > PERFORMANCE_MAX_WINDOW_MS * PERFORMANCE_WARMUP_WINDOWS
93
+ || evidence.durationMs < PERFORMANCE_DURATION_MS || evidence.durationMs > PERFORMANCE_MAX_WINDOW_MS * PERFORMANCE_SAMPLE_WINDOWS || evidence.sampleCount !== PERFORMANCE_SAMPLE_WINDOWS
94
+ || !Number.isFinite(evidence.meanCpuPercent) || evidence.meanCpuPercent < 0
95
+ || !Number.isFinite(evidence.p95CpuPercent) || evidence.p95CpuPercent < 0
96
+ || !Number.isInteger(evidence.sustainedHighWindowCount)
97
+ || evidence.sustainedHighWindowCount < 0
98
+ || evidence.sustainedHighWindowCount > evidence.sampleCount) {
99
+ throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: incomplete, stale or mismatched performance evidence');
100
+ }
101
+ const sustained = evidence.sustainedHighWindowCount * 2 >= evidence.sampleCount;
102
+ if (evidence.meanCpuPercent > RECOVERY_RUNAWAY_MEAN_CPU_PERCENT || sustained) {
103
+ throw new Error(`RECOVERY_PERFORMANCE_REJECTED: mean=${evidence.meanCpuPercent.toFixed(2)}% p95=${evidence.p95CpuPercent.toFixed(2)}% sustained=${evidence.sustainedHighWindowCount}/${evidence.sampleCount}`);
104
+ }
105
+ }
106
+
107
+ /** Observe 10 seconds of warmup followed by twenty 2.5-second CPU-time delta windows. */
108
+ export async function measureRuntimePerformance(
109
+ observeIdentity: () => RuntimePerformanceIdentity,
110
+ dependencies: RuntimePerformanceDependencies = {},
111
+ ): Promise<RuntimePerformanceEvidence> {
112
+ const readCpu = dependencies.readCpu ?? readRuntimeCpu;
113
+ const monotonicNow = dependencies.monotonicNow ?? (() => performance.now());
114
+ const wallNow = dependencies.wallNow ?? Date.now;
115
+ const sleep = dependencies.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
116
+ const identity = observeIdentity();
117
+ const initial = readCpu(identity.pid);
118
+ const observe = () => {
119
+ if (!samePerformanceIdentity(identity, observeIdentity())) {
120
+ throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: Runtime or release authority changed');
121
+ }
122
+ const cpu = readCpu(identity.pid);
123
+ if (cpu.processStartTime !== initial.processStartTime || !Number.isFinite(cpu.cpuMs)) {
124
+ throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: process identity changed');
125
+ }
126
+ return cpu;
127
+ };
128
+ const warmingAt = monotonicNow();
129
+ let previousWarmupAt = warmingAt;
130
+ for (let i = 0; i < PERFORMANCE_WARMUP_WINDOWS; i++) {
131
+ await sleep(PERFORMANCE_WINDOW_MS);
132
+ observe();
133
+ const nextWarmupAt = monotonicNow();
134
+ const elapsed = nextWarmupAt - previousWarmupAt;
135
+ if (elapsed < PERFORMANCE_WINDOW_MS || elapsed > PERFORMANCE_MAX_WINDOW_MS) {
136
+ throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: interrupted CPU warmup window');
137
+ }
138
+ previousWarmupAt = nextWarmupAt;
139
+ }
140
+ const warmupMs = monotonicNow() - warmingAt;
141
+ const measuredFrom = new Date(wallNow()).toISOString();
142
+ let previousCpu = observe().cpuMs;
143
+ let previousAt = monotonicNow();
144
+ const startedAt = previousAt;
145
+ let totalCpuMs = 0;
146
+ const windows: number[] = [];
147
+ for (let i = 0; i < PERFORMANCE_SAMPLE_WINDOWS; i++) {
148
+ await sleep(PERFORMANCE_WINDOW_MS);
149
+ const nextCpu = observe().cpuMs;
150
+ const nextAt = monotonicNow();
151
+ const elapsed = nextAt - previousAt;
152
+ const cpuDelta = nextCpu - previousCpu;
153
+ // Suspended/overloaded collectors cannot pass as ordinary sample windows.
154
+ if (elapsed < PERFORMANCE_WINDOW_MS || elapsed > PERFORMANCE_MAX_WINDOW_MS || cpuDelta < 0) {
155
+ throw new Error('RECOVERY_PERFORMANCE_UNKNOWN: interrupted CPU observation window');
156
+ }
157
+ windows.push(cpuDelta / elapsed * 100);
158
+ totalCpuMs += cpuDelta;
159
+ previousCpu = nextCpu;
160
+ previousAt = nextAt;
161
+ }
162
+ const durationMs = previousAt - startedAt;
163
+ windows.sort((a, b) => a - b);
164
+ const evidence: RuntimePerformanceEvidence = {
165
+ ...identity, policy: 'runaway-cpu-v4', measuredFrom, measuredUntil: new Date(wallNow()).toISOString(),
166
+ warmupMs, durationMs, sampleCount: windows.length,
167
+ meanCpuPercent: totalCpuMs / durationMs * 100,
168
+ p95CpuPercent: windows[Math.ceil(windows.length * 0.95) - 1]!,
169
+ sustainedHighWindowCount: windows.filter((cpuPercent) => cpuPercent >= RECOVERY_RUNAWAY_P95_CPU_PERCENT).length,
170
+ };
171
+ assertRuntimePerformanceEvidence(evidence, observeIdentity(), wallNow());
172
+ return evidence;
173
+ }
@@ -15,8 +15,8 @@ import {
15
15
  import { dirname, join, relative, resolve, sep } from 'path';
16
16
  import { writeJsonAtomic } from '../shared/json-files';
17
17
 
18
- export const RECOVERY_RELEASE_BINARIES = [
19
- 'forge-recovery',
18
+ export const RECOVERY_RELEASE_BINARIES = ['forge-recovery'] as const;
19
+ export const RECOVERY_RELEASE_COMPATIBILITY_BINARIES = [
20
20
  'forge-recovery-gateway',
21
21
  'forge-recovery-watchdog',
22
22
  ] as const;
@@ -24,7 +24,8 @@ export const RECOVERY_RELEASE_BINARIES = [
24
24
  export const RECOVERY_RELEASE_ROLE_CANARY_ARG = '--forge-release-role-canary';
25
25
 
26
26
  export type RecoveryReleaseBinary = (typeof RECOVERY_RELEASE_BINARIES)[number];
27
- export type RecoveryRuntimeRole = 'gateway' | 'watchdog';
27
+ /** daemon is the only current persistent owner; gateway/watchdog remain legacy CLI compatibility roles. */
28
+ export type RecoveryRuntimeRole = 'daemon' | 'gateway' | 'watchdog';
28
29
  export interface RecoveryReleaseManifest {
29
30
  schemaVersion: 1;
30
31
  releaseRevision: string;
@@ -32,6 +33,8 @@ export interface RecoveryReleaseManifest {
32
33
  sourceRoot: string;
33
34
  cleanWorkspace: boolean;
34
35
  builtAt: string;
36
+ /** Product version derived from the source package and bound by the manifest hash. */
37
+ productVersion?: string;
35
38
  legacy?: boolean;
36
39
  artifacts: Record<RecoveryReleaseBinary, { sha256: string }>;
37
40
  }
@@ -42,6 +45,7 @@ export interface RecoveryReleaseDescriptor {
42
45
  sourceCommit: string;
43
46
  sourceRoot: string;
44
47
  cleanWorkspace: boolean;
48
+ productVersion?: string;
45
49
  manifestSha256: string;
46
50
  artifacts: RecoveryReleaseManifest['artifacts'];
47
51
  legacy: boolean;
@@ -81,6 +85,49 @@ export function recoveryRuntimeStatePath(controllerHome: string, role: RecoveryR
81
85
  return join(recoveryRoot(controllerHome), 'state', `${role}-runtime.json`);
82
86
  }
83
87
 
88
+ export function recoveryGatewayDrainMarkerPath(controllerHome: string): string {
89
+ return join(recoveryRoot(controllerHome), 'state', 'gateway-draining.json');
90
+ }
91
+
92
+ const RECOVERY_GATEWAY_DRAIN_MARKER_TTL_MS = 5 * 60_000;
93
+
94
+ export function recoveryGatewayIsDraining(controllerHome: string, now = Date.now()): boolean {
95
+ const path = recoveryGatewayDrainMarkerPath(controllerHome);
96
+ if (!existsSync(path)) return false;
97
+ try {
98
+ const marker = JSON.parse(readFileSync(path, 'utf8')) as { pid?: unknown; at?: unknown };
99
+ const pid = Number(marker.pid);
100
+ const at = typeof marker.at === 'string' ? Date.parse(marker.at) : Number.NaN;
101
+ if (!Number.isInteger(pid) || pid <= 0 || !Number.isFinite(at) || now - at > RECOVERY_GATEWAY_DRAIN_MARKER_TTL_MS) {
102
+ rmSync(path, { force: true });
103
+ return false;
104
+ }
105
+ try {
106
+ process.kill(pid, 0);
107
+ return true;
108
+ } catch (error) {
109
+ const code = (error as NodeJS.ErrnoException).code;
110
+ if (code === 'EPERM') return true;
111
+ rmSync(path, { force: true });
112
+ return false;
113
+ }
114
+ } catch {
115
+ rmSync(path, { force: true });
116
+ return false;
117
+ }
118
+ }
119
+
120
+ export function setRecoveryGatewayDraining(controllerHome: string, draining: boolean): void {
121
+ const path = recoveryGatewayDrainMarkerPath(controllerHome);
122
+ if (!draining) {
123
+ rmSync(path, { force: true });
124
+ return;
125
+ }
126
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
127
+ writeJsonAtomic(path, { schemaVersion: 1, draining: true, pid: process.pid, at: new Date().toISOString() });
128
+ chmodSync(path, 0o600);
129
+ }
130
+
84
131
  function fileSha256(path: string): string {
85
132
  return createHash('sha256').update(readFileSync(path)).digest('hex');
86
133
  }
@@ -109,6 +156,7 @@ export function readRecoveryRelease(path: string | undefined): RecoveryReleaseDe
109
156
  if (typeof parsed.sourceCommit !== 'string' || !parsed.sourceCommit.trim()) return undefined;
110
157
  if (typeof parsed.sourceRoot !== 'string' || !parsed.sourceRoot.trim()) return undefined;
111
158
  if (typeof parsed.cleanWorkspace !== 'boolean') return undefined;
159
+ if (parsed.productVersion !== undefined && (typeof parsed.productVersion !== 'string' || !parsed.productVersion.trim())) return undefined;
112
160
  if (!parsed.artifacts || typeof parsed.artifacts !== 'object') return undefined;
113
161
  const artifacts = {} as RecoveryReleaseManifest['artifacts'];
114
162
  for (const binary of RECOVERY_RELEASE_BINARIES) {
@@ -123,6 +171,7 @@ export function readRecoveryRelease(path: string | undefined): RecoveryReleaseDe
123
171
  sourceCommit: parsed.sourceCommit,
124
172
  sourceRoot: resolve(parsed.sourceRoot),
125
173
  cleanWorkspace: parsed.cleanWorkspace,
174
+ productVersion: typeof parsed.productVersion === 'string' ? parsed.productVersion.trim() : undefined,
126
175
  manifestSha256: createHash('sha256').update(bytes).digest('hex'),
127
176
  artifacts,
128
177
  legacy: parsed.legacy === true,
@@ -179,11 +228,15 @@ export function publishRecoveryCompatibilityLinks(controllerHome: string): void
179
228
  assertRecoveryReleaseContained(controllerHome, current);
180
229
  const binRoot = join(recoveryRoot(controllerHome), 'bin');
181
230
  mkdirSync(binRoot, { recursive: true, mode: 0o700 });
182
- for (const binary of RECOVERY_RELEASE_BINARIES) {
231
+ const compatibilityTargets = [
232
+ ...RECOVERY_RELEASE_BINARIES.map((binary) => ({ binary, target: binary })),
233
+ ...RECOVERY_RELEASE_COMPATIBILITY_BINARIES.map((binary) => ({ binary, target: 'forge-recovery' as const })),
234
+ ];
235
+ for (const { binary, target } of compatibilityTargets) {
183
236
  const destination = join(binRoot, binary);
184
237
  const temporary = `${destination}.${process.pid}.tmp`;
185
238
  rmSync(temporary, { force: true });
186
- symlinkSync(join('..', 'current', binary), temporary);
239
+ symlinkSync(join('..', 'current', target), temporary);
187
240
  renameSync(temporary, destination);
188
241
  }
189
242
  }
@@ -1,2 +1,5 @@
1
- export const RECOVERY_GATEWAY_LABEL = 'com.moretea.forge-recovery-gateway';
2
- export const RECOVERY_WATCHDOG_LABEL = 'com.moretea.forge-recovery-watchdog';
1
+ export {
2
+ FORGE_RECOVERY_DAEMON_LABEL as RECOVERY_DAEMON_LABEL,
3
+ FORGE_RECOVERY_GATEWAY_LABEL as RECOVERY_GATEWAY_LABEL,
4
+ FORGE_RECOVERY_WATCHDOG_LABEL as RECOVERY_WATCHDOG_LABEL,
5
+ } from '../platform/service-inventory';
@@ -151,10 +151,13 @@ export function evaluateRecoveryWatchdogHealth(input: {
151
151
  return { ok: true, detail: 'Recovery Watchdog heartbeat, PID, and immutable release identity are current', pulseAgeMs, heartbeat, runtimeIdentity, currentReleaseRevision: current.releaseRevision };
152
152
  }
153
153
 
154
- export function observeRecoveryWatchdogHealth(controllerHome: string): RecoveryWatchdogHealth {
154
+ export function observeRecoveryWatchdogHealth(controllerHome: string, enabled = true): RecoveryWatchdogHealth {
155
+ if (!enabled) {
156
+ return { ok: true, detail: 'Recovery Watchdog is disabled by the configured install profile' };
157
+ }
155
158
  return evaluateRecoveryWatchdogHealth({
156
159
  heartbeat: readRecoveryWatchdogHeartbeat(controllerHome),
157
- runtimeIdentity: readRecoveryRuntimeIdentity(controllerHome, 'watchdog'),
160
+ runtimeIdentity: readRecoveryRuntimeIdentity(controllerHome, 'daemon'),
158
161
  currentRelease: readCurrentRecoveryRelease(controllerHome),
159
162
  });
160
163
  }
@@ -3,7 +3,7 @@ import { getLocalBridgeJobEventsSnapshot, listLocalBridgeJobSnapshots } from '..
3
3
  import type { RepositoryRecord } from '../../cli/repositories/types';
4
4
  import { listExecutionJobs } from '../execution/jobs/store';
5
5
  import { collectRuntimePerformanceDiagnostics, type RuntimePerformanceDiagnostics } from '../diagnostics/performance';
6
- import { listSchedules } from '../workflow/schedules/store';
6
+ import { listSchedules } from '../../../packages/kernel/scheduler/api/index';
7
7
 
8
8
  const ACTIVE_AGENT_STATUSES = new Set(['queued', 'starting', 'running']);
9
9
 
@@ -82,6 +82,7 @@ async function browserAction(
82
82
  occurrenceId: string,
83
83
  actionId: string,
84
84
  args: Record<string, unknown>,
85
+ authorizationGrantRefs: readonly string[],
85
86
  ): Promise<Record<string, unknown>> {
86
87
  return executeBrowserPluginAction({
87
88
  controllerHome,
@@ -92,9 +93,16 @@ async function browserAction(
92
93
  requestId: `schedule-browser-probe:${occurrenceId}:${actionId}`,
93
94
  args,
94
95
  origin: { surface: 'schedule', actor: 'browser-probe', correlationId: occurrenceId },
96
+ authorizationGrantRefs,
95
97
  });
96
98
  }
97
99
 
100
+ /** Exact interactive grants attached to this Schedule; contents remain Controller-owned. */
101
+ export function scheduledBrowserProbeAuthorizationGrantRefs(args: Record<string, unknown>): string[] {
102
+ if (!Array.isArray(args.authorization_grant_refs)) return [];
103
+ return [...new Set(args.authorization_grant_refs.map(String).map((value) => value.trim()).filter(Boolean))];
104
+ }
105
+
98
106
  interface ScheduledBrowserSessionMetadata {
99
107
  url?: string;
100
108
  ownership?: string;
@@ -137,8 +145,9 @@ async function scheduledBrowserSessionMetadata(
137
145
  repository: RepositoryRecord,
138
146
  occurrenceId: string,
139
147
  sessionId: string,
148
+ authorizationGrantRefs: readonly string[],
140
149
  ): Promise<ScheduledBrowserSessionMetadata | undefined> {
141
- const inventory = await browserAction(controllerHome, repository, occurrenceId, 'list_sessions', {});
150
+ const inventory = await browserAction(controllerHome, repository, occurrenceId, 'list_sessions', {}, authorizationGrantRefs);
142
151
  const sessions = Array.isArray(inventory.sessions) ? inventory.sessions : [];
143
152
  const saved = sessions
144
153
  .map((entry) => recordValue(entry))
@@ -170,10 +179,12 @@ export async function executeScheduledBrowserProbe(input: {
170
179
  const url = stringValue(input.args.probe_url) ?? stringValue(input.args.url);
171
180
  if (!requestedSessionId && !url) throw new Error('SCHEDULE_BROWSER_PROBE_TARGET_REQUIRED');
172
181
 
182
+ const authorizationGrantRefs = scheduledBrowserProbeAuthorizationGrantRefs(input.args);
183
+
173
184
  const waitUntil = stringValue(input.args.wait_until) ?? 'domcontentloaded';
174
185
  const timeoutMs = boundedNumber(input.args.timeout_ms, 60_000, 1_000, 120_000);
175
186
  const savedSession = requestedSessionId
176
- ? await scheduledBrowserSessionMetadata(input.controllerHome, input.repository, input.occurrenceId, requestedSessionId)
187
+ ? await scheduledBrowserSessionMetadata(input.controllerHome, input.repository, input.occurrenceId, requestedSessionId, authorizationGrantRefs)
177
188
  : undefined;
178
189
  const navigationAction = scheduledBrowserProbeNavigationAction(savedSession?.ownership, Boolean(url));
179
190
  const managedRehydrateIntent = scheduledBrowserProbeManagedRehydrateIntent(savedSession);
@@ -188,7 +199,7 @@ export async function executeScheduledBrowserProbe(input: {
188
199
  state: waitUntil,
189
200
  timeout_ms: timeoutMs,
190
201
  ...managedRehydrateIntent,
191
- });
202
+ }, authorizationGrantRefs);
192
203
  } else if (navigationAction === 'navigate') {
193
204
  navigation = await browserAction(input.controllerHome, input.repository, input.occurrenceId, 'navigate', {
194
205
  ...(requestedSessionId ? { session_id: requestedSessionId } : {}),
@@ -197,14 +208,14 @@ export async function executeScheduledBrowserProbe(input: {
197
208
  timeout_ms: timeoutMs,
198
209
  retries: 1,
199
210
  ...managedRehydrateIntent,
200
- });
211
+ }, authorizationGrantRefs);
201
212
  } else {
202
213
  navigation = await browserAction(input.controllerHome, input.repository, input.occurrenceId, 'reload', {
203
214
  session_id: requestedSessionId!,
204
215
  wait_until: waitUntil,
205
216
  timeout_ms: timeoutMs,
206
217
  ...managedRehydrateIntent,
207
- });
218
+ }, authorizationGrantRefs);
208
219
  }
209
220
 
210
221
  const session = recordValue(navigation.session);
@@ -224,7 +235,7 @@ export async function executeScheduledBrowserProbe(input: {
224
235
  session_id: sessionId,
225
236
  ...(stringValue(input.args.selector) ? { selector: stringValue(input.args.selector) } : {}),
226
237
  max_chars: boundedNumber(input.args.max_chars, 20_000, 256, 100_000),
227
- });
238
+ }, authorizationGrantRefs);
228
239
  rawText = stringValue(textResult.text) ?? '';
229
240
  truncated = textResult.truncated === true;
230
241
  }