@moretea-labs/forge 1.8.0 → 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 (528) hide show
  1. package/AGENTS.md +70 -7
  2. package/CHANGELOG.md +14 -0
  3. package/CLAUDE.md +17 -2
  4. package/CONTRIBUTING.md +3 -2
  5. package/THIRD_PARTY_NOTICES.md +1 -1
  6. package/adapters/chatgpt/browser-delivery-host.ts +7 -1
  7. package/adapters/chatgpt/browser-delivery-runtime.ts +529 -56
  8. package/adapters/chatgpt/controller-binding-store.ts +101 -22
  9. package/adapters/chatgpt/controller-round-host.ts +15 -25
  10. package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
  11. package/adapters/chatgpt/provider-delivery.ts +228 -1
  12. package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
  13. package/adapters/computer/chatgpt-extension-target.ts +463 -0
  14. package/adapters/computer/chatgpt-target-router.ts +103 -0
  15. package/adapters/computer/chrome-extension/background.js +385 -0
  16. package/adapters/computer/chrome-extension/content.js +378 -0
  17. package/adapters/computer/chrome-extension/core.js +24 -0
  18. package/adapters/computer/chrome-extension/manifest.json +30 -0
  19. package/adapters/computer/desktop-operator-discovery.ts +11 -31
  20. package/adapters/computer/interaction-target-authority.ts +142 -18
  21. package/adapters/mcp/auth.ts +0 -1
  22. package/adapters/mcp/instructions.ts +5 -4
  23. package/adapters/mcp/multi-repository.ts +3 -19
  24. package/adapters/mcp/oauth.ts +73 -0
  25. package/adapters/mcp/paths.ts +4 -1
  26. package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
  27. package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
  28. package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
  29. package/adapters/mcp/runtime-gateway/context-adapter.ts +411 -73
  30. package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
  31. package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
  32. package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
  33. package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
  34. package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
  35. package/adapters/mcp/runtime-gateway/execution-tools.ts +8 -42
  36. package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
  37. package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
  38. package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
  39. package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
  40. package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
  41. package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
  42. package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
  43. package/adapters/mcp/runtime-gateway/router.ts +18 -504
  44. package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
  45. package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
  46. package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
  47. package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
  48. package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
  49. package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
  50. package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
  51. package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
  52. package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
  53. package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
  54. package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
  55. package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
  56. package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
  57. package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
  58. package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
  59. package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
  60. package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
  61. package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
  62. package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
  63. package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
  64. package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
  65. package/adapters/mcp/server.ts +67 -23
  66. package/adapters/mcp/setup.ts +1 -3
  67. package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
  68. package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
  69. package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
  70. package/adapters/mcp/toolset-names.ts +5 -0
  71. package/adapters/mcp/toolset.ts +6 -5
  72. package/adapters/mcp/transports/http-observation.ts +365 -0
  73. package/adapters/mcp/transports/http.ts +154 -677
  74. package/adapters/mcp/transports/oauth-http.ts +322 -0
  75. package/adapters/mcp/transports/session-registry.ts +6 -0
  76. package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
  77. package/assets/plugin-registry.v1.json +6 -4
  78. package/assets/reference-configs/agentic-development-flow.md +25 -0
  79. package/assets/reference-configs/global-working-rules.md +19 -0
  80. package/assets/skill-version.json +2 -2
  81. package/docs/architecture/CURRENT.md +111 -41
  82. package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
  83. package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
  84. package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
  85. package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
  86. package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
  87. package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
  88. package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
  89. package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
  90. package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
  91. package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
  92. package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
  93. package/docs/architecture/domains/verification.md +1 -0
  94. package/docs/architecture/domains/workflow-engine.md +6 -0
  95. package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
  96. package/docs/forge-plugin-management.md +2 -2
  97. package/docs/operations/controller-performance-and-502.md +17 -0
  98. package/docs/operations/controller-reliability-runbook.md +2 -2
  99. package/docs/operations/features.md +1 -1
  100. package/docs/operations/features.zh-CN.md +1 -1
  101. package/docs/operations/homebrew.md +2 -2
  102. package/docs/operations/mcp-tool-exposure.md +2 -0
  103. package/docs/operations/releasing.md +2 -0
  104. package/docs/operations/standalone-disaster-recovery.md +14 -6
  105. package/docs/wiki/Implementation.md +1 -1
  106. package/package.json +25 -14
  107. package/packages/kernel/cognition/api/index.ts +6 -0
  108. package/packages/kernel/cognition/application/activation-service.ts +451 -0
  109. package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
  110. package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
  111. package/packages/kernel/cognition/application/memory-service.ts +64 -0
  112. package/packages/kernel/cognition/domain/learning.ts +106 -0
  113. package/packages/kernel/cognition/domain/memory.ts +254 -0
  114. package/packages/kernel/controller/api/index.ts +1 -0
  115. package/packages/kernel/controller/application/continuation-service.ts +281 -0
  116. package/packages/kernel/controller/application/controller-round-service.ts +12 -0
  117. package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
  118. package/packages/kernel/controller/domain/controller-round.ts +4 -1
  119. package/packages/kernel/controller/domain/execution-quality.ts +3 -1
  120. package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
  121. package/packages/kernel/controller/infrastructure/controller-session-store.ts +297 -71
  122. package/packages/kernel/controller/ports/controller-host.ts +2 -0
  123. package/packages/kernel/identity/api/index.ts +10 -0
  124. package/packages/kernel/identity/domain/activity-projection.ts +43 -0
  125. package/packages/kernel/identity/domain/capability-broker.ts +60 -0
  126. package/packages/kernel/identity/domain/grant.ts +72 -0
  127. package/packages/kernel/identity/domain/owned-resource.ts +116 -0
  128. package/packages/kernel/identity/domain/user-request.ts +93 -0
  129. package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
  130. package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
  131. package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
  132. package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
  133. package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
  134. package/packages/kernel/scheduler/api/index.ts +0 -2
  135. package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
  136. package/packages/kernel/scheduler/application/settlement.ts +0 -15
  137. package/packages/kernel/scheduler/domain/schedule.ts +87 -0
  138. package/packages/kernel/scheduler/infrastructure/schedule-store.ts +153 -133
  139. package/packages/kernel/work/api/index.ts +3 -2
  140. package/packages/kernel/work/application/work-service.ts +17 -42
  141. package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
  142. package/packages/kernel/work/domain/engineering-design.ts +10 -5
  143. package/packages/kernel/work/domain/engineering-profile.ts +8 -12
  144. package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
  145. package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
  146. package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
  147. package/packages/kernel/work/domain/implementation-review.ts +14 -331
  148. package/packages/kernel/work/domain/objective-graph.ts +119 -0
  149. package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
  150. package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
  151. package/packages/kernel/work/domain/state-machine.ts +25 -63
  152. package/packages/kernel/work/domain/types.ts +57 -51
  153. package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
  154. package/packages/kernel/work/ports/work-contract-store.ts +5 -2
  155. package/packages/plugin-runtime/browser/session-authority.ts +2 -1
  156. package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
  157. package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
  158. package/packages/plugin-runtime/computer/index.ts +2 -0
  159. package/packages/plugin-runtime/computer/target-authority.ts +26 -1
  160. package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
  161. package/packages/protocols/computer/contract.ts +27 -1
  162. package/scripts/activate-source-baseline.ts +7 -9
  163. package/scripts/canary-controller-semantic-wait.ts +12 -24
  164. package/scripts/check-mcp-compatibility.ts +48 -136
  165. package/scripts/check-runtime-architecture.mjs +622 -217
  166. package/scripts/forge-local-recovery-helper.mjs +93 -15
  167. package/scripts/lib/project-init-lib.sh +3 -0
  168. package/scripts/open-source-audit-allowlist.txt +1 -2
  169. package/scripts/run-bounded-command.mjs +5 -0
  170. package/scripts/run-governed-gate.ts +0 -1
  171. package/scripts/run-mobile-monitor-bridge.ts +0 -1
  172. package/scripts/smoke-control-plane-failure-domain.ts +94 -0
  173. package/scripts/smoke-mcp-http-runtime.ts +5 -0
  174. package/scripts/smoke-runtime-recovery.ts +12 -43
  175. package/scripts/smoke-schedule-engine.ts +23 -15
  176. package/scripts/smoke-unattended-transport-recovery.ts +223 -0
  177. package/scripts/smoke-user-request-continuation-restart.ts +232 -0
  178. package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
  179. package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
  180. package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
  181. package/scripts/smoke-workflow-supervisor.ts +103 -0
  182. package/scripts/verify-forge-runtime.sh +2 -1
  183. package/src/cli/agent-jobs/executor-health.ts +11 -34
  184. package/src/cli/agent-jobs/integration.ts +18 -49
  185. package/src/cli/agent-jobs/job-manager.ts +7 -3
  186. package/src/cli/commands/brain-assistant.ts +27 -13
  187. package/src/cli/commands/brain.ts +13 -15
  188. package/src/cli/commands/chatgpt.ts +1 -163
  189. package/src/cli/commands/recovery.ts +135 -121
  190. package/src/cli/commands/runtime.ts +3 -3
  191. package/src/cli/commands/setup-profile.ts +8 -0
  192. package/src/cli/controller/check-runner.ts +13 -2
  193. package/src/cli/controller/completion-backlog.ts +3 -3
  194. package/src/cli/controller/completion-orchestrator.ts +4 -43
  195. package/src/cli/controller/completion-target.ts +3 -72
  196. package/src/cli/controller/context/source-materializer.ts +81 -100
  197. package/src/cli/controller/context-pack.ts +10 -8
  198. package/src/cli/controller/execution-completion.ts +4 -7
  199. package/src/cli/controller/execution-policy.ts +36 -153
  200. package/src/cli/controller/governance.ts +2 -3
  201. package/src/cli/controller/issue-store.ts +4 -99
  202. package/src/cli/controller/launch-agents.ts +59 -18
  203. package/src/cli/controller/operational-plan.ts +24 -51
  204. package/src/cli/controller/runtime-config.ts +5 -1
  205. package/src/cli/controller/stuck-state-migration.ts +2 -3
  206. package/src/cli/controller/systemd-user.ts +39 -1
  207. package/src/cli/editing/edit-session.ts +1 -7
  208. package/src/cli/local-bridge/console-automations.ts +18 -13
  209. package/src/cli/local-bridge/console-view-models.ts +3 -12
  210. package/src/cli/local-bridge/facade-api.ts +64 -191
  211. package/src/cli/local-bridge/server.ts +24 -147
  212. package/src/cli/local-bridge/types.ts +0 -1
  213. package/src/cli/mcp/oauth-client-retirement.ts +74 -0
  214. package/src/cli/repositories/command-executor.ts +29 -23
  215. package/src/cli/repositories/command-scope.ts +35 -16
  216. package/src/cli/repositories/controller-home.ts +48 -0
  217. package/src/cli/repositories/ephemeral-workspace.ts +20 -30
  218. package/src/cli/repositories/git-command-executor.ts +2 -2
  219. package/src/cli/repositories/registry.ts +77 -11
  220. package/src/cli/repositories/structured-git.ts +62 -2
  221. package/src/cli/repository/session-cache.ts +92 -6
  222. package/src/runtime/context/assistant-context.ts +20 -7
  223. package/src/runtime/context/assistant-work-context.ts +89 -27
  224. package/src/runtime/context/automatic-learning.ts +565 -0
  225. package/src/runtime/context/cognitive-attention.ts +173 -0
  226. package/src/runtime/context/cognitive-skill-canary.ts +158 -0
  227. package/src/runtime/context/context-closure.ts +46 -9
  228. package/src/runtime/context/context-pack-process.ts +103 -0
  229. package/src/runtime/context/context-plane.ts +1 -9
  230. package/src/runtime/context/direct-controller-learning.ts +298 -0
  231. package/src/runtime/context/semantic-navigation-contract.ts +9 -0
  232. package/src/runtime/context/semantic-navigation.ts +6 -34
  233. package/src/runtime/context/typescript-navigation-process.ts +145 -0
  234. package/src/runtime/context/typescript-navigation.ts +89 -3
  235. package/src/runtime/control-plane/cleanup-artifact-retention.ts +212 -9
  236. package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
  237. package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
  238. package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
  239. package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
  240. package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
  241. package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
  242. package/src/runtime/control-plane/execution/session-store.ts +31 -1
  243. package/src/runtime/control-plane/execution/validation.ts +6 -8
  244. package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
  245. package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
  246. package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
  247. package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
  248. package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
  249. package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
  250. package/src/runtime/control-plane/execution/work-handle-authority.ts +188 -109
  251. package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
  252. package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
  253. package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
  254. package/src/runtime/control-plane/execution/work-operation-service.ts +43 -27
  255. package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
  256. package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
  257. package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
  258. package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +173 -186
  259. package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
  260. package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
  261. package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
  262. package/src/runtime/control-plane/facade/capability-registry.ts +362 -37
  263. package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
  264. package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
  265. package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
  266. package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
  267. package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
  268. package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
  269. package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
  270. package/src/runtime/control-plane/facade/index.ts +0 -1
  271. package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
  272. package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
  273. package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
  274. package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
  275. package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
  276. package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
  277. package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
  278. package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
  279. package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
  280. package/src/runtime/control-plane/facade/types.ts +49 -108
  281. package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
  282. package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
  283. package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
  284. package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
  285. package/src/runtime/control-plane/global-scheduler/maintenance.ts +239 -112
  286. package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
  287. package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
  288. package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
  289. package/src/runtime/control-plane/governance/access-policy.ts +19 -2
  290. package/src/runtime/control-plane/governance/authorization.ts +20 -3
  291. package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
  292. package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -300
  293. package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
  294. package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
  295. package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
  296. package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
  297. package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
  298. package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
  299. package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
  300. package/src/runtime/control-plane/release-retention.ts +135 -47
  301. package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
  302. package/src/runtime/control-plane/runtime-cleanup.ts +290 -21
  303. package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
  304. package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
  305. package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
  306. package/src/runtime/diagnostics/incident-repair.ts +313 -146
  307. package/src/runtime/diagnostics/mcp-timing.ts +114 -0
  308. package/src/runtime/evidence/artifact-store.ts +158 -40
  309. package/src/runtime/evidence/evidence-store.ts +112 -8
  310. package/src/runtime/evidence/output-handle-index.ts +225 -0
  311. package/src/runtime/evidence/result-store.ts +158 -44
  312. package/src/runtime/execution/jobs/store.ts +3 -4
  313. package/src/runtime/execution/managed-workspace.ts +57 -0
  314. package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
  315. package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
  316. package/src/runtime/execution/process-runtime/check-result.ts +105 -1
  317. package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
  318. package/src/runtime/execution/process-runtime/command-facade.ts +79 -27
  319. package/src/runtime/execution/process-runtime/gc.ts +15 -2
  320. package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
  321. package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
  322. package/src/runtime/execution/process-runtime/index.ts +3 -0
  323. package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
  324. package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
  325. package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
  326. package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
  327. package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
  328. package/src/runtime/execution/process-runtime/runtime.ts +35 -2
  329. package/src/runtime/execution/process-runtime/store.ts +30 -2
  330. package/src/runtime/execution/process-runtime/types.ts +6 -1
  331. package/src/runtime/execution/workers/executor.ts +2 -6
  332. package/src/runtime/platform/service-inventory.ts +130 -0
  333. package/src/runtime/platform/service-manager.ts +8 -0
  334. package/src/runtime/plugins/action-application.ts +85 -28
  335. package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
  336. package/src/runtime/plugins/browser-adapter.ts +757 -34
  337. package/src/runtime/plugins/browser-automation-service.ts +23 -3
  338. package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
  339. package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
  340. package/src/runtime/plugins/browser-native-session-service.ts +63 -13
  341. package/src/runtime/plugins/browser-registration.ts +16 -0
  342. package/src/runtime/plugins/browser-runtime.ts +14 -1
  343. package/src/runtime/plugins/browser-session-authority.ts +2 -2
  344. package/src/runtime/plugins/browser-session-store.ts +46 -76
  345. package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
  346. package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
  347. package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
  348. package/src/runtime/plugins/computer-registration.ts +222 -11
  349. package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
  350. package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
  351. package/src/runtime/plugins/external-adapter.ts +42 -6
  352. package/src/runtime/plugins/external-registration.ts +21 -1
  353. package/src/runtime/plugins/gmail-adapter.ts +23 -2
  354. package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
  355. package/src/runtime/plugins/google-shared.ts +14 -7
  356. package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
  357. package/src/runtime/plugins/ios-adapter.ts +1 -1
  358. package/src/runtime/plugins/lightweight-action.ts +208 -2
  359. package/src/runtime/plugins/local-system-adapter.ts +12 -2
  360. package/src/runtime/plugins/managed-process-adapter.ts +12 -5
  361. package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
  362. package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
  363. package/src/runtime/plugins/store.ts +602 -428
  364. package/src/runtime/plugins/types.ts +20 -0
  365. package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
  366. package/src/runtime/projections/invalidation.ts +7 -3
  367. package/src/runtime/projections/materialized-view.ts +80 -36
  368. package/src/runtime/recovery/actions.ts +3 -3
  369. package/src/runtime/recovery/capability-action-application.ts +46 -45
  370. package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
  371. package/src/runtime/recovery/maintenance-executor.ts +374 -123
  372. package/src/runtime/recovery/store.ts +29 -11
  373. package/src/runtime/release/release-coordinator.ts +296 -0
  374. package/src/runtime/release/release-session.ts +716 -0
  375. package/src/runtime/release/release-state-migration.ts +25 -0
  376. package/src/runtime/resources/leases/store.ts +56 -25
  377. package/src/runtime/root/computer-composition.ts +191 -6
  378. package/src/runtime/root/controller-progression-composition.ts +192 -0
  379. package/src/runtime/root/controller-round-composition.ts +20 -1
  380. package/src/runtime/root/deployment-topology.ts +106 -0
  381. package/src/runtime/root/entry.ts +4 -3
  382. package/src/runtime/root/known-good-recovery.ts +184 -0
  383. package/src/runtime/root/local-bridge.ts +0 -1
  384. package/src/runtime/root/mcp-transport.ts +111 -18
  385. package/src/runtime/root/ownership.ts +261 -9
  386. package/src/runtime/root/package-connector-service.ts +105 -19
  387. package/src/runtime/root/package-runtime-release.ts +117 -18
  388. package/src/runtime/root/package-runtime-service.ts +17 -11
  389. package/src/runtime/root/release-execution-canary.ts +44 -12
  390. package/src/runtime/root/release-loader.ts +90 -8
  391. package/src/runtime/root/release-manifest.ts +80 -6
  392. package/src/runtime/root/release-materialize.ts +372 -28
  393. package/src/runtime/root/release-store.ts +395 -36
  394. package/src/runtime/root/runtime-lane.ts +191 -0
  395. package/src/runtime/root/runtime.ts +159 -27
  396. package/src/runtime/root/scheduled-controller-composition.ts +28 -3
  397. package/src/runtime/root/service-runner.ts +2 -2
  398. package/src/runtime/root/service.ts +36 -33
  399. package/src/runtime/root/status.ts +48 -0
  400. package/src/runtime/root/types.ts +32 -3
  401. package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
  402. package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
  403. package/src/runtime/root/write-fence.ts +50 -2
  404. package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
  405. package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
  406. package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
  407. package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
  408. package/src/runtime/shared/process-environment.ts +20 -9
  409. package/src/runtime/shared/response-budget.ts +1 -3
  410. package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
  411. package/src/runtime/standalone-recovery/core.ts +3702 -342
  412. package/src/runtime/standalone-recovery/entry.ts +469 -39
  413. package/src/runtime/standalone-recovery/installer.ts +262 -148
  414. package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
  415. package/src/runtime/standalone-recovery/operation-lock.ts +1 -1
  416. package/src/runtime/standalone-recovery/performance.ts +54 -16
  417. package/src/runtime/standalone-recovery/release.ts +53 -5
  418. package/src/runtime/standalone-recovery/service-labels.ts +5 -2
  419. package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
  420. package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
  421. package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +10 -3
  422. package/src/runtime/workflow/schedules/engine.ts +138 -172
  423. package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
  424. package/src/runtime/workflows/runtime.ts +15 -19
  425. package/src/testing/test-governance.ts +5 -1
  426. package/supervisor/chatgpt-conversation.ts +23 -0
  427. package/supervisor/client.ts +201 -0
  428. package/supervisor/control-plane.ts +868 -0
  429. package/supervisor/entry.ts +15 -0
  430. package/supervisor/forge-validators.ts +80 -0
  431. package/supervisor/index.ts +5 -0
  432. package/supervisor/native-browser-adapter.ts +786 -0
  433. package/supervisor/native-messaging/host.ts +39 -0
  434. package/supervisor/native-messaging/manifest.ts +26 -0
  435. package/supervisor/native-messaging/protocol.ts +27 -0
  436. package/supervisor/paths.ts +18 -0
  437. package/supervisor/protocol.ts +202 -0
  438. package/supervisor/server.ts +404 -0
  439. package/supervisor/store.ts +1451 -0
  440. package/supervisor/tsconfig.json +8 -0
  441. package/supervisor/types.ts +255 -0
  442. package/adapters/chatgpt/controller-host.ts +0 -119
  443. package/adapters/mcp/controller-round-compatibility.ts +0 -184
  444. package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
  445. package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
  446. package/packages/kernel/progression/api/index.ts +0 -2
  447. package/packages/kernel/progression/application/projector.ts +0 -211
  448. package/packages/kernel/progression/domain/types.ts +0 -116
  449. package/packages/kernel/progression/index.ts +0 -1
  450. package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
  451. package/packages/kernel/scheduler/domain/continuation.ts +0 -38
  452. package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
  453. package/packages/kernel/work/domain/admission-policy.ts +0 -34
  454. package/scripts/benchmark-background-check-overlap.ts +0 -228
  455. package/scripts/benchmark-computer-hotpath.ts +0 -255
  456. package/scripts/benchmark-controller-hotpath.ts +0 -212
  457. package/scripts/benchmark-controller-round2.ts +0 -191
  458. package/scripts/benchmark-ios-agent-device.ts +0 -511
  459. package/scripts/benchmark-mcp-host.sh +0 -117
  460. package/scripts/benchmark-mcp-transport.ts +0 -169
  461. package/scripts/benchmark-operational-memory-activation.ts +0 -235
  462. package/scripts/benchmark-operational-shadow.ts +0 -28
  463. package/scripts/benchmark-quality-harness.ts +0 -146
  464. package/scripts/benchmark-route-session-concurrency.ts +0 -915
  465. package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
  466. package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
  467. package/scripts/benchmark-thin-harness.ts +0 -251
  468. package/scripts/benchmark-typescript-navigation.ts +0 -186
  469. package/scripts/benchmark-work-efficiency.ts +0 -334
  470. package/scripts/build-controller-ui.ts +0 -28
  471. package/scripts/check-npm-release.sh +0 -32
  472. package/scripts/check-public-release-surface.sh +0 -19
  473. package/scripts/check-release-published.sh +0 -57
  474. package/scripts/check-release-readiness.sh +0 -37
  475. package/scripts/check-release-version.mjs +0 -74
  476. package/scripts/check-tarball-install-smoke.sh +0 -150
  477. package/scripts/package-source-archive.sh +0 -147
  478. package/scripts/public-release-files.txt +0 -39
  479. package/scripts/public-release.ts +0 -174
  480. package/scripts/publish-release-tarball.sh +0 -27
  481. package/scripts/route-nl-vs-ts-eval.ts +0 -679
  482. package/scripts/stage-runtime-release.ts +0 -44
  483. package/src/cli/controller/progress.ts +0 -656
  484. package/src/cli/controller/work-mode.ts +0 -181
  485. package/src/cli/local-bridge/console-assets.ts +0 -17
  486. package/src/cli/local-bridge/dashboard.ts +0 -17
  487. package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
  488. package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
  489. package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
  490. package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
  491. package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
  492. package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
  493. package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
  494. package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
  495. package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
  496. package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
  497. package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
  498. package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
  499. package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
  500. package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
  501. package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
  502. package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
  503. package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
  504. package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
  505. package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
  506. package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
  507. package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
  508. package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
  509. package/src/cli/local-bridge/frontend/src/styles.css +0 -28
  510. package/src/cli/local-bridge/frontend/src/types.ts +0 -15
  511. package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
  512. package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
  513. package/src/cli/local-bridge/ui-dist/app.css +0 -1
  514. package/src/cli/local-bridge/ui-dist/app.js +0 -11228
  515. package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
  516. package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
  517. package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
  518. package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
  519. package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
  520. package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
  521. package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
  522. package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
  523. package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
  524. package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
  525. package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
  526. package/src/runtime/control-plane/routing/index.ts +0 -1
  527. package/src/runtime/control-plane/routing/route-policy.ts +0 -401
  528. package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
