@kbediako/codex-orchestrator 0.1.38 → 0.2.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 (311) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/README.md +46 -317
  3. package/bin/codex-orchestrator.js +161 -0
  4. package/codex.orchestrator.json +149 -13
  5. package/dist/bin/codex-orchestrator.js +797 -1154
  6. package/dist/orchestrator/src/cli/adapters/CommandBuilder.js +50 -0
  7. package/dist/orchestrator/src/cli/adapters/CommandPlanner.js +22 -4
  8. package/dist/orchestrator/src/cli/adapters/CommandReviewer.js +3 -3
  9. package/dist/orchestrator/src/cli/adapters/CommandTester.js +2 -2
  10. package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +295 -11
  11. package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +402 -0
  12. package/dist/orchestrator/src/cli/coStatusCliShell.js +451 -0
  13. package/dist/orchestrator/src/cli/coStatusOperatorAutopilotCliShell.js +120 -0
  14. package/dist/orchestrator/src/cli/codexCliShell.js +119 -0
  15. package/dist/orchestrator/src/cli/codexDefaultsSetup.js +265 -36
  16. package/dist/orchestrator/src/cli/config/delegationConfig.js +317 -5
  17. package/dist/orchestrator/src/cli/config/repoConfigPolicy.js +2 -3
  18. package/dist/orchestrator/src/cli/config/userConfig.js +28 -13
  19. package/dist/orchestrator/src/cli/control/authenticatedControlRouteGate.js +69 -0
  20. package/dist/orchestrator/src/cli/control/authenticatedRouteComposition.js +267 -0
  21. package/dist/orchestrator/src/cli/control/authenticatedRouteController.js +5 -0
  22. package/dist/orchestrator/src/cli/control/authenticatedRouteDispatcher.js +41 -0
  23. package/dist/orchestrator/src/cli/control/compatibilityIssuePresenter.js +1035 -0
  24. package/dist/orchestrator/src/cli/control/confirmationApproveController.js +62 -0
  25. package/dist/orchestrator/src/cli/control/confirmationCreateController.js +69 -0
  26. package/dist/orchestrator/src/cli/control/confirmationIssueConsumeController.js +43 -0
  27. package/dist/orchestrator/src/cli/control/confirmationListController.js +22 -0
  28. package/dist/orchestrator/src/cli/control/confirmationValidateController.js +58 -0
  29. package/dist/orchestrator/src/cli/control/confirmations.js +25 -3
  30. package/dist/orchestrator/src/cli/control/controlActionCancelConfirmation.js +65 -0
  31. package/dist/orchestrator/src/cli/control/controlActionController.js +77 -0
  32. package/dist/orchestrator/src/cli/control/controlActionControllerSequencing.js +161 -0
  33. package/dist/orchestrator/src/cli/control/controlActionExecution.js +142 -0
  34. package/dist/orchestrator/src/cli/control/controlActionFinalization.js +43 -0
  35. package/dist/orchestrator/src/cli/control/controlActionOutcome.js +60 -0
  36. package/dist/orchestrator/src/cli/control/controlActionPreflight.js +476 -0
  37. package/dist/orchestrator/src/cli/control/controlAuthenticatedRouteHandoff.js +57 -0
  38. package/dist/orchestrator/src/cli/control/controlBootstrapAssembly.js +39 -0
  39. package/dist/orchestrator/src/cli/control/controlBootstrapMetadataPersistence.js +16 -0
  40. package/dist/orchestrator/src/cli/control/controlEventTransport.js +49 -0
  41. package/dist/orchestrator/src/cli/control/controlExpiryLifecycle.js +102 -0
  42. package/dist/orchestrator/src/cli/control/controlHostOwnership.js +480 -0
  43. package/dist/orchestrator/src/cli/control/controlHostSupervision.js +630 -0
  44. package/dist/orchestrator/src/cli/control/controlOversightFacade.js +8 -0
  45. package/dist/orchestrator/src/cli/control/controlOversightReadContract.js +1 -0
  46. package/dist/orchestrator/src/cli/control/controlOversightReadService.js +16 -0
  47. package/dist/orchestrator/src/cli/control/controlOversightUpdateContract.js +1 -0
  48. package/dist/orchestrator/src/cli/control/controlPersistenceFiles.js +6 -0
  49. package/dist/orchestrator/src/cli/control/controlQuestionChildResolution.js +18 -0
  50. package/dist/orchestrator/src/cli/control/controlRequestContext.js +42 -0
  51. package/dist/orchestrator/src/cli/control/controlRequestController.js +9 -0
  52. package/dist/orchestrator/src/cli/control/controlRequestPredispatch.js +17 -0
  53. package/dist/orchestrator/src/cli/control/controlRequestRouteDispatch.js +44 -0
  54. package/dist/orchestrator/src/cli/control/controlRuntime.js +1003 -0
  55. package/dist/orchestrator/src/cli/control/controlServer.js +23 -1456
  56. package/dist/orchestrator/src/cli/control/controlServerAuditAndErrorHelpers.js +115 -0
  57. package/dist/orchestrator/src/cli/control/controlServerAuthenticatedRouteBranch.js +29 -0
  58. package/dist/orchestrator/src/cli/control/controlServerBootstrapLifecycle.js +30 -0
  59. package/dist/orchestrator/src/cli/control/controlServerBootstrapStartSequence.js +21 -0
  60. package/dist/orchestrator/src/cli/control/controlServerOwnedRuntimeLifecycle.js +67 -0
  61. package/dist/orchestrator/src/cli/control/controlServerPublicLifecycle.js +756 -0
  62. package/dist/orchestrator/src/cli/control/controlServerPublicRouteHelpers.js +86 -0
  63. package/dist/orchestrator/src/cli/control/controlServerReadyInstanceLifecycle.js +25 -0
  64. package/dist/orchestrator/src/cli/control/controlServerReadyInstanceStartup.js +18 -0
  65. package/dist/orchestrator/src/cli/control/controlServerRequestBodyHelpers.js +37 -0
  66. package/dist/orchestrator/src/cli/control/controlServerRequestShell.js +40 -0
  67. package/dist/orchestrator/src/cli/control/controlServerRequestShellBinding.js +17 -0
  68. package/dist/orchestrator/src/cli/control/controlServerSeedLoading.js +27 -0
  69. package/dist/orchestrator/src/cli/control/controlServerSeededRuntimeAssembly.js +186 -0
  70. package/dist/orchestrator/src/cli/control/controlServerStartupInputPreparation.js +31 -0
  71. package/dist/orchestrator/src/cli/control/controlServerStartupSequence.js +49 -0
  72. package/dist/orchestrator/src/cli/control/controlState.js +233 -2
  73. package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +1904 -0
  74. package/dist/orchestrator/src/cli/control/controlTelegramBridgeBootstrapLifecycle.js +22 -0
  75. package/dist/orchestrator/src/cli/control/controlTelegramBridgeLifecycle.js +67 -0
  76. package/dist/orchestrator/src/cli/control/controlTelegramBridgeOversightFacadeFactory.js +8 -0
  77. package/dist/orchestrator/src/cli/control/controlTelegramCommandController.js +49 -0
  78. package/dist/orchestrator/src/cli/control/controlTelegramDispatchRead.js +40 -0
  79. package/dist/orchestrator/src/cli/control/controlTelegramPollingController.js +89 -0
  80. package/dist/orchestrator/src/cli/control/controlTelegramProjectionNotificationController.js +29 -0
  81. package/dist/orchestrator/src/cli/control/controlTelegramPushState.js +63 -0
  82. package/dist/orchestrator/src/cli/control/controlTelegramQuestionRead.js +13 -0
  83. package/dist/orchestrator/src/cli/control/controlTelegramReadController.js +216 -0
  84. package/dist/orchestrator/src/cli/control/controlTelegramUpdateHandler.js +63 -0
  85. package/dist/orchestrator/src/cli/control/controlWatcher.js +73 -5
  86. package/dist/orchestrator/src/cli/control/delegationRegisterController.js +35 -0
  87. package/dist/orchestrator/src/cli/control/dynamicToolBridgePolicy.js +139 -0
  88. package/dist/orchestrator/src/cli/control/eventsSseController.js +12 -0
  89. package/dist/orchestrator/src/cli/control/linearBudgetState.js +1789 -0
  90. package/dist/orchestrator/src/cli/control/linearDispatchSource.js +1137 -0
  91. package/dist/orchestrator/src/cli/control/linearGraphqlClient.js +150 -0
  92. package/dist/orchestrator/src/cli/control/linearRateLimit.js +102 -0
  93. package/dist/orchestrator/src/cli/control/linearWebhookController.js +499 -0
  94. package/dist/orchestrator/src/cli/control/liveLinearAdvisoryRuntime.js +70 -0
  95. package/dist/orchestrator/src/cli/control/observabilityApiController.js +173 -0
  96. package/dist/orchestrator/src/cli/control/observabilityReadModel.js +500 -0
  97. package/dist/orchestrator/src/cli/control/observabilitySurface.js +284 -0
  98. package/dist/orchestrator/src/cli/control/observabilityUpdateNotifier.js +22 -0
  99. package/dist/orchestrator/src/cli/control/operatorDashboardPresenter.js +252 -0
  100. package/dist/orchestrator/src/cli/control/providerAgentCapacity.js +70 -0
  101. package/dist/orchestrator/src/cli/control/providerControlHostFreshnessGauge.js +1068 -0
  102. package/dist/orchestrator/src/cli/control/providerIntakeState.js +473 -0
  103. package/dist/orchestrator/src/cli/control/providerIssueHandoff.js +6811 -0
  104. package/dist/orchestrator/src/cli/control/providerIssueObservability.js +1348 -0
  105. package/dist/orchestrator/src/cli/control/providerIssueRetryQueue.js +84 -0
  106. package/dist/orchestrator/src/cli/control/providerLinearRuntimeProof.js +588 -0
  107. package/dist/orchestrator/src/cli/control/providerLinearScreenshotProof.js +473 -0
  108. package/dist/orchestrator/src/cli/control/providerLinearWorkerTruth.js +383 -0
  109. package/dist/orchestrator/src/cli/control/providerLinearWorkflowAudit.js +254 -0
  110. package/dist/orchestrator/src/cli/control/providerLinearWorkflowFacade.js +5573 -0
  111. package/dist/orchestrator/src/cli/control/providerLinearWorkflowStates.js +115 -0
  112. package/dist/orchestrator/src/cli/control/providerMergeCloseout.js +1868 -0
  113. package/dist/orchestrator/src/cli/control/providerOperatorAutopilot.js +1580 -0
  114. package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLifecycle.js +154 -0
  115. package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLocalRolloutExecution.js +1006 -0
  116. package/dist/orchestrator/src/cli/control/providerPollingHealth.js +435 -0
  117. package/dist/orchestrator/src/cli/control/providerTerminalCleanup.js +516 -0
  118. package/dist/orchestrator/src/cli/control/providerWorkerHosts.js +191 -0
  119. package/dist/orchestrator/src/cli/control/providerWorkflowConfigStore.js +515 -0
  120. package/dist/orchestrator/src/cli/control/questionChildResolutionAdapter.js +361 -0
  121. package/dist/orchestrator/src/cli/control/questionQueueController.js +181 -0
  122. package/dist/orchestrator/src/cli/control/questionReadRetryDeduplication.js +9 -0
  123. package/dist/orchestrator/src/cli/control/questionReadSequence.js +10 -0
  124. package/dist/orchestrator/src/cli/control/securityViolationController.js +27 -0
  125. package/dist/orchestrator/src/cli/control/selectedRunProjection.js +1885 -0
  126. package/dist/orchestrator/src/cli/control/telegramOversightApiClient.js +48 -0
  127. package/dist/orchestrator/src/cli/control/telegramOversightBridge.js +180 -0
  128. package/dist/orchestrator/src/cli/control/telegramOversightBridgeProjectionDeliveryQueue.js +25 -0
  129. package/dist/orchestrator/src/cli/control/telegramOversightBridgeRuntimeLifecycle.js +45 -0
  130. package/dist/orchestrator/src/cli/control/telegramOversightBridgeStateStore.js +77 -0
  131. package/dist/orchestrator/src/cli/control/telegramOversightControlActionApiClient.js +45 -0
  132. package/dist/orchestrator/src/cli/control/trackerDispatchPilot.js +439 -0
  133. package/dist/orchestrator/src/cli/control/uiDataController.js +34 -0
  134. package/dist/orchestrator/src/cli/control/uiSessionController.js +100 -0
  135. package/dist/orchestrator/src/cli/controlHostCliShell.js +860 -0
  136. package/dist/orchestrator/src/cli/controlHostFreshnessGaugeCliShell.js +129 -0
  137. package/dist/orchestrator/src/cli/controlHostSupervisionCliShell.js +2127 -0
  138. package/dist/orchestrator/src/cli/delegationCliShell.js +62 -0
  139. package/dist/orchestrator/src/cli/delegationServer.js +567 -678
  140. package/dist/orchestrator/src/cli/delegationServerCliShell.js +52 -0
  141. package/dist/orchestrator/src/cli/delegationServerQuestionFlowShell.js +228 -0
  142. package/dist/orchestrator/src/cli/delegationServerToolDispatchShell.js +411 -0
  143. package/dist/orchestrator/src/cli/delegationServerTransport.js +274 -0
  144. package/dist/orchestrator/src/cli/delegationSetup.js +51 -171
  145. package/dist/orchestrator/src/cli/devtoolsCliShell.js +34 -0
  146. package/dist/orchestrator/src/cli/doctor.js +678 -164
  147. package/dist/orchestrator/src/cli/doctorCliRequestShell.js +72 -0
  148. package/dist/orchestrator/src/cli/doctorCliShell.js +138 -0
  149. package/dist/orchestrator/src/cli/doctorUsage.js +119 -15
  150. package/dist/orchestrator/src/cli/exec/experience.js +16 -2
  151. package/dist/orchestrator/src/cli/exec/summary.js +3 -0
  152. package/dist/orchestrator/src/cli/execCliShell.js +51 -0
  153. package/dist/orchestrator/src/cli/flowCliRequestShell.js +44 -0
  154. package/dist/orchestrator/src/cli/flowCliShell.js +239 -0
  155. package/dist/orchestrator/src/cli/frontendTestCliRequestShell.js +80 -0
  156. package/dist/orchestrator/src/cli/frontendTestCliShell.js +41 -0
  157. package/dist/orchestrator/src/cli/init.js +95 -1
  158. package/dist/orchestrator/src/cli/initCliShell.js +50 -0
  159. package/dist/orchestrator/src/cli/linearCliShell.js +1200 -0
  160. package/dist/orchestrator/src/cli/mcpEnableCliShell.js +132 -0
  161. package/dist/orchestrator/src/cli/metrics/metricsAggregator.js +3 -2
  162. package/dist/orchestrator/src/cli/metrics/metricsRecorder.js +56 -0
  163. package/dist/orchestrator/src/cli/orchestrator.js +66 -1376
  164. package/dist/orchestrator/src/cli/planCliShell.js +19 -0
  165. package/dist/orchestrator/src/cli/prCliShell.js +41 -0
  166. package/dist/orchestrator/src/cli/providerLinearChildLanePhaseContract.js +204 -0
  167. package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +1835 -0
  168. package/dist/orchestrator/src/cli/providerLinearChildLaneShell.js +2420 -0
  169. package/dist/orchestrator/src/cli/providerLinearChildStreamShell.js +385 -0
  170. package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +6834 -0
  171. package/dist/orchestrator/src/cli/resumeCliShell.js +14 -0
  172. package/dist/orchestrator/src/cli/reviewCliLaunchShell.js +72 -0
  173. package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
  174. package/dist/orchestrator/src/cli/rlm/context.js +94 -7
  175. package/dist/orchestrator/src/cli/rlm/rlmCodexRuntimeShell.js +546 -0
  176. package/dist/orchestrator/src/cli/rlm/symbolic.js +4 -2
  177. package/dist/orchestrator/src/cli/rlmCliRequestShell.js +42 -0
  178. package/dist/orchestrator/src/cli/rlmCompletionCliShell.js +46 -0
  179. package/dist/orchestrator/src/cli/rlmLaunchCliShell.js +51 -0
  180. package/dist/orchestrator/src/cli/rlmRunner.js +83 -523
  181. package/dist/orchestrator/src/cli/run/blockMemory.js +500 -0
  182. package/dist/orchestrator/src/cli/run/manifest.js +410 -73
  183. package/dist/orchestrator/src/cli/run/manifestPersister.js +45 -14
  184. package/dist/orchestrator/src/cli/run/runMemoryController.js +216 -0
  185. package/dist/orchestrator/src/cli/run/source0.js +690 -0
  186. package/dist/orchestrator/src/cli/run/workspacePath.js +101 -0
  187. package/dist/orchestrator/src/cli/runtime/mode.js +2 -1
  188. package/dist/orchestrator/src/cli/runtime/provider.js +39 -2
  189. package/dist/orchestrator/src/cli/selfCheckCliShell.js +12 -0
  190. package/dist/orchestrator/src/cli/services/commandRunner.js +698 -18
  191. package/dist/orchestrator/src/cli/services/execRuntime.js +66 -1
  192. package/dist/orchestrator/src/cli/services/orchestratorAutoScoutEvidenceRecorder.js +71 -0
  193. package/dist/orchestrator/src/cli/services/orchestratorCloudBranchResolution.js +8 -0
  194. package/dist/orchestrator/src/cli/services/orchestratorCloudEnvironmentResolution.js +22 -0
  195. package/dist/orchestrator/src/cli/services/orchestratorCloudExecutionLifecycleShell.js +39 -0
  196. package/dist/orchestrator/src/cli/services/orchestratorCloudPromptBuilder.js +37 -0
  197. package/dist/orchestrator/src/cli/services/orchestratorCloudRouteFallbackContract.js +45 -0
  198. package/dist/orchestrator/src/cli/services/orchestratorCloudRouteShell.js +36 -0
  199. package/dist/orchestrator/src/cli/services/orchestratorCloudTargetExecutor.js +277 -0
  200. package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycle.js +98 -0
  201. package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycleShell.js +54 -0
  202. package/dist/orchestrator/src/cli/services/orchestratorExecutionLifecycle.js +112 -0
  203. package/dist/orchestrator/src/cli/services/orchestratorExecutionModePolicy.js +27 -0
  204. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteAdapterShell.js +59 -0
  205. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteDecisionShell.js +57 -0
  206. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteState.js +21 -0
  207. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouter.js +2 -0
  208. package/dist/orchestrator/src/cli/services/orchestratorLocalPipelineExecutor.js +149 -0
  209. package/dist/orchestrator/src/cli/services/orchestratorLocalRouteShell.js +63 -0
  210. package/dist/orchestrator/src/cli/services/orchestratorPlanShell.js +54 -0
  211. package/dist/orchestrator/src/cli/services/orchestratorPlanTargetTracker.js +16 -0
  212. package/dist/orchestrator/src/cli/services/orchestratorResumePreparationShell.js +84 -0
  213. package/dist/orchestrator/src/cli/services/orchestratorResumeTokenValidation.js +15 -0
  214. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleCompletion.js +31 -0
  215. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleExecutionRegistration.js +37 -0
  216. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleOrchestrationShell.js +83 -0
  217. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleTaskManagerShell.js +37 -0
  218. package/dist/orchestrator/src/cli/services/orchestratorRuntimeManifestMutation.js +20 -0
  219. package/dist/orchestrator/src/cli/services/orchestratorStartPreparationShell.js +56 -0
  220. package/dist/orchestrator/src/cli/services/orchestratorStatusShell.js +70 -0
  221. package/dist/orchestrator/src/cli/services/pipelineResolver.js +7 -3
  222. package/dist/orchestrator/src/cli/services/plannerMemory.js +119 -0
  223. package/dist/orchestrator/src/cli/services/runPreparation.js +7 -3
  224. package/dist/orchestrator/src/cli/services/runSummaryWriter.js +9 -0
  225. package/dist/orchestrator/src/cli/setupBootstrapShell.js +114 -0
  226. package/dist/orchestrator/src/cli/setupCliShell.js +51 -0
  227. package/dist/orchestrator/src/cli/skillsCliShell.js +56 -0
  228. package/dist/orchestrator/src/cli/startCliRequestShell.js +53 -0
  229. package/dist/orchestrator/src/cli/startCliShell.js +68 -0
  230. package/dist/orchestrator/src/cli/statusCliShell.js +22 -0
  231. package/dist/orchestrator/src/cli/utils/authProvenanceFingerprint.js +27 -0
  232. package/dist/orchestrator/src/cli/utils/cloudPreflight.js +285 -7
  233. package/dist/orchestrator/src/cli/utils/codexFeatures.js +60 -0
  234. package/dist/orchestrator/src/cli/utils/delegationConfigParser.js +250 -0
  235. package/dist/orchestrator/src/cli/utils/delegationMcpHealth.js +1382 -0
  236. package/dist/orchestrator/src/cli/utils/devtools.js +2 -54
  237. package/dist/orchestrator/src/cli/utils/mcpServerEntry.js +53 -0
  238. package/dist/orchestrator/src/cli/utils/packageProgramResolver.js +151 -0
  239. package/dist/orchestrator/src/cli/utils/providerOverrideEnv.js +71 -0
  240. package/dist/orchestrator/src/cli/utils/trailingJsonObject.js +59 -0
  241. package/dist/orchestrator/src/learning/crystalizer.js +2 -2
  242. package/dist/orchestrator/src/manager.js +74 -4
  243. package/dist/orchestrator/src/persistence/ExperienceStore.js +233 -49
  244. package/dist/orchestrator/src/persistence/TaskStateStore.js +6 -6
  245. package/dist/orchestrator/src/persistence/lockFile.js +70 -4
  246. package/dist/orchestrator/src/persistence/sanitizeIdentifier.js +39 -0
  247. package/dist/orchestrator/src/sync/createCloudSyncWorker.js +3 -2
  248. package/dist/orchestrator/src/utils/atomicWrite.js +17 -2
  249. package/dist/packages/orchestrator/src/exec/unified-exec.js +99 -6
  250. package/dist/packages/orchestrator/src/instructions/promptPacks.js +150 -19
  251. package/dist/packages/sdk-node/src/orchestrator.js +137 -13
  252. package/dist/packages/shared/config/designConfig.js +8 -1
  253. package/dist/packages/shared/streams/stdio.js +1 -1
  254. package/dist/scripts/design/pipeline/permit.js +15 -0
  255. package/dist/scripts/lib/docs-catalog.js +399 -0
  256. package/dist/scripts/lib/docs-helpers.js +87 -5
  257. package/dist/scripts/lib/pr-watch-merge.js +1088 -80
  258. package/dist/scripts/lib/provider-run-contract.js +26 -0
  259. package/dist/scripts/lib/review-command-intent-classification.js +532 -0
  260. package/dist/scripts/lib/review-command-probe-classification.js +385 -0
  261. package/dist/scripts/lib/review-execution-boundary-preflight.js +279 -0
  262. package/dist/scripts/lib/review-execution-runtime.js +753 -0
  263. package/dist/scripts/lib/review-execution-state.js +1144 -0
  264. package/dist/scripts/lib/review-execution-telemetry.js +215 -0
  265. package/dist/scripts/lib/review-inspection-target-parsing.js +78 -0
  266. package/dist/scripts/lib/review-launch-attempt.js +601 -0
  267. package/dist/scripts/lib/review-meta-surface-boundary-analysis.js +300 -0
  268. package/dist/scripts/lib/review-meta-surface-normalization.js +746 -0
  269. package/dist/scripts/lib/review-non-interactive-handoff.js +61 -0
  270. package/dist/scripts/lib/review-prompt-context.js +376 -0
  271. package/dist/scripts/lib/review-scope-advisory.js +286 -0
  272. package/dist/scripts/lib/review-scope-paths.js +123 -0
  273. package/dist/scripts/lib/review-shell-command-parser.js +389 -0
  274. package/dist/scripts/lib/review-shell-env-interpreter.js +340 -0
  275. package/dist/scripts/lib/run-manifests.js +192 -36
  276. package/dist/scripts/lib/spark-policy-classifier.js +593 -0
  277. package/dist/scripts/run-review.js +507 -1777
  278. package/docs/README.md +43 -20
  279. package/docs/book/README.md +19 -0
  280. package/docs/book/codex-cli-0124-adoption.md +68 -0
  281. package/docs/book/local-hook-impact.md +73 -0
  282. package/docs/book/operations.md +60 -0
  283. package/docs/book/public-posture.md +34 -0
  284. package/docs/book/setup.md +91 -0
  285. package/docs/book/skills.md +11 -0
  286. package/docs/guides/codex-version-policy.md +104 -0
  287. package/docs/public/downstream-setup.md +113 -0
  288. package/docs/public/provider-onboarding.md +173 -0
  289. package/package.json +23 -10
  290. package/plugins/codex-orchestrator/.codex-plugin/plugin.json +30 -0
  291. package/plugins/codex-orchestrator/.mcp.json +13 -0
  292. package/plugins/codex-orchestrator/launcher.mjs +361 -0
  293. package/schemas/manifest.json +411 -0
  294. package/skills/README.md +26 -0
  295. package/skills/collab-subagents-first/SKILL.md +1 -1
  296. package/skills/delegation-usage/DELEGATION_GUIDE.md +30 -12
  297. package/skills/delegation-usage/SKILL.md +25 -14
  298. package/skills/land/SKILL.md +77 -0
  299. package/skills/linear/SKILL.md +255 -0
  300. package/skills/release/SKILL.md +47 -3
  301. package/skills/standalone-review/SKILL.md +6 -1
  302. package/templates/README.md +4 -2
  303. package/templates/codex/.codex/agents/awaiter-high.toml +2 -2
  304. package/templates/codex/.codex/agents/worker-complex.toml +1 -1
  305. package/templates/codex/.codex/config.toml +3 -4
  306. package/templates/codex/.codex/providers/README.md +13 -0
  307. package/templates/codex/.codex/providers/control.example.json +18 -0
  308. package/templates/codex/.codex/providers/provider.env.example +15 -0
  309. package/templates/codex/AGENTS.md +15 -8
  310. package/templates/codex/mcp-client.json +5 -1
  311. package/docs/assets/setup.gif +0 -0
