@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
@@ -10,13 +10,28 @@ import {
10
10
  } from 'fs';
11
11
  import { dirname, join } from 'path';
12
12
  import { resolveControllerHome } from '../../cli/repositories/controller-home';
13
- import { isProcessAlive } from '../shared/process-tree';
13
+ import { isProcessAlive, terminateProcessTree, type ProcessTreeTerminationResult } from '../shared/process-tree';
14
+ import { defaultProcessIdentityProbe, executableFingerprint, processIdentityMatches } from '../shared/process-identity';
14
15
 
15
16
  export interface RuntimeOwnerRecord {
16
- schemaVersion: 1;
17
+ schemaVersion: 1 | 2;
17
18
  runtimeInstanceId: string;
18
19
  pid: number;
19
20
  acquiredAt: string;
21
+ /** Monotonic Controller-Home writer epoch. Schema v1 owners predate it. */
22
+ fencingGeneration?: number;
23
+ /** Optional OS-process identity evidence used only for bounded crash recovery. */
24
+ processStartTime?: string;
25
+ executableFingerprint?: string;
26
+ }
27
+
28
+ export interface RuntimeIncarnationRecord {
29
+ schemaVersion: 1;
30
+ controllerHome: string;
31
+ runtimeInstanceId: string;
32
+ pid: number;
33
+ fencingGeneration: number;
34
+ activatedAt: string;
20
35
  }
21
36
 
