@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,13 +1,16 @@
1
1
  import { createHash } from 'crypto';
2
2
  import { closeSync, existsSync, openSync, readSync, realpathSync, statSync } from 'fs';
3
- import { join, resolve } from 'path';
3
+ import { dirname, join, resolve } from 'path';
4
4
  import { spawnSync } from 'child_process';
5
5
  import { listRepositories, selectRepositoryCheckout } from '../../cli/repositories/registry';
6
+ import { repositoryControllerRoot } from '../../cli/repositories/controller-home';
6
7
  import { withControllerLock } from '../../cli/repositories/locks';
7
8
  import type { RepositoryRecord } from '../../cli/repositories/types';
8
9
  import { loadRuntimeReleaseManifest } from '../root/release-manifest';
9
- import { appendWorkEvidence, getWorkContract, listWorkContracts } from '../../../packages/kernel/work/api/index';
10
- import { routeWorkStart } from '../control-plane/facade/goal-workloop';
10
+ import { readRuntimeReleaseAuthority } from '../root/release-store';
11
+ import { appendRuntimeEvent, type RuntimeEntityEvent } from '../evidence/event-ledger';
12
+ import { listReleaseSessions } from '../release/release-session';
13
+ import { appendWorkEvidence, createWorkSemanticContext, getWorkContract, listWorkContracts } from '../../../packages/kernel/work/api/index';
11
14
  import { createWorkContinuationSchedule } from '../workflow/schedules/work-continuation';
12
15
  import { touchSchedulerWakeSignal } from '../control-plane/global-scheduler/wake-signal';
13
16
  import { recentMcpIncidents, type McpIncident } from './mcp-timing';
@@ -16,7 +19,7 @@ const RECURRENCE_WINDOW_MS = 30 * 60_000;
16
19
  const RECURRENCE_THRESHOLD = 3;
17
20
  const INCIDENT_TAIL_BYTES = 256 * 1024;
18
21
  const INCIDENT_WORK_PREFIX = 'forge-incident-repair';
19
- const TERMINAL_WORK_STATUSES = new Set(['completed', 'failed', 'cancelled']);
22
+ const ACTIONABLE_FAILURE_EVENT = 'forge_actionable_failure_observed';
20
23
 
