@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,1006 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { access, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
3
+ import { dirname, join } from 'node:path';
4
+ import process from 'node:process';
5
+ import { promisify } from 'node:util';
6
+ import { acquireLockWithRetry } from '../../persistence/lockFile.js';
7
+ import { isoTimestamp } from '../utils/time.js';
8
+ const execFileAsync = promisify(execFile);
9
+ export const PROVIDER_OPERATOR_AUTOPILOT_LOCAL_ROLLOUT_EXECUTION_FILENAME = 'provider-operator-autopilot-local-rollout-executions.json';
10
+ const LOCAL_ROLLOUT_EXECUTION_LOCK_RETRY = {
11
+ maxAttempts: 450,
12
+ initialDelayMs: 10,
13
+ backoffFactor: 1.2,
14
+ maxDelayMs: 100,
15
+ staleMs: 30_000
16
+ };
17
+ const DEFAULT_LOCAL_ROLLOUT_EXECUTION_TIMEOUT_MS = 15_000;
18
+ const SUPPORTED_NODE_PLATFORMS = new Set([
19
+ 'aix',
20
+ 'android',
21
+ 'darwin',
22
+ 'freebsd',
23
+ 'haiku',
24
+ 'linux',
25
+ 'openbsd',
26
+ 'sunos',
27
+ 'win32',
28
+ 'cygwin',
29
+ 'netbsd'
30
+ ]);
31
+ export function resolveProviderOperatorAutopilotLocalRolloutExecutionPath(runDir) {
32
+ return join(runDir, PROVIDER_OPERATOR_AUTOPILOT_LOCAL_ROLLOUT_EXECUTION_FILENAME);
33
+ }
34
+ export async function readProviderOperatorAutopilotLocalRolloutExecutionRecords(executionPath) {
35
+ let raw;
36
+ try {
37
+ raw = await readFile(executionPath, 'utf8');
38
+ }
39
+ catch (error) {
40
+ if (error?.code === 'ENOENT') {
41
+ return [];
42
+ }
43
+ throw error;
44
+ }
45
+ const parsed = JSON.parse(raw);
46
+ return parseExecutionStore(parsed).records;
47
+ }
48
+ export async function appendProviderOperatorAutopilotLocalRolloutExecutionRecord(executionPath, record) {
49
+ return withExecutionWriteLock(executionPath, async () => {
50
+ const records = await readProviderOperatorAutopilotLocalRolloutExecutionRecords(executionPath);
51
+ const nextStore = {
52
+ version: 1,
53
+ records: [...records, cloneLocalRolloutExecutionAttempt(record)]
54
+ };
55
+ await writeExecutionStore(executionPath, nextStore);
56
+ return {
57
+ version: 1,
58
+ records: nextStore.records.map(cloneLocalRolloutExecutionAttempt)
59
+ };
60
+ });
61
+ }
62
+ export function cloneLocalRolloutExecutionAttempt(record) {
63
+ return {
64
+ record_kind: record.record_kind ?? 'terminal',
65
+ action_instance_id: record.action_instance_id,
66
+ action_id: record.action_id,
67
+ issue_id: record.issue_id,
68
+ issue_identifier: record.issue_identifier,
69
+ preflight: { ...record.preflight },
70
+ started_at: record.started_at,
71
+ ended_at: record.ended_at,
72
+ terminal_state: record.terminal_state,
73
+ reason: record.reason,
74
+ summary: record.summary,
75
+ command: {
76
+ runner: record.command.runner,
77
+ command: record.command.command,
78
+ args: [...record.command.args],
79
+ cwd: record.command.cwd,
80
+ timeout_ms: record.command.timeout_ms
81
+ },
82
+ exit_code: record.exit_code,
83
+ stdout: record.stdout,
84
+ stderr: record.stderr
85
+ };
86
+ }
87
+ export function resolveProviderOperatorAutopilotLocalRolloutExecutionConfig(value) {
88
+ const postMergeRollout = asRecord(value);
89
+ const execution = asRecord(postMergeRollout?.execution ?? postMergeRollout?.local_rollout_execution);
90
+ const enabled = readBoolean(execution, 'enabled') ?? false;
91
+ const actionValues = Array.isArray(execution?.actions) ? execution.actions : [];
92
+ const actions = actionValues
93
+ .map(parseActionConfig)
94
+ .filter((action) => Boolean(action))
95
+ .sort(compareActionConfig);
96
+ return { enabled, actions };
97
+ }
98
+ export function resolveEnabledLocalRolloutExecutionActionIds(config) {
99
+ if (!config.enabled) {
100
+ return [];
101
+ }
102
+ return uniqueStrings(config.actions.filter((action) => action.enabled).sort(compareActionConfig).map((action) => action.id));
103
+ }
104
+ export async function executeProviderOperatorAutopilotLocalRolloutActions(input, deps = {}) {
105
+ const now = deps.now ?? isoTimestamp;
106
+ const platform = deps.platform ?? process.platform;
107
+ const runCommand = deps.runCommand ?? runLocalRolloutCommand;
108
+ const fileExists = deps.fileExists ?? defaultFileExists;
109
+ const actionMap = buildActionConfigMap(input.config.actions);
110
+ const priorAttempts = (input.priorAttempts ?? []).map(cloneLocalRolloutExecutionAttempt);
111
+ const relevantAttempts = [];
112
+ const lifecycleRecords = [];
113
+ if (!input.config.enabled) {
114
+ return { attempts: [], lifecycle_records: [] };
115
+ }
116
+ const priorByActionKey = new Map();
117
+ const priorAttemptsByActionKey = new Map();
118
+ const priorByActionKeyForEmptyProjection = new Map();
119
+ for (const attempt of priorAttempts) {
120
+ const attemptKey = executionAttemptKey(attempt);
121
+ priorByActionKey.set(attemptKey, selectPriorExecutionAttempt(priorByActionKey.get(attemptKey), attempt));
122
+ priorAttemptsByActionKey.set(attemptKey, [
123
+ ...(priorAttemptsByActionKey.get(attemptKey) ?? []),
124
+ cloneLocalRolloutExecutionAttempt(attempt)
125
+ ]);
126
+ priorByActionKeyForEmptyProjection.set(attemptKey, selectPriorExecutionAttemptForProjection(priorByActionKeyForEmptyProjection.get(attemptKey), attempt));
127
+ }
128
+ for (const pendingAction of input.pendingActions) {
129
+ const actionIds = uniqueStrings(pendingAction.executable_action_ids ?? []);
130
+ const succeededActionIds = new Set();
131
+ let sawNonSuccess = false;
132
+ if (actionIds.length === 0) {
133
+ appendPriorAttemptsForActionInstance({
134
+ target: relevantAttempts,
135
+ priorByActionKey: priorByActionKeyForEmptyProjection,
136
+ priorAttemptsByActionKey,
137
+ actionInstanceId: pendingAction.action_instance_id
138
+ });
139
+ continue;
140
+ }
141
+ for (const actionId of actionIds) {
142
+ const actionKey = `${pendingAction.action_instance_id}\u0000${actionId}`;
143
+ const priorAttempt = priorByActionKey.get(actionKey);
144
+ const priorAttemptCandidates = priorAttemptsByActionKey.get(actionKey) ?? [];
145
+ if (priorAttempt && shouldReusePriorExecutionAttempt(priorAttempt, priorAttemptCandidates)) {
146
+ relevantAttempts.push(...selectPriorExecutionAttemptsForReuse(priorAttemptCandidates, priorAttempt));
147
+ if (isSucceededTerminalAttempt(priorAttempt)) {
148
+ succeededActionIds.add(actionId);
149
+ }
150
+ else {
151
+ sawNonSuccess = true;
152
+ break;
153
+ }
154
+ continue;
155
+ }
156
+ const actionResult = await runSingleLocalRolloutAction({
157
+ action: actionMap.get(actionId) ?? null,
158
+ actionId,
159
+ pendingAction,
160
+ repoRoot: input.repoRoot,
161
+ now,
162
+ platform,
163
+ runCommand,
164
+ fileExists,
165
+ appendExecutionAttempt: deps.appendExecutionAttempt
166
+ });
167
+ const shouldAppendTerminalAttempt = Boolean(deps.appendExecutionAttempt) && actionResult.appendTerminalAttempt;
168
+ const recordsReadyForProjection = shouldAppendTerminalAttempt
169
+ ? actionResult.records.filter((record) => record !== actionResult.terminalAttempt)
170
+ : actionResult.records;
171
+ for (const record of recordsReadyForProjection) {
172
+ relevantAttempts.push(cloneLocalRolloutExecutionAttempt(record));
173
+ }
174
+ const attempt = actionResult.terminalAttempt;
175
+ let terminalAttemptPersisted = false;
176
+ if (!actionResult.appendTerminalAttempt) {
177
+ terminalAttemptPersisted = false;
178
+ }
179
+ if (deps.appendExecutionAttempt && actionResult.appendTerminalAttempt) {
180
+ try {
181
+ await deps.appendExecutionAttempt(attempt);
182
+ terminalAttemptPersisted = true;
183
+ relevantAttempts.push(cloneLocalRolloutExecutionAttempt(attempt));
184
+ }
185
+ catch {
186
+ const failedAttempt = buildSyntheticAttempt({
187
+ pendingAction,
188
+ actionId,
189
+ now,
190
+ state: 'failed',
191
+ reason: 'execution_audit_failed',
192
+ summary: 'Local rollout command finished, but terminal execution audit persistence failed.'
193
+ });
194
+ relevantAttempts.push(cloneLocalRolloutExecutionAttempt(failedAttempt));
195
+ }
196
+ }
197
+ if (isSucceededTerminalAttempt(attempt) && terminalAttemptPersisted) {
198
+ succeededActionIds.add(actionId);
199
+ }
200
+ else {
201
+ sawNonSuccess = true;
202
+ break;
203
+ }
204
+ }
205
+ if (!sawNonSuccess && succeededActionIds.size === actionIds.length) {
206
+ if (!deps.appendLifecycleRecord) {
207
+ const failedAttempt = buildSyntheticAttempt({
208
+ pendingAction,
209
+ actionId: actionIds.at(-1) ?? 'unknown',
210
+ now,
211
+ state: 'failed',
212
+ reason: 'lifecycle_record_failed',
213
+ summary: 'Local rollout actions succeeded, but lifecycle clear persistence is unavailable.'
214
+ });
215
+ relevantAttempts.push(cloneLocalRolloutExecutionAttempt(failedAttempt));
216
+ continue;
217
+ }
218
+ const lifecycleRecord = {
219
+ action_instance_id: pendingAction.action_instance_id,
220
+ kind: 'local_rollout',
221
+ issue_id: pendingAction.issue_id,
222
+ issue_identifier: pendingAction.issue_identifier,
223
+ state: 'cleared',
224
+ actor: 'operator-autopilot',
225
+ reason: `unattended local rollout actions succeeded: ${actionIds.join(', ')}`,
226
+ recorded_at: now(),
227
+ source: 'operator-autopilot'
228
+ };
229
+ try {
230
+ await deps.appendLifecycleRecord(lifecycleRecord);
231
+ lifecycleRecords.push(lifecycleRecord);
232
+ }
233
+ catch {
234
+ const failedAttempt = buildSyntheticAttempt({
235
+ pendingAction,
236
+ actionId: actionIds.at(-1) ?? 'unknown',
237
+ now,
238
+ state: 'failed',
239
+ reason: 'lifecycle_record_failed',
240
+ summary: 'Local rollout actions succeeded, but lifecycle clear persistence failed.'
241
+ });
242
+ relevantAttempts.push(cloneLocalRolloutExecutionAttempt(failedAttempt));
243
+ }
244
+ }
245
+ }
246
+ return {
247
+ attempts: relevantAttempts.map(cloneLocalRolloutExecutionAttempt),
248
+ lifecycle_records: lifecycleRecords
249
+ };
250
+ }
251
+ function appendPriorAttemptsForActionInstance(input) {
252
+ for (const [actionKey, attempt] of input.priorByActionKey.entries()) {
253
+ if (attempt.action_instance_id !== input.actionInstanceId) {
254
+ continue;
255
+ }
256
+ input.target.push(...selectPriorExecutionAttemptsForReuse(input.priorAttemptsByActionKey.get(actionKey) ?? [], attempt));
257
+ }
258
+ }
259
+ function parseActionConfig(value) {
260
+ const record = asRecord(value);
261
+ if (!record) {
262
+ return null;
263
+ }
264
+ const id = readNonEmptyString(record, 'id');
265
+ const runner = normalizeRunnerKind(record.runner);
266
+ if (!id || !runner) {
267
+ return null;
268
+ }
269
+ const platformConfig = readPlatformArray(record, 'supported_platforms', 'supportedPlatforms');
270
+ return {
271
+ id,
272
+ enabled: readBoolean(record, 'enabled') ?? false,
273
+ order: readInteger(record, 'order') ?? Number.MAX_SAFE_INTEGER,
274
+ runner,
275
+ args: readStringArray(record, 'args') ?? [],
276
+ script: readNonEmptyString(record, 'script'),
277
+ timeout_ms: readPositiveInteger(record, 'timeout_ms', 'timeoutMs') ??
278
+ DEFAULT_LOCAL_ROLLOUT_EXECUTION_TIMEOUT_MS,
279
+ require_clean_repo: readBoolean(record, 'require_clean_repo', 'requireCleanRepo') ?? true,
280
+ required_branch: readNonEmptyString(record, 'required_branch', 'requiredBranch'),
281
+ supported_platforms: platformConfig?.supported ?? [],
282
+ invalid_supported_platforms: platformConfig?.invalid ?? [],
283
+ deploy_class: readBoolean(record, 'deploy_class', 'deployClass') ?? false,
284
+ deploy_opt_in: readBoolean(record, 'deploy_opt_in', 'deployOptIn') ?? false,
285
+ requires_issue_identifier: readBoolean(record, 'requires_issue_identifier', 'requiresIssueIdentifier') ?? false
286
+ };
287
+ }
288
+ function compareActionConfig(left, right) {
289
+ if (left.order !== right.order) {
290
+ return left.order - right.order;
291
+ }
292
+ return left.id.localeCompare(right.id);
293
+ }
294
+ function buildActionConfigMap(actions) {
295
+ const actionMap = new Map();
296
+ for (const action of [...actions].sort(compareActionConfig)) {
297
+ const existing = actionMap.get(action.id);
298
+ if (!existing || (!existing.enabled && action.enabled)) {
299
+ actionMap.set(action.id, action);
300
+ }
301
+ }
302
+ return actionMap;
303
+ }
304
+ async function runSingleLocalRolloutAction(input) {
305
+ const checkedAt = input.now();
306
+ if (!input.appendExecutionAttempt) {
307
+ const failedAttempt = buildAttempt({
308
+ pendingAction: input.pendingAction,
309
+ actionId: input.actionId,
310
+ preflight: {
311
+ status: 'failed',
312
+ reason: 'execution_audit_failed',
313
+ checked_at: checkedAt,
314
+ summary: 'Local rollout action was not launched because execution audit persistence is unavailable.'
315
+ },
316
+ startedAt: null,
317
+ endedAt: input.now(),
318
+ terminalState: 'failed',
319
+ reason: 'execution_audit_failed',
320
+ summary: 'Local rollout action was not launched because execution audit persistence is unavailable.',
321
+ command: {
322
+ runner: input.action?.runner ?? null,
323
+ command: null,
324
+ args: [],
325
+ cwd: input.repoRoot,
326
+ timeout_ms: input.action?.timeout_ms ?? null
327
+ },
328
+ exitCode: null,
329
+ stdout: null,
330
+ stderr: null
331
+ });
332
+ return {
333
+ records: [failedAttempt],
334
+ terminalAttempt: failedAttempt,
335
+ appendTerminalAttempt: false
336
+ };
337
+ }
338
+ const preflight = await preflightLocalRolloutAction(input);
339
+ if (preflight.status !== 'passed' || !preflight.command) {
340
+ const attempt = buildAttempt({
341
+ pendingAction: input.pendingAction,
342
+ actionId: input.actionId,
343
+ preflight: {
344
+ status: preflight.status,
345
+ reason: preflight.reason,
346
+ checked_at: checkedAt,
347
+ summary: preflight.summary
348
+ },
349
+ startedAt: null,
350
+ endedAt: input.now(),
351
+ terminalState: preflight.status === 'failed' ? 'failed' : 'skipped',
352
+ reason: preflight.reason,
353
+ summary: preflight.summary,
354
+ command: preflight.command,
355
+ exitCode: null,
356
+ stdout: null,
357
+ stderr: null
358
+ });
359
+ return { records: [attempt], terminalAttempt: attempt, appendTerminalAttempt: true };
360
+ }
361
+ const command = preflight.command;
362
+ if (!command.command || !command.cwd || command.timeout_ms === null) {
363
+ const attempt = buildAttempt({
364
+ pendingAction: input.pendingAction,
365
+ actionId: input.actionId,
366
+ preflight: {
367
+ status: 'skipped',
368
+ reason: 'missing_binary',
369
+ checked_at: checkedAt,
370
+ summary: `Local rollout action ${input.actionId} could not resolve its runner binary.`
371
+ },
372
+ startedAt: null,
373
+ endedAt: input.now(),
374
+ terminalState: 'skipped',
375
+ reason: 'missing_binary',
376
+ summary: `Local rollout action ${input.actionId} could not resolve its runner binary.`,
377
+ command,
378
+ exitCode: null,
379
+ stdout: null,
380
+ stderr: null
381
+ });
382
+ return { records: [attempt], terminalAttempt: attempt, appendTerminalAttempt: true };
383
+ }
384
+ const startedAt = input.now();
385
+ const startedAttempt = buildAttempt({
386
+ pendingAction: input.pendingAction,
387
+ actionId: input.actionId,
388
+ recordKind: 'started',
389
+ preflight: {
390
+ status: 'passed',
391
+ reason: null,
392
+ checked_at: checkedAt,
393
+ summary: 'Local rollout action preflight passed.'
394
+ },
395
+ startedAt,
396
+ endedAt: startedAt,
397
+ terminalState: 'failed',
398
+ reason: 'execution_interrupted',
399
+ summary: `Local rollout action ${input.actionId} started; terminal result has not been recorded.`,
400
+ command: preflight.command,
401
+ exitCode: null,
402
+ stdout: null,
403
+ stderr: null
404
+ });
405
+ try {
406
+ await input.appendExecutionAttempt?.(startedAttempt);
407
+ }
408
+ catch {
409
+ const failedAttempt = buildAttempt({
410
+ pendingAction: input.pendingAction,
411
+ actionId: input.actionId,
412
+ preflight: {
413
+ status: 'failed',
414
+ reason: 'execution_audit_failed',
415
+ checked_at: checkedAt,
416
+ summary: 'Local rollout action preflight passed, but started audit persistence failed.'
417
+ },
418
+ startedAt: null,
419
+ endedAt: input.now(),
420
+ terminalState: 'failed',
421
+ reason: 'execution_audit_failed',
422
+ summary: 'Local rollout action was not launched because started audit persistence failed.',
423
+ command: preflight.command,
424
+ exitCode: null,
425
+ stdout: null,
426
+ stderr: null
427
+ });
428
+ return {
429
+ records: [failedAttempt],
430
+ terminalAttempt: failedAttempt,
431
+ appendTerminalAttempt: false
432
+ };
433
+ }
434
+ const result = await input.runCommand({
435
+ command: command.command,
436
+ args: command.args,
437
+ cwd: command.cwd,
438
+ timeoutMs: command.timeout_ms
439
+ });
440
+ const endedAt = input.now();
441
+ const terminalAttempt = buildAttempt({
442
+ pendingAction: input.pendingAction,
443
+ actionId: input.actionId,
444
+ preflight: {
445
+ status: 'passed',
446
+ reason: null,
447
+ checked_at: checkedAt,
448
+ summary: 'Local rollout action preflight passed.'
449
+ },
450
+ startedAt,
451
+ endedAt,
452
+ terminalState: result.ok ? 'succeeded' : 'failed',
453
+ reason: result.ok ? null : 'command_failed',
454
+ summary: result.ok
455
+ ? `Executed local rollout action ${input.actionId}.`
456
+ : `Local rollout action ${input.actionId} failed.`,
457
+ command: preflight.command,
458
+ exitCode: result.exitCode,
459
+ stdout: result.stdout,
460
+ stderr: result.stderr
461
+ });
462
+ return {
463
+ records: [startedAttempt, terminalAttempt],
464
+ terminalAttempt,
465
+ appendTerminalAttempt: true
466
+ };
467
+ }
468
+ async function preflightLocalRolloutAction(input) {
469
+ const action = input.action;
470
+ if (!action) {
471
+ return preflightSkip('undeclared_action', `Local rollout action ${input.actionId} is not declared.`);
472
+ }
473
+ if (!action.enabled) {
474
+ return preflightSkip('missing_config', `Local rollout action ${action.id} is disabled.`);
475
+ }
476
+ if (action.deploy_class && !action.deploy_opt_in) {
477
+ return preflightSkip('deploy_class_not_opted_in', `Deploy-class local rollout action ${action.id} is not explicitly opted in.`);
478
+ }
479
+ if (action.invalid_supported_platforms.length > 0) {
480
+ return preflightSkip('unsupported_host', `Local rollout action ${action.id} has unsupported platform entries: ${action.invalid_supported_platforms.join(', ')}.`);
481
+ }
482
+ if (action.supported_platforms.length > 0 &&
483
+ !action.supported_platforms.includes(input.platform)) {
484
+ return preflightSkip('unsupported_host', `Local rollout action ${action.id} does not support host platform ${input.platform}.`);
485
+ }
486
+ if (action.requires_issue_identifier && !input.pendingAction.issue_identifier) {
487
+ return preflightSkip('ambiguous_target', `Local rollout action ${action.id} requires an issue identifier.`);
488
+ }
489
+ if (action.require_clean_repo) {
490
+ const statusResult = await input.runCommand({
491
+ command: 'git',
492
+ args: ['-C', input.repoRoot, 'status', '--porcelain'],
493
+ cwd: input.repoRoot,
494
+ timeoutMs: DEFAULT_LOCAL_ROLLOUT_EXECUTION_TIMEOUT_MS
495
+ });
496
+ if (!statusResult.ok) {
497
+ return preflightSkip('command_failed', normalizeCommandText(statusResult.stderr) ||
498
+ `Local rollout action ${action.id} could not verify repository cleanliness.`);
499
+ }
500
+ if (normalizeCommandText(statusResult.stdout)) {
501
+ return preflightSkip('dirty_repo', `Local rollout action ${action.id} requires a clean repository.`);
502
+ }
503
+ }
504
+ if (action.required_branch) {
505
+ const branchResult = await input.runCommand({
506
+ command: 'git',
507
+ args: ['-C', input.repoRoot, 'branch', '--show-current'],
508
+ cwd: input.repoRoot,
509
+ timeoutMs: DEFAULT_LOCAL_ROLLOUT_EXECUTION_TIMEOUT_MS
510
+ });
511
+ if (!branchResult.ok) {
512
+ return preflightSkip('command_failed', normalizeCommandText(branchResult.stderr) ||
513
+ `Local rollout action ${action.id} could not verify the current branch.`);
514
+ }
515
+ const currentBranch = normalizeCommandText(branchResult.stdout);
516
+ if (currentBranch !== action.required_branch) {
517
+ return preflightSkip('wrong_branch', `Local rollout action ${action.id} requires branch ${action.required_branch}; current branch is ${currentBranch || 'detached'}.`);
518
+ }
519
+ }
520
+ const command = await resolveActionCommand({
521
+ action,
522
+ repoRoot: input.repoRoot,
523
+ platform: input.platform,
524
+ fileExists: input.fileExists
525
+ });
526
+ if (!command) {
527
+ return preflightSkip('missing_binary', `Local rollout action ${action.id} could not resolve its runner binary.`);
528
+ }
529
+ return {
530
+ status: 'passed',
531
+ reason: null,
532
+ summary: 'Local rollout action preflight passed.',
533
+ command
534
+ };
535
+ }
536
+ function preflightSkip(reason, summary) {
537
+ return {
538
+ status: reason === 'command_failed' || reason === 'lifecycle_record_failed' ? 'failed' : 'skipped',
539
+ reason,
540
+ summary,
541
+ command: null
542
+ };
543
+ }
544
+ async function resolveActionCommand(input) {
545
+ if (input.action.runner === 'codex_orchestrator') {
546
+ const cliPath = join(input.repoRoot, 'bin', 'codex-orchestrator.js');
547
+ if (!(await input.fileExists(cliPath))) {
548
+ return null;
549
+ }
550
+ return {
551
+ runner: 'codex_orchestrator',
552
+ command: process.execPath,
553
+ args: [cliPath, ...input.action.args],
554
+ cwd: input.repoRoot,
555
+ timeout_ms: input.action.timeout_ms
556
+ };
557
+ }
558
+ if (input.action.runner === 'npm_script') {
559
+ if (!input.action.script) {
560
+ return null;
561
+ }
562
+ const packageJsonPath = join(input.repoRoot, 'package.json');
563
+ if (!(await input.fileExists(packageJsonPath))) {
564
+ return null;
565
+ }
566
+ return {
567
+ runner: 'npm_script',
568
+ command: input.platform === 'win32' ? 'npm.cmd' : 'npm',
569
+ args: [
570
+ 'run',
571
+ input.action.script,
572
+ ...(input.action.args.length > 0 ? ['--', ...input.action.args] : [])
573
+ ],
574
+ cwd: input.repoRoot,
575
+ timeout_ms: input.action.timeout_ms
576
+ };
577
+ }
578
+ return null;
579
+ }
580
+ function buildSyntheticAttempt(input) {
581
+ const at = input.now();
582
+ return buildAttempt({
583
+ pendingAction: input.pendingAction,
584
+ actionId: input.actionId,
585
+ preflight: {
586
+ status: 'failed',
587
+ reason: input.reason,
588
+ checked_at: at,
589
+ summary: input.summary
590
+ },
591
+ startedAt: null,
592
+ endedAt: at,
593
+ terminalState: input.state,
594
+ reason: input.reason,
595
+ summary: input.summary,
596
+ command: null,
597
+ exitCode: null,
598
+ stdout: null,
599
+ stderr: null
600
+ });
601
+ }
602
+ function buildAttempt(input) {
603
+ return {
604
+ record_kind: input.recordKind ?? 'terminal',
605
+ action_instance_id: input.pendingAction.action_instance_id,
606
+ action_id: input.actionId,
607
+ issue_id: input.pendingAction.issue_id,
608
+ issue_identifier: input.pendingAction.issue_identifier,
609
+ preflight: input.preflight,
610
+ started_at: input.startedAt,
611
+ ended_at: input.endedAt,
612
+ terminal_state: input.terminalState,
613
+ reason: input.reason,
614
+ summary: input.summary,
615
+ command: input.command ?? {
616
+ runner: null,
617
+ command: null,
618
+ args: [],
619
+ cwd: null,
620
+ timeout_ms: null
621
+ },
622
+ exit_code: input.exitCode,
623
+ stdout: input.stdout,
624
+ stderr: input.stderr
625
+ };
626
+ }
627
+ function selectPriorExecutionAttemptsForReuse(candidates, selected) {
628
+ if (selected.record_kind !== 'terminal' || selected.reason !== 'execution_audit_failed') {
629
+ return [cloneLocalRolloutExecutionAttempt(selected)];
630
+ }
631
+ const started = candidates
632
+ .filter((candidate) => candidate.record_kind === 'started')
633
+ .reduce((current, candidate) => current
634
+ ? selectPriorExecutionAttemptForProjection(current, candidate)
635
+ : candidate, null);
636
+ return [
637
+ ...(started ? [cloneLocalRolloutExecutionAttempt(started)] : []),
638
+ cloneLocalRolloutExecutionAttempt(selected)
639
+ ];
640
+ }
641
+ function selectPriorExecutionAttempt(existing, candidate) {
642
+ if (!existing) {
643
+ return candidate;
644
+ }
645
+ const recency = compareExecutionAttemptRecency(candidate, existing);
646
+ if (recency > 0 && candidate.record_kind === 'started') {
647
+ return candidate;
648
+ }
649
+ if (recency < 0 && existing.record_kind === 'started') {
650
+ return existing;
651
+ }
652
+ if (candidate.reason === 'lifecycle_record_failed' &&
653
+ isSucceededTerminalAttempt(existing)) {
654
+ return existing;
655
+ }
656
+ if (existing.reason === 'lifecycle_record_failed' &&
657
+ isSucceededTerminalAttempt(candidate)) {
658
+ return candidate;
659
+ }
660
+ if (recency > 0) {
661
+ return candidate;
662
+ }
663
+ if (recency < 0) {
664
+ return existing;
665
+ }
666
+ if (candidate.record_kind === 'terminal') {
667
+ return candidate;
668
+ }
669
+ if (existing.record_kind === 'terminal') {
670
+ return existing;
671
+ }
672
+ return candidate;
673
+ }
674
+ function selectPriorExecutionAttemptForProjection(existing, candidate) {
675
+ if (!existing) {
676
+ return candidate;
677
+ }
678
+ const recency = compareExecutionAttemptRecency(candidate, existing);
679
+ if (recency > 0) {
680
+ return candidate;
681
+ }
682
+ if (recency < 0) {
683
+ return existing;
684
+ }
685
+ if (candidate.record_kind === 'terminal') {
686
+ return candidate;
687
+ }
688
+ if (existing.record_kind === 'terminal') {
689
+ return existing;
690
+ }
691
+ return candidate;
692
+ }
693
+ function shouldReusePriorExecutionAttempt(attempt, candidates) {
694
+ if (attempt.record_kind === 'started') {
695
+ return true;
696
+ }
697
+ if (attempt.reason === 'execution_audit_failed') {
698
+ return candidates.some((candidate) => candidate.record_kind === 'started');
699
+ }
700
+ return attempt.terminal_state !== 'skipped';
701
+ }
702
+ function isSucceededTerminalAttempt(attempt) {
703
+ return attempt.record_kind === 'terminal' && attempt.terminal_state === 'succeeded';
704
+ }
705
+ function compareExecutionAttemptRecency(left, right) {
706
+ const leftTime = executionAttemptRecordedAtMs(left);
707
+ const rightTime = executionAttemptRecordedAtMs(right);
708
+ if (leftTime !== null && rightTime !== null && leftTime !== rightTime) {
709
+ return leftTime > rightTime ? 1 : -1;
710
+ }
711
+ if (leftTime !== null && rightTime === null) {
712
+ return 1;
713
+ }
714
+ if (leftTime === null && rightTime !== null) {
715
+ return -1;
716
+ }
717
+ return 0;
718
+ }
719
+ function executionAttemptRecordedAtMs(attempt) {
720
+ return parseExecutionAttemptTimestamp(attempt.ended_at || attempt.started_at || attempt.preflight.checked_at);
721
+ }
722
+ function parseExecutionAttemptTimestamp(value) {
723
+ if (!value) {
724
+ return null;
725
+ }
726
+ const parsed = Date.parse(value);
727
+ return Number.isFinite(parsed) ? parsed : null;
728
+ }
729
+ async function runLocalRolloutCommand(input) {
730
+ try {
731
+ const { stdout, stderr } = await execFileAsync(input.command, input.args, {
732
+ cwd: input.cwd,
733
+ timeout: input.timeoutMs,
734
+ maxBuffer: 10 * 1024 * 1024,
735
+ shell: shouldUseShellForLocalRolloutCommand(input.command)
736
+ });
737
+ return { ok: true, exitCode: 0, stdout, stderr };
738
+ }
739
+ catch (error) {
740
+ const execError = error;
741
+ return {
742
+ ok: false,
743
+ exitCode: typeof execError.code === 'number' ? execError.code : null,
744
+ stdout: execError.stdout ?? '',
745
+ stderr: execError.stderr ?? execError.message
746
+ };
747
+ }
748
+ }
749
+ export function shouldUseShellForLocalRolloutCommand(command, platform = process.platform) {
750
+ return platform === 'win32' && /\.(?:cmd|bat)$/i.test(command);
751
+ }
752
+ function executionAttemptKey(attempt) {
753
+ return `${attempt.action_instance_id}\u0000${attempt.action_id}`;
754
+ }
755
+ async function defaultFileExists(path) {
756
+ try {
757
+ await access(path);
758
+ return true;
759
+ }
760
+ catch {
761
+ return false;
762
+ }
763
+ }
764
+ function normalizeCommandText(value) {
765
+ return (value ?? '').trim();
766
+ }
767
+ async function writeExecutionStore(executionPath, store) {
768
+ await mkdir(dirname(executionPath), { recursive: true });
769
+ const tempPath = `${executionPath}.${process.pid}.${Date.now()}.${Math.random()
770
+ .toString(16)
771
+ .slice(2)}.tmp`;
772
+ try {
773
+ await writeFile(tempPath, `${JSON.stringify(store, null, 2)}\n`, 'utf8');
774
+ await rename(tempPath, executionPath);
775
+ }
776
+ catch (error) {
777
+ await rm(tempPath, { force: true }).catch(() => undefined);
778
+ throw error;
779
+ }
780
+ }
781
+ async function withExecutionWriteLock(executionPath, body) {
782
+ const lockPath = `${executionPath}.lock`;
783
+ const lock = await acquireLockWithRetry({
784
+ taskId: 'provider-operator-autopilot-local-rollout-execution',
785
+ lockPath,
786
+ retry: LOCAL_ROLLOUT_EXECUTION_LOCK_RETRY,
787
+ ensureDirectory: async () => {
788
+ await mkdir(dirname(lockPath), { recursive: true });
789
+ },
790
+ createError: (_taskId, attempts) => new Error(`Timed out waiting for local rollout execution store lock after ${attempts} attempts.`)
791
+ });
792
+ try {
793
+ return await body();
794
+ }
795
+ finally {
796
+ await lock.release();
797
+ }
798
+ }
799
+ function parseExecutionStore(value) {
800
+ const record = asRecord(value);
801
+ if (!record || record.version !== 1 || !Array.isArray(record.records)) {
802
+ throw new Error('Operator autopilot local rollout execution store is malformed.');
803
+ }
804
+ const records = record.records.map(parseExecutionAttemptRecord);
805
+ if (records.some((entry) => entry === null)) {
806
+ throw new Error('Operator autopilot local rollout execution store contains malformed records.');
807
+ }
808
+ return {
809
+ version: 1,
810
+ records: records.map((entry) => cloneLocalRolloutExecutionAttempt(entry))
811
+ };
812
+ }
813
+ function parseExecutionAttemptRecord(value) {
814
+ const record = asRecord(value);
815
+ const preflight = asRecord(record?.preflight);
816
+ const command = asRecord(record?.command);
817
+ if (!record || !preflight || !command) {
818
+ return null;
819
+ }
820
+ const actionInstanceId = readNonEmptyString(record, 'action_instance_id');
821
+ const actionId = readNonEmptyString(record, 'action_id');
822
+ const issueId = readNonEmptyString(record, 'issue_id');
823
+ const checkedAt = readNonEmptyString(preflight, 'checked_at');
824
+ const endedAt = readNonEmptyString(record, 'ended_at');
825
+ const terminalState = normalizeTerminalState(record.terminal_state);
826
+ const preflightStatus = normalizePreflightStatus(preflight.status);
827
+ const preflightReason = normalizePreflightReason(preflight.reason);
828
+ const reason = normalizePreflightReason(record.reason);
829
+ if (!actionInstanceId || !actionId || !issueId || !checkedAt || !endedAt || !terminalState || !preflightStatus) {
830
+ return null;
831
+ }
832
+ return {
833
+ record_kind: normalizeExecutionRecordKind(record.record_kind),
834
+ action_instance_id: actionInstanceId,
835
+ action_id: actionId,
836
+ issue_id: issueId,
837
+ issue_identifier: readOptionalString(record, 'issue_identifier'),
838
+ preflight: {
839
+ status: preflightStatus,
840
+ reason: preflightReason,
841
+ checked_at: checkedAt,
842
+ summary: readNonEmptyString(preflight, 'summary') ?? ''
843
+ },
844
+ started_at: readOptionalString(record, 'started_at'),
845
+ ended_at: endedAt,
846
+ terminal_state: terminalState,
847
+ reason,
848
+ summary: readNonEmptyString(record, 'summary') ?? '',
849
+ command: {
850
+ runner: normalizeRunnerKind(command.runner),
851
+ command: readOptionalString(command, 'command'),
852
+ args: readStringArray(command, 'args') ?? [],
853
+ cwd: readOptionalString(command, 'cwd'),
854
+ timeout_ms: readInteger(command, 'timeout_ms')
855
+ },
856
+ exit_code: readInteger(record, 'exit_code'),
857
+ stdout: readRawOptionalString(record, 'stdout'),
858
+ stderr: readRawOptionalString(record, 'stderr')
859
+ };
860
+ }
861
+ function normalizeRunnerKind(value) {
862
+ return value === 'codex_orchestrator' || value === 'npm_script' ? value : null;
863
+ }
864
+ function normalizeTerminalState(value) {
865
+ return value === 'succeeded' || value === 'skipped' || value === 'failed'
866
+ ? value
867
+ : null;
868
+ }
869
+ function normalizeExecutionRecordKind(value) {
870
+ return value === 'started' || value === 'terminal' ? value : 'terminal';
871
+ }
872
+ function normalizePreflightStatus(value) {
873
+ return value === 'passed' || value === 'skipped' || value === 'failed' ? value : null;
874
+ }
875
+ function normalizePreflightReason(value) {
876
+ return value === 'missing_config' ||
877
+ value === 'undeclared_action' ||
878
+ value === 'dirty_repo' ||
879
+ value === 'wrong_branch' ||
880
+ value === 'missing_binary' ||
881
+ value === 'unsupported_host' ||
882
+ value === 'ambiguous_target' ||
883
+ value === 'deploy_class_not_opted_in' ||
884
+ value === 'execution_audit_failed' ||
885
+ value === 'execution_interrupted' ||
886
+ value === 'command_failed' ||
887
+ value === 'lifecycle_record_failed'
888
+ ? value
889
+ : null;
890
+ }
891
+ function asRecord(value) {
892
+ return typeof value === 'object' && value !== null ? value : null;
893
+ }
894
+ function readBoolean(record, ...keys) {
895
+ for (const key of keys) {
896
+ const value = record?.[key];
897
+ if (typeof value === 'boolean') {
898
+ return value;
899
+ }
900
+ }
901
+ return null;
902
+ }
903
+ function readNonEmptyString(record, ...keys) {
904
+ for (const key of keys) {
905
+ const value = record?.[key];
906
+ if (typeof value === 'string' && value.trim()) {
907
+ return value.trim();
908
+ }
909
+ }
910
+ return null;
911
+ }
912
+ function readOptionalString(record, ...keys) {
913
+ for (const key of keys) {
914
+ const value = record?.[key];
915
+ if (typeof value === 'string' && value.trim()) {
916
+ return value.trim();
917
+ }
918
+ }
919
+ return null;
920
+ }
921
+ function readRawOptionalString(record, ...keys) {
922
+ for (const key of keys) {
923
+ const value = record?.[key];
924
+ if (typeof value === 'string') {
925
+ return value;
926
+ }
927
+ }
928
+ return null;
929
+ }
930
+ function readStringArray(record, ...keys) {
931
+ for (const key of keys) {
932
+ const value = record?.[key];
933
+ if (!Array.isArray(value)) {
934
+ continue;
935
+ }
936
+ const strings = value
937
+ .map((entry) => (typeof entry === 'string' ? entry.trim() : ''))
938
+ .filter((entry) => entry.length > 0);
939
+ return strings;
940
+ }
941
+ return null;
942
+ }
943
+ function readPlatformArray(record, ...keys) {
944
+ for (const key of keys) {
945
+ if (!record || !(key in record)) {
946
+ continue;
947
+ }
948
+ const values = record[key];
949
+ if (!Array.isArray(values)) {
950
+ return { supported: [], invalid: [formatInvalidPlatformEntry(values)] };
951
+ }
952
+ const supported = [];
953
+ const invalid = [];
954
+ for (const value of values) {
955
+ if (typeof value !== 'string') {
956
+ invalid.push(formatInvalidPlatformEntry(value));
957
+ continue;
958
+ }
959
+ const platform = value.trim();
960
+ if (!platform) {
961
+ invalid.push(formatInvalidPlatformEntry(value));
962
+ }
963
+ else if (SUPPORTED_NODE_PLATFORMS.has(platform)) {
964
+ supported.push(platform);
965
+ }
966
+ else {
967
+ invalid.push(platform);
968
+ }
969
+ }
970
+ return { supported, invalid };
971
+ }
972
+ return null;
973
+ }
974
+ function formatInvalidPlatformEntry(value) {
975
+ if (typeof value === 'string') {
976
+ return value.trim() || '<blank>';
977
+ }
978
+ if (value === null) {
979
+ return 'null';
980
+ }
981
+ if (value === undefined) {
982
+ return 'undefined';
983
+ }
984
+ if (typeof value === 'number' ||
985
+ typeof value === 'boolean' ||
986
+ typeof value === 'bigint') {
987
+ return String(value);
988
+ }
989
+ return '<non-string>';
990
+ }
991
+ function uniqueStrings(values) {
992
+ return [...new Set(values)];
993
+ }
994
+ function readInteger(record, ...keys) {
995
+ for (const key of keys) {
996
+ const value = record?.[key];
997
+ if (typeof value === 'number' && Number.isInteger(value)) {
998
+ return value;
999
+ }
1000
+ }
1001
+ return null;
1002
+ }
1003
+ function readPositiveInteger(record, ...keys) {
1004
+ const value = readInteger(record, ...keys);
1005
+ return value !== null && value > 0 ? value : null;
1006
+ }