@@ -1,6 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { createRequire } from 'node:module';
3
- import { copyFileSync, existsSync, mkdirSync, renameSync, statSync, unlinkSync } from 'fs';
3
+ import { closeSync, copyFileSync, existsSync, mkdirSync, openSync, readSync, renameSync, statSync, unlinkSync } from 'fs';
4
4
  import { dirname, join } from 'path';
5
5
  import { durableControllerHome } from '../../../cli/repositories/controller-home';
6
6
 
@@ -62,6 +62,36 @@ export interface ControlPlaneDatabaseInspection {
62
62
  orphanRecordCount: number;
63
63
  }
64
64
 
65
+ /**
66
+ * Ephemeral database-wide change fence. SQLite data_version changes whenever a
67
+ * different connection commits to the same database, including domain tables
68
+ * that do not participate in control_plane_audit.
69
+ */
70
+ export interface ControlPlaneDatabaseChangeObserver {
71
+ path: string;
72
+ dataVersion(): number;
73
+ close(): void;
74
+ }
75
+
76
+ const CONTROL_PLANE_DATABASE_HASH_CHUNK_BYTES = 1024 * 1024;
77
+
78
+ /** Full snapshot identity without allocating the whole SQLite file. */
79
+ export function sha256ControlPlaneDatabaseFile(path: string): string {
80
+ const descriptor = openSync(path, 'r');
81
+ const hash = createHash('sha256');
82
+ const buffer = Buffer.allocUnsafe(CONTROL_PLANE_DATABASE_HASH_CHUNK_BYTES);
83
+ try {
84
+ for (;;) {
85
+ const bytesRead = readSync(descriptor, buffer, 0, buffer.length, null);
86
+ if (bytesRead === 0) break;
87
+ hash.update(buffer.subarray(0, bytesRead));
88
+ }
89
+ return hash.digest('hex');
90
+ } finally {
91
+ closeSync(descriptor);
92
+ }
93
+ }
94
+
65
95
  export const CONTROL_PLANE_SQLITE_MAINTENANCE_POLICY_VERSION = 'control-plane-sqlite-maintenance-v1' as const;