22
37
  export interface RuntimeOwnershipHandle {
@@ -28,11 +43,18 @@ export function runtimeOwnerPath(controllerHome: string): string {
28
43
  return join(resolveControllerHome(controllerHome), 'runtime', 'active-runtime-owner.json');
29
44
  }
30
45
 
46
+ export function runtimeIncarnationPath(controllerHome: string): string {
47
+ return join(resolveControllerHome(controllerHome), 'runtime', 'runtime-incarnation.json');
48
+ }
49
+
31
50
  function readOwnerPath(path: string): RuntimeOwnerRecord | undefined {
32
51
  if (!existsSync(path)) return undefined;
33
52
  try {
34
53
  const value = JSON.parse(readFileSync(path, 'utf8')) as RuntimeOwnerRecord;
35
- if (value.schemaVersion !== 1 || !value.runtimeInstanceId || !Number.isInteger(value.pid)) return undefined;
54
+ if ((value.schemaVersion !== 1 && value.schemaVersion !== 2) || !value.runtimeInstanceId || !Number.isInteger(value.pid)) return undefined;
55
+ if (value.schemaVersion === 2 && (!Number.isInteger(value.fencingGeneration) || value.fencingGeneration! < 1)) return undefined;
56
+ if ((value.processStartTime === undefined) !== (value.executableFingerprint === undefined)) return undefined;
57
+ if (value.processStartTime !== undefined && (!value.processStartTime.trim() || !value.executableFingerprint?.trim())) return undefined;
36
58
  return value;
37
59
  } catch {
38
60
  return undefined;
@@ -43,6 +65,208 @@ export function readRuntimeOwner(controllerHome: string): RuntimeOwnerRecord | u
43
65
  return readOwnerPath(runtimeOwnerPath(controllerHome));
44
66
  }
45
67
 
68
+ export function readRuntimeIncarnation(controllerHome: string): RuntimeIncarnationRecord | undefined {
69
+ const path = runtimeIncarnationPath(controllerHome);
70
+ if (!existsSync(path)) return undefined;
71
+ try {
72
+ const value = JSON.parse(readFileSync(path, 'utf8')) as RuntimeIncarnationRecord;
73
+ if (
74
+ value.schemaVersion !== 1
75
+ || resolveControllerHome(value.controllerHome) !== resolveControllerHome(controllerHome)
76
+ || !value.runtimeInstanceId
77
+ || !Number.isInteger(value.pid)
78
+ || !Number.isInteger(value.fencingGeneration)
79
+ || value.fencingGeneration < 1
80
+ || !Number.isFinite(Date.parse(value.activatedAt))
81
+ ) return undefined;
82
+ return value;
83
+ } catch {
84
+ return undefined;
85
+ }
86
+ }
87
+
88
+ function nextFencingGeneration(controllerHome: string, minimum = 1): number {
89
+ const incarnationGeneration = readRuntimeIncarnation(controllerHome)?.fencingGeneration ?? 0;
90
+ const ownerGeneration = readRuntimeOwner(controllerHome)?.fencingGeneration ?? 0;
91
+ return Math.max(minimum - 1, incarnationGeneration, ownerGeneration) + 1;
92
+ }
93
+
94
+ function writeRuntimeIncarnation(record: RuntimeIncarnationRecord): void {
95
+ const path = runtimeIncarnationPath(record.controllerHome);
96
+ const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
97
+ writeFileSync(temporary, `${JSON.stringify(record, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
98
+ renameSync(temporary, path);
99
+ }
100
+
101
+
102
+ export interface RuntimeOwnershipInspection {
103
+ owner?: RuntimeOwnerRecord;
104
+ incarnation?: RuntimeIncarnationRecord;
105
+ ownerAlive: boolean;
106
+ incarnationAlive: boolean;
107
+ coherent: boolean;
108
+ }
109
+
110
+ export function inspectRuntimeOwnership(controllerHome: string): RuntimeOwnershipInspection {
111
+ const owner = readRuntimeOwner(controllerHome);
112
+ const incarnation = readRuntimeIncarnation(controllerHome);
113
+ const coherent = Boolean(
114
+ owner
115
+ && incarnation
116
+ && owner.runtimeInstanceId === incarnation.runtimeInstanceId
117
+ && owner.pid === incarnation.pid
118
+ && (owner.fencingGeneration ?? incarnation.fencingGeneration) === incarnation.fencingGeneration,
119
+ );
120
+ // Schema-v2 owners carry OS-process identity. Once present, raw PID liveness
121
+ // is insufficient because a stopped Runtime PID may be reused by another
122
+ // process before Recovery reconciles durable ownership.
123
+ const ownerAlive = Boolean(owner && (
124
+ owner.processStartTime && owner.executableFingerprint
125
+ ? runtimeOwnerProcessIdentityMatches(owner)
126
+ : isProcessAlive(owner.pid)
127
+ ));
128
+ // A coherent incarnation is the same Runtime owner epoch, so inherit the
129
+ // stronger owner identity result instead of re-introducing PID-only liveness.
130
+ // Incarnation-only legacy evidence remains conservative because it has no
131
+ // independent process identity fields.
132
+ const incarnationAlive = Boolean(incarnation && (
133
+ coherent
134
+ ? ownerAlive
135
+ : isProcessAlive(incarnation.pid)
136
+ ));
137
+ return { owner, incarnation, ownerAlive, incarnationAlive, coherent };
138
+ }
139
+
140
+ export function runtimeOwnerProcessIdentityMatches(record: RuntimeOwnerRecord | undefined): boolean {
141
+ if (!record?.processStartTime || !record.executableFingerprint) return false;
142
+ return processIdentityMatches({
143
+ pid: record.pid,
144
+ processStartTime: record.processStartTime,
145
+ executableFingerprint: record.executableFingerprint,
146
+ }, record.pid).matches;
147
+ }
148
+
149
+ /**
150
+ * Recovery calls this only after the service manager and Runtime listener have
151
+ * been proven stopped. It never kills a live process. Dead owner evidence is
152
+ * renamed, not discarded, so fencing generations and forensic evidence survive.
153
+ */
154
+ export function reconcileStoppedRuntimeOwnership(controllerHome: string): {
155
+ ok: boolean;
156
+ changed: boolean;
157
+ detail: string;
158
+ inspection: RuntimeOwnershipInspection;
159
+ staleOwnerPath?: string;
160
+ } {
161
+ const inspection = inspectRuntimeOwnership(controllerHome);
162
+ if (inspection.ownerAlive || inspection.incarnationAlive) {
163
+ return {
164
+ ok: false,
165
+ changed: false,
166
+ detail: 'RUNTIME_OWNERSHIP_STILL_LIVE',
167
+ inspection,
168
+ };
169
+ }
170
+ const ownerPath = runtimeOwnerPath(controllerHome);
171
+ if (!inspection.owner || !existsSync(ownerPath)) {
172
+ return {
173
+ ok: true,
174
+ changed: false,
175
+ detail: 'Runtime ownership is already quiescent',
176
+ inspection,
177
+ };
178
+ }
179
+ const staleOwnerPath = `${ownerPath}.stale-${Date.now()}`;
180
+ renameSync(ownerPath, staleOwnerPath);
181
+ return {
182
+ ok: true,
183
+ changed: true,
184
+ detail: 'dead Runtime owner evidence was fenced out after service shutdown',
185
+ inspection,
186
+ staleOwnerPath,
187
+ };
188
+ }
189
+
190
+
191
+ export async function terminateVerifiedRuntimeOwner(
192
+ controllerHome: string,
193
+ expectedOwner?: RuntimeOwnerRecord | null,
194
+ ): Promise<{
195
+ ok: boolean;
196
+ attempted: boolean;
197
+ detail: string;
198
+ owner?: RuntimeOwnerRecord;
199
+ termination?: ProcessTreeTerminationResult;
200
+ }> {
201
+ const owner = readRuntimeOwner(controllerHome);
202
+ if (expectedOwner) {
203
+ if (!owner) {
204
+ return {
205
+ ok: true,
206
+ attempted: false,
207
+ detail: 'Runtime owner disappeared during stop',
208
+ owner: expectedOwner,
209
+ };
210
+ }
211
+ if (
212
+ owner.pid !== expectedOwner.pid
213
+ || owner.runtimeInstanceId !== expectedOwner.runtimeInstanceId
214
+ || owner.fencingGeneration !== expectedOwner.fencingGeneration
215
+ || owner.processStartTime !== expectedOwner.processStartTime
216
+ || owner.executableFingerprint !== expectedOwner.executableFingerprint
217
+ ) {
218
+ return {
219
+ ok: false,
220
+ attempted: false,
221
+ detail: 'RUNTIME_OWNER_CHANGED_DURING_STOP',
222
+ owner,
223
+ };
224
+ }
225
+ } else if (owner) {
226
+ return {
227
+ ok: false,
228
+ attempted: false,
229
+ detail: 'RUNTIME_OWNER_APPEARED_DURING_STOP',
230
+ owner,
231
+ };
232
+ }
233
+ if (!owner) return { ok: true, attempted: false, detail: 'Runtime owner is already absent' };
234
+ if (!isProcessAlive(owner.pid)) {
235
+ return { ok: true, attempted: false, detail: 'Runtime owner process is already dead', owner };
236
+ }
237
+ if (!owner.processStartTime || !owner.executableFingerprint) {
238
+ return {
239
+ ok: false,
240
+ attempted: false,
241
+ detail: 'RUNTIME_OWNER_IDENTITY_EVIDENCE_MISSING',
242
+ owner,
243
+ };
244
+ }
245
+ if (!runtimeOwnerProcessIdentityMatches(owner)) {
246
+ return {
247
+ ok: false,
248
+ attempted: false,
249
+ detail: 'RUNTIME_OWNER_IDENTITY_CHANGED',
250
+ owner,
251
+ };
252
+ }
253
+ const termination = await terminateProcessTree(owner.pid, {
254
+ gracePeriodMs: 1_500,
255
+ killAfterMs: 5_000,
256
+ pollIntervalMs: 50,
257
+ });
258
+ const exited = termination.exited && !isProcessAlive(owner.pid);
259
+ return {
260
+ ok: exited,
261
+ attempted: true,
262
+ detail: exited
263
+ ? 'verified orphan Runtime owner process tree terminated after service shutdown'
264
+ : `verified orphan Runtime owner did not fully exit; remaining pids=${termination.remainingPids.join(',')}`,
265
+ owner,
266
+ termination,
267
+ };
268
+ }
269
+
46
270
  export function acquireRuntimeOwnership(
47
271
  controllerHome: string,
48
272
  runtimeInstanceId: string,
@@ -51,14 +275,23 @@ export function acquireRuntimeOwnership(
51
275
  if (!runtimeInstanceId.trim()) throw new Error('RUNTIME_INSTANCE_ID_REQUIRED');
52
276
  const path = runtimeOwnerPath(controllerHome);
53
277
  mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
54
- const record: RuntimeOwnerRecord = {
55
- schemaVersion: 1,
56
- runtimeInstanceId,
57
- pid: process.pid,
58
- acquiredAt: now(),
59
- };
278
+ let minimumGeneration = nextFencingGeneration(controllerHome);
60
279
 
61
280
  for (let attempt = 0; attempt < 3; attempt += 1) {
281
+ const generation = nextFencingGeneration(controllerHome, minimumGeneration);
282
+ const processStartTime = defaultProcessIdentityProbe.startTime(process.pid);
283
+ const processCommand = defaultProcessIdentityProbe.command(process.pid);
284
+ const record: RuntimeOwnerRecord = {
285
+ schemaVersion: 2,
286
+ runtimeInstanceId,
287
+ pid: process.pid,
288
+ acquiredAt: now(),
289
+ fencingGeneration: generation,
290
+ ...(processStartTime && processCommand ? {
291
+ processStartTime,
292
+ executableFingerprint: executableFingerprint(processCommand),
293
+ } : {}),
294
+ };
62
295
  try {
63
296
  const fd = openSync(path, 'wx', 0o600);
64
297
  try {
@@ -66,6 +299,19 @@ export function acquireRuntimeOwnership(
66
299
  } finally {
67
300
  closeSync(fd);
68
301
  }
302
+ try {
303
+ writeRuntimeIncarnation({
304
+ schemaVersion: 1,
305
+ controllerHome: resolveControllerHome(controllerHome),
306
+ runtimeInstanceId,
307
+ pid: process.pid,
308
+ fencingGeneration: generation,
309
+ activatedAt: record.acquiredAt,
310
+ });
311
+ } catch (writeError) {
312
+ try { unlinkSync(path); } catch { /* ownership did not become usable */ }
313
+ throw writeError;
314
+ }
69
315
  return {
70
316
  record,
71
317
  release: () => {
@@ -84,6 +330,12 @@ export function acquireRuntimeOwnership(
84
330
  `RUNTIME_OWNERSHIP_CONFLICT: controller home is owned by ${current.runtimeInstanceId} pid=${current.pid}`,
85
331
  );
86
332
  }
333
+ minimumGeneration = Math.max(
334
+ minimumGeneration,
335
+ generation + 1,
336
+ (current?.fencingGeneration ?? 0) + 1,
337
+ (readRuntimeIncarnation(controllerHome)?.fencingGeneration ?? 0) + 1,
338
+ );
87
339
  const stalePath = `${path}.stale-${Date.now()}-${attempt}`;
88
340
  try { renameSync(path, stalePath); } catch (renameError) {
89
341
  if ((renameError as NodeJS.ErrnoException).code !== 'ENOENT') throw renameError;
@@ -1,10 +1,12 @@
1
1
  import { createHash } from 'crypto';
2
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
2
+ import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'fs';
3
3
  import { homedir } from 'os';
4
4
  import { basename, dirname, join, resolve } from 'path';
5
5
  import { loadMcpServiceLocalConfig } from '../../cli/mcp/auth';
6
+ import { runtimeAuthorityFreeEnvironment } from '../shared/process-environment';
6
7
  import type { PackageRuntimeRelease } from './package-runtime-release';
7
8
  import { createPlatformServiceManagerHost, platformLaunchdInstalledPath, type PlatformServiceManagerHost, type SystemdUserUnitInput } from '../platform/service-manager';
9
+ import { forgeConnectorPersistentServiceLabel } from '../platform/service-inventory';
8
10
 
9
11
  export interface PackageConnectorServicePaths {
10
12
  label: string;
@@ -14,9 +16,13 @@ export interface PackageConnectorServicePaths {
14
16
  stdoutPath: string;
15
17
  stderrPath: string;
16
18
  authorityPath: string;
19
+ activeEntrypointPath: string;
17
20
  }
18
21
 
19
- export type PackageConnectorReleaseBinding = Pick<PackageRuntimeRelease, 'releaseId' | 'releaseRoot' | 'packageRoot'>;
22
+ export type PackageConnectorReleaseBinding = Pick<PackageRuntimeRelease, 'releaseId' | 'releaseRoot' | 'packageRoot'> & {
23
+ connectorEntrypoint?: 'forge-mcp-gateway';
24
+ connectorArtifactIdentity?: string;
25
+ };
20
26
 
21
27
  export interface PackageConnectorServiceAuthority {
22
28
  schemaVersion: 1;
@@ -27,6 +33,7 @@ export interface PackageConnectorServiceAuthority {
27
33
  mode: 'launchd' | 'systemd-user' | 'portable';
28
34
  persistent: boolean;
29
35
  servicePath?: string;
36
+ connectorArtifactIdentity?: string;
30
37
  installedAt: string;
31
38
  }
32
39
 
@@ -37,6 +44,7 @@ export interface PackageConnectorServiceResult {
37
44
  servicePath?: string;
38
45
  pid?: number;
39
46
  reused?: boolean;
47
+ rebound?: boolean;
40
48
  releaseId?: string;
41
49
  releaseRoot?: string;
42
50
  }
@@ -56,8 +64,7 @@ function atomicWrite(path: string, content: string, mode = 0o600): void {
56
64
 
57
65
  export function packageConnectorServicePaths(controllerHome: string, accountHome = process.env.HOME ?? homedir()): PackageConnectorServicePaths {
58
66
  const home = resolve(controllerHome);
59
- const suffix = createHash('sha256').update(home).digest('hex').slice(0, 12);
60
- const label = `com.moretea.forge.mcp-gateway.${suffix}`;
67
+ const label = forgeConnectorPersistentServiceLabel(home);
61
68
  const serviceRoot = join(home, 'runtime', 'connector-service');
62
69
  return {
63
70
  label,
@@ -67,6 +74,7 @@ export function packageConnectorServicePaths(controllerHome: string, accountHome
67
74
  stdoutPath: join(serviceRoot, 'logs', 'stdout.log'),
68
75
  stderrPath: join(serviceRoot, 'logs', 'stderr.log'),
69
76
  authorityPath: join(serviceRoot, 'authority.json'),
77
+ activeEntrypointPath: join(serviceRoot, 'active-forge-mcp-gateway'),
70
78
  };
71
79
  }
72
80
 
@@ -82,13 +90,15 @@ export function readPackageConnectorServiceAuthority(controllerHome: string): Pa
82
90
  || typeof parsed.packageRoot !== 'string'
83
91
  || !['launchd', 'systemd-user', 'portable'].includes(String(parsed.mode))
84
92
  || typeof parsed.persistent !== 'boolean'
93
+ || (parsed.connectorArtifactIdentity !== undefined && !/^sha256:[a-f0-9]{64}$/i.test(parsed.connectorArtifactIdentity))
85
94
  || typeof parsed.installedAt !== 'string'
86
95
  ) throw new Error('FORGE_PACKAGE_CONNECTOR_AUTHORITY_INVALID');
87
96
  return parsed as PackageConnectorServiceAuthority;
88
97
  }
89
98
 
90
- function writePackageConnectorServiceAuthority(input: { release: PackageConnectorReleaseBinding; controllerHome: string; result: PackageConnectorServiceResult }): void {
99
+ function writePackageConnectorServiceAuthority(input: { release: PackageConnectorReleaseBinding; controllerHome: string; result: PackageConnectorServiceResult; installedAt?: string }): void {
91
100
  const paths = packageConnectorServicePaths(input.controllerHome);
101
+ const artifact = attestedCompiledConnector(input.release);
92
102
  const authority: PackageConnectorServiceAuthority = {
93
103
  schemaVersion: 1,
94
104
  endpoint: input.result.endpoint,
@@ -98,7 +108,8 @@ function writePackageConnectorServiceAuthority(input: { release: PackageConnecto
98
108
  mode: input.result.mode,
99
109
  persistent: input.result.persistent,
100
110
  ...(input.result.servicePath ? { servicePath: input.result.servicePath } : {}),
101
- installedAt: new Date().toISOString(),
111
+ ...(artifact ? { connectorArtifactIdentity: artifact.identity } : {}),
112
+ installedAt: input.installedAt ?? new Date().toISOString(),
102
113
  };
103
114
  atomicWrite(paths.authorityPath, `${JSON.stringify(authority, null, 2)}\n`);
104
115
  }
@@ -173,13 +184,73 @@ export function packageConnectorAuthMode(controllerHome: string): PackageConnect
173
184
  : 'oauth';
174
185
  }
175
186
 
187
+ function attestedCompiledConnector(release: PackageConnectorReleaseBinding): { target: string; identity: string } | undefined {
188
+ const entrypoint = release.connectorEntrypoint;
189
+ const identity = release.connectorArtifactIdentity?.trim();
190
+ if (!entrypoint && !identity) return undefined;
191
+ if (entrypoint !== 'forge-mcp-gateway' || !identity || !/^sha256:[a-f0-9]{64}$/i.test(identity)) {
192
+ throw new Error('FORGE_PACKAGE_CONNECTOR_ARTIFACT_ATTESTATION_INVALID');
193
+ }
194
+ const target = resolve(release.releaseRoot, entrypoint);
195
+ const root = resolve(release.releaseRoot);
196
+ if (dirname(target) !== root || !existsSync(target)) throw new Error('FORGE_PACKAGE_CONNECTOR_ARTIFACT_MISSING');
197
+ const status = lstatSync(target);
198
+ if (!status.isFile() || status.isSymbolicLink()) throw new Error('FORGE_PACKAGE_CONNECTOR_ARTIFACT_INVALID');
199
+ const actual = `sha256:${createHash('sha256').update(readFileSync(target)).digest('hex')}`;
200
+ if (actual !== identity.toLowerCase()) throw new Error('FORGE_PACKAGE_CONNECTOR_ARTIFACT_IDENTITY_MISMATCH');
201
+ return { target, identity: actual };
202
+ }
203
+
204
+ function stableConnectorEntrypointMatches(path: string, target: string): boolean {
205
+ try {
206
+ const current = lstatSync(path);
207
+ const desired = statSync(target);
208
+ if (!current.isFile() || current.isSymbolicLink() || !desired.isFile()) return false;
209
+ if (current.size !== desired.size || (current.mode & 0o777) !== (desired.mode & 0o777)) return false;
210
+ return readFileSync(path).equals(readFileSync(target));
211
+ } catch {
212
+ return false;
213
+ }
214
+ }
215
+
216
+ export function syncPackageConnectorActiveEntrypoint(input: { release: PackageConnectorReleaseBinding; controllerHome: string; accountHome?: string }): { path: string; target?: string; artifactIdentity?: string; changed: boolean } {
217
+ const paths = packageConnectorServicePaths(input.controllerHome, input.accountHome);
218
+ const artifact = attestedCompiledConnector(input.release);
219
+ if (!artifact) return { path: paths.activeEntrypointPath, changed: false };
220
+ if (stableConnectorEntrypointMatches(paths.activeEntrypointPath, artifact.target)) {
221
+ return { path: paths.activeEntrypointPath, target: artifact.target, artifactIdentity: artifact.identity, changed: false };
222
+ }
223
+ mkdirSync(dirname(paths.activeEntrypointPath), { recursive: true, mode: 0o700 });
224
+ const temporary = `${paths.activeEntrypointPath}.${process.pid}.tmp`;
225
+ rmSync(temporary, { force: true, recursive: true });
226
+ try {
227
+ copyFileSync(artifact.target, temporary);
228
+ chmodSync(temporary, statSync(artifact.target).mode & 0o777);
229
+ renameSync(temporary, paths.activeEntrypointPath);
230
+ } finally {
231
+ rmSync(temporary, { force: true, recursive: true });
232
+ }
233
+ if (!stableConnectorEntrypointMatches(paths.activeEntrypointPath, artifact.target)) {
234
+ throw new Error('FORGE_PACKAGE_CONNECTOR_STABLE_ENTRYPOINT_MIRROR_FAILED');
235
+ }
236
+ return { path: paths.activeEntrypointPath, target: artifact.target, artifactIdentity: artifact.identity, changed: true };
237
+ }
238
+
176
239
  export function packageConnectorLaunchSpec(input: { release: PackageConnectorReleaseBinding; controllerHome: string; endpoint: string; executable?: string }): { executable: string; args: string[]; environment: Record<string, string>; port: number; authMode: PackageConnectorAuthMode } {
177
240
  const parsed = new URL(input.endpoint);
178
241
  const port = Number(parsed.port);
179
242
  if (parsed.protocol !== 'http:' || parsed.hostname !== '127.0.0.1' || parsed.pathname !== '/mcp' || !Number.isInteger(port) || port < 1 || port > 65_535) {
180
243
  throw new Error('FORGE_PACKAGE_CONNECTOR_ENDPOINT_INVALID');
181
244
  }
182
- const executable = resolve(input.executable ?? process.env.FORGE_CONNECTOR_EXECUTABLE ?? process.execPath);
245
+ const attestedConnector = attestedCompiledConnector(input.release);
246
+ const legacyCompiledConnector = join(resolve(input.release.releaseRoot), 'forge-mcp-gateway');
247
+ const hasLegacyCompiledConnector = !attestedConnector && existsSync(legacyCompiledConnector);
248
+ const hasCompiledConnector = Boolean(attestedConnector) || hasLegacyCompiledConnector;
249
+ const executable = resolve(attestedConnector
250
+ ? packageConnectorServicePaths(input.controllerHome).activeEntrypointPath
251
+ : hasLegacyCompiledConnector
252
+ ? legacyCompiledConnector
253
+ : input.executable ?? process.env.FORGE_CONNECTOR_EXECUTABLE ?? process.execPath);
183
254
  if (/^forge-recovery-(?:gateway|watchdog)$/i.test(basename(executable))) {
184
255
  throw new Error('FORGE_PACKAGE_CONNECTOR_EXECUTABLE_INVALID');
185
256
  }
@@ -201,7 +272,7 @@ export function packageConnectorLaunchSpec(input: { release: PackageConnectorRel
201
272
  ];
202
273
  return {
203
274
  executable,
204
- args: isBun ? [cliEntry, ...cliArgs] : ['--loader', nodeLoader, cliEntry, ...cliArgs],
275
+ args: hasCompiledConnector ? cliArgs : isBun ? [cliEntry, ...cliArgs] : ['--loader', nodeLoader, cliEntry, ...cliArgs],
205
276
  environment: {
206
277
  FORGE_CONTROLLER_HOME: resolve(input.controllerHome),
207
278
  FORGE_CONTROLLER_LIFECYCLE_OWNER: '1',
@@ -253,9 +324,14 @@ export function packageConnectorServiceMatchesRelease(input: {
253
324
  executable?: string;
254
325
  }): boolean {
255
326
  try {
256
- if (
257
- input.authority.endpoint !== input.endpoint
258
- || input.authority.releaseId !== input.release.releaseId
327
+ if (input.authority.endpoint !== input.endpoint) return false;
328
+ const artifact = attestedCompiledConnector(input.release);
329
+ if (artifact) {
330
+ const paths = packageConnectorServicePaths(input.controllerHome, input.env?.HOME);
331
+ if (input.authority.connectorArtifactIdentity !== artifact.identity) return false;
332
+ if (!stableConnectorEntrypointMatches(paths.activeEntrypointPath, artifact.target)) return false;
333
+ } else if (
334
+ input.authority.releaseId !== input.release.releaseId
259
335
  || resolve(input.authority.releaseRoot) !== resolve(input.release.releaseRoot)
260
336
  || resolve(input.authority.packageRoot) !== resolve(input.release.packageRoot)
261
337
  ) return false;
@@ -295,11 +371,7 @@ function installSystemd(paths: PackageConnectorServicePaths, launch: ReturnType<
295
371
  function startPortable(paths: PackageConnectorServicePaths, launch: ReturnType<typeof packageConnectorLaunchSpec>, env: NodeJS.ProcessEnv, host: PlatformServiceManagerHost): number {
296
372
  // A connector is not the Canonical Runtime writer. Never let a transient
297
373
  // installer/worker write claim escape into this long-lived process.
298
- const childEnv = { ...env };
299
- for (const key of [
300
- 'FORGE_RUNTIME_INSTANCE_ID', 'FORGE_RUNTIME_OWNER_PID', 'FORGE_RELEASE_AUTHORITY_REVISION',
301
- 'FORGE_RELEASE_FENCING_TOKEN', 'FORGE_RELEASE_ID', 'FORGE_ARTIFACT_IDENTITY', 'FORGE_WORKER_PROTOCOL_VERSION',
302
- ]) delete childEnv[key];
374
+ const childEnv = runtimeAuthorityFreeEnvironment(env);
303
375
  return host.startDetached({
304
376
  executable: launch.executable,
305
377
  args: launch.args,
@@ -313,6 +385,7 @@ function startPortable(paths: PackageConnectorServicePaths, launch: ReturnType<t
313
385
  export async function installPackageConnectorService(input: { release: PackageConnectorReleaseBinding; controllerHome: string; endpoint: string; executable?: string; platform?: NodeJS.Platform; env?: NodeJS.ProcessEnv; forcePortable?: boolean; probeEndpoint?: (endpoint: string) => Promise<boolean> }): Promise<PackageConnectorServiceResult> {
314
386
  const paths = packageConnectorServicePaths(input.controllerHome, input.env?.HOME);
315
387
  mkdirSync(join(paths.serviceRoot, 'logs'), { recursive: true, mode: 0o700 });
388
+ syncPackageConnectorActiveEntrypoint({ release: input.release, controllerHome: input.controllerHome, accountHome: input.env?.HOME });
316
389
  const launch = packageConnectorLaunchSpec({
317
390
  release: input.release,
318
391
  controllerHome: input.controllerHome,
@@ -393,15 +466,28 @@ export async function ensurePackageConnectorService(input: {
393
466
  })
394
467
  && await (input.probeEndpoint ?? defaultConnectorEndpointProbe)(input.endpoint)
395
468
  ) {
396
- return {
469
+ const rebound = authority.releaseId !== input.release.releaseId
470
+ || resolve(authority.releaseRoot) !== resolve(input.release.releaseRoot)
471
+ || resolve(authority.packageRoot) !== resolve(input.release.packageRoot);
472
+ const reused: PackageConnectorServiceResult = {
397
473
  endpoint: authority.endpoint,
398
474
  mode: authority.mode,
399
475
  persistent: true,
400
476
  ...(authority.servicePath ? { servicePath: authority.servicePath } : {}),
401
477
  reused: true,
402
- releaseId: authority.releaseId,
403
- releaseRoot: authority.releaseRoot,
478
+ ...(rebound ? { rebound: true } : {}),
479
+ releaseId: input.release.releaseId,
480
+ releaseRoot: input.release.releaseRoot,
404
481
  };
482
+ if (rebound) {
483
+ writePackageConnectorServiceAuthority({
484
+ release: input.release,
485
+ controllerHome: input.controllerHome,
486
+ result: reused,
487
+ installedAt: authority.installedAt,
488
+ });
489
+ }
490
+ return reused;
405
491
  }
406
492
  }
407
493
  return installPackageConnectorService(input);