21
24
  export interface ForgeIncidentRepairClassification {
22
25
  eligible: boolean;
@@ -38,6 +41,16 @@ export interface ForgeIncidentRepairRegistration {
38
41
  reason: string;
39
42
  }
40
43
 
44
+ export interface ForgeActionableFailureObservation {
45
+ observationId: string;
46
+ source: 'progression' | 'release' | 'maintenance';
47
+ code: string;
48
+ message: string;
49
+ at?: string;
50
+ repoId?: string;
51
+ workId?: string;
52
+ }
53
+
41
54
  interface PersistedMcpIncident extends McpIncident {
42
55
  schemaVersion?: number;
43
56
  at?: string;
@@ -57,6 +70,13 @@ function transportFailureMessage(message: string): boolean {
57
70
  export function classifyForgeIncidentForRepair(incident: McpIncident): ForgeIncidentRepairClassification {
58
71
  const code = incident.code.trim().toUpperCase();
59
72
  if (!code) return { eligible: false, reason: 'incident code is empty' };
73
+ // Browser diagnostics on the native Apple Events provider are intentionally
74
+ // unsupported and already fail closed at the plugin boundary. Repeating that
75
+ // expected capability limitation is not evidence of a Forge infrastructure
76
+ // defect and must not manufacture recurrent repair Work.
77
+ if (code === 'PLUGIN_BROWSER_DIAGNOSTICS_UNAVAILABLE') {
78
+ return { eligible: false, reason: `expected provider capability limitation ${code}` };
79
+ }
60
80
 
61
81
  const rootCode = (() => {
62
82
  if (code === 'MCP_REQUEST_EXCEPTION' && transportFailureMessage(incident.message)) return 'MCP_TRANSPORT_UNAVAILABLE';
@@ -80,13 +100,12 @@ function incidentAuditPath(controllerHome: string): string {
80
100
  return join(resolve(controllerHome), 'audit', 'mcp-incidents.jsonl');
81
101
  }
82
102
 
83
- function readBoundedIncidentTail(controllerHome: string): PersistedMcpIncident[] {
84
- const path = incidentAuditPath(controllerHome);
103
+ function readBoundedJsonLines<T>(path: string, maxBytes = INCIDENT_TAIL_BYTES): T[] {
85
104
  if (!existsSync(path)) return [];
86
105
  let fd: number | undefined;
87
106
  try {
88
107
  const size = statSync(path).size;
89
- const length = Math.min(size, INCIDENT_TAIL_BYTES);
108
+ const length = Math.min(size, maxBytes);
90
109
  const start = Math.max(0, size - length);
91
110
  const buffer = Buffer.alloc(length);
92
111
  fd = openSync(path, 'r');
@@ -98,7 +117,7 @@ function readBoundedIncidentTail(controllerHome: string): PersistedMcpIncident[]
98
117
  }
99
118
  return text.split(/\r?\n/).filter(Boolean).flatMap((line) => {
100
119
  try {
101
- const parsed = JSON.parse(line) as PersistedMcpIncident;
120
+ const parsed = JSON.parse(line) as T;
102
121
  return parsed && typeof parsed === 'object' ? [parsed] : [];
103
122
  } catch {
104
123
  return [];
@@ -111,6 +130,10 @@ function readBoundedIncidentTail(controllerHome: string): PersistedMcpIncident[]
111
130
  }
112
131
  }
113
132
 
133
+ function readBoundedIncidentTail(controllerHome: string): PersistedMcpIncident[] {
134
+ return readBoundedJsonLines<PersistedMcpIncident>(incidentAuditPath(controllerHome));
135
+ }
136
+
114
137
  function recentRootIncidents(
115
138
  controllerHome: string,
116
139
  classification: ForgeIncidentRepairClassification,
@@ -128,15 +151,108 @@ function recentRootIncidents(
128
151
  return [...unique.values()];
129
152
  }
130
153
 
131
- function gitContainsCommit(root: string, commit: string): boolean {
132
- const exists = spawnSync('git', ['-C', root, 'cat-file', '-e', `${commit}^{commit}`], {
133
- encoding: 'utf8', stdio: ['ignore', 'ignore', 'ignore'], timeout: 10_000,
134
- });
135
- if (exists.status !== 0) return false;
136
- const ancestor = spawnSync('git', ['-C', root, 'merge-base', '--is-ancestor', commit, 'HEAD'], {
137
- encoding: 'utf8', stdio: ['ignore', 'ignore', 'ignore'], timeout: 10_000,
138
- });
139
- return ancestor.status === 0;
154
+ function actionableFailureLedgerPath(controllerHome: string, repoId: string): string {
155
+ return join(repositoryControllerRoot(controllerHome, repoId), 'events', 'ledger.jsonl');
156
+ }
157
+
158
+ function readActionableFailureEvents(controllerHome: string, repoId: string): RuntimeEntityEvent[] {
159
+ return readBoundedJsonLines<RuntimeEntityEvent>(actionableFailureLedgerPath(controllerHome, repoId))
160
+ .filter((event) => event.eventType === ACTIONABLE_FAILURE_EVENT && event.entityType === 'portfolio');
161
+ }
162
+
163
+ function normalizedFailureMessage(message: string): string {
164
+ return message.toUpperCase()
165
+ .replace(/[A-F0-9]{16,64}/g, '<ID>')
166
+ .replace(/\b\d{2,}\b/g, '<N>')
167
+ .replace(/\s+/g, ' ')
168
+ .trim()
169
+ .slice(0, 500);
170
+ }
171
+
172
+ export function deriveForgeActionableFailureCode(prefix: string, message: string): string {
173
+ const normalizedPrefix = prefix.toUpperCase().replace(/[^A-Z0-9_]+/g, '_').replace(/^_+|_+$/g, '') || 'FORGE_FAILURE';
174
+ const normalizedMessage = normalizedFailureMessage(message);
175
+ const explicit = normalizedMessage.match(/\b(?:[A-Z][A-Z0-9]*_){1,}[A-Z0-9_]+\b/)?.[0];
176
+ if (explicit) return explicit.slice(0, 120);
177
+ const digest = createHash('sha256').update(normalizedMessage || normalizedPrefix).digest('hex').slice(0, 12).toUpperCase();
178
+ return `${normalizedPrefix}_${digest}`.slice(0, 120);
179
+ }
180
+
181
+ export function classifyForgeActionableFailureForRepair(observation: ForgeActionableFailureObservation): ForgeIncidentRepairClassification {
182
+ const code = observation.code.trim().toUpperCase();
183
+ if (!code) return { eligible: false, reason: 'actionable failure code is empty' };
184
+ const blockerText = `${code} ${observation.message}`.toUpperCase();
185
+ if (
186
+ blockerText.includes('EXTERNAL_EFFECT_AUTHORIZATION_REQUIRED')
187
+ || blockerText.includes('PLUGIN_BROWSER_JAVASCRIPT_PERMISSION_REQUIRED')
188
+ || blockerText.includes('LOGIN_REQUIRED')
189
+ || blockerText.includes('PERMISSION_REQUIRED')
190
+ || blockerText.includes('CONSENT_REQUIRED')
191
+ || blockerText.includes('WAITING_FOR_USER')
192
+ || blockerText.includes('USER_ACTION_REQUIRED')
193
+ || blockerText.includes('OUTCOME_UNKNOWN')
194
+ ) return { eligible: false, reason: `explicit user/ambiguity blocker ${code}` };
195
+
196
+ const rootCode = (
197
+ code.startsWith('CONTROLLER_')
198
+ || code.startsWith('SCHEDULER_')
199
+ || code.startsWith('WORKFLOW_SUPERVISOR_')
200
+ || code.startsWith('RUNTIME_')
201
+ || code.startsWith('RECOVERY_')
202
+ || code.startsWith('PROCESS_')
203
+ || code.startsWith('RELEASE_SESSION_')
204
+ || code.startsWith('MAINTENANCE_')
205
+ || /^PLUGIN_[A-Z0-9_]+_(?:UNAVAILABLE|MISSING|MISMATCH|FAILED)$/.test(code)
206
+ ) ? code : undefined;
207
+ if (!rootCode) return { eligible: false, reason: `non-infrastructure actionable failure class ${code}` };
208
+ const fingerprint = createHash('sha256').update(`forge-infrastructure:${rootCode}`).digest('hex').slice(0, 24);
209
+ return { eligible: true, rootCode, fingerprint, reason: `eligible Forge infrastructure root ${rootCode}` };
210
+ }
211
+
212
+ function activeRuntimeSourceRoot(controllerHome: string): string | undefined {
213
+ const authority = readRuntimeReleaseAuthority(controllerHome);
214
+ return authority?.active.manifestPath ? dirname(authority.active.manifestPath) : undefined;
215
+ }
216
+
217
+ function recentActionableRootEvents(
218
+ controllerHome: string,
219
+ repoId: string,
220
+ classification: ForgeIncidentRepairClassification,
221
+ nowMs: number,
222
+ ): RuntimeEntityEvent[] {
223
+ if (!classification.eligible || !classification.rootCode) return [];
224
+ const unique = new Map<string, RuntimeEntityEvent>();
225
+ for (const event of readActionableFailureEvents(controllerHome, repoId)) {
226
+ const data = event.data ?? {};
227
+ const rootCode = typeof data.rootCode === 'string' ? data.rootCode : '';
228
+ const observationId = typeof data.observationId === 'string' ? data.observationId : '';
229
+ const observedAt = typeof data.observedAt === 'string' ? data.observedAt : event.occurredAt;
230
+ const at = Date.parse(observedAt);
231
+ if (rootCode !== classification.rootCode || !observationId) continue;
232
+ if (!Number.isFinite(at) || at < nowMs - RECURRENCE_WINDOW_MS || at > nowMs + 60_000) continue;
233
+ unique.set(observationId, event);
234
+ }
235
+ return [...unique.values()].sort((left, right) => left.occurredAt.localeCompare(right.occurredAt));
236
+ }
237
+
238
+ function actionableEvidence(event: RuntimeEntityEvent, rootCode: string, ordinal: number) {
239
+ const data = event.data ?? {};
240
+ const observationId = typeof data.observationId === 'string' ? data.observationId : event.eventId;
241
+ const source = typeof data.source === 'string' ? data.source : 'unknown';
242
+ const affectedRepo = typeof data.affectedRepoId === 'string' ? data.affectedRepoId : undefined;
243
+ const workId = typeof data.workId === 'string' ? data.workId : undefined;
244
+ return {
245
+ evidenceId: `FAILOBS-${createHash('sha256').update(observationId).digest('hex').slice(0, 24)}`,
246
+ title: `recurrent Forge failure ${rootCode}`,
247
+ summary: [
248
+ `Occurrence ${ordinal} for ${rootCode}.`,
249
+ `source=${source}`,
250
+ ...(affectedRepo ? [`affectedRepo=${affectedRepo}`] : []),
251
+ ...(workId ? [`work=${workId}`] : []),
252
+ `observation=${observationId}`,
253
+ ].join(' ').slice(0, 1_000),
254
+ detailLevel: 'summary' as const,
255
+ };
140
256
  }
141
257
 
142
258
  function gitHead(root: string): string | undefined {
@@ -154,8 +270,10 @@ function samePath(left: string, right: string): boolean {
154
270
  /**
155
271
  * Resolve the registered Forge source authority. A user/business repository
156
272
  * affected by a Runtime defect is never treated as the repair repository.
157
- * Source-mode Runtime uses exact checkout path identity; immutable/package mode
158
- * must prove its release sourceCommit exists in exactly one enabled repo.
273
+ * Source-mode Runtime uses exact checkout path identity. Immutable/package mode
274
+ * uses the release manifest's sourceRepositoryId, which is minted by the staged
275
+ * release contract. Scheduler/incident reconciliation must not rediscover that
276
+ * identity by synchronously walking Git history across registered repositories.
159
277
  */
160
278
  export function resolveRuntimeSourceRepairRepository(
161
279
  controllerHome: string,
@@ -172,19 +290,16 @@ export function resolveRuntimeSourceRepairRepository(
172
290
 
173
291
  const manifestPath = join(resolve(root), 'manifest.json');
174
292
  if (!existsSync(manifestPath)) return undefined;
175
- let sourceCommit: string | undefined;
293
+ let sourceRepositoryId: string | undefined;
176
294
  try {
177
- sourceCommit = loadRuntimeReleaseManifest(manifestPath, controllerHome).sourceCommit;
295
+ sourceRepositoryId = loadRuntimeReleaseManifest(manifestPath, controllerHome).sourceRepositoryId?.trim();
178
296
  } catch {
179
297
  return undefined;
180
298
  }
181
- if (!sourceCommit || !/^[a-f0-9]{40}$/i.test(sourceCommit)) return undefined;
182
- const containing = repositories.filter((repository) => {
183
- const selected = selectRepositoryCheckout(repository, repository.activeCheckoutId);
184
- return gitContainsCommit(selected.canonicalRoot, sourceCommit!);
185
- });
186
- if (containing.length !== 1) return undefined;
187
- return selectRepositoryCheckout(containing[0]!, containing[0]!.activeCheckoutId);
299
+ if (!sourceRepositoryId) return undefined;
300
+ const sourceRepository = repositories.find((repository) => repository.repoId === sourceRepositoryId);
301
+ if (!sourceRepository) return undefined;
302
+ return selectRepositoryCheckout(sourceRepository, sourceRepository.activeCheckoutId);
188
303
  }
189
304
 
190
305
  function requestBase(fingerprint: string): string {
@@ -242,42 +357,39 @@ function ensureAutomaticContinuation(
242
357
  }
243
358
  }
244
359
 
245
- /**
246
- * Promote only recurrent, source-authority-proven Forge infrastructure incidents
247
- * into canonical primary Work. The JSONL incident log remains evidence only;
248
- * WorkContract + existing continuation Schedule are the sole durable authorities.
249
- */
250
- export function maybeRegisterMcpIncidentRepair(input: {
360
+ interface RepairEvidenceRef {
361
+ evidenceId?: string;
362
+ title: string;
363
+ summary: string;
364
+ detailLevel: 'summary';
365
+ }
366
+
367
+ function registerRecurringForgeRepair(input: {
251
368
  controllerHome: string;
252
369
  runtimeSourceRoot?: string;
253
- incident: McpIncident;
254
- now?: () => number;
370
+ classification: ForgeIncidentRepairClassification;
371
+ occurrenceCount: number;
372
+ evidence: RepairEvidenceRef[];
373
+ repairRepository?: RepositoryRecord;
255
374
  }): ForgeIncidentRepairRegistration {
256
- const classification = classifyForgeIncidentForRepair(input.incident);
375
+ const { classification } = input;
257
376
  if (!classification.eligible || !classification.fingerprint || !classification.rootCode) {
258
377
  return { eligible: false, recurrent: false, occurrenceCount: 0, reason: classification.reason };
259
378
  }
260
- const nowMs = input.now?.() ?? Date.now();
261
- const occurrences = recentRootIncidents(input.controllerHome, classification, nowMs);
262
- if (occurrences.length < RECURRENCE_THRESHOLD) {
379
+ if (input.occurrenceCount < RECURRENCE_THRESHOLD) {
263
380
  return {
264
- eligible: true,
265
- recurrent: false,
266
- occurrenceCount: occurrences.length,
267
- fingerprint: classification.fingerprint,
268
- rootCode: classification.rootCode,
381
+ eligible: true, recurrent: false, occurrenceCount: input.occurrenceCount,
382
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
269
383
  reason: `waiting for ${RECURRENCE_THRESHOLD} occurrences within ${RECURRENCE_WINDOW_MS / 60_000} minutes`,
270
384
  };
271
385
  }
272
386
 
273
- const repairRepository = resolveRuntimeSourceRepairRepository(input.controllerHome, input.runtimeSourceRoot);
387
+ const repairRepository = input.repairRepository
388
+ ?? resolveRuntimeSourceRepairRepository(input.controllerHome, input.runtimeSourceRoot);
274
389
  if (!repairRepository) {
275
390
  return {
276
- eligible: true,
277
- recurrent: true,
278
- occurrenceCount: occurrences.length,
279
- fingerprint: classification.fingerprint,
280
- rootCode: classification.rootCode,
391
+ eligible: true, recurrent: true, occurrenceCount: input.occurrenceCount,
392
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
281
393
  reason: 'runtime source authority could not be mapped unambiguously to one registered repository',
282
394
  };
283
395
  }
@@ -286,28 +398,23 @@ export function maybeRegisterMcpIncidentRepair(input: {
286
398
  const lockResource = `incident-repair-${classification.fingerprint}`;
287
399
  return withControllerLock(input.controllerHome, { scope: 'global', resource: lockResource }, lockResource, () => {
288
400
  const store = { controllerHome: input.controllerHome, repoId: repairRepository.repoId };
289
- const matching = listWorkContracts({ ...store, status: 'all', limit: 500 })
401
+ const matching = listWorkContracts({ ...store, state: 'all', limit: 500 })
290
402
  .filter((work) => requestGeneration(work.requestId, base) !== undefined)
291
403
  .sort((left, right) => (requestGeneration(left.requestId, base) ?? 0) - (requestGeneration(right.requestId, base) ?? 0));
292
- const active = [...matching].reverse().find((work) => !TERMINAL_WORK_STATUSES.has(work.status));
293
- const recentEvidence = occurrences.slice(-RECURRENCE_THRESHOLD);
404
+ const active = [...matching].reverse().find((work) => work.semanticState === 'open');
405
+ const recentEvidence = input.evidence.slice(-RECURRENCE_THRESHOLD);
406
+
294
407
  if (active) {
295
- for (const [index, occurrence] of recentEvidence.entries()) {
296
- if (active.evidenceRefs.some((entry) => entry.evidenceId === `MCPINC-${occurrence.traceId}`)) continue;
297
- appendWorkEvidence(store, active.workId, incidentEvidence(occurrence, classification.rootCode!, occurrences.length - recentEvidence.length + index + 1));
408
+ for (const evidence of recentEvidence) {
409
+ if (evidence.evidenceId && active.evidenceRefs.some((entry) => entry.evidenceId === evidence.evidenceId)) continue;
410
+ appendWorkEvidence(store, active.workId, evidence);
298
411
  }
299
412
  const scheduleId = ensureAutomaticContinuation(input.controllerHome, repairRepository.repoId, active.workId, classification.rootCode!);
300
413
  return {
301
- eligible: true,
302
- recurrent: true,
303
- occurrenceCount: occurrences.length,
304
- fingerprint: classification.fingerprint,
305
- rootCode: classification.rootCode,
306
- repairRepoId: repairRepository.repoId,
307
- workId: active.workId,
308
- reusedExistingWork: true,
309
- scheduleId,
310
- reason: 'reused active canonical incident-repair Work',
414
+ eligible: true, recurrent: true, occurrenceCount: input.occurrenceCount,
415
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
416
+ repairRepoId: repairRepository.repoId, workId: active.workId, reusedExistingWork: true,
417
+ scheduleId, reason: 'reused active canonical incident-repair Work',
311
418
  };
312
419
  }
313
420
 
@@ -315,92 +422,152 @@ export function maybeRegisterMcpIncidentRepair(input: {
315
422
  const generation = (predecessor ? (requestGeneration(predecessor.requestId, base) ?? 0) : 0) + 1;
316
423
  const requestId = `${base}:g${generation}`;
317
424
  const head = gitHead(repairRepository.canonicalRoot);
318
- if (!head) {
425
+ if (!head) return {
426
+ eligible: true, recurrent: true, occurrenceCount: input.occurrenceCount,
427
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
428
+ repairRepoId: repairRepository.repoId, reason: 'repair repository HEAD could not be proven',
429
+ };
430
+
431
+ try {
432
+ createWorkSemanticContext(store, {
433
+ workId: `work-incident-${classification.fingerprint}-g${generation}`,
434
+ objective: `Repair recurrent Forge infrastructure incident ${classification.rootCode} automatically registered after ${input.occurrenceCount} occurrences within ${RECURRENCE_WINDOW_MS / 60_000} minutes.`,
435
+ requestId,
436
+ requestedBy: 'system',
437
+ });
438
+ } catch (error) {
319
439
  return {
320
- eligible: true,
321
- recurrent: true,
322
- occurrenceCount: occurrences.length,
323
- fingerprint: classification.fingerprint,
324
- rootCode: classification.rootCode,
440
+ eligible: true, recurrent: true, occurrenceCount: input.occurrenceCount,
441
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
325
442
  repairRepoId: repairRepository.repoId,
326
- reason: 'repair repository HEAD could not be proven',
443
+ reason: `semantic Work creation failed: ${error instanceof Error ? error.message : String(error)}`,
327
444
  };
328
445
  }
329
- const routed = routeWorkStart({
330
- workStore: store,
331
- handoffStore: store,
332
- repoId: repairRepository.repoId,
333
- sourceRevision: head,
334
- checkoutId: repairRepository.activeCheckoutId,
335
- }, {
336
- objective: `Repair recurrent Forge infrastructure incident ${classification.rootCode} automatically registered after ${occurrences.length} occurrences within ${RECURRENCE_WINDOW_MS / 60_000} minutes.`,
337
- acceptanceCriteria: [
338
- `Reproduce and eliminate root incident ${classification.rootCode} without bypassing canonical Runtime/Recovery/Controller authority.`,
339
- 'Preserve fail-closed behavior for expected policy, ownership, user-code, and approval failures.',
340
- 'Run focused affected checks and live verification before terminalizing the Work.',
341
- ],
342
- allowedPaths: ['src/**', 'tests/**', 'scripts/**', 'package.json'],
343
- initialLikelyPaths: [],
344
- forbiddenPaths: ['node_modules/**', '_ops/**'],
345
- constraints: { workspaceMode: 'auto', requireHandoffOnAmbiguity: true },
346
- modeInput: {
347
- scopeClear: false,
348
- mutation: true,
349
- requiresInvestigation: true,
350
- requiresRecovery: true,
351
- risk: 'workspace_write',
352
- },
353
- requestedBy: 'system',
354
- requestId,
355
- relatedWorkId: predecessor?.workId,
356
- workRelation: 'new_goal',
357
- workKind: 'repository_change',
446
+
447
+ const created = listWorkContracts({ ...store, state: 'all', limit: 500 }).find((work) => work.requestId === requestId);
448
+ if (!created) return {
449
+ eligible: true, recurrent: true, occurrenceCount: input.occurrenceCount,
450
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
451
+ repairRepoId: repairRepository.repoId,
452
+ reason: 'canonical Work admission succeeded without a request-bound readable Work',
453
+ };
454
+
455
+ if (predecessor) appendWorkEvidence(store, created.workId, {
456
+ title: 'incident repair predecessor',
457
+ summary: `Recurrent root ${classification.rootCode} created successor generation ${generation} after terminal Work ${predecessor.workId} (${predecessor.semanticState}).`,
458
+ detailLevel: 'summary',
358
459
  });
359
- if (routed.status !== 'ok') {
360
- return {
361
- eligible: true,
362
- recurrent: true,
363
- occurrenceCount: occurrences.length,
364
- fingerprint: classification.fingerprint,
365
- rootCode: classification.rootCode,
366
- repairRepoId: repairRepository.repoId,
367
- reason: `canonical Work admission did not create repair Work: ${routed.summary}`,
368
- };
369
- }
370
- const created = listWorkContracts({ ...store, status: 'all', limit: 500 }).find((work) => work.requestId === requestId);
371
- if (!created) {
372
- return {
373
- eligible: true,
374
- recurrent: true,
375
- occurrenceCount: occurrences.length,
376
- fingerprint: classification.fingerprint,
377
- rootCode: classification.rootCode,
378
- repairRepoId: repairRepository.repoId,
379
- reason: 'canonical Work admission succeeded without a request-bound readable Work',
380
- };
381
- }
382
- if (predecessor) {
383
- appendWorkEvidence(store, created.workId, {
384
- title: 'incident repair predecessor',
385
- summary: `Recurrent root ${classification.rootCode} created successor generation ${generation} after terminal Work ${predecessor.workId} (${predecessor.status}).`,
386
- detailLevel: 'summary',
387
- });
388
- }
389
- for (const [index, occurrence] of recentEvidence.entries()) {
390
- appendWorkEvidence(store, created.workId, incidentEvidence(occurrence, classification.rootCode!, occurrences.length - recentEvidence.length + index + 1));
391
- }
460
+ for (const evidence of recentEvidence) appendWorkEvidence(store, created.workId, evidence);
392
461
  const scheduleId = ensureAutomaticContinuation(input.controllerHome, repairRepository.repoId, created.workId, classification.rootCode!);
393
462
  return {
394
- eligible: true,
395
- recurrent: true,
396
- occurrenceCount: occurrences.length,
397
- fingerprint: classification.fingerprint,
398
- rootCode: classification.rootCode,
399
- repairRepoId: repairRepository.repoId,
400
- workId: created.workId,
401
- reusedExistingWork: false,
402
- scheduleId,
403
- reason: 'created canonical recurrent-incident repair Work',
463
+ eligible: true, recurrent: true, occurrenceCount: input.occurrenceCount,
464
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
465
+ repairRepoId: repairRepository.repoId, workId: created.workId, reusedExistingWork: false,
466
+ scheduleId, reason: 'created canonical recurrent-incident repair Work',
404
467
  };
405
468
  }, 10_000);
406
469
  }
470
+
471
+ export function maybeRegisterMcpIncidentRepair(input: {
472
+ controllerHome: string;
473
+ runtimeSourceRoot?: string;
474
+ incident: McpIncident;
475
+ now?: () => number;
476
+ }): ForgeIncidentRepairRegistration {
477
+ const classification = classifyForgeIncidentForRepair(input.incident);
478
+ if (!classification.eligible || !classification.fingerprint || !classification.rootCode) {
479
+ return { eligible: false, recurrent: false, occurrenceCount: 0, reason: classification.reason };
480
+ }
481
+ const occurrences = recentRootIncidents(input.controllerHome, classification, input.now?.() ?? Date.now());
482
+ return registerRecurringForgeRepair({
483
+ controllerHome: input.controllerHome,
484
+ runtimeSourceRoot: input.runtimeSourceRoot,
485
+ classification,
486
+ occurrenceCount: occurrences.length,
487
+ evidence: occurrences.map((incident, index) => incidentEvidence(incident, classification.rootCode!, index + 1)),
488
+ });
489
+ }
490
+
491
+ export function maybeRegisterForgeActionableFailureRepair(input: {
492
+ controllerHome: string;
493
+ runtimeSourceRoot?: string;
494
+ observation: ForgeActionableFailureObservation;
495
+ now?: () => number;
496
+ }): ForgeIncidentRepairRegistration {
497
+ const classification = classifyForgeActionableFailureForRepair(input.observation);
498
+ if (!classification.eligible || !classification.fingerprint || !classification.rootCode) {
499
+ return { eligible: false, recurrent: false, occurrenceCount: 0, reason: classification.reason };
500
+ }
501
+
502
+ const runtimeSourceRoot = input.runtimeSourceRoot ?? activeRuntimeSourceRoot(input.controllerHome);
503
+ const repairRepository = resolveRuntimeSourceRepairRepository(input.controllerHome, runtimeSourceRoot);
504
+ if (!repairRepository) return {
505
+ eligible: true, recurrent: false, occurrenceCount: 0,
506
+ fingerprint: classification.fingerprint, rootCode: classification.rootCode,
507
+ reason: 'runtime source authority could not be mapped unambiguously to one registered repository',
508
+ };
509
+
510
+ const nowMs = input.now?.() ?? Date.now();
511
+ const observedAt = input.observation.at?.trim() || new Date(nowMs).toISOString();
512
+ const existing = readActionableFailureEvents(input.controllerHome, repairRepository.repoId);
513
+ if (!existing.some((event) => event.data?.observationId === input.observation.observationId)) {
514
+ appendRuntimeEvent(input.controllerHome, {
515
+ repoId: repairRepository.repoId,
516
+ entityType: 'portfolio',
517
+ entityId: `forge-failure:${classification.fingerprint}`,
518
+ eventType: ACTIONABLE_FAILURE_EVENT,
519
+ requestId: `forge-actionable-failure:${input.observation.observationId}`,
520
+ revision: 1,
521
+ data: {
522
+ observationId: input.observation.observationId,
523
+ source: input.observation.source,
524
+ rootCode: classification.rootCode,
525
+ message: input.observation.message.slice(0, 2_000),
526
+ observedAt,
527
+ ...(input.observation.repoId ? { affectedRepoId: input.observation.repoId } : {}),
528
+ ...(input.observation.workId ? { workId: input.observation.workId } : {}),
529
+ },
530
+ });
531
+ }
532
+
533
+ const occurrences = recentActionableRootEvents(input.controllerHome, repairRepository.repoId, classification, nowMs);
534
+ return registerRecurringForgeRepair({
535
+ controllerHome: input.controllerHome,
536
+ runtimeSourceRoot,
537
+ repairRepository,
538
+ classification,
539
+ occurrenceCount: occurrences.length,
540
+ evidence: occurrences.map((event, index) => actionableEvidence(event, classification.rootCode!, index + 1)),
541
+ });
542
+ }
543
+
544
+ export function maybeRegisterFailedReleaseSessionRepairs(input: {
545
+ controllerHome: string;
546
+ runtimeSourceRoot?: string;
547
+ now?: () => number;
548
+ }): ForgeIncidentRepairRegistration[] {
549
+ return listReleaseSessions(input.controllerHome, { maxEntries: 128 }).sessions
550
+ .filter((session) => session.phase === 'failed')
551
+ .slice(-32)
552
+ .map((session) => {
553
+ const lastReceipt = session.receipts.at(-1);
554
+ const message = lastReceipt?.summary?.trim()
555
+ || `ReleaseSession ${session.sessionId} entered failed phase without a diagnostic receipt.`;
556
+ return maybeRegisterForgeActionableFailureRepair({
557
+ controllerHome: input.controllerHome,
558
+ runtimeSourceRoot: input.runtimeSourceRoot,
559
+ now: input.now,
560
+ observation: {
561
+ observationId: `release:${session.sessionId}:r${session.revision}`,
562
+ source: 'release',
563
+ code: deriveForgeActionableFailureCode(
564
+ `RELEASE_SESSION_${(lastReceipt?.kind ?? 'UNKNOWN').toUpperCase()}_FAILED`,
565
+ message,
566
+ ),
567
+ message,
568
+ at: session.updatedAt,
569
+ repoId: session.candidateRelease?.sourceRepositoryId,
570
+ },
571
+ });
572
+ });
573
+ }