66
96
  export const DEFAULT_CONTROL_PLANE_SQLITE_VACUUM_MIN_RECLAIMABLE_BYTES = 64 * 1024 * 1024;
67
97
  export const DEFAULT_CONTROL_PLANE_SQLITE_VACUUM_MIN_RECLAIMABLE_RATIO = 0.20;
@@ -294,9 +324,10 @@ function openDatabase(controllerHome: string): SqliteDatabase {
294
324
  // inspectOpenDatabase(), which is the authoritative integrity boundary.
295
325
  // Keep schema fail-closed on every open, but reserve the full integrity scan
296
326
  // for those lifecycle/inspection boundaries.
327
+ let schemaVersion: number | undefined;
297
328
  if (existed) {
298
329
  try {
299
- assertSupportedSchema(database, path);
330
+ schemaVersion = assertSupportedSchema(database, path);
300
331
  } catch (error) {
301
332
  const busy = sqliteBusyError(path, error);
302
333
  if (busy) throw busy;
@@ -306,8 +337,14 @@ function openDatabase(controllerHome: string): SqliteDatabase {
306
337
  }
307
338
  }
308
339
  database.exec('PRAGMA journal_mode = WAL;');
309
- initializeSchema(database);
310
- assertSupportedSchema(database, path, true);
340
+ // Schema DDL is bootstrap work, not transaction work. Existing supported
341
+ // databases have already crossed the fail-closed schema boundary above;
342
+ // rerunning CREATE INDEX/TABLE + INSERT OR IGNORE on every write only burns
343
+ // allocations/SQLite preparation and then validates the same schema twice.
344
+ if (schemaVersion === undefined) {
345
+ initializeSchema(database);
346
+ assertSupportedSchema(database, path, true);
347
+ }
311
348
  return database;
312
349
  } catch (error) {
313
350
  database.close();
@@ -346,6 +383,27 @@ function openDatabaseForRead(controllerHome: string): SqliteDatabase {
346
383
  return openDatabase(controllerHome);
347
384
  }
348
385
 
386
+ export function openControlPlaneDatabaseChangeObserver(controllerHome: string): ControlPlaneDatabaseChangeObserver {
387
+ const path = controlPlaneDatabasePath(controllerHome);
388
+ const database = openDatabaseForRead(controllerHome);
389
+ let closed = false;
390
+ const dataVersion = () => {
391
+ if (closed) throw new Error('CONTROL_PLANE_DATABASE_CHANGE_OBSERVER_CLOSED');
392
+ return integerPragma(database, 'PRAGMA data_version', 'data_version');
393
+ };
394
+ // Prime the connection before returning it so the first caller observation
395
+ // is relative to an established SQLite connection, not connection startup.
396
+ dataVersion();
397
+ return {
398
+ path,
399
+ dataVersion,
400
+ close() {
401
+ if (closed) return;
402
+ closed = true;
403
+ database.close();
404
+ },
405
+ };
406
+ }
349
407
 
350
408
  function withDatabaseForRead<T>(controllerHome: string, operation: (database: SqliteDatabase) => T): T {
351
409
  const path = controlPlaneDatabasePath(controllerHome);
@@ -382,6 +440,11 @@ function withDatabaseForRead<T>(controllerHome: string, operation: (database: Sq
382
440
  }
383
441
  }
384
442
 
443
+ /** Read-only snapshot boundary for domain stores that need several indexed lookups in one hot-path operation. */
444
+ export function withControlPlaneReadDatabase<T>(controllerHome: string, operation: (database: SqliteDatabase) => T): T {
445
+ return withDatabaseForRead(controllerHome, operation);
446
+ }
447
+
385
448
  function rowToRecord<T>(row: StoredRecordRow): ControlPlaneRecord<T> {
386
449
  let value: T;
387
450
  try {
@@ -508,6 +571,22 @@ export function readControlPlaneRecord<T>(controllerHome: string, namespace: str
508
571
  selectRecord<T>(database, namespace, scope, key));
509
572
  }
510
573
 
574
+ export function listControlPlaneRecordKeys(
575
+ controllerHome: string,
576
+ input: { namespace: string; scope: string; limit?: number },
577
+ ): string[] {
578
+ const limit = Math.max(1, Math.min(Math.trunc(input.limit ?? 5_000), 5_000));
579
+ return withDatabaseForRead(controllerHome, (database) =>
580
+ withSqliteStatement(database, `
581
+ SELECT record_key
582
+ FROM control_plane_records
583
+ WHERE namespace = ? AND scope = ?
584
+ ORDER BY record_key ASC
585
+ LIMIT ?
586
+ `, (statement) => (statement.all(input.namespace, input.scope, limit) as Array<{ record_key: string }>)
587
+ .map((row) => row.record_key)));
588
+ }
589
+
511
590
  export function writeControlPlaneRecord<T>(
512
591
  controllerHome: string,
513
592
  input: {
@@ -633,6 +712,24 @@ export function listControlPlaneRecords<T>(
633
712
  listControlPlaneRecordsWithinTransaction<T>(database, input));
634
713
  }
635
714
 
715
+ /** Exact stable-key lookup across scopes. This is a read of the existing Control Plane authority, not a second id registry. */
716
+ export function findControlPlaneRecordsByKey<T>(
717
+ controllerHome: string,
718
+ input: { namespace: string; key: string; limit?: number },
719
+ ): ControlPlaneRecord<T>[] {
720
+ const limit = Math.max(1, Math.min(Math.trunc(input.limit ?? 2), 100));
721
+ return withDatabaseForRead(controllerHome, (database) => {
722
+ const rows = withSqliteStatement(database, `
723
+ SELECT namespace, scope, record_key, schema_version, revision, payload, created_at, updated_at
724
+ FROM control_plane_records
725
+ WHERE namespace = ? AND record_key = ?
726
+ ORDER BY scope ASC
727
+ LIMIT ?
728
+ `, (statement) => statement.all(input.namespace, input.key, limit));
729
+ return (rows as StoredRecordRow[]).map((row) => rowToRecord<T>(row));
730
+ });
731
+ }
732
+
636
733
  /**
637
734
  * Candidate-only read optimization for top-level JSON text fields. This never
638
735
  * establishes domain authority: missing/null/non-text values remain candidates,
@@ -660,6 +757,11 @@ function payloadTextExclusionPredicate(input: PayloadTextExclusion): string {
660
757
  return `${namespace} AND (${extraction} IS NULL OR ${extraction} NOT IN (${values.map(literal).join(', ')}))`;
661
758
  }
662
759
 
760
+ function payloadTextExclusionIndexName(input: PayloadTextExclusion, predicate = payloadTextExclusionPredicate(input)): string {
761
+ const prefix = `control_plane_candidate_${createHash('sha256').update(`${input.namespace}/${input.field}`).digest('hex').slice(0, 16)}_`;
762
+ return `${prefix}${createHash('sha256').update(predicate).digest('hex').slice(0, 16)}`;
763
+ }
764
+
663
765
  /** Explicit startup DDL. JSON remains authority; SQLite maintains the derived index in every write transaction. */
664
766
  export function initializeControlPlanePayloadTextExclusionIndex(
665
767
  controllerHome: string,
@@ -667,7 +769,7 @@ export function initializeControlPlanePayloadTextExclusionIndex(
667
769
  ): void {
668
770
  const predicate = payloadTextExclusionPredicate(input);
669
771
  const prefix = `control_plane_candidate_${createHash('sha256').update(`${input.namespace}/${input.field}`).digest('hex').slice(0, 16)}_`;
670
- const name = `${prefix}${createHash('sha256').update(predicate).digest('hex').slice(0, 16)}`;
772
+ const name = payloadTextExclusionIndexName(input, predicate);
671
773
  withControlPlaneTransaction(controllerHome, (database) => {
672
774
  database.exec(`CREATE INDEX IF NOT EXISTS ${name} ON control_plane_records (scope, updated_at, record_key) WHERE ${predicate}`);
673
775
  // Retire obsolete predicates for this domain field in the same transaction.
@@ -686,11 +788,16 @@ export function listControlPlaneRecordsExcludingPayloadTextValues<T>(
686
788
  input: PayloadTextExclusion & { scope: string; limit?: number },
687
789
  ): ControlPlaneRecord<T>[] {
688
790
  const predicate = payloadTextExclusionPredicate(input);
791
+ const candidateIndex = payloadTextExclusionIndexName(input, predicate);
689
792
  const limit = Math.max(1, Math.min(Math.trunc(input.limit ?? 1_000), 5_000));
690
793
  return withDatabaseForRead(controllerHome, (database) => {
794
+ const candidateIndexExists = withSqliteStatement(database,
795
+ "SELECT 1 AS present FROM sqlite_master WHERE type = 'index' AND name = ? LIMIT 1",
796
+ (statement) => statement.get(candidateIndex) != null);
797
+ const indexHint = candidateIndexExists ? ` INDEXED BY ${candidateIndex}` : '';
691
798
  const rows = withSqliteStatement(database, `
692
799
  SELECT namespace, scope, record_key, schema_version, revision, payload, created_at, updated_at
693
- FROM control_plane_records
800
+ FROM control_plane_records${indexHint}
694
801
  WHERE ${predicate} AND scope = ?
695
802
  ORDER BY updated_at ASC, record_key ASC
696
803
  LIMIT ?
@@ -8,6 +8,7 @@ import {
8
8
  } from 'fs';
9
9
  import { basename, dirname, join, relative, resolve } from 'path';
10
10
  import { measureReclaimablePath } from './lifecycle-retention-metrics';
11
+ import { inspectKnownGoodRecoveryBundle, type KnownGoodReleaseIdentity } from '../root/known-good-recovery';
11
12
 
12
13
  const DEFAULT_RELEASE_RETENTION_GRACE_MS = 30 * 60_000;
13
14
  const DEFAULT_STAGING_RETENTION_GRACE_MS = 6 * 60 * 60_000;
@@ -48,6 +49,14 @@ interface RuntimeProtection {
48
49
  backupAuthoritySafe: boolean;
49
50
  }
50
51
 
52
+ interface RuntimeReleasePublicationLease {
53
+ schemaVersion: 1;
54
+ pid: number;
55
+ operationId: string;
56
+ candidateReleasePath: string;
57
+ backupPath?: string;
58
+ }
59
+
51
60
  interface LinkedReleaseProtection {
52
61
  releasesRoot: string;
53
62
  releasePaths: Set<string>;
@@ -61,26 +70,17 @@ function canonical(path: string): string {
61
70
  }
62
71
  }
63
72
 
64
- /**
65
- * Canonicalize a path even when its leaf has already been removed by resolving
66
- * the nearest existing ancestor first and then projecting the missing suffix.
67
- * This preserves filesystem identity across logical aliases such as macOS
68
- * /var -> /private/var without requiring historical artifacts to still exist.
69
- */
70
- function canonicalProjectedPath(path: string): string {
71
- let cursor = resolve(path);
72
- const missingSuffix: string[] = [];
73
- while (!existsSync(cursor)) {
74
- const parent = dirname(cursor);
75
- if (parent === cursor) return resolve(path);
76
- missingSuffix.unshift(basename(cursor));
77
- cursor = parent;
78
- }
79
- return resolve(canonical(cursor), ...missingSuffix);
80
- }
81
-
82
73
  function directChild(root: string, path: string): boolean {
83
- return dirname(canonical(path)) === canonical(root);
74
+ // Resolve the parent rather than the child: a reclaimed path may no longer
75
+ // exist, while its managed parent still does (and may itself be a symlink).
76
+ // An existing child must not itself be a symlink; otherwise a lexical child
77
+ // under Controller Home could retain or delete an external target.
78
+ if (canonical(dirname(path)) !== canonical(root)) return false;
79
+ try {
80
+ return !lstatSync(path).isSymbolicLink();
81
+ } catch {
82
+ return true;
83
+ }
84
84
  }
85
85
 
86
86
  function entryExists(path: string): boolean {
@@ -151,31 +151,81 @@ function loadPackageConnectorReleaseProtection(controllerHome: string, releasesR
151
151
  return canonical(releaseRoot);
152
152
  }
153
153
 
154
- function validateRecoveryKnownGoodHistory(controllerHome: string, releasesRoot: string): void {
154
+ function loadRecoveryKnownGoodProtection(
155
+ controllerHome: string,
156
+ releasesRoot: string,
157
+ rollbackReleasePaths: ReadonlySet<string>,
158
+ ): Set<string> {
159
+ const protectedPaths = new Set<string>();
155
160
  const knownGoodPath = join(controllerHome, 'recovery', 'state', 'known-good.json');
156
- if (!existsSync(knownGoodPath)) return;
161
+ if (!existsSync(knownGoodPath)) return protectedPaths;
157
162
  const parsed = JSON.parse(readFileSync(knownGoodPath, 'utf8')) as Record<string, unknown>;
158
- if (parsed.schemaVersion !== 1 || !Array.isArray(parsed.releases)) {
163
+ // Schema v1 was metadata-only evidence. It deliberately has no retention
164
+ // authority: only v2 entries pass the same release + DB + service-contract
165
+ // recoverability check that Recovery uses before attesting known-good.
166
+ if (parsed.schemaVersion === 1) return protectedPaths;
167
+ if (parsed.schemaVersion !== 2 || !Array.isArray(parsed.releases)) {
159
168
  throw new Error('standalone recovery known-good authority is invalid');
160
169
  }
161
170
  for (const raw of parsed.releases) {
162
171
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('standalone recovery known-good release record is invalid');
163
- const record = raw as Record<string, unknown>;
164
- const releaseId = typeof record.revision === 'string' ? record.revision.trim() : '';
165
- const manifestPathValue = typeof record.path === 'string' ? record.path.trim() : '';
166
- if (!releaseId || !manifestPathValue) throw new Error('standalone recovery known-good release identity is incomplete');
167
- const manifestPath = resolve(manifestPathValue);
168
- const releaseRoot = dirname(manifestPath);
169
- const exactHistoricalManifestPath = resolve(canonical(releasesRoot), releaseId, 'manifest.json');
170
- const historicalManifestPath = canonicalProjectedPath(manifestPath);
172
+ const entry = raw as Record<string, unknown>;
173
+ const manifestPath = typeof entry.path === 'string' ? entry.path.trim() : '';
174
+ const revision = typeof entry.revision === 'string' ? entry.revision.trim() : '';
175
+ const releaseRoot = manifestPath ? dirname(resolve(manifestPath)) : '';
171
176
  if (
172
- basename(manifestPath) !== 'manifest.json'
173
- || basename(releaseRoot) !== releaseId
174
- || historicalManifestPath !== exactHistoricalManifestPath
175
- ) {
177
+ !manifestPath
178
+ || !revision
179
+ || basename(manifestPath) !== 'manifest.json'
180
+ || basename(releaseRoot) !== revision
181
+ || !directChild(releasesRoot, releaseRoot)
182
+ ) throw new Error('standalone recovery known-good release is outside runtime releases');
183
+ // Historical records are not protection. Do not inspect them after their
184
+ // release tree has been reclaimed, or one old record would block cleanup
185
+ // of every later candidate in the same pass.
186
+ if (!rollbackReleasePaths.has(canonical(releaseRoot))) continue;
187
+ let inspected;
188
+ try {
189
+ inspected = inspectKnownGoodRecoveryBundle(controllerHome, raw as KnownGoodReleaseIdentity);
190
+ } catch (error) {
191
+ throw new Error(`standalone recovery known-good bundle is not recoverable: ${error instanceof Error ? error.message : String(error)}`);
192
+ }
193
+ const inspectedReleaseRoot = canonical(dirname(inspected.releaseRoot));
194
+ if (inspectedReleaseRoot !== canonical(releasesRoot)) {
176
195
  throw new Error('standalone recovery known-good release is outside runtime releases');
177
196
  }
197
+ // Historical attestations are evidence, not rollback authority. Recovery
198
+ // can only target releases currently named by the committed Runtime.
199
+ protectedPaths.add(canonical(inspected.releaseRoot));
178
200
  }
201
+ return protectedPaths;
202
+ }
203
+
204
+ function loadPinnedRuntimeReleaseProtection(controllerHome: string, releasesRoot: string): string | undefined {
205
+ const pinPath = join(controllerHome, 'recovery', 'state', 'runtime-pin.json');
206
+ if (!existsSync(pinPath)) return undefined;
207
+ let parsed: Record<string, unknown>;
208
+ try { parsed = JSON.parse(readFileSync(pinPath, 'utf8')) as Record<string, unknown>; }
209
+ catch (error) { throw new Error(`runtime pin authority is invalid: ${error instanceof Error ? error.message : String(error)}`); }
210
+ const release = parsed.release;
211
+ if (parsed.schemaVersion !== 1 || !release || typeof release !== 'object' || Array.isArray(release)) {
212
+ throw new Error('runtime pin authority is invalid');
213
+ }
214
+ const record = release as Record<string, unknown>;
215
+ const releaseId = typeof record.revision === 'string' ? record.revision.trim() : '';
216
+ const manifestPathValue = typeof record.path === 'string' ? record.path.trim() : '';
217
+ if (!releaseId || !manifestPathValue) throw new Error('runtime pin release identity is incomplete');
218
+ const manifestPath = resolve(manifestPathValue);
219
+ const releaseRoot = dirname(manifestPath);
220
+ if (
221
+ basename(manifestPath) !== 'manifest.json'
222
+ || basename(releaseRoot) !== releaseId
223
+ || !directChild(releasesRoot, releaseRoot)
224
+ || !existsSync(releaseRoot)
225
+ ) {
226
+ throw new Error('runtime pin release is outside runtime release authority or missing');
227
+ }
228
+ return canonical(releaseRoot);
179
229
  }
180
230
 
181
231
  function loadRuntimeProtection(controllerHome: string): RuntimeProtection | undefined {
@@ -186,11 +236,12 @@ function loadRuntimeProtection(controllerHome: string): RuntimeProtection | unde
186
236
  if (!existsSync(authorityPath)) throw new Error('runtime release authority is missing');
187
237
 
188
238
  const parsed = JSON.parse(readFileSync(authorityPath, 'utf8')) as Record<string, unknown>;
189
- if (parsed.schemaVersion !== 1 || parsed.status !== 'committed') {
190
- throw new Error('runtime release authority is not committed schemaVersion=1');
239
+ if (parsed.schemaVersion !== 2 || parsed.status !== 'committed') {
240
+ throw new Error('runtime release authority is not committed schemaVersion=2');
191
241
  }
192
242
 
193
243
  const releasePaths = new Set<string>();
244
+ const backupPaths = new Set<string>();
194
245
  releasePaths.add(releasePathFromAuthorityRecord(releasesRoot, parsed.active, 'active'));
195
246
  const previous = parsed.previous;
196
247
  if (previous !== undefined) {
@@ -198,17 +249,54 @@ function loadRuntimeProtection(controllerHome: string): RuntimeProtection | unde
198
249
  }
199
250
  const connectorRelease = loadPackageConnectorReleaseProtection(controllerHome, releasesRoot);
200
251
  if (connectorRelease) releasePaths.add(connectorRelease);
201
- // Recovery known-good is append-only attestation evidence, not a storage
202
- // ownership authority. Recovery itself only accepts a known-good entry when
203
- // it still matches the current active/previous release authority, both of
204
- // which are already protected above. Keeping every extant historical entry
205
- // here creates a circular retention leak: the artifact can never disappear
206
- // because its historical evidence exists, while the evidence is allowed to
207
- // outlive the artifact. Validate the ledger fail-closed, but do not grant old
208
- // attestations independent retention authority.
209
- validateRecoveryKnownGoodHistory(controllerHome, releasesRoot);
252
+ const pinnedRelease = loadPinnedRuntimeReleaseProtection(controllerHome, releasesRoot);
253
+ if (pinnedRelease) releasePaths.add(pinnedRelease);
254
+ // Only known-good entries that are also named by the committed Runtime
255
+ // authority are rollback protection. Older attestations are historical
256
+ // evidence and must not pin immutable release trees.
257
+ for (const knownGoodRelease of loadRecoveryKnownGoodProtection(controllerHome, releasesRoot, releasePaths)) {
258
+ releasePaths.add(knownGoodRelease);
259
+ }
260
+
261
+ // A publication writes the rollback backup before it atomically updates
262
+ // authority.json. Keep both the candidate tree and backup leased for the
263
+ // lifetime of that publication, so periodic cleanup cannot win the race.
264
+ const publicationLeasesRoot = join(releasesRoot, '.publication-leases');
265
+ if (existsSync(publicationLeasesRoot)) {
266
+ for (const entry of readdirSync(publicationLeasesRoot, { withFileTypes: true })) {
267
+ if (!entry.isFile() || !entry.name.endsWith('.json')) continue;
268
+ const leasePath = join(publicationLeasesRoot, entry.name);
269
+ let lease: RuntimeReleasePublicationLease;
270
+ try {
271
+ lease = JSON.parse(readFileSync(leasePath, 'utf8')) as RuntimeReleasePublicationLease;
272
+ } catch (error) {
273
+ throw new Error(`runtime release publication lease is invalid: ${error instanceof Error ? error.message : String(error)}`);
274
+ }
275
+ if (
276
+ lease.schemaVersion !== 1
277
+ || !Number.isInteger(lease.pid)
278
+ || lease.pid <= 0
279
+ || typeof lease.operationId !== 'string'
280
+ || !lease.operationId.trim()
281
+ || typeof lease.candidateReleasePath !== 'string'
282
+ || !directChild(releasesRoot, resolve(lease.candidateReleasePath))
283
+ ) throw new Error('runtime release publication lease is invalid');
284
+ let alive = true;
285
+ try { process.kill(lease.pid, 0); } catch (error) {
286
+ alive = (error as NodeJS.ErrnoException).code === 'EPERM';
287
+ }
288
+ if (!alive) {
289
+ rmSync(leasePath, { force: true });
290
+ continue;
291
+ }
292
+ releasePaths.add(canonical(lease.candidateReleasePath));
293
+ if (lease.backupPath !== undefined) {
294
+ if (!directChild(backupsRoot, resolve(lease.backupPath))) throw new Error('runtime release publication lease backup is invalid');
295
+ backupPaths.add(canonical(lease.backupPath));
296
+ }
297
+ }
298
+ }
210
299
 
211
- const backupPaths = new Set<string>();
212
300
  let backupAuthoritySafe = true;
213
301
  if (previous && typeof previous === 'object' && !Array.isArray(previous)) {
214
302
  const databaseBackup = (previous as Record<string, unknown>).databaseBackup;
@@ -321,7 +409,7 @@ function scanRuntimeReleases(
321
409
  if (!protection) return;
322
410
 
323
411
  for (const entry of readdirSync(protection.releasesRoot, { withFileTypes: true })) {
324
- if (entry.name === 'backups' || entry.name === 'authority.json') continue;
412
+ if (entry.name === 'backups' || entry.name === 'authority.json' || entry.name === '.publication-leases') continue;
325
413
  const path = join(protection.releasesRoot, entry.name);
326
414
  state.inspected += 1;
327
415
 
@@ -5,7 +5,7 @@ import { listRepositories } from '../../cli/repositories/registry';
5
5
  import { listActiveExecutionJobs } from '../execution/jobs/store';
6
6
  import { listActiveProcessIds } from '../execution/process-runtime/store';
7
7
  import { listActiveLeases } from '../resources/leases/store';
8
- import { isTerminalWorkContractStatus, readWorkContractStore } from '../../../packages/kernel/work/api/index';
8
+ import { isTerminalSemanticWorkState, readWorkContractStore } from '../../../packages/kernel/work/api/index';
9
9
  import { listControlPlaneRecords } from './persistence/sqlite-store';
10
10
  import { measureReclaimablePath } from './lifecycle-retention-metrics';
11
11
 
@@ -88,7 +88,7 @@ function activeAuthorityBlockers(controllerHome: string, repoId: string): string
88
88
 
89
89
  const workStore = readWorkContractStore({ controllerHome, repoId });
90
90
  for (const work of workStore.contracts) {
91
- if (!isTerminalWorkContractStatus(work.status)) {
91
+ if (!isTerminalSemanticWorkState(work.semanticState)) {
92
92
  blockers.push('active_work');
93
93
  break;
94
94
  }