@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
@@ -17,6 +17,7 @@ import { operationReceiptMatchesJobOwnership, readOperationReceipt } from '../..
17
17
  import { releaseExecutionLeases, renewExecutionLeases } from '../../resources/leases/store';
18
18
  import { isProcessAlive, terminateProcessTree, terminateProcessTreeSync, type ProcessTreeTerminationResult } from '../../shared/process-tree';
19
19
  import { settleScheduledExecution } from '../../../../packages/kernel/scheduler/api/index';
20
+ import { isRuntimeWriteFenceError } from '../../root/write-fence';
20
21
 
21
22
  const WORKER_HEARTBEAT_STALE_MS = 45_000;
22
23
 
@@ -64,7 +65,7 @@ function recordIsolatedReconciliationFailure(job: ExecutionJob, error: unknown):
64
65
  // Losing the canonical write fence is a Runtime-wide invariant violation,
65
66
  // not corrupt state owned by one historical Job. Preserve the Scheduler's
66
67
  // fatal path so Runtime Root can stop the complete Runtime.
67
- if (message.startsWith('WRITER_FENCED:')) throw error;
68
+ if (isRuntimeWriteFenceError(error)) throw error;
68
69
  process.stderr.write(`${JSON.stringify({
69
70
  event: 'forge_scheduler_execution_job_reconciliation_isolated',
70
71
  repoId: job.repoId,
@@ -23,16 +23,15 @@ import { reconcileTerminalWorkCleanups } from '../execution/work-terminal-cleanu
23
23
  import { gcTerminalProcesses } from '../../execution/process-runtime/gc';
24
24
  import { reconcilePendingWorkValidations } from '../execution/work-validation-reconciler';
25
25
  import { reconcilePendingEditValidations } from '../execution/edit-validation-coordinator';
26
- import { schedulerDispatchAllowed } from '../facade/work-admission-policy';
27
26
  import {
28
- runSchedulerControllerRoundRecovery,
29
27
  runSchedulerPeriodicCleanup,
30
28
  runSchedulerValidationReconciliation,
31
29
  } from './maintenance';
32
30
  import { planSchedulerSourceSampling } from './source-scan';
31
+ import { runSchedulerAutonomousContinuationReconciliation } from './autonomous-continuation';
33
32
  import {
34
33
  runSchedulerDurableAdmission,
35
- schedulerDurableAdmissionRequiresPolicy,
34
+ SCHEDULE_TICK_INTERVAL_MS,
36
35
  } from './durable-admission';
37
36
  import { sampleRepositoryGitStatusForRepositories } from '../../projections/git-status-sampler';
38
37
  import { selectExecutionJobDispatchRepositories } from '../dispatch-priority';
@@ -98,7 +97,43 @@ export type { SchedulerWorkerCommand, SchedulerWorkerLaunchDescriptor } from './
98
97
  export { selectSchedulerSourceScanRepositories } from './source-scan';
99
98
 
100
99
  const DARWIN_MEMORY_SAMPLE_TTL_MS = 5_000;
100
+ export const SCHEDULER_RECONCILIATION_INTERVAL_MS = 5_000;
101
101
  const RUNTIME_CLEANUP_INTERVAL_MS = Math.max(30_000, Number(process.env.FORGE_RUNTIME_CLEANUP_INTERVAL_MS ?? 60_000));
102
+
103
+ function remainingRecurringDeadlineMs(nowMs: number, lastRanAt: number, intervalMs: number): number {
104
+ if (lastRanAt <= 0) return intervalMs;
105
+ const elapsed = Math.max(0, nowMs - lastRanAt);
106
+ return elapsed < intervalMs ? intervalMs - elapsed : intervalMs;
107
+ }
108
+
109
+ export function schedulerIdleWaitDelayMs(input: {
110
+ nowMs: number;
111
+ lastScheduleTickAt: number;
112
+ }): number {
113
+ // Idle execution is event-driven. ExecutionJob/lease/policy mutations and
114
+ // check Process terminal persistence wake the scheduler immediately through
115
+ // the existing notification revision. The 30-second schedule cadence is the
116
+ // bounded idle lost-event safety deadline.
117
+ return remainingRecurringDeadlineMs(
118
+ input.nowMs,
119
+ input.lastScheduleTickAt,
120
+ SCHEDULE_TICK_INTERVAL_MS,
121
+ );
122
+ }
123
+
124
+ export function schedulerActiveWaitDelayMs(input: {
125
+ nowMs: number;
126
+ lastReconcileAt: number;
127
+ }): number {
128
+ // Active execution uses the same canonical wake notifications as idle
129
+ // execution. A full scheduler tick is only the lost-event safety net, bounded
130
+ // by the existing reconciliation cadence instead of the legacy 250ms poll.
131
+ return remainingRecurringDeadlineMs(
132
+ input.nowMs,
133
+ input.lastReconcileAt,
134
+ SCHEDULER_RECONCILIATION_INTERVAL_MS,
135
+ );
136
+ }
102
137
  const DARWIN_RECLAIMABLE_PAGE_LABELS = new Set([
103
138
  'Pages free',
104
139
  'Pages inactive',
@@ -510,7 +545,7 @@ export class GlobalScheduler {
510
545
  this.lastTickAt = this.lastHeartbeatAt;
511
546
  this.persistState();
512
547
  const repositories = this.repositoryList(this.controllerHome).filter((repo) => repo.enabled && !repo.removedAt);
513
- let periodicCleanupRan = false;
548
+ let reconciliationRan = false;
514
549
  if (now - this.lastCleanupAt >= RUNTIME_CLEANUP_INTERVAL_MS) {
515
550
  // Advance the interval before cleanup so a failing pass cannot create a
516
551
  // tight retry loop on every scheduler tick. Canonical Runtime launches the
@@ -531,9 +566,8 @@ export class GlobalScheduler {
531
566
  processGc: this.processGc,
532
567
  });
533
568
  }
534
- periodicCleanupRan = true;
535
569
  }
536
- if (now - this.lastReconcile >= 5_000) {
570
+ if (now - this.lastReconcile >= SCHEDULER_RECONCILIATION_INTERVAL_MS) {
537
571
  await reconcileExecutionJobsAsync(this.controllerHome);
538
572
  for (const repository of repositories) {
539
573
  try {
@@ -551,6 +585,7 @@ export class GlobalScheduler {
551
585
  });
552
586
  this.lastReconcile = now;
553
587
  this.lastReconcileAt = new Date(now).toISOString();
588
+ reconciliationRan = true;
554
589
  }
555
590
  const activeJobSnapshot = listActiveExecutionJobs(this.controllerHome);
556
591
  const activeSourceRepoIds = new Set(activeJobSnapshot.map((job) => job.repoId));
@@ -587,34 +622,17 @@ export class GlobalScheduler {
587
622
  .map((repository) => [repository.repoId, repository] as const),
588
623
  ).values());
589
624
  this.sourceScansAvoided += sourceSampling.avoidedRepositoryCount;
590
- // Phase 0 reuses one durable Work admission policy. Exclusive-Work mode stops
591
- // ordinary schedule/workflow advancement and Worker dispatch while preserving
592
- // cleanup and projections. Convergence mode remains dispatchable because new
593
- // Work creation is independently fenced at the Work contract authority, so
594
- // existing Work continuations can keep draining the backlog.
595
- const admissionPolicyRequired = periodicCleanupRan || schedulerDurableAdmissionRequiresPolicy({
596
- activeJobs: activeJobSnapshot,
597
- nowMs: now,
598
- lastScheduleTickAt: this.lastScheduleTick,
599
- });
600
- if (admissionPolicyRequired && !schedulerDispatchAllowed(this.controllerHome)) {
601
- refreshSchedulerRepositoryProjections({
602
- controllerHome: this.controllerHome,
603
- repositories,
604
- sourceScanRepositories: projectionMaintenanceRepositories,
605
- projectionRefreshRepoIds: [],
606
- controllerPid: this.controllerPid,
607
- });
608
- this.lastHeartbeatAt = new Date().toISOString();
609
- this.persistState(true);
610
- return { activeJobs: activeJobSnapshot.length };
611
- }
612
- if (periodicCleanupRan) {
613
- await runSchedulerControllerRoundRecovery({
625
+ // Migration-era global Work admission gates are retired. Scheduler dispatch
626
+ // is constrained by durable admission, placement and concrete resource authority.
627
+ if (reconciliationRan) {
628
+ const liveness = await runSchedulerAutonomousContinuationReconciliation({
614
629
  controllerHome: this.controllerHome,
615
630
  nowMs: now,
616
631
  repositories,
617
632
  });
633
+ if (liveness.failed > 0) {
634
+ console.error('[forge liveness] controller progression reconciliation reported ' + liveness.failed + ' failure(s)');
635
+ }
618
636
  }
619
637
  const durableAdmission = await runSchedulerDurableAdmission({
620
638
  controllerHome: this.controllerHome,
@@ -731,30 +749,38 @@ export class GlobalScheduler {
731
749
  this.persistState(true);
732
750
  }, this.config.heartbeatIntervalMs);
733
751
  heartbeatTimer.unref?.();
734
- let idleStreak = 0;
735
752
  let activeJobs = 0;
736
753
  try {
737
754
  while (!signal?.aborted) {
755
+ let tickFailed = false;
738
756
  try {
739
757
  activeJobs = (await this.tick()).activeJobs;
740
- idleStreak = activeJobs === 0 ? idleStreak + 1 : 0;
741
758
  } catch (error) {
742
759
  if (this.fatalOnTickError) throw error;
743
- idleStreak = 0;
760
+ tickFailed = true;
744
761
  this.lastHeartbeatAt = new Date().toISOString();
745
762
  this.lastTickAt = this.lastHeartbeatAt;
746
763
  this.persistState(true);
747
764
  console.error('[forge scheduler] tick failed:', error);
748
765
  }
749
- const delayMs = idleStreak > 0
750
- ? Math.min(
751
- this.config.idleBackoffMaxMs,
752
- this.config.pollIntervalMs * (2 ** Math.min(idleStreak, 6)),
753
- )
754
- : this.config.pollIntervalMs;
766
+ const now = Date.now();
767
+ const delayMs = tickFailed
768
+ ? this.config.pollIntervalMs
769
+ : activeJobs > 0
770
+ ? schedulerActiveWaitDelayMs({
771
+ nowMs: now,
772
+ lastReconcileAt: this.lastReconcile,
773
+ })
774
+ : schedulerIdleWaitDelayMs({
775
+ nowMs: now,
776
+ lastScheduleTickAt: this.lastScheduleTick,
777
+ });
755
778
  const wakeRevision = readSchedulerWakeSignal(this.controllerHome).revision;
756
779
  const waitResult = await waitForSchedulerWakeSignal(this.controllerHome, wakeRevision, delayMs, signal, {
757
- fallbackPollMs: activeJobs > 0 ? 250 : Math.min(1_000, Math.max(500, delayMs)),
780
+ // fs.watch is authoritative for ordinary wakeups. Polling is only a
781
+ // lost-event safety net, so active execution must not regress to a
782
+ // 250ms JSON-read loop after removing the full-tick poll.
783
+ fallbackPollMs: Math.min(5_000, Math.max(1_000, delayMs)),
758
784
  });
759
785
  if (waitResult === 'aborted') break;
760
786
  }
@@ -35,6 +35,35 @@ export function touchSchedulerWakeSignal(controllerHome: string, reason: string)
35
35
  return next;
36
36
  }
37
37
 
38
+ export function isSchedulerWakeSignalEvent(filename: string | Buffer | null | undefined): boolean {
39
+ // The wake file shares a directory with scheduler health/state persistence.
40
+ // Atomic writes to those sibling files can emit multiple directory events.
41
+ // Node/macOS reports the final filename, while Bun/macOS may report only the
42
+ // wake file's atomic temporary name; both belong to the same wake authority.
43
+ // Platforms that omit the filename remain conservative and re-check revision.
44
+ if (filename == null) return true;
45
+ const observed = filename.toString();
46
+ return observed === 'wake-signal.json'
47
+ || (observed.startsWith('wake-signal.json.') && observed.endsWith('.tmp'));
48
+ }
49
+
50
+ export function shouldWakeForSchedulerEvent(
51
+ filename: string | Buffer | null | undefined,
52
+ expectedRevision: number,
53
+ observedRevision: number,
54
+ ): boolean {
55
+ if (!isSchedulerWakeSignalEvent(filename)) return false;
56
+ // A null filename is an ambiguous directory event on some Bun/macOS
57
+ // combinations. Only treat it as a wake when the durable revision changed;
58
+ // otherwise the Scheduler's own state.json write would wake it immediately
59
+ // and turn the idle loop into a CPU-consuming self-trigger cycle.
60
+ if (filename == null) return observedRevision !== expectedRevision;
61
+ // A named wake-file event is authoritative even when the revision is equal:
62
+ // concurrent writers may coalesce onto one revision, while the lifecycle
63
+ // truth remains in the canonical stores.
64
+ return true;
65
+ }
66
+
38
67
  export async function waitForSchedulerWakeSignal(
39
68
  controllerHome: string,
40
69
  expectedRevision: number,
@@ -71,7 +100,18 @@ export async function waitForSchedulerWakeSignal(
71
100
 
72
101
  signal?.addEventListener('abort', onAbort, { once: true });
73
102
  try {
74
- watcher = watch(dirname(path), maybeWake);
103
+ watcher = watch(dirname(path), (_eventType, filename) => {
104
+ if (!shouldWakeForSchedulerEvent(
105
+ filename,
106
+ expectedRevision,
107
+ readSchedulerWakeSignal(controllerHome).revision,
108
+ )) return;
109
+ // A named canonical wake-file event is itself the notification. Do not
110
+ // make event delivery depend on observing a strictly newer JSON
111
+ // revision: concurrent writers may legitimately coalesce onto one
112
+ // revision, while lifecycle truth is read from canonical stores.
113
+ finish('wakeup');
114
+ });
75
115
  watcher.on?.('error', maybeWake);
76
116
  } catch {
77
117
  watcher = undefined;
@@ -79,7 +119,7 @@ export async function waitForSchedulerWakeSignal(
79
119
  // fs.watch is the primary wake path. Polling is only a lost-event safety
80
120
  // net, so keep it coarse enough that an idle scheduler does not perform a
81
121
  // read/stat storm while still bounding cross-platform wake loss.
82
- const fallbackPollMs = Math.min(2_000, Math.max(250, Math.trunc(options.fallbackPollMs ?? 1_000)));
122
+ const fallbackPollMs = Math.min(10_000, Math.max(250, Math.trunc(options.fallbackPollMs ?? 1_000)));
83
123
  poller = setInterval(maybeWake, fallbackPollMs);
84
124
  poller.unref?.();
85
125
  timer = setTimeout(() => finish('timeout'), Math.max(0, timeoutMs));
@@ -6,6 +6,7 @@ import {
6
6
  writeFileSync,
7
7
  } from 'fs';
8
8
  import { dirname, join, resolve } from 'path';
9
+ import { isWorkspaceScopeKey, workspaceScopeRoot } from '../../../cli/repositories/controller-home';
9
10
 
10
11
  export const ACCESS_MODES = ['request', 'full_access'] as const;
11
12
  export type AccessMode = (typeof ACCESS_MODES)[number];
@@ -75,7 +76,23 @@ export function normalizeAccessMode(value: unknown, fallback: AccessMode = 'full
75
76
  }
76
77
 
77
78
  export function repositoryAccessPolicyPath(controllerHome: string, repoId: string): string {
78
- return join(resolve(controllerHome), 'repositories', repoId, 'controller', 'access-policy.json');
79
+ // A workspace scope keeps its own access policy in the workspace partition
80
+ // instead of a synthetic repository partition. Repository/controller scopes
81
+ // keep their established location.
82
+ return isWorkspaceScopeKey(repoId)
83
+ ? join(workspaceScopeRoot(controllerHome, repoId), 'controller', 'access-policy.json')
84
+ : join(resolve(controllerHome), 'repositories', repoId, 'controller', 'access-policy.json');
85
+ }
86
+
87
+ /**
88
+ * Bounded migration read: a workspace policy written to the legacy repository
89
+ * location still applies until it is rewritten in the workspace partition.
90
+ */
91
+ function readableAccessPolicyPath(controllerHome: string, repoId: string): string {
92
+ const current = repositoryAccessPolicyPath(controllerHome, repoId);
93
+ if (existsSync(current) || !isWorkspaceScopeKey(repoId)) return current;
94
+ const legacy = join(resolve(controllerHome), 'repositories', repoId, 'controller', 'access-policy.json');
95
+ return existsSync(legacy) ? legacy : current;
79
96
  }
80
97
 
81
98
  function defaultPolicy(repoId: string): RepositoryAccessPolicy {
@@ -90,7 +107,7 @@ function defaultPolicy(repoId: string): RepositoryAccessPolicy {
90
107
  }
91
108
 
92
109
  export function readRepositoryAccessPolicy(controllerHome: string, repoId: string): RepositoryAccessPolicy {
93
- const path = repositoryAccessPolicyPath(controllerHome, repoId);
110
+ const path = readableAccessPolicyPath(controllerHome, repoId);
94
111
  if (!existsSync(path)) return defaultPolicy(repoId);
95
112
  try {
96
113
  const parsed = JSON.parse(readFileSync(path, 'utf-8')) as Partial<RepositoryAccessPolicy>;
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from 'crypto';
2
2
  import { existsSync, mkdirSync } from 'fs';
3
3
  import { join, relative, resolve } from 'path';
4
- import { repositoryControllerRoot } from '../../../cli/repositories/controller-home';
4
+ import { isWorkspaceScopeKey, repositoryControllerRoot, scopedOperationRoot } from '../../../cli/repositories/controller-home';
5
5
  import { readJsonFile, sanitizeFileComponent, writeJsonAtomic } from '../../shared/json-files';
6
6
  import type { AccessMode } from './access-policy';
7
7
 
@@ -81,7 +81,7 @@ export interface AuthorizationContext {
81
81
  }
82
82
 
83
83
  function requestRoot(controllerHome: string, repoId: string): string {
84
- const root = join(repositoryControllerRoot(controllerHome, repoId), 'controller', 'approval-requests');
84
+ const root = join(scopedOperationRoot(controllerHome, repoId), 'controller', 'approval-requests');
85
85
  mkdirSync(root, { recursive: true, mode: 0o700 });
86
86
  return root;
87
87
  }
@@ -90,6 +90,23 @@ function requestPath(controllerHome: string, repoId: string, requestId: string):
90
90
  return join(requestRoot(controllerHome, repoId), `${sanitizeFileComponent(requestId)}.json`);
91
91
  }
92
92
 
93
+ /**
94
+ * Bounded migration read: an approval issued for a workspace scope before the
95
+ * workspace partition existed is still resolvable instead of failing closed as
96
+ * a missing request.
97
+ */
98
+ function readableRequestPath(controllerHome: string, repoId: string, requestId: string): string {
99
+ const current = requestPath(controllerHome, repoId, requestId);
100
+ if (existsSync(current) || !isWorkspaceScopeKey(repoId)) return current;
101
+ const legacy = join(
102
+ repositoryControllerRoot(controllerHome, repoId),
103
+ 'controller',
104
+ 'approval-requests',
105
+ `${sanitizeFileComponent(requestId)}.json`,
106
+ );
107
+ return existsSync(legacy) ? legacy : current;
108
+ }
109
+
93
110
  function scopeMatches(context: AuthorizationContext): boolean {
94
111
  if (context.currentRepositoryId && context.repositoryId !== context.currentRepositoryId) return false;
95
112
  if (context.workId && context.boundWorkId && context.workId !== context.boundWorkId) return false;
@@ -163,7 +180,7 @@ export function createGoalDelegation(input: Omit<GoalDelegation, 'schemaVersion'
163
180
  }
164
181
 
165
182
  export function readAuthorizationRequest(controllerHome: string, repositoryId: string, approvalRequestId: string): AuthorizationRequestRecord {
166
- const path = requestPath(controllerHome, repositoryId, approvalRequestId);
183
+ const path = readableRequestPath(controllerHome, repositoryId, approvalRequestId);
167
184
  if (!existsSync(path)) throw new Error(`APPROVAL_REQUEST_NOT_FOUND: ${approvalRequestId}`);
168
185
  const request = readJsonFile<AuthorizationRequestRecord>(path);
169
186
  if (request.repositoryId !== repositoryId || request.approvalRequestId !== approvalRequestId) throw new Error('APPROVAL_REQUEST_IDENTITY_MISMATCH');