@@ -0,0 +1,756 @@
1
+ import { isoTimestamp } from '../utils/time.js';
2
+ import { readSharedLinearBudgetStatus, resolveLinearPollingInterval } from './linearBudgetState.js';
3
+ import { resolveLiveLinearTrackedIssues, } from './linearDispatchSource.js';
4
+ import { resolveLinearWebhookSourceSetup } from './linearWebhookController.js';
5
+ import { initializeProviderPollingHealth, isProviderPollingStuck, flushProviderPollingHealthUpdates, markProviderPollingStuck, markProviderPollingCompleted, markProviderPollingStarted, noteProviderPollingRequest, readProviderPollingHealth, scheduleProviderPolling } from './providerPollingHealth.js';
6
+ import { beginClosingControlServerHttpServer, closeControlServerOwnedRuntime, startControlServerReadyInstanceLifecycle } from './controlServerReadyInstanceLifecycle.js';
7
+ import { prepareControlServerStartupInputs } from './controlServerStartupInputPreparation.js';
8
+ import { acquireControlHostOwnership } from './controlHostOwnership.js';
9
+ const EXPIRY_INTERVAL_MS = 15_000;
10
+ const PROVIDER_REFRESH_INTERVAL_MS = 15_000;
11
+ const PROVIDER_REFRESH_STUCK_AFTER_MS = 45_000;
12
+ const PROVIDER_CLOSE_STUCK_DRAIN_GRACE_MS = 1_000;
13
+ const PROVIDER_FULL_RECOVERY_SWEEP_INTERVAL_MS = 10 * 60 * 1000;
14
+ const SESSION_TTL_MS = 15 * 60 * 1000;
15
+ const providerIssueHandoffOperations = new WeakMap();
16
+ export async function startControlServerPublicLifecycle(options) {
17
+ let controlHostOwnership = null;
18
+ try {
19
+ controlHostOwnership =
20
+ !options.controlHostOwnership
21
+ ? null
22
+ : await acquireControlHostOwnership({
23
+ paths: options.paths,
24
+ runId: options.runId,
25
+ repoRoot: options.controlHostOwnership?.repoRoot,
26
+ taskId: options.controlHostOwnership?.taskId,
27
+ pipelineId: options.controlHostOwnership?.pipelineId
28
+ });
29
+ const startupInputs = await prepareControlServerStartupInputs({
30
+ paths: options.paths,
31
+ config: options.config,
32
+ eventStream: options.eventStream,
33
+ runId: options.runId,
34
+ sessionTtlMs: SESSION_TTL_MS,
35
+ providerWorkflowConfigStore: options.providerWorkflowConfigStore,
36
+ createProviderIssueHandoff: options.createProviderIssueHandoff
37
+ });
38
+ const readyInstance = await startControlServerReadyInstanceLifecycle({
39
+ requestContextShared: startupInputs.requestContextShared,
40
+ host: startupInputs.host,
41
+ controlToken: startupInputs.controlToken,
42
+ intervalMs: EXPIRY_INTERVAL_MS
43
+ });
44
+ const providerRefreshCoordinator = startupInputs.requestContextShared.providerIssueHandoff
45
+ ? createProviderRefreshCoordinator(startupInputs.requestContextShared.providerIssueHandoff, {
46
+ readFeatureToggles: startupInputs.requestContextShared.controlStore
47
+ ? () => startupInputs.requestContextShared.controlStore.snapshot().feature_toggles
48
+ : null
49
+ })
50
+ : null;
51
+ if (startupInputs.requestContextShared.providerIssueHandoff) {
52
+ const persistProviderIntakePolling = startupInputs.requestContextShared.persist?.providerIntakePolling ?? null;
53
+ const persistedPollingSnapshot = startupInputs.requestContextShared.providerIntakeState?.polling ?? null;
54
+ initializeProviderPollingHealth(startupInputs.requestContextShared.providerIssueHandoff, {
55
+ intervalMs: PROVIDER_REFRESH_INTERVAL_MS,
56
+ stuckAfterMs: PROVIDER_REFRESH_STUCK_AFTER_MS,
57
+ controlHostOwner: controlHostOwnership?.polling ?? null,
58
+ skipInitialUpdate: persistedPollingSnapshot !== null,
59
+ onUpdate: startupInputs.requestContextShared.providerIntakeState && persistProviderIntakePolling
60
+ ? async (polling) => {
61
+ const pollingUpdatedAt = typeof polling.updated_at === 'string' && polling.updated_at.trim().length > 0
62
+ ? polling.updated_at
63
+ : isoTimestamp();
64
+ const stateUpdatedAt = pickLatestTimestamp(startupInputs.requestContextShared.providerIntakeState.updated_at, pollingUpdatedAt);
65
+ const nextPolling = {
66
+ ...polling,
67
+ updated_at: pollingUpdatedAt
68
+ };
69
+ startupInputs.requestContextShared.providerIntakeState.polling = nextPolling;
70
+ startupInputs.requestContextShared.providerIntakeState.updated_at = stateUpdatedAt;
71
+ await persistProviderIntakePolling(nextPolling, stateUpdatedAt);
72
+ }
73
+ : null
74
+ });
75
+ }
76
+ const providerRefreshStartupTrigger = providerRefreshCoordinator
77
+ ? scheduleStartupProviderRefresh(providerRefreshCoordinator.trigger)
78
+ : null;
79
+ return {
80
+ server: readyInstance.server,
81
+ requestContextShared: startupInputs.requestContextShared,
82
+ lifecycleState: readyInstance.lifecycleState,
83
+ ...(controlHostOwnership ? { controlHostOwnership } : {}),
84
+ ...(providerRefreshCoordinator
85
+ ? {
86
+ providerRefreshTimer: providerRefreshCoordinator.timer,
87
+ providerRefreshStartupTrigger,
88
+ triggerProviderRefresh: providerRefreshCoordinator.trigger
89
+ }
90
+ : {}),
91
+ baseUrl: readyInstance.baseUrl
92
+ };
93
+ }
94
+ catch (error) {
95
+ await controlHostOwnership?.release().catch(() => undefined);
96
+ throw error;
97
+ }
98
+ }
99
+ export async function closeControlServerPublicLifecycle(state) {
100
+ if (state.providerRefreshStartupTrigger) {
101
+ clearTimeout(state.providerRefreshStartupTrigger);
102
+ }
103
+ if (state.providerRefreshTimer) {
104
+ state.providerRefreshTimer.cancel();
105
+ }
106
+ const serverClosePromise = beginClosingControlServerHttpServer(state.server);
107
+ void serverClosePromise.catch(() => undefined);
108
+ const providerIssueHandoff = state.requestContextShared.providerIssueHandoff ?? null;
109
+ let closeError = null;
110
+ const captureCloseError = (error) => {
111
+ if (closeError === null) {
112
+ closeError = error;
113
+ }
114
+ };
115
+ if (providerIssueHandoff) {
116
+ try {
117
+ await waitForProviderIssueHandoffQueueToDrain(providerIssueHandoff, () => resolveProviderIssueHandoffWatchdogDelayMs(providerIssueHandoff), { settleStuckPending: true });
118
+ await flushProviderPollingHealthUpdates(providerIssueHandoff);
119
+ }
120
+ catch (error) {
121
+ captureCloseError(error);
122
+ }
123
+ }
124
+ try {
125
+ await closeControlServerOwnedRuntime({
126
+ server: state.server,
127
+ requestContextShared: state.requestContextShared,
128
+ lifecycleState: state.lifecycleState,
129
+ serverClosePromise
130
+ });
131
+ }
132
+ catch (error) {
133
+ captureCloseError(error);
134
+ }
135
+ try {
136
+ await serverClosePromise;
137
+ }
138
+ catch (error) {
139
+ captureCloseError(error);
140
+ }
141
+ try {
142
+ await state.controlHostOwnership?.release();
143
+ }
144
+ catch (error) {
145
+ captureCloseError(error);
146
+ }
147
+ if (closeError !== null) {
148
+ throw closeError;
149
+ }
150
+ }
151
+ export function runProviderIssueHandoffRefresh(providerIssueHandoff, options) {
152
+ const state = getProviderIssueHandoffOperationState(providerIssueHandoff);
153
+ const acknowledgeAccepted = options?.acknowledgeAccepted === true;
154
+ const allowIdleRestartRequiredRetry = options?.allowIdleRestartRequiredRetry === true;
155
+ if (state.active) {
156
+ const continueWhileBusy = () => {
157
+ if (!options?.queueIfBusy) {
158
+ return mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, waitForProviderIssueHandoffPending(providerIssueHandoff, state.active), {
159
+ queued: true,
160
+ coalesced: true
161
+ });
162
+ }
163
+ noteProviderPollingRequest(providerIssueHandoff, {
164
+ mode: 'refresh',
165
+ queued: true,
166
+ preserveActiveMode: true
167
+ });
168
+ if (state.queuedRefresh) {
169
+ const queuedOutcome = {
170
+ queued: true,
171
+ coalesced: true
172
+ };
173
+ return acknowledgeAccepted
174
+ ? acknowledgeProviderIssueHandoffAccepted(state.queuedRefresh, queuedOutcome)
175
+ : mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, state.queuedRefresh, queuedOutcome);
176
+ }
177
+ const queuedRefresh = queueProviderIssueHandoffRefresh(providerIssueHandoff, state, () => providerIssueHandoff.refresh(), {
178
+ mode: 'refresh'
179
+ });
180
+ const queuedOutcome = {
181
+ queued: true,
182
+ coalesced: false
183
+ };
184
+ return acknowledgeAccepted
185
+ ? acknowledgeProviderIssueHandoffAccepted(queuedRefresh, queuedOutcome)
186
+ : mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, queuedRefresh, queuedOutcome);
187
+ };
188
+ if (isProviderPollingStuck(providerIssueHandoff)) {
189
+ return (async () => {
190
+ const stuckOutcome = await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff);
191
+ if (!stuckOutcome) {
192
+ return continueWhileBusy();
193
+ }
194
+ if (allowIdleRestartRequiredRetry) {
195
+ detachProviderIssueHandoffPending(state.active);
196
+ detachProviderIssueHandoffPending(state.queuedRefresh);
197
+ state.active = null;
198
+ state.queuedRefresh = null;
199
+ providerIssueHandoff.resetStuckRefreshLifecycle?.();
200
+ const activeRefresh = waitForProviderIssueHandoffPending(providerIssueHandoff, startProviderIssueHandoffOperation(providerIssueHandoff, state, () => providerIssueHandoff.refresh(), {
201
+ mode: 'refresh'
202
+ }));
203
+ const activeOutcome = {
204
+ queued: true,
205
+ coalesced: false
206
+ };
207
+ return acknowledgeAccepted
208
+ ? acknowledgeProviderIssueHandoffAccepted(activeRefresh, activeOutcome)
209
+ : mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, activeRefresh, activeOutcome);
210
+ }
211
+ noteProviderPollingRequest(providerIssueHandoff, {
212
+ mode: 'refresh',
213
+ queued: state.queuedRefresh !== null,
214
+ replaceQueued: true,
215
+ preserveActiveMode: true
216
+ });
217
+ return stuckOutcome;
218
+ })();
219
+ }
220
+ return continueWhileBusy();
221
+ }
222
+ const idleStuckError = buildProviderIssueHandoffRestartRequiredError(providerIssueHandoff);
223
+ if (idleStuckError && !allowIdleRestartRequiredRetry) {
224
+ clearProviderIssueHandoffOperationState(providerIssueHandoff, state);
225
+ return mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, Promise.reject(idleStuckError), {
226
+ queued: true,
227
+ coalesced: true
228
+ });
229
+ }
230
+ const activeRefresh = waitForProviderIssueHandoffPending(providerIssueHandoff, startProviderIssueHandoffOperation(providerIssueHandoff, state, () => providerIssueHandoff.refresh(), {
231
+ mode: 'refresh'
232
+ }));
233
+ const activeOutcome = {
234
+ queued: true,
235
+ coalesced: false
236
+ };
237
+ return acknowledgeAccepted
238
+ ? acknowledgeProviderIssueHandoffAccepted(activeRefresh, activeOutcome)
239
+ : mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, activeRefresh, activeOutcome);
240
+ }
241
+ export function runProviderIssueHandoffRehydrate(providerIssueHandoff) {
242
+ return runProviderIssueHandoffOperation(providerIssueHandoff, () => providerIssueHandoff.rehydrate());
243
+ }
244
+ export function runProviderIssueHandoffPoll(providerIssueHandoff, input, options) {
245
+ return runProviderIssueHandoffOperation(providerIssueHandoff, () => providerIssueHandoff.poll
246
+ ? providerIssueHandoff.poll(input)
247
+ : providerIssueHandoff.refresh(), options, {
248
+ mode: providerIssueHandoff.poll ? 'poll' : 'refresh'
249
+ });
250
+ }
251
+ function createProviderRefreshCoordinator(providerIssueHandoff, context) {
252
+ let stopped = false;
253
+ let timer = null;
254
+ let rescheduleGeneration = 0;
255
+ let lastSuccessfulFullRecoverySweepAtMs = null;
256
+ const clearScheduledTrigger = () => {
257
+ if (!timer) {
258
+ return;
259
+ }
260
+ clearTimeout(timer);
261
+ timer = null;
262
+ };
263
+ const scheduleNextTriggerAsync = async () => {
264
+ if (stopped || timer) {
265
+ return;
266
+ }
267
+ const schedule = await resolveProviderRefreshSchedule().catch(() => ({
268
+ interval_ms: PROVIDER_REFRESH_INTERVAL_MS,
269
+ reason: null,
270
+ linear_budget: null
271
+ }));
272
+ if (stopped || timer) {
273
+ return;
274
+ }
275
+ scheduleProviderPolling(providerIssueHandoff, {
276
+ intervalMs: schedule.interval_ms,
277
+ reason: schedule.reason,
278
+ linearBudget: schedule.linear_budget
279
+ });
280
+ timer = setTimeout(() => {
281
+ timer = null;
282
+ void trigger();
283
+ }, schedule.interval_ms);
284
+ timer.unref?.();
285
+ };
286
+ const resolveProviderRefreshSchedule = async () => resolveLinearPollingInterval({
287
+ budget: await readSharedLinearBudgetStatus(process.env, {
288
+ operation: 'dispatch_source_tracked_issues'
289
+ }).catch(() => null),
290
+ default_interval_ms: PROVIDER_REFRESH_INTERVAL_MS,
291
+ operation: 'dispatch_source_tracked_issues'
292
+ });
293
+ const resolveWatchdogDelayMs = () => resolveProviderIssueHandoffWatchdogDelayMs(providerIssueHandoff);
294
+ const shouldRunFullRecoverySweep = (nowMs) => lastSuccessfulFullRecoverySweepAtMs === null ||
295
+ nowMs - lastSuccessfulFullRecoverySweepAtMs >= PROVIDER_FULL_RECOVERY_SWEEP_INTERVAL_MS;
296
+ const trigger = async () => {
297
+ if (stopped) {
298
+ return;
299
+ }
300
+ const preflightSchedule = await resolveProviderRefreshSchedule().catch(() => null);
301
+ if (stopped) {
302
+ clearScheduledTrigger();
303
+ return;
304
+ }
305
+ if (preflightSchedule?.linear_budget?.cooldown_active) {
306
+ clearScheduledTrigger();
307
+ await scheduleNextTriggerAsync();
308
+ return;
309
+ }
310
+ if (isProviderPollingStuck(providerIssueHandoff)) {
311
+ await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff);
312
+ await scheduleNextTriggerAsync();
313
+ return;
314
+ }
315
+ clearScheduledTrigger();
316
+ const generation = ++rescheduleGeneration;
317
+ try {
318
+ const operation = runProviderIssueHandoffOperation(providerIssueHandoff, async () => {
319
+ if (!providerIssueHandoff.poll || !context.readFeatureToggles) {
320
+ await providerIssueHandoff.refresh();
321
+ return;
322
+ }
323
+ const refetchTrackedIssues = async (input) => await resolveProviderPollTrackedIssues(context, input);
324
+ if (shouldRunFullRecoverySweep(Date.now())) {
325
+ const pollResolution = await refetchTrackedIssues({
326
+ mode: 'recovery_sweep'
327
+ });
328
+ if (pollResolution.kind === 'ready') {
329
+ await providerIssueHandoff.poll({
330
+ trackedIssues: pollResolution.trackedIssues,
331
+ refetchTrackedIssues,
332
+ allowPollFailClosed: true
333
+ });
334
+ lastSuccessfulFullRecoverySweepAtMs = Date.now();
335
+ return;
336
+ }
337
+ if (pollResolution.reason === 'dispatch_source_provider_rate_limited') {
338
+ return;
339
+ }
340
+ noteProviderPollingRequest(providerIssueHandoff, {
341
+ mode: 'refresh',
342
+ queued: getProviderIssueHandoffOperationState(providerIssueHandoff).queuedRefresh !== null,
343
+ replaceQueued: true
344
+ });
345
+ await providerIssueHandoff.refresh();
346
+ return;
347
+ }
348
+ await providerIssueHandoff.poll({
349
+ trackedIssues: [],
350
+ refetchTrackedIssues,
351
+ deferFreshDiscovery: true
352
+ });
353
+ return;
354
+ }, undefined, {
355
+ mode: providerIssueHandoff.poll && context.readFeatureToggles ? 'poll' : 'refresh'
356
+ });
357
+ await waitForProviderIssueHandoffPendingWithWatchdog(providerIssueHandoff, operation, resolveWatchdogDelayMs);
358
+ }
359
+ catch {
360
+ // Best-effort provider refreshes should not crash the public lifecycle.
361
+ }
362
+ await waitForProviderIssueHandoffQueueToDrain(providerIssueHandoff, resolveWatchdogDelayMs);
363
+ if (stopped || generation !== rescheduleGeneration) {
364
+ return;
365
+ }
366
+ await scheduleNextTriggerAsync();
367
+ };
368
+ return {
369
+ timer: {
370
+ cancel: () => {
371
+ stopped = true;
372
+ rescheduleGeneration += 1;
373
+ clearScheduledTrigger();
374
+ }
375
+ },
376
+ trigger
377
+ };
378
+ }
379
+ function scheduleStartupProviderRefresh(trigger) {
380
+ const startupTrigger = setTimeout(() => {
381
+ void trigger();
382
+ }, 0);
383
+ startupTrigger.unref?.();
384
+ return startupTrigger;
385
+ }
386
+ function resolveProviderIssueHandoffWatchdogDelayMs(providerIssueHandoff) {
387
+ const health = readProviderPollingHealth(providerIssueHandoff);
388
+ if (!health?.checking || health.operation_elapsed_ms === null) {
389
+ return PROVIDER_REFRESH_STUCK_AFTER_MS;
390
+ }
391
+ return Math.max(0, PROVIDER_REFRESH_STUCK_AFTER_MS - health.operation_elapsed_ms);
392
+ }
393
+ async function resolveProviderPollTrackedIssues(context, input) {
394
+ if (!context.readFeatureToggles) {
395
+ return {
396
+ kind: 'skip',
397
+ reason: 'dispatch_source_unavailable'
398
+ };
399
+ }
400
+ const sourceSetup = resolveLinearWebhookSourceSetup(context.readFeatureToggles(), process.env);
401
+ if ('error' in sourceSetup) {
402
+ return {
403
+ kind: 'skip',
404
+ reason: sourceSetup.error
405
+ };
406
+ }
407
+ const resolution = await resolveLiveLinearTrackedIssues({
408
+ sourceSetup: sourceSetup.sourceSetup,
409
+ env: process.env,
410
+ queryMode: input?.mode,
411
+ eligibleIssueTargetCount: input?.eligibleTargetCount,
412
+ eligibleStateSlotCounts: input?.eligibleStateSlotCounts,
413
+ excludedIssueIds: input?.excludedIssueIds
414
+ });
415
+ if (resolution.kind !== 'ready') {
416
+ return {
417
+ kind: 'skip',
418
+ reason: resolution.reason
419
+ };
420
+ }
421
+ return {
422
+ kind: 'ready',
423
+ trackedIssues: dedupeProviderPollTrackedIssues(resolution.tracked_issues)
424
+ };
425
+ }
426
+ function dedupeProviderPollTrackedIssues(trackedIssues) {
427
+ const seenIssueIds = new Set();
428
+ const deduped = [];
429
+ for (const trackedIssue of trackedIssues) {
430
+ if (seenIssueIds.has(trackedIssue.id)) {
431
+ continue;
432
+ }
433
+ seenIssueIds.add(trackedIssue.id);
434
+ deduped.push(trackedIssue);
435
+ }
436
+ return deduped;
437
+ }
438
+ function pickLatestTimestamp(currentIso, candidateIso) {
439
+ const currentMs = Date.parse(currentIso ?? '');
440
+ const candidateMs = Date.parse(candidateIso);
441
+ if (!Number.isFinite(currentMs)) {
442
+ return candidateIso;
443
+ }
444
+ if (!Number.isFinite(candidateMs)) {
445
+ return currentIso ?? candidateIso;
446
+ }
447
+ return candidateMs >= currentMs ? candidateIso : currentIso ?? candidateIso;
448
+ }
449
+ function runProviderIssueHandoffOperation(providerIssueHandoff, operation, options, healthContext) {
450
+ const state = getProviderIssueHandoffOperationState(providerIssueHandoff);
451
+ if (state.active) {
452
+ const continueWhileBusy = () => {
453
+ if (!options?.queueIfBusy) {
454
+ return waitForProviderIssueHandoffPending(providerIssueHandoff, state.active);
455
+ }
456
+ if (healthContext) {
457
+ noteProviderPollingRequest(providerIssueHandoff, {
458
+ mode: healthContext.mode,
459
+ queued: true,
460
+ preserveActiveMode: true
461
+ });
462
+ }
463
+ return queueProviderIssueHandoffRefresh(providerIssueHandoff, state, operation, healthContext);
464
+ };
465
+ if (isProviderPollingStuck(providerIssueHandoff)) {
466
+ return (async () => {
467
+ const stuckOutcome = await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff);
468
+ if (!stuckOutcome) {
469
+ return continueWhileBusy();
470
+ }
471
+ if (healthContext) {
472
+ noteProviderPollingRequest(providerIssueHandoff, {
473
+ mode: healthContext.mode,
474
+ queued: state.queuedRefresh !== null,
475
+ replaceQueued: true,
476
+ preserveActiveMode: true
477
+ });
478
+ }
479
+ throw new Error(stuckOutcome?.reason ?? 'provider_refresh_lifecycle_stuck');
480
+ })();
481
+ }
482
+ return continueWhileBusy();
483
+ }
484
+ const idleStuckError = buildProviderIssueHandoffRestartRequiredError(providerIssueHandoff);
485
+ if (idleStuckError) {
486
+ clearProviderIssueHandoffOperationState(providerIssueHandoff, state);
487
+ return Promise.reject(idleStuckError);
488
+ }
489
+ return waitForProviderIssueHandoffPending(providerIssueHandoff, startProviderIssueHandoffOperation(providerIssueHandoff, state, operation, healthContext));
490
+ }
491
+ function buildProviderIssueHandoffRestartRequiredError(providerIssueHandoff) {
492
+ if (!isProviderPollingStuck(providerIssueHandoff)) {
493
+ return null;
494
+ }
495
+ return new Error(readProviderPollingHealth(providerIssueHandoff)?.reason ?? 'provider_refresh_lifecycle_stuck');
496
+ }
497
+ function startProviderIssueHandoffOperation(providerIssueHandoff, state, operation, healthContext) {
498
+ resetProviderIssueHandoffStuckSignal(state);
499
+ if (healthContext) {
500
+ markProviderPollingStarted(providerIssueHandoff, {
501
+ mode: healthContext.mode
502
+ });
503
+ }
504
+ let operationResult;
505
+ try {
506
+ operationResult = operation();
507
+ }
508
+ catch (error) {
509
+ operationResult = Promise.reject(error);
510
+ }
511
+ const operationPromise = operationResult
512
+ .then((value) => {
513
+ if (healthContext && state.active === operationPromise) {
514
+ markProviderPollingCompleted(providerIssueHandoff);
515
+ }
516
+ return value;
517
+ }, (error) => {
518
+ if (healthContext && state.active === operationPromise) {
519
+ markProviderPollingCompleted(providerIssueHandoff, {
520
+ error
521
+ });
522
+ }
523
+ throw error;
524
+ })
525
+ .finally(() => {
526
+ if (state.active === operationPromise) {
527
+ state.active = null;
528
+ clearProviderIssueHandoffOperationState(providerIssueHandoff, state);
529
+ }
530
+ });
531
+ state.active = operationPromise;
532
+ return operationPromise;
533
+ }
534
+ function queueProviderIssueHandoffRefresh(providerIssueHandoff, state, operation, healthContext) {
535
+ if (state.queuedRefresh) {
536
+ return state.queuedRefresh;
537
+ }
538
+ const queuedRefresh = waitForProviderIssueHandoffPending(providerIssueHandoff, state.active)
539
+ .catch(async (error) => {
540
+ const stuckReason = resolveProviderIssueHandoffStuckErrorReason(error);
541
+ if (stuckReason) {
542
+ throw new Error(stuckReason);
543
+ }
544
+ if (await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff)) {
545
+ throw new Error(readProviderPollingHealth(providerIssueHandoff)?.reason ??
546
+ 'provider_refresh_lifecycle_stuck');
547
+ }
548
+ })
549
+ .then(async () => {
550
+ if (await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff)) {
551
+ throw new Error(readProviderPollingHealth(providerIssueHandoff)?.reason ??
552
+ 'provider_refresh_lifecycle_stuck');
553
+ }
554
+ if (state.queuedRefresh !== queuedRefresh) {
555
+ return;
556
+ }
557
+ state.queuedRefresh = null;
558
+ if (state.active) {
559
+ return queueProviderIssueHandoffRefresh(providerIssueHandoff, state, operation, healthContext);
560
+ }
561
+ return waitForProviderIssueHandoffPending(providerIssueHandoff, startProviderIssueHandoffOperation(providerIssueHandoff, state, operation, healthContext));
562
+ })
563
+ .finally(() => {
564
+ if (state.queuedRefresh === queuedRefresh) {
565
+ state.queuedRefresh = null;
566
+ }
567
+ clearProviderIssueHandoffOperationState(providerIssueHandoff, state);
568
+ });
569
+ state.queuedRefresh = queuedRefresh;
570
+ return queuedRefresh;
571
+ }
572
+ function detachProviderIssueHandoffPending(pending) {
573
+ if (!pending) {
574
+ return;
575
+ }
576
+ void pending.catch(() => undefined);
577
+ }
578
+ async function waitForProviderIssueHandoffQueueToDrain(providerIssueHandoff, resolveWatchdogDelayMs, options = {}) {
579
+ for (;;) {
580
+ const state = getProviderIssueHandoffOperationState(providerIssueHandoff);
581
+ const pending = state.active ?? state.queuedRefresh;
582
+ if (!pending) {
583
+ return;
584
+ }
585
+ if (await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff)) {
586
+ if (options.settleStuckPending) {
587
+ await settleProviderIssueHandoffStuckPending(providerIssueHandoff, state, pending, options);
588
+ continue;
589
+ }
590
+ return;
591
+ }
592
+ try {
593
+ await waitForProviderIssueHandoffPendingWithWatchdog(providerIssueHandoff, pending, resolveWatchdogDelayMs);
594
+ }
595
+ catch {
596
+ if (await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff)) {
597
+ if (options.settleStuckPending) {
598
+ await settleProviderIssueHandoffStuckPending(providerIssueHandoff, state, pending, options);
599
+ continue;
600
+ }
601
+ return;
602
+ }
603
+ }
604
+ }
605
+ }
606
+ async function settleProviderIssueHandoffStuckPending(providerIssueHandoff, state, pending, options) {
607
+ let timeout = null;
608
+ const graceMs = Math.max(0, options.stuckPendingGraceMs ?? PROVIDER_CLOSE_STUCK_DRAIN_GRACE_MS);
609
+ const outcome = await Promise.race([
610
+ pending.then(() => 'settled', () => 'settled'),
611
+ new Promise((resolve) => {
612
+ timeout = setTimeout(() => resolve('timed_out'), graceMs);
613
+ timeout.unref?.();
614
+ })
615
+ ]);
616
+ if (timeout) {
617
+ clearTimeout(timeout);
618
+ }
619
+ if (outcome === 'settled') {
620
+ return;
621
+ }
622
+ detachProviderIssueHandoffPending(pending);
623
+ providerIssueHandoff.resetStuckRefreshLifecycle?.();
624
+ if (state.active === pending) {
625
+ state.active = null;
626
+ }
627
+ if (state.queuedRefresh === pending) {
628
+ state.queuedRefresh = null;
629
+ }
630
+ clearProviderIssueHandoffOperationState(providerIssueHandoff, state);
631
+ }
632
+ function getProviderIssueHandoffOperationState(providerIssueHandoff) {
633
+ const existingState = providerIssueHandoffOperations.get(providerIssueHandoff);
634
+ if (existingState) {
635
+ return existingState;
636
+ }
637
+ const nextState = {
638
+ active: null,
639
+ queuedRefresh: null,
640
+ ...createProviderIssueHandoffStuckSignal()
641
+ };
642
+ providerIssueHandoffOperations.set(providerIssueHandoff, nextState);
643
+ return nextState;
644
+ }
645
+ function clearProviderIssueHandoffOperationState(providerIssueHandoff, state) {
646
+ if (!state.active && !state.queuedRefresh) {
647
+ providerIssueHandoffOperations.delete(providerIssueHandoff);
648
+ }
649
+ }
650
+ async function resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff) {
651
+ if (!isProviderPollingStuck(providerIssueHandoff)) {
652
+ return null;
653
+ }
654
+ await markProviderPollingStuck(providerIssueHandoff);
655
+ const outcome = {
656
+ queued: true,
657
+ coalesced: true,
658
+ stuck: true,
659
+ restart_required: true,
660
+ reason: readProviderPollingHealth(providerIssueHandoff)?.reason ?? 'provider_refresh_lifecycle_stuck'
661
+ };
662
+ signalProviderIssueHandoffStuck(providerIssueHandoff, outcome);
663
+ return outcome;
664
+ }
665
+ function mapProviderIssueHandoffRefreshOutcome(providerIssueHandoff, pending, successOutcome) {
666
+ return pending.then(() => successOutcome, async (error) => {
667
+ const stuckOutcome = await resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff);
668
+ if (stuckOutcome) {
669
+ return stuckOutcome;
670
+ }
671
+ const stuckReason = resolveProviderIssueHandoffStuckErrorReason(error);
672
+ if (stuckReason) {
673
+ return {
674
+ queued: true,
675
+ coalesced: true,
676
+ stuck: true,
677
+ restart_required: true,
678
+ reason: stuckReason
679
+ };
680
+ }
681
+ throw error;
682
+ });
683
+ }
684
+ function resolveProviderIssueHandoffStuckErrorReason(error) {
685
+ if (!(error instanceof Error)) {
686
+ return null;
687
+ }
688
+ if (error.name === 'ProviderRefreshLifecycleStuckError' ||
689
+ error.message === 'provider_refresh_lifecycle_stuck') {
690
+ return 'provider_refresh_lifecycle_stuck';
691
+ }
692
+ if (error.name === 'ProviderPollLifecycleStuckError' ||
693
+ error.message === 'provider_poll_lifecycle_stuck') {
694
+ return 'provider_poll_lifecycle_stuck';
695
+ }
696
+ return null;
697
+ }
698
+ function acknowledgeProviderIssueHandoffAccepted(pending, successOutcome) {
699
+ // Public refresh routes return as soon as the lifecycle accepts the work, so
700
+ // keep the detached refresh promise from surfacing later failures as
701
+ // unhandled rejections.
702
+ void pending.catch(() => undefined);
703
+ return Promise.resolve(successOutcome);
704
+ }
705
+ function waitForProviderIssueHandoffPending(providerIssueHandoff, pending) {
706
+ const state = getProviderIssueHandoffOperationState(providerIssueHandoff);
707
+ return Promise.race([
708
+ pending,
709
+ state.stuckSignal.then((outcome) => {
710
+ throw new Error(outcome.reason ?? 'provider_refresh_lifecycle_stuck');
711
+ })
712
+ ]);
713
+ }
714
+ async function waitForProviderIssueHandoffPendingWithWatchdog(providerIssueHandoff, pending, resolveWatchdogDelayMs) {
715
+ let stuckWatchdog = null;
716
+ try {
717
+ await Promise.race([
718
+ waitForProviderIssueHandoffPending(providerIssueHandoff, pending),
719
+ new Promise((resolve) => {
720
+ const watchdogDelayMs = resolveWatchdogDelayMs();
721
+ stuckWatchdog = setTimeout(() => {
722
+ void resolveProviderIssueHandoffStuckOutcome(providerIssueHandoff).finally(resolve);
723
+ }, watchdogDelayMs);
724
+ stuckWatchdog.unref?.();
725
+ })
726
+ ]);
727
+ }
728
+ finally {
729
+ if (stuckWatchdog) {
730
+ clearTimeout(stuckWatchdog);
731
+ }
732
+ }
733
+ }
734
+ function createProviderIssueHandoffStuckSignal() {
735
+ let resolveStuckSignal = null;
736
+ const stuckSignal = new Promise((resolve) => {
737
+ resolveStuckSignal = resolve;
738
+ });
739
+ return {
740
+ stuckSignal,
741
+ resolveStuckSignal
742
+ };
743
+ }
744
+ function resetProviderIssueHandoffStuckSignal(state) {
745
+ const nextSignal = createProviderIssueHandoffStuckSignal();
746
+ state.stuckSignal = nextSignal.stuckSignal;
747
+ state.resolveStuckSignal = nextSignal.resolveStuckSignal;
748
+ }
749
+ function signalProviderIssueHandoffStuck(providerIssueHandoff, outcome) {
750
+ const state = providerIssueHandoffOperations.get(providerIssueHandoff);
751
+ if (!state?.resolveStuckSignal) {
752
+ return;
753
+ }
754
+ state.resolveStuckSignal(outcome);
755
+ state.resolveStuckSignal = null;
756
+ }