@kbediako/codex-orchestrator 0.1.38 → 0.2.0

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 (299) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/README.md +70 -301
  3. package/bin/codex-orchestrator.js +161 -0
  4. package/codex.orchestrator.json +149 -13
  5. package/dist/bin/codex-orchestrator.js +795 -1154
  6. package/dist/orchestrator/src/cli/adapters/CommandPlanner.js +22 -4
  7. package/dist/orchestrator/src/cli/adapters/CommandReviewer.js +3 -3
  8. package/dist/orchestrator/src/cli/adapters/CommandTester.js +2 -2
  9. package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +183 -11
  10. package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +402 -0
  11. package/dist/orchestrator/src/cli/coStatusCliShell.js +429 -0
  12. package/dist/orchestrator/src/cli/coStatusOperatorAutopilotCliShell.js +120 -0
  13. package/dist/orchestrator/src/cli/codexCliShell.js +72 -0
  14. package/dist/orchestrator/src/cli/codexDefaultsSetup.js +49 -11
  15. package/dist/orchestrator/src/cli/config/delegationConfig.js +317 -5
  16. package/dist/orchestrator/src/cli/config/repoConfigPolicy.js +2 -3
  17. package/dist/orchestrator/src/cli/config/userConfig.js +28 -13
  18. package/dist/orchestrator/src/cli/control/authenticatedControlRouteGate.js +69 -0
  19. package/dist/orchestrator/src/cli/control/authenticatedRouteComposition.js +267 -0
  20. package/dist/orchestrator/src/cli/control/authenticatedRouteController.js +5 -0
  21. package/dist/orchestrator/src/cli/control/authenticatedRouteDispatcher.js +41 -0
  22. package/dist/orchestrator/src/cli/control/compatibilityIssuePresenter.js +1035 -0
  23. package/dist/orchestrator/src/cli/control/confirmationApproveController.js +62 -0
  24. package/dist/orchestrator/src/cli/control/confirmationCreateController.js +69 -0
  25. package/dist/orchestrator/src/cli/control/confirmationIssueConsumeController.js +43 -0
  26. package/dist/orchestrator/src/cli/control/confirmationListController.js +22 -0
  27. package/dist/orchestrator/src/cli/control/confirmationValidateController.js +58 -0
  28. package/dist/orchestrator/src/cli/control/confirmations.js +25 -3
  29. package/dist/orchestrator/src/cli/control/controlActionCancelConfirmation.js +65 -0
  30. package/dist/orchestrator/src/cli/control/controlActionController.js +77 -0
  31. package/dist/orchestrator/src/cli/control/controlActionControllerSequencing.js +161 -0
  32. package/dist/orchestrator/src/cli/control/controlActionExecution.js +142 -0
  33. package/dist/orchestrator/src/cli/control/controlActionFinalization.js +43 -0
  34. package/dist/orchestrator/src/cli/control/controlActionOutcome.js +60 -0
  35. package/dist/orchestrator/src/cli/control/controlActionPreflight.js +476 -0
  36. package/dist/orchestrator/src/cli/control/controlAuthenticatedRouteHandoff.js +57 -0
  37. package/dist/orchestrator/src/cli/control/controlBootstrapAssembly.js +39 -0
  38. package/dist/orchestrator/src/cli/control/controlBootstrapMetadataPersistence.js +16 -0
  39. package/dist/orchestrator/src/cli/control/controlEventTransport.js +49 -0
  40. package/dist/orchestrator/src/cli/control/controlExpiryLifecycle.js +102 -0
  41. package/dist/orchestrator/src/cli/control/controlHostOwnership.js +480 -0
  42. package/dist/orchestrator/src/cli/control/controlHostSupervision.js +608 -0
  43. package/dist/orchestrator/src/cli/control/controlOversightFacade.js +8 -0
  44. package/dist/orchestrator/src/cli/control/controlOversightReadContract.js +1 -0
  45. package/dist/orchestrator/src/cli/control/controlOversightReadService.js +16 -0
  46. package/dist/orchestrator/src/cli/control/controlOversightUpdateContract.js +1 -0
  47. package/dist/orchestrator/src/cli/control/controlPersistenceFiles.js +6 -0
  48. package/dist/orchestrator/src/cli/control/controlQuestionChildResolution.js +18 -0
  49. package/dist/orchestrator/src/cli/control/controlRequestContext.js +42 -0
  50. package/dist/orchestrator/src/cli/control/controlRequestController.js +9 -0
  51. package/dist/orchestrator/src/cli/control/controlRequestPredispatch.js +17 -0
  52. package/dist/orchestrator/src/cli/control/controlRequestRouteDispatch.js +44 -0
  53. package/dist/orchestrator/src/cli/control/controlRuntime.js +992 -0
  54. package/dist/orchestrator/src/cli/control/controlServer.js +23 -1456
  55. package/dist/orchestrator/src/cli/control/controlServerAuditAndErrorHelpers.js +115 -0
  56. package/dist/orchestrator/src/cli/control/controlServerAuthenticatedRouteBranch.js +29 -0
  57. package/dist/orchestrator/src/cli/control/controlServerBootstrapLifecycle.js +30 -0
  58. package/dist/orchestrator/src/cli/control/controlServerBootstrapStartSequence.js +21 -0
  59. package/dist/orchestrator/src/cli/control/controlServerOwnedRuntimeLifecycle.js +67 -0
  60. package/dist/orchestrator/src/cli/control/controlServerPublicLifecycle.js +756 -0
  61. package/dist/orchestrator/src/cli/control/controlServerPublicRouteHelpers.js +86 -0
  62. package/dist/orchestrator/src/cli/control/controlServerReadyInstanceLifecycle.js +25 -0
  63. package/dist/orchestrator/src/cli/control/controlServerReadyInstanceStartup.js +18 -0
  64. package/dist/orchestrator/src/cli/control/controlServerRequestBodyHelpers.js +37 -0
  65. package/dist/orchestrator/src/cli/control/controlServerRequestShell.js +40 -0
  66. package/dist/orchestrator/src/cli/control/controlServerRequestShellBinding.js +17 -0
  67. package/dist/orchestrator/src/cli/control/controlServerSeedLoading.js +27 -0
  68. package/dist/orchestrator/src/cli/control/controlServerSeededRuntimeAssembly.js +186 -0
  69. package/dist/orchestrator/src/cli/control/controlServerStartupInputPreparation.js +31 -0
  70. package/dist/orchestrator/src/cli/control/controlServerStartupSequence.js +49 -0
  71. package/dist/orchestrator/src/cli/control/controlState.js +233 -2
  72. package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +1899 -0
  73. package/dist/orchestrator/src/cli/control/controlTelegramBridgeBootstrapLifecycle.js +22 -0
  74. package/dist/orchestrator/src/cli/control/controlTelegramBridgeLifecycle.js +67 -0
  75. package/dist/orchestrator/src/cli/control/controlTelegramBridgeOversightFacadeFactory.js +8 -0
  76. package/dist/orchestrator/src/cli/control/controlTelegramCommandController.js +49 -0
  77. package/dist/orchestrator/src/cli/control/controlTelegramDispatchRead.js +40 -0
  78. package/dist/orchestrator/src/cli/control/controlTelegramPollingController.js +89 -0
  79. package/dist/orchestrator/src/cli/control/controlTelegramProjectionNotificationController.js +29 -0
  80. package/dist/orchestrator/src/cli/control/controlTelegramPushState.js +63 -0
  81. package/dist/orchestrator/src/cli/control/controlTelegramQuestionRead.js +13 -0
  82. package/dist/orchestrator/src/cli/control/controlTelegramReadController.js +216 -0
  83. package/dist/orchestrator/src/cli/control/controlTelegramUpdateHandler.js +63 -0
  84. package/dist/orchestrator/src/cli/control/controlWatcher.js +73 -5
  85. package/dist/orchestrator/src/cli/control/delegationRegisterController.js +35 -0
  86. package/dist/orchestrator/src/cli/control/dynamicToolBridgePolicy.js +139 -0
  87. package/dist/orchestrator/src/cli/control/eventsSseController.js +12 -0
  88. package/dist/orchestrator/src/cli/control/linearBudgetState.js +1789 -0
  89. package/dist/orchestrator/src/cli/control/linearDispatchSource.js +1137 -0
  90. package/dist/orchestrator/src/cli/control/linearGraphqlClient.js +150 -0
  91. package/dist/orchestrator/src/cli/control/linearRateLimit.js +102 -0
  92. package/dist/orchestrator/src/cli/control/linearWebhookController.js +499 -0
  93. package/dist/orchestrator/src/cli/control/liveLinearAdvisoryRuntime.js +70 -0
  94. package/dist/orchestrator/src/cli/control/observabilityApiController.js +173 -0
  95. package/dist/orchestrator/src/cli/control/observabilityReadModel.js +500 -0
  96. package/dist/orchestrator/src/cli/control/observabilitySurface.js +284 -0
  97. package/dist/orchestrator/src/cli/control/observabilityUpdateNotifier.js +22 -0
  98. package/dist/orchestrator/src/cli/control/operatorDashboardPresenter.js +252 -0
  99. package/dist/orchestrator/src/cli/control/providerAgentCapacity.js +70 -0
  100. package/dist/orchestrator/src/cli/control/providerControlHostFreshnessGauge.js +1068 -0
  101. package/dist/orchestrator/src/cli/control/providerIntakeState.js +473 -0
  102. package/dist/orchestrator/src/cli/control/providerIssueHandoff.js +6811 -0
  103. package/dist/orchestrator/src/cli/control/providerIssueObservability.js +1348 -0
  104. package/dist/orchestrator/src/cli/control/providerIssueRetryQueue.js +84 -0
  105. package/dist/orchestrator/src/cli/control/providerLinearRuntimeProof.js +588 -0
  106. package/dist/orchestrator/src/cli/control/providerLinearScreenshotProof.js +473 -0
  107. package/dist/orchestrator/src/cli/control/providerLinearWorkerTruth.js +383 -0
  108. package/dist/orchestrator/src/cli/control/providerLinearWorkflowAudit.js +254 -0
  109. package/dist/orchestrator/src/cli/control/providerLinearWorkflowFacade.js +5573 -0
  110. package/dist/orchestrator/src/cli/control/providerLinearWorkflowStates.js +115 -0
  111. package/dist/orchestrator/src/cli/control/providerMergeCloseout.js +1868 -0
  112. package/dist/orchestrator/src/cli/control/providerOperatorAutopilot.js +1580 -0
  113. package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLifecycle.js +154 -0
  114. package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLocalRolloutExecution.js +1006 -0
  115. package/dist/orchestrator/src/cli/control/providerPollingHealth.js +435 -0
  116. package/dist/orchestrator/src/cli/control/providerTerminalCleanup.js +516 -0
  117. package/dist/orchestrator/src/cli/control/providerWorkerHosts.js +191 -0
  118. package/dist/orchestrator/src/cli/control/providerWorkflowConfigStore.js +515 -0
  119. package/dist/orchestrator/src/cli/control/questionChildResolutionAdapter.js +361 -0
  120. package/dist/orchestrator/src/cli/control/questionQueueController.js +181 -0
  121. package/dist/orchestrator/src/cli/control/questionReadRetryDeduplication.js +9 -0
  122. package/dist/orchestrator/src/cli/control/questionReadSequence.js +10 -0
  123. package/dist/orchestrator/src/cli/control/securityViolationController.js +27 -0
  124. package/dist/orchestrator/src/cli/control/selectedRunProjection.js +1838 -0
  125. package/dist/orchestrator/src/cli/control/telegramOversightApiClient.js +48 -0
  126. package/dist/orchestrator/src/cli/control/telegramOversightBridge.js +180 -0
  127. package/dist/orchestrator/src/cli/control/telegramOversightBridgeProjectionDeliveryQueue.js +25 -0
  128. package/dist/orchestrator/src/cli/control/telegramOversightBridgeRuntimeLifecycle.js +45 -0
  129. package/dist/orchestrator/src/cli/control/telegramOversightBridgeStateStore.js +77 -0
  130. package/dist/orchestrator/src/cli/control/telegramOversightControlActionApiClient.js +45 -0
  131. package/dist/orchestrator/src/cli/control/trackerDispatchPilot.js +439 -0
  132. package/dist/orchestrator/src/cli/control/uiDataController.js +34 -0
  133. package/dist/orchestrator/src/cli/control/uiSessionController.js +100 -0
  134. package/dist/orchestrator/src/cli/controlHostCliShell.js +860 -0
  135. package/dist/orchestrator/src/cli/controlHostFreshnessGaugeCliShell.js +129 -0
  136. package/dist/orchestrator/src/cli/controlHostSupervisionCliShell.js +2127 -0
  137. package/dist/orchestrator/src/cli/delegationCliShell.js +62 -0
  138. package/dist/orchestrator/src/cli/delegationServer.js +567 -678
  139. package/dist/orchestrator/src/cli/delegationServerCliShell.js +52 -0
  140. package/dist/orchestrator/src/cli/delegationServerQuestionFlowShell.js +228 -0
  141. package/dist/orchestrator/src/cli/delegationServerToolDispatchShell.js +411 -0
  142. package/dist/orchestrator/src/cli/delegationServerTransport.js +274 -0
  143. package/dist/orchestrator/src/cli/delegationSetup.js +51 -171
  144. package/dist/orchestrator/src/cli/devtoolsCliShell.js +34 -0
  145. package/dist/orchestrator/src/cli/doctor.js +542 -122
  146. package/dist/orchestrator/src/cli/doctorCliRequestShell.js +72 -0
  147. package/dist/orchestrator/src/cli/doctorCliShell.js +138 -0
  148. package/dist/orchestrator/src/cli/doctorUsage.js +119 -15
  149. package/dist/orchestrator/src/cli/exec/experience.js +16 -2
  150. package/dist/orchestrator/src/cli/exec/summary.js +3 -0
  151. package/dist/orchestrator/src/cli/execCliShell.js +51 -0
  152. package/dist/orchestrator/src/cli/flowCliRequestShell.js +44 -0
  153. package/dist/orchestrator/src/cli/flowCliShell.js +239 -0
  154. package/dist/orchestrator/src/cli/frontendTestCliRequestShell.js +80 -0
  155. package/dist/orchestrator/src/cli/frontendTestCliShell.js +41 -0
  156. package/dist/orchestrator/src/cli/init.js +1 -0
  157. package/dist/orchestrator/src/cli/initCliShell.js +50 -0
  158. package/dist/orchestrator/src/cli/linearCliShell.js +1200 -0
  159. package/dist/orchestrator/src/cli/mcpEnableCliShell.js +132 -0
  160. package/dist/orchestrator/src/cli/metrics/metricsAggregator.js +3 -2
  161. package/dist/orchestrator/src/cli/metrics/metricsRecorder.js +56 -0
  162. package/dist/orchestrator/src/cli/orchestrator.js +66 -1376
  163. package/dist/orchestrator/src/cli/planCliShell.js +19 -0
  164. package/dist/orchestrator/src/cli/prCliShell.js +41 -0
  165. package/dist/orchestrator/src/cli/providerLinearChildLanePhaseContract.js +204 -0
  166. package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +1772 -0
  167. package/dist/orchestrator/src/cli/providerLinearChildLaneShell.js +2420 -0
  168. package/dist/orchestrator/src/cli/providerLinearChildStreamShell.js +385 -0
  169. package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +5738 -0
  170. package/dist/orchestrator/src/cli/resumeCliShell.js +14 -0
  171. package/dist/orchestrator/src/cli/reviewCliLaunchShell.js +72 -0
  172. package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
  173. package/dist/orchestrator/src/cli/rlm/context.js +94 -7
  174. package/dist/orchestrator/src/cli/rlm/rlmCodexRuntimeShell.js +546 -0
  175. package/dist/orchestrator/src/cli/rlm/symbolic.js +4 -2
  176. package/dist/orchestrator/src/cli/rlmCliRequestShell.js +42 -0
  177. package/dist/orchestrator/src/cli/rlmCompletionCliShell.js +46 -0
  178. package/dist/orchestrator/src/cli/rlmLaunchCliShell.js +51 -0
  179. package/dist/orchestrator/src/cli/rlmRunner.js +83 -523
  180. package/dist/orchestrator/src/cli/run/blockMemory.js +500 -0
  181. package/dist/orchestrator/src/cli/run/manifest.js +410 -73
  182. package/dist/orchestrator/src/cli/run/manifestPersister.js +45 -14
  183. package/dist/orchestrator/src/cli/run/runMemoryController.js +216 -0
  184. package/dist/orchestrator/src/cli/run/source0.js +690 -0
  185. package/dist/orchestrator/src/cli/run/workspacePath.js +101 -0
  186. package/dist/orchestrator/src/cli/runtime/mode.js +2 -1
  187. package/dist/orchestrator/src/cli/runtime/provider.js +39 -2
  188. package/dist/orchestrator/src/cli/selfCheckCliShell.js +12 -0
  189. package/dist/orchestrator/src/cli/services/commandRunner.js +667 -18
  190. package/dist/orchestrator/src/cli/services/execRuntime.js +66 -1
  191. package/dist/orchestrator/src/cli/services/orchestratorAutoScoutEvidenceRecorder.js +71 -0
  192. package/dist/orchestrator/src/cli/services/orchestratorCloudBranchResolution.js +8 -0
  193. package/dist/orchestrator/src/cli/services/orchestratorCloudEnvironmentResolution.js +22 -0
  194. package/dist/orchestrator/src/cli/services/orchestratorCloudExecutionLifecycleShell.js +39 -0
  195. package/dist/orchestrator/src/cli/services/orchestratorCloudPromptBuilder.js +37 -0
  196. package/dist/orchestrator/src/cli/services/orchestratorCloudRouteFallbackContract.js +45 -0
  197. package/dist/orchestrator/src/cli/services/orchestratorCloudRouteShell.js +36 -0
  198. package/dist/orchestrator/src/cli/services/orchestratorCloudTargetExecutor.js +277 -0
  199. package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycle.js +98 -0
  200. package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycleShell.js +54 -0
  201. package/dist/orchestrator/src/cli/services/orchestratorExecutionLifecycle.js +112 -0
  202. package/dist/orchestrator/src/cli/services/orchestratorExecutionModePolicy.js +27 -0
  203. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteAdapterShell.js +59 -0
  204. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteDecisionShell.js +57 -0
  205. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteState.js +21 -0
  206. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouter.js +2 -0
  207. package/dist/orchestrator/src/cli/services/orchestratorLocalPipelineExecutor.js +149 -0
  208. package/dist/orchestrator/src/cli/services/orchestratorLocalRouteShell.js +63 -0
  209. package/dist/orchestrator/src/cli/services/orchestratorPlanShell.js +54 -0
  210. package/dist/orchestrator/src/cli/services/orchestratorPlanTargetTracker.js +16 -0
  211. package/dist/orchestrator/src/cli/services/orchestratorResumePreparationShell.js +84 -0
  212. package/dist/orchestrator/src/cli/services/orchestratorResumeTokenValidation.js +15 -0
  213. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleCompletion.js +31 -0
  214. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleExecutionRegistration.js +37 -0
  215. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleOrchestrationShell.js +83 -0
  216. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleTaskManagerShell.js +37 -0
  217. package/dist/orchestrator/src/cli/services/orchestratorRuntimeManifestMutation.js +20 -0
  218. package/dist/orchestrator/src/cli/services/orchestratorStartPreparationShell.js +56 -0
  219. package/dist/orchestrator/src/cli/services/orchestratorStatusShell.js +70 -0
  220. package/dist/orchestrator/src/cli/services/pipelineResolver.js +7 -3
  221. package/dist/orchestrator/src/cli/services/plannerMemory.js +119 -0
  222. package/dist/orchestrator/src/cli/services/runPreparation.js +7 -3
  223. package/dist/orchestrator/src/cli/services/runSummaryWriter.js +9 -0
  224. package/dist/orchestrator/src/cli/setupBootstrapShell.js +114 -0
  225. package/dist/orchestrator/src/cli/setupCliShell.js +51 -0
  226. package/dist/orchestrator/src/cli/skillsCliShell.js +56 -0
  227. package/dist/orchestrator/src/cli/startCliRequestShell.js +53 -0
  228. package/dist/orchestrator/src/cli/startCliShell.js +68 -0
  229. package/dist/orchestrator/src/cli/statusCliShell.js +22 -0
  230. package/dist/orchestrator/src/cli/utils/authProvenanceFingerprint.js +27 -0
  231. package/dist/orchestrator/src/cli/utils/cloudPreflight.js +83 -1
  232. package/dist/orchestrator/src/cli/utils/delegationConfigParser.js +250 -0
  233. package/dist/orchestrator/src/cli/utils/delegationMcpHealth.js +1382 -0
  234. package/dist/orchestrator/src/cli/utils/devtools.js +2 -54
  235. package/dist/orchestrator/src/cli/utils/mcpServerEntry.js +53 -0
  236. package/dist/orchestrator/src/cli/utils/packageProgramResolver.js +151 -0
  237. package/dist/orchestrator/src/cli/utils/providerOverrideEnv.js +71 -0
  238. package/dist/orchestrator/src/cli/utils/trailingJsonObject.js +59 -0
  239. package/dist/orchestrator/src/learning/crystalizer.js +2 -2
  240. package/dist/orchestrator/src/persistence/ExperienceStore.js +233 -49
  241. package/dist/orchestrator/src/persistence/TaskStateStore.js +6 -6
  242. package/dist/orchestrator/src/persistence/lockFile.js +70 -4
  243. package/dist/orchestrator/src/persistence/sanitizeIdentifier.js +39 -0
  244. package/dist/orchestrator/src/sync/createCloudSyncWorker.js +3 -2
  245. package/dist/orchestrator/src/utils/atomicWrite.js +17 -2
  246. package/dist/packages/orchestrator/src/exec/unified-exec.js +99 -6
  247. package/dist/packages/orchestrator/src/instructions/promptPacks.js +150 -19
  248. package/dist/packages/sdk-node/src/orchestrator.js +137 -13
  249. package/dist/packages/shared/config/designConfig.js +8 -1
  250. package/dist/packages/shared/streams/stdio.js +1 -1
  251. package/dist/scripts/design/pipeline/permit.js +15 -0
  252. package/dist/scripts/lib/docs-catalog.js +365 -0
  253. package/dist/scripts/lib/docs-helpers.js +87 -5
  254. package/dist/scripts/lib/pr-watch-merge.js +1088 -80
  255. package/dist/scripts/lib/provider-run-contract.js +26 -0
  256. package/dist/scripts/lib/review-command-intent-classification.js +532 -0
  257. package/dist/scripts/lib/review-command-probe-classification.js +385 -0
  258. package/dist/scripts/lib/review-execution-boundary-preflight.js +279 -0
  259. package/dist/scripts/lib/review-execution-runtime.js +753 -0
  260. package/dist/scripts/lib/review-execution-state.js +1144 -0
  261. package/dist/scripts/lib/review-execution-telemetry.js +215 -0
  262. package/dist/scripts/lib/review-inspection-target-parsing.js +78 -0
  263. package/dist/scripts/lib/review-launch-attempt.js +601 -0
  264. package/dist/scripts/lib/review-meta-surface-boundary-analysis.js +300 -0
  265. package/dist/scripts/lib/review-meta-surface-normalization.js +746 -0
  266. package/dist/scripts/lib/review-non-interactive-handoff.js +61 -0
  267. package/dist/scripts/lib/review-prompt-context.js +376 -0
  268. package/dist/scripts/lib/review-scope-advisory.js +286 -0
  269. package/dist/scripts/lib/review-scope-paths.js +123 -0
  270. package/dist/scripts/lib/review-shell-command-parser.js +389 -0
  271. package/dist/scripts/lib/review-shell-env-interpreter.js +340 -0
  272. package/dist/scripts/lib/run-manifests.js +192 -36
  273. package/dist/scripts/lib/spark-policy-classifier.js +593 -0
  274. package/dist/scripts/run-review.js +507 -1777
  275. package/docs/public/downstream-setup.md +106 -0
  276. package/docs/public/provider-onboarding.md +173 -0
  277. package/package.json +20 -10
  278. package/plugins/codex-orchestrator/.codex-plugin/plugin.json +30 -0
  279. package/plugins/codex-orchestrator/.mcp.json +13 -0
  280. package/plugins/codex-orchestrator/launcher.mjs +359 -0
  281. package/schemas/manifest.json +394 -0
  282. package/skills/collab-subagents-first/SKILL.md +1 -1
  283. package/skills/delegation-usage/DELEGATION_GUIDE.md +24 -11
  284. package/skills/delegation-usage/SKILL.md +19 -13
  285. package/skills/land/SKILL.md +77 -0
  286. package/skills/linear/SKILL.md +255 -0
  287. package/skills/release/SKILL.md +47 -3
  288. package/skills/standalone-review/SKILL.md +6 -1
  289. package/templates/README.md +4 -2
  290. package/templates/codex/.codex/agents/awaiter-high.toml +2 -2
  291. package/templates/codex/.codex/agents/worker-complex.toml +1 -1
  292. package/templates/codex/.codex/config.toml +3 -4
  293. package/templates/codex/.codex/providers/README.md +13 -0
  294. package/templates/codex/.codex/providers/control.example.json +18 -0
  295. package/templates/codex/.codex/providers/provider.env.example +15 -0
  296. package/templates/codex/AGENTS.md +12 -7
  297. package/templates/codex/mcp-client.json +5 -1
  298. package/docs/README.md +0 -310
  299. package/docs/assets/setup.gif +0 -0
@@ -1,4 +1,5 @@
1
1
  import { createWriteStream } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
2
3
  import { join } from 'node:path';
3
4
  import { ToolInvocationFailedError } from '../../../../packages/orchestrator/src/index.js';
4
5
  import { getCliExecRunner, getPrivacyGuard, getExecHandleService } from './execRuntime.js';
@@ -6,15 +7,30 @@ import { logger } from '../../logger.js';
6
7
  import { relativeToRepo } from '../run/runPaths.js';
7
8
  import { appendCommandError, updateCommandStatus } from '../run/manifest.js';
8
9
  import { persistManifest } from '../run/manifestPersister.js';
10
+ import { PROVIDER_LINEAR_WORKER_PROOF_FILENAME } from '../providerLinearWorkerRunner.js';
9
11
  import { slugify } from '../utils/strings.js';
10
12
  import { isoTimestamp } from '../utils/time.js';
13
+ import { buildCommandPreview } from '../utils/commandPreview.js';
11
14
  import { EnvUtils } from '../../../../packages/shared/config/index.js';
15
+ import { deriveReviewOutcomeDisposition } from '../../../../scripts/lib/review-execution-telemetry.js';
12
16
  import { findPackageRoot } from '../utils/packageInfo.js';
17
+ import { applyResolvedProgramInvocationEnvOverrides, resolvePackageProgramInvocation, resolveProviderLinearWorkerProgramInvocation } from '../utils/packageProgramResolver.js';
18
+ import { buildProviderLinearWorkerTerminalSummary, deriveDeterministicProviderMutationSuppressions, formatDeterministicProviderMutationDegradationSummary, isProviderLinearWorkerProofFreshForStage, resolveProviderLinearWorkerAttemptStartedAt, resolveProviderLinearWorkerTerminalReason, resolveProviderLinearWorkerTerminalStatus } from '../control/providerLinearWorkerTruth.js';
13
19
  const MAX_BUFFERED_OUTPUT_BYTES = 64 * 1024;
14
20
  const EMIT_COMMAND_STREAM_MIRRORS = EnvUtils.getBoolean('CODEX_ORCHESTRATOR_EMIT_COMMAND_STREAMS', false);
15
21
  export const MAX_CAPTURED_CHUNK_EVENTS = EnvUtils.getInt('CODEX_ORCHESTRATOR_EXEC_EVENT_MAX_CHUNKS', 500);
16
22
  const MAX_COLLAB_TOOL_CALLS = EnvUtils.getInt('CODEX_ORCHESTRATOR_COLLAB_MAX_EVENTS', 200);
17
23
  const PACKAGE_ROOT = findPackageRoot();
24
+ const REVIEW_EVIDENCE_CONSISTENCY_ENV_KEY = 'CODEX_REVIEW_ENFORCE_EVIDENCE_CONSISTENCY';
25
+ const REVIEW_EVIDENCE_WAIVER_REASON_ENV_KEY = 'CODEX_REVIEW_EVIDENCE_WAIVER_REASON';
26
+ const REVIEW_TELEMETRY_POLL_INTERVAL_MS = 50;
27
+ const REVIEW_TELEMETRY_WAIT_TIMEOUT_MS = 2_000;
28
+ const REVIEW_OUTCOME_BOUNDARY_PRESENCE_SENTINEL = {
29
+ kind: 'timeout',
30
+ provenance: 'review-timeout',
31
+ reason: '',
32
+ sample: null
33
+ };
18
34
  export async function runCommandStage(context, hooks = {}) {
19
35
  const { env, paths, manifest, stage, index, events, persister, envOverrides } = context;
20
36
  const entryIndex = index - 1;
@@ -44,8 +60,8 @@ export async function runCommandStage(context, hooks = {}) {
44
60
  runnerLog.write(payload);
45
61
  commandLog.write(payload);
46
62
  };
47
- writeEvent({ type: 'command:start', command: stage.command });
48
63
  const runner = getCliExecRunner();
64
+ let invocationPreview = stage.command;
49
65
  let activeCorrelationId = null;
50
66
  let stdoutBytes = 0;
51
67
  let stderrBytes = 0;
@@ -111,7 +127,7 @@ export async function runCommandStage(context, hooks = {}) {
111
127
  stageIndex: index,
112
128
  toolName: 'exec',
113
129
  status: 'started',
114
- message: stage.command,
130
+ message: invocationPreview,
115
131
  attempt: event.attempt
116
132
  });
117
133
  break;
@@ -175,17 +191,32 @@ export async function runCommandStage(context, hooks = {}) {
175
191
  CODEX_ORCHESTRATOR_ROOT: env.repoRoot,
176
192
  CODEX_ORCHESTRATOR_PACKAGE_ROOT: PACKAGE_ROOT
177
193
  };
194
+ baseEnv.CODEX_ORCHESTRATOR_NODE_BIN = process.execPath;
178
195
  baseEnv.CODEX_ORCHESTRATOR_RUNTIME_MODE_ACTIVE =
179
196
  context.runtimeMode ?? (manifest.runtime_mode === 'appserver' ? 'appserver' : 'cli');
180
197
  // Keep both keys during migration because downstream tools still read either name.
181
198
  baseEnv.CODEX_ORCHESTRATOR_RUNTIME_MODE = baseEnv.CODEX_ORCHESTRATOR_RUNTIME_MODE_ACTIVE;
182
199
  const execEnv = { ...baseEnv, ...stage.env };
200
+ execEnv.CODEX_ORCHESTRATOR_NODE_BIN = process.execPath;
201
+ const invocation = resolveStageInvocation(stage, execEnv);
202
+ applyResolvedProgramInvocationEnvOverrides(execEnv, invocation.envOverrides);
203
+ if (invocation.warning) {
204
+ logger.warn(invocation.warning);
205
+ writeEvent({ type: 'command:warning', warning: invocation.warning });
206
+ }
207
+ invocationPreview = invocation.preview;
208
+ writeEvent({ type: 'command:start', command: invocationPreview });
209
+ const timeoutMs = resolveStageTimeoutMs(stage, execEnv);
183
210
  const invocationId = `cli-command:${manifest.run_id}:${stage.id}:${Date.now()}`;
211
+ if (timeoutMs !== null) {
212
+ writeEvent({ type: 'command:config', timeout_ms: timeoutMs });
213
+ }
184
214
  let result;
185
215
  const eventCapture = MAX_CAPTURED_CHUNK_EVENTS > 0 ? { maxChunkEvents: MAX_CAPTURED_CHUNK_EVENTS } : undefined;
186
216
  try {
187
217
  result = await runner.run({
188
- command: stage.command,
218
+ command: invocation.command,
219
+ args: invocation.args,
189
220
  cwd: stage.cwd ?? env.repoRoot,
190
221
  env: execEnv,
191
222
  sessionId: effectiveSessionId ?? undefined,
@@ -194,6 +225,7 @@ export async function runCommandStage(context, hooks = {}) {
194
225
  invocationId,
195
226
  toolId: 'cli:command',
196
227
  description: stage.title,
228
+ ...(timeoutMs !== null ? { timeoutMs } : {}),
197
229
  eventCapture,
198
230
  metadata: {
199
231
  stageId: stage.id,
@@ -233,11 +265,161 @@ export async function runCommandStage(context, hooks = {}) {
233
265
  const normalizedExitCode = result.exitCode ?? (result.signal ? 128 : 0);
234
266
  const stdoutText = result.stdout.trim();
235
267
  const stderrText = result.stderr.trim();
236
- const summary = buildSummary(stage, normalizedExitCode, stdoutText, stderrText, result.signal);
268
+ const timeoutBoundMs = typeof result.timeoutMs === 'number' && Number.isFinite(result.timeoutMs) && result.timeoutMs > 0
269
+ ? Math.trunc(result.timeoutMs)
270
+ : timeoutMs;
271
+ const timedOut = result.timedOut === true;
272
+ const summary = buildSummary(stage, normalizedExitCode, stdoutText, stderrText, result.signal, {
273
+ timedOut,
274
+ timeoutMs: timeoutBoundMs
275
+ });
276
+ const enforceReviewEvidenceConsistency = shouldEnforceReviewEvidenceConsistency(stage);
277
+ const providerLinearWorkerStage = isProviderLinearWorkerCommandStage(stage);
278
+ const reviewTelemetryPath = join(paths.runDir, 'review', 'telemetry.json');
279
+ const shouldAwaitReviewTelemetry = (isReviewCommandStage(stage) || providerLinearWorkerStage) &&
280
+ shouldAwaitReviewTelemetryEvidence(execEnv, enforceReviewEvidenceConsistency);
281
+ const reviewTelemetry = isReviewCommandStage(stage) || providerLinearWorkerStage
282
+ ? await loadReviewTelemetryEvidence(reviewTelemetryPath, {
283
+ waitForEvidence: shouldAwaitReviewTelemetry
284
+ })
285
+ : null;
286
+ const reviewEvidenceMismatch = isReviewCommandStage(stage) && (enforceReviewEvidenceConsistency || reviewTelemetry !== null)
287
+ ? await verifyReviewEvidenceConsistency({
288
+ env,
289
+ paths,
290
+ expectedStatus: result.status === 'succeeded' ? 'succeeded' : 'failed',
291
+ startedAt: entry.started_at,
292
+ telemetry: reviewTelemetry,
293
+ telemetryPreloaded: shouldAwaitReviewTelemetry,
294
+ telemetryPath: reviewTelemetryPath
295
+ })
296
+ : null;
297
+ const providerReviewTelemetryMismatch = providerLinearWorkerStage && reviewTelemetry !== null
298
+ ? verifyReviewTelemetryFreshness({
299
+ env,
300
+ paths,
301
+ startedAt: entry.started_at,
302
+ telemetry: reviewTelemetry,
303
+ telemetryPath: reviewTelemetryPath
304
+ })
305
+ : null;
306
+ const providerReviewTelemetry = providerReviewTelemetryMismatch === null
307
+ ? reviewTelemetry
308
+ : null;
309
+ const reviewEvidenceWaiverReason = resolveReviewEvidenceWaiverReason(stage.env);
310
+ let effectiveSummary = summary;
311
+ let forceReviewEvidenceFailure = false;
312
+ let forceProviderLinearWorkerFailure = false;
313
+ let providerLinearWorkerFailureReason = null;
314
+ let providerLinearWorkerTerminalStatus = null;
315
+ let providerLinearWorkerTerminalReason = null;
316
+ let providerLinearWorkerReviewOutcomeSummary = null;
317
+ if (reviewEvidenceMismatch && enforceReviewEvidenceConsistency) {
318
+ if (reviewEvidenceWaiverReason) {
319
+ effectiveSummary = `${summary} (review evidence waiver: ${reviewEvidenceWaiverReason}; ${reviewEvidenceMismatch.message})`;
320
+ writeEvent({
321
+ type: 'command:waiver',
322
+ waiver: 'review-evidence-consistency',
323
+ reason: reviewEvidenceWaiverReason,
324
+ telemetry_path: relativeToRepo(env, reviewEvidenceMismatch.telemetryPath),
325
+ detail: reviewEvidenceMismatch.message
326
+ });
327
+ events?.log({
328
+ stageId: stage.id,
329
+ stageIndex: index,
330
+ level: 'warn',
331
+ source: 'system',
332
+ message: `Review evidence waiver applied: ${reviewEvidenceMismatch.message}`
333
+ });
334
+ }
335
+ else {
336
+ effectiveSummary =
337
+ result.status === 'succeeded'
338
+ ? `Review evidence mismatch: ${reviewEvidenceMismatch.message}`
339
+ : `Review evidence mismatch after command failure: ${reviewEvidenceMismatch.message} Command result: ${summary}`;
340
+ forceReviewEvidenceFailure = true;
341
+ }
342
+ }
343
+ if (!reviewEvidenceMismatch) {
344
+ const reviewOutcomeSummary = formatReviewTelemetryOutcomeSummary(providerLinearWorkerStage ? providerReviewTelemetry : reviewTelemetry);
345
+ if (reviewOutcomeSummary) {
346
+ effectiveSummary = `${effectiveSummary} (${reviewOutcomeSummary})`;
347
+ }
348
+ }
349
+ if (providerLinearWorkerStage) {
350
+ let providerLinearWorkerProof = await loadProviderLinearWorkerProof(join(paths.runDir, PROVIDER_LINEAR_WORKER_PROOF_FILENAME));
351
+ let providerLinearWorkerProofRecord = providerLinearWorkerProof;
352
+ if (providerLinearWorkerProofRecord &&
353
+ !isProviderLinearWorkerProofFreshForStage(providerLinearWorkerProofRecord, entry.started_at ?? null)) {
354
+ providerLinearWorkerProof = null;
355
+ providerLinearWorkerProofRecord = null;
356
+ }
357
+ if (result.status === 'succeeded' && providerLinearWorkerProofRecord === null) {
358
+ providerLinearWorkerFailureReason = 'provider_linear_worker_proof_missing_or_unreadable';
359
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
360
+ status: 'failed',
361
+ endReason: 'provider_linear_worker_proof_missing_or_unreadable'
362
+ });
363
+ forceProviderLinearWorkerFailure = true;
364
+ }
365
+ const proofTerminalStatus = resolveProviderLinearWorkerTerminalStatus(providerLinearWorkerProofRecord);
366
+ const proofTerminalReason = resolveProviderLinearWorkerTerminalReason(providerLinearWorkerProofRecord);
367
+ providerLinearWorkerTerminalStatus = proofTerminalStatus;
368
+ providerLinearWorkerTerminalReason = proofTerminalReason;
369
+ const proofAttemptStartedAt = resolveProviderLinearWorkerAttemptStartedAt(providerLinearWorkerProofRecord) ?? entry.started_at ?? null;
370
+ const reviewTelemetryStatus = coerceTelemetryStatusValue(providerReviewTelemetry?.status);
371
+ const reviewOutcomeSummary = formatReviewTelemetryOutcomeSummary(providerReviewTelemetry);
372
+ providerLinearWorkerReviewOutcomeSummary = reviewOutcomeSummary;
373
+ const mutationSuppressions = deriveDeterministicProviderMutationSuppressions(providerLinearWorkerProof?.linear_audit ?? null, {
374
+ recordedAtNotBefore: proofAttemptStartedAt,
375
+ issueId: providerLinearWorkerProof?.issue_id ?? null
376
+ });
377
+ const degradationSummary = formatDeterministicProviderMutationDegradationSummary(mutationSuppressions);
378
+ if (proofTerminalStatus === 'failed') {
379
+ providerLinearWorkerFailureReason = 'provider_linear_worker_terminal_failed';
380
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
381
+ status: 'failed',
382
+ endReason: proofTerminalReason,
383
+ reviewOutcomeSummary,
384
+ degradationSummary
385
+ });
386
+ forceProviderLinearWorkerFailure = true;
387
+ }
388
+ else if (providerLinearWorkerFailureReason === null && reviewTelemetryStatus === 'failed') {
389
+ providerLinearWorkerFailureReason = 'provider_linear_worker_review_failed';
390
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
391
+ status: 'failed',
392
+ endReason: null,
393
+ reviewOutcomeSummary: reviewOutcomeSummary ?? 'review telemetry reported terminal failure',
394
+ degradationSummary
395
+ });
396
+ forceProviderLinearWorkerFailure = true;
397
+ }
398
+ else if (proofTerminalStatus === 'succeeded' && result.status === 'succeeded') {
399
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
400
+ status: 'succeeded',
401
+ endReason: proofTerminalReason,
402
+ reviewOutcomeSummary,
403
+ degradationSummary
404
+ });
405
+ }
406
+ else if (degradationSummary) {
407
+ effectiveSummary = `${effectiveSummary} (${degradationSummary})`;
408
+ }
409
+ }
410
+ const effectiveExitCode = (forceReviewEvidenceFailure || forceProviderLinearWorkerFailure) && normalizedExitCode === 0
411
+ ? 1
412
+ : normalizedExitCode;
237
413
  entry.completed_at = isoTimestamp();
238
- entry.exit_code = normalizedExitCode;
239
- entry.summary = summary;
240
- entry.status = result.status === 'succeeded' ? 'succeeded' : stage.allowFailure ? 'skipped' : 'failed';
414
+ entry.exit_code = effectiveExitCode;
415
+ entry.summary = effectiveSummary;
416
+ entry.status = forceReviewEvidenceFailure || forceProviderLinearWorkerFailure
417
+ ? 'failed'
418
+ : result.status === 'succeeded'
419
+ ? 'succeeded'
420
+ : stage.allowFailure
421
+ ? 'skipped'
422
+ : 'failed';
241
423
  if (collabBuffer.trim()) {
242
424
  const record = parseCollabToolCallLine(collabBuffer, stage.id, entry.index);
243
425
  if (record) {
@@ -245,22 +427,113 @@ export async function runCommandStage(context, hooks = {}) {
245
427
  }
246
428
  collabBuffer = '';
247
429
  }
248
- if (entry.status === 'failed') {
249
- const errorDetails = {
430
+ if (result.status !== 'succeeded' && entry.status === 'skipped') {
431
+ const fallbackReason = timedOut ? 'timed_out' : 'command_failed';
432
+ writeEvent({
433
+ type: 'command:fallback',
434
+ fallback: 'allow_failure',
435
+ reason: fallbackReason,
250
436
  exit_code: normalizedExitCode,
437
+ signal: result.signal,
438
+ timeout_ms: timeoutBoundMs
439
+ });
440
+ events?.log({
441
+ stageId: stage.id,
442
+ stageIndex: index,
443
+ level: 'warn',
444
+ source: 'system',
445
+ message: timedOut
446
+ ? `Non-fatal fallback applied after timeout (${timeoutBoundMs !== null ? `${timeoutBoundMs}ms` : 'configured timeout'}).`
447
+ : 'Non-fatal fallback applied after command failure.'
448
+ });
449
+ }
450
+ if (result.status !== 'succeeded') {
451
+ const failureReason = timedOut ? 'timed_out' : 'command_failed';
452
+ const errorDetails = {
453
+ exit_code: effectiveExitCode,
251
454
  sandbox_state: result.sandboxState,
252
- stderr: stderrText
455
+ stderr: stderrText,
456
+ failure_reason: failureReason
253
457
  };
458
+ if (effectiveExitCode !== normalizedExitCode) {
459
+ errorDetails.command_exit_code = normalizedExitCode;
460
+ }
254
461
  if (result.signal) {
255
462
  errorDetails.signal = result.signal;
256
463
  }
464
+ if (timeoutBoundMs !== null) {
465
+ errorDetails.timeout_ms = timeoutBoundMs;
466
+ }
467
+ if (timedOut) {
468
+ errorDetails.timed_out = true;
469
+ }
470
+ if (entry.status === 'skipped') {
471
+ errorDetails.non_fatal_fallback = true;
472
+ }
257
473
  if (stdoutTruncated) {
258
474
  errorDetails.stdout_truncated = true;
259
475
  }
260
476
  if (stderrTruncated) {
261
477
  errorDetails.stderr_truncated = true;
262
478
  }
263
- entry.error_file = await appendCommandError(env, paths, manifest, entry, 'command-failed', errorDetails);
479
+ entry.error_file = await appendCommandError(env, paths, manifest, entry, entry.status === 'skipped' ? 'command-allow-failure' : 'command-failed', errorDetails);
480
+ }
481
+ if (forceProviderLinearWorkerFailure && result.status === 'succeeded' && !entry.error_file) {
482
+ const errorDetails = {
483
+ exit_code: effectiveExitCode,
484
+ command_exit_code: normalizedExitCode,
485
+ sandbox_state: result.sandboxState,
486
+ failure_reason: providerLinearWorkerFailureReason ?? 'provider_linear_worker_authoritative_failure',
487
+ detail: effectiveSummary
488
+ };
489
+ if (providerLinearWorkerTerminalStatus) {
490
+ errorDetails.provider_linear_worker_terminal_status = providerLinearWorkerTerminalStatus;
491
+ }
492
+ if (providerLinearWorkerTerminalReason) {
493
+ errorDetails.provider_linear_worker_end_reason = providerLinearWorkerTerminalReason;
494
+ }
495
+ if (providerLinearWorkerReviewOutcomeSummary) {
496
+ errorDetails.review_outcome_summary = providerLinearWorkerReviewOutcomeSummary;
497
+ }
498
+ if (stdoutTruncated) {
499
+ errorDetails.stdout_truncated = true;
500
+ }
501
+ if (stderrTruncated) {
502
+ errorDetails.stderr_truncated = true;
503
+ }
504
+ entry.error_file = await appendCommandError(env, paths, manifest, entry, 'provider-linear-worker-authoritative-failed', errorDetails);
505
+ }
506
+ if (forceReviewEvidenceFailure && reviewEvidenceMismatch) {
507
+ if (entry.error_file) {
508
+ writeEvent({
509
+ type: 'command:warning',
510
+ warning: 'review-evidence-inconsistent',
511
+ preserved_error_file: entry.error_file,
512
+ telemetry_path: relativeToRepo(env, reviewEvidenceMismatch.telemetryPath),
513
+ detail: reviewEvidenceMismatch.message
514
+ });
515
+ events?.log({
516
+ stageId: stage.id,
517
+ stageIndex: index,
518
+ level: 'warn',
519
+ source: 'system',
520
+ message: `Review evidence mismatch preserved alongside the original command failure: ${reviewEvidenceMismatch.message}`
521
+ });
522
+ }
523
+ else {
524
+ entry.error_file = await appendCommandError(env, paths, manifest, entry, 'review-evidence-inconsistent', {
525
+ exit_code: effectiveExitCode,
526
+ command_exit_code: normalizedExitCode,
527
+ sandbox_state: result.sandboxState,
528
+ expected_review_status: result.status === 'succeeded' ? 'succeeded' : 'failed',
529
+ telemetry_status: reviewEvidenceMismatch.telemetryStatus,
530
+ telemetry_generated_at: reviewEvidenceMismatch.telemetryGeneratedAt,
531
+ telemetry_output_log_path: reviewEvidenceMismatch.telemetryOutputLogPath,
532
+ telemetry_path: relativeToRepo(env, reviewEvidenceMismatch.telemetryPath),
533
+ failure_reason: 'review_evidence_inconsistent',
534
+ detail: reviewEvidenceMismatch.message
535
+ });
536
+ }
264
537
  }
265
538
  await persistManifest(paths, manifest, persister, { force: true });
266
539
  events?.stageCompleted({
@@ -273,7 +546,7 @@ export async function runCommandStage(context, hooks = {}) {
273
546
  summary: entry.summary,
274
547
  logPath: entry.log_path
275
548
  });
276
- return { exitCode: normalizedExitCode, summary };
549
+ return { exitCode: effectiveExitCode, summary: effectiveSummary };
277
550
  }
278
551
  finally {
279
552
  unsubscribe();
@@ -282,6 +555,302 @@ export async function runCommandStage(context, hooks = {}) {
282
555
  privacyLog.end();
283
556
  }
284
557
  }
558
+ function shouldEnforceReviewEvidenceConsistency(stage) {
559
+ return (parseBooleanEnvFlag(stage.env?.[REVIEW_EVIDENCE_CONSISTENCY_ENV_KEY]) &&
560
+ isReviewCommandStage(stage));
561
+ }
562
+ function shouldAwaitReviewTelemetryEvidence(execEnv, enforceReviewEvidenceConsistency) {
563
+ if (enforceReviewEvidenceConsistency) {
564
+ return true;
565
+ }
566
+ const forced = parseBooleanEnvFlag(execEnv.FORCE_CODEX_REVIEW);
567
+ const nonInteractive = process.stdin.isTTY !== true ||
568
+ parseBooleanEnvFlag(execEnv.CODEX_REVIEW_NON_INTERACTIVE) ||
569
+ parseBooleanEnvFlag(execEnv.CODEX_NON_INTERACTIVE) ||
570
+ parseBooleanEnvFlag(execEnv.CODEX_NO_INTERACTIVE);
571
+ return forced || !nonInteractive;
572
+ }
573
+ function isReviewCommandStage(stage) {
574
+ const stageId = stage.id.trim().toLowerCase();
575
+ if (stageId === 'review') {
576
+ return true;
577
+ }
578
+ const haystack = `${stage.title} ${stage.command}`.toLowerCase();
579
+ return (haystack.includes('npm run review') ||
580
+ haystack.includes('codex review') ||
581
+ haystack.includes('codex-orchestrator review') ||
582
+ haystack.includes('run-review.ts') ||
583
+ haystack.includes('run-review.js'));
584
+ }
585
+ function isProviderLinearWorkerCommandStage(stage) {
586
+ const stageId = stage.id.trim().toLowerCase();
587
+ if (stageId === 'provider-linear-worker') {
588
+ return true;
589
+ }
590
+ const haystack = `${stage.title} ${stage.command}`.toLowerCase();
591
+ return haystack.includes('providerlinearworkerrunner');
592
+ }
593
+ function resolveStageInvocation(stage, env) {
594
+ if (isProviderLinearWorkerCommandStage(stage)) {
595
+ const providerWorkerPackageRoot = normalizeOptionalString(env.CODEX_ORCHESTRATOR_PACKAGE_ROOT) ?? PACKAGE_ROOT;
596
+ const invocation = resolveProviderLinearWorkerProgramInvocation({
597
+ allowConfiguredForeignPackageRoot: true,
598
+ env,
599
+ execPath: normalizeOptionalString(env.CODEX_ORCHESTRATOR_NODE_BIN) ?? process.execPath,
600
+ packageRoot: providerWorkerPackageRoot
601
+ });
602
+ return {
603
+ command: invocation.command,
604
+ args: invocation.args,
605
+ preview: buildCommandPreview(invocation.command, invocation.args),
606
+ warning: invocation.warning,
607
+ envOverrides: invocation.envOverrides
608
+ };
609
+ }
610
+ const packageRootInvocation = resolvePackageRootDistStageInvocation(stage.command, env);
611
+ if (packageRootInvocation) {
612
+ return packageRootInvocation;
613
+ }
614
+ return {
615
+ command: stage.command,
616
+ preview: stage.command
617
+ };
618
+ }
619
+ function resolvePackageRootDistStageInvocation(commandLine, env) {
620
+ const match = commandLine.match(/^\s*node\s+["']?\$CODEX_ORCHESTRATOR_PACKAGE_ROOT\/dist\/([^"'\s]+?\.js)["']?(.*)$/u);
621
+ if (!match) {
622
+ return null;
623
+ }
624
+ const [, distRelativePath, trailingArgsRaw] = match;
625
+ const invocation = resolvePackageProgramInvocation({
626
+ allowConfiguredForeignPackageRoot: true,
627
+ env,
628
+ packageRoot: PACKAGE_ROOT,
629
+ execPath: normalizeOptionalString(env.CODEX_ORCHESTRATOR_NODE_BIN) ?? process.execPath,
630
+ distRelativePath
631
+ });
632
+ const command = `${buildCommandPreview(invocation.command, invocation.args)}${trailingArgsRaw}`;
633
+ return {
634
+ command,
635
+ preview: command,
636
+ warning: invocation.warning,
637
+ envOverrides: invocation.envOverrides
638
+ };
639
+ }
640
+ function resolveReviewEvidenceWaiverReason(env) {
641
+ const reason = env?.[REVIEW_EVIDENCE_WAIVER_REASON_ENV_KEY]?.trim();
642
+ return reason && reason.length > 0 ? reason : null;
643
+ }
644
+ function parseBooleanEnvFlag(value) {
645
+ if (!value) {
646
+ return false;
647
+ }
648
+ const normalized = value.trim().toLowerCase();
649
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
650
+ }
651
+ async function verifyReviewEvidenceConsistency(options) {
652
+ const telemetryPath = options.telemetryPath ?? join(options.paths.runDir, 'review', 'telemetry.json');
653
+ const telemetry = options.telemetryPreloaded === true
654
+ ? options.telemetry ?? null
655
+ : options.telemetry ?? (await waitForReviewTelemetryEvidence(telemetryPath));
656
+ if (!telemetry) {
657
+ return {
658
+ message: 'review telemetry is missing, unreadable, or incomplete at terminal stage closeout.',
659
+ telemetryPath,
660
+ telemetryStatus: null,
661
+ telemetryGeneratedAt: null,
662
+ telemetryOutputLogPath: null
663
+ };
664
+ }
665
+ const freshnessMismatch = verifyReviewTelemetryFreshness({
666
+ env: options.env,
667
+ paths: options.paths,
668
+ startedAt: options.startedAt,
669
+ telemetry,
670
+ telemetryPath
671
+ });
672
+ if (freshnessMismatch) {
673
+ return freshnessMismatch;
674
+ }
675
+ const generatedAt = coerceTelemetryString(telemetry.generated_at);
676
+ const telemetryStatus = coerceTelemetryString(telemetry.status);
677
+ const telemetryOutputLogPath = coerceTelemetryString(telemetry.output_log_path);
678
+ if (telemetryStatus !== options.expectedStatus) {
679
+ return {
680
+ message: `review telemetry status ${telemetryStatus ?? '<missing>'} does not match terminal stage result ${options.expectedStatus}.`,
681
+ telemetryPath,
682
+ telemetryStatus,
683
+ telemetryGeneratedAt: generatedAt,
684
+ telemetryOutputLogPath
685
+ };
686
+ }
687
+ return null;
688
+ }
689
+ function verifyReviewTelemetryFreshness(options) {
690
+ const { env, paths, startedAt, telemetry, telemetryPath } = options;
691
+ const generatedAt = typeof telemetry.generated_at === 'string' && telemetry.generated_at.trim().length > 0
692
+ ? telemetry.generated_at
693
+ : null;
694
+ if (!generatedAt) {
695
+ return {
696
+ message: 'review telemetry is missing generated_at, so terminal evidence freshness cannot be verified.',
697
+ telemetryPath,
698
+ telemetryStatus: coerceTelemetryString(telemetry.status),
699
+ telemetryGeneratedAt: null,
700
+ telemetryOutputLogPath: coerceTelemetryString(telemetry.output_log_path)
701
+ };
702
+ }
703
+ const generatedAtMs = Date.parse(generatedAt);
704
+ if (!Number.isFinite(generatedAtMs)) {
705
+ return {
706
+ message: `review telemetry generated_at is invalid (${generatedAt}).`,
707
+ telemetryPath,
708
+ telemetryStatus: coerceTelemetryString(telemetry.status),
709
+ telemetryGeneratedAt: generatedAt,
710
+ telemetryOutputLogPath: coerceTelemetryString(telemetry.output_log_path)
711
+ };
712
+ }
713
+ const startedAtMs = typeof startedAt === 'string' ? Date.parse(startedAt) : Number.NaN;
714
+ if (Number.isFinite(startedAtMs) && generatedAtMs < startedAtMs) {
715
+ return {
716
+ message: `review telemetry is stale (generated_at ${generatedAt} precedes stage start ${startedAt}).`,
717
+ telemetryPath,
718
+ telemetryStatus: coerceTelemetryString(telemetry.status),
719
+ telemetryGeneratedAt: generatedAt,
720
+ telemetryOutputLogPath: coerceTelemetryString(telemetry.output_log_path)
721
+ };
722
+ }
723
+ const expectedOutputLogPath = relativeToRepo(env, join(paths.runDir, 'review', 'output.log'));
724
+ const telemetryStatus = coerceTelemetryString(telemetry.status);
725
+ const telemetryOutputLogPath = coerceTelemetryString(telemetry.output_log_path);
726
+ if (telemetryOutputLogPath !== expectedOutputLogPath) {
727
+ return {
728
+ message: `review telemetry output_log_path ${telemetryOutputLogPath ?? '<missing>'} does not match the active run artifact ${expectedOutputLogPath}.`,
729
+ telemetryPath,
730
+ telemetryStatus,
731
+ telemetryGeneratedAt: generatedAt,
732
+ telemetryOutputLogPath
733
+ };
734
+ }
735
+ return null;
736
+ }
737
+ async function loadReviewTelemetryEvidence(telemetryPath, options) {
738
+ if (options.waitForEvidence) {
739
+ return await waitForReviewTelemetryEvidence(telemetryPath);
740
+ }
741
+ return await readReviewTelemetryEvidence(telemetryPath);
742
+ }
743
+ async function waitForReviewTelemetryEvidence(telemetryPath) {
744
+ const deadline = Date.now() + REVIEW_TELEMETRY_WAIT_TIMEOUT_MS;
745
+ for (;;) {
746
+ const telemetry = await readReviewTelemetryEvidence(telemetryPath);
747
+ if (telemetry) {
748
+ return telemetry;
749
+ }
750
+ if (Date.now() >= deadline) {
751
+ return null;
752
+ }
753
+ await delay(REVIEW_TELEMETRY_POLL_INTERVAL_MS);
754
+ }
755
+ }
756
+ async function readReviewTelemetryEvidence(telemetryPath) {
757
+ try {
758
+ const raw = await readFile(telemetryPath, 'utf8');
759
+ const parsed = JSON.parse(raw);
760
+ return parsed && typeof parsed === 'object' ? parsed : null;
761
+ }
762
+ catch {
763
+ return null;
764
+ }
765
+ }
766
+ async function loadProviderLinearWorkerProof(proofPath) {
767
+ try {
768
+ const raw = await readFile(proofPath, 'utf8');
769
+ const parsed = JSON.parse(raw);
770
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
771
+ }
772
+ catch {
773
+ return null;
774
+ }
775
+ }
776
+ function coerceTelemetryString(value) {
777
+ if (typeof value !== 'string') {
778
+ return null;
779
+ }
780
+ const trimmed = value.trim();
781
+ return trimmed.length > 0 ? trimmed : null;
782
+ }
783
+ function coerceTelemetryStatusValue(value) {
784
+ if (value === 'succeeded' || value === 'failed') {
785
+ return value;
786
+ }
787
+ return null;
788
+ }
789
+ function coerceReviewOutcomeDisposition(value) {
790
+ switch (value) {
791
+ case 'clean-success':
792
+ case 'bounded-success':
793
+ case 'failed-boundary':
794
+ case 'failed-other':
795
+ return value;
796
+ default:
797
+ return null;
798
+ }
799
+ }
800
+ function hasTelemetryTerminationBoundary(telemetry) {
801
+ return coerceTelemetryTerminationBoundaryKind(telemetry) !== null;
802
+ }
803
+ function coerceTelemetryTerminationBoundaryKind(telemetry) {
804
+ if (!telemetry) {
805
+ return null;
806
+ }
807
+ const boundary = telemetry.termination_boundary;
808
+ if (boundary === null || typeof boundary !== 'object' || Array.isArray(boundary)) {
809
+ return null;
810
+ }
811
+ return coerceTelemetryString(boundary.kind);
812
+ }
813
+ function resolveReviewTelemetryOutcomeDisposition(telemetry) {
814
+ if (!telemetry) {
815
+ return null;
816
+ }
817
+ const explicitDisposition = coerceReviewOutcomeDisposition(telemetry.review_outcome);
818
+ const telemetryStatus = coerceTelemetryStatusValue(telemetry.status);
819
+ if (!telemetryStatus) {
820
+ return null;
821
+ }
822
+ const derivedDisposition = deriveReviewOutcomeDisposition({
823
+ status: telemetryStatus,
824
+ terminationBoundary: hasTelemetryTerminationBoundary(telemetry)
825
+ ? REVIEW_OUTCOME_BOUNDARY_PRESENCE_SENTINEL
826
+ : null
827
+ });
828
+ return explicitDisposition === derivedDisposition ? explicitDisposition : derivedDisposition;
829
+ }
830
+ function formatReviewTelemetryOutcomeSummary(telemetry) {
831
+ const disposition = resolveReviewTelemetryOutcomeDisposition(telemetry);
832
+ if (!disposition) {
833
+ return null;
834
+ }
835
+ const boundaryKind = coerceTelemetryTerminationBoundaryKind(telemetry);
836
+ switch (disposition) {
837
+ case 'clean-success':
838
+ return 'review outcome: clean success';
839
+ case 'bounded-success':
840
+ return boundaryKind
841
+ ? `review outcome: bounded success via ${boundaryKind}; not a wrapper failure`
842
+ : 'review outcome: bounded success with preserved termination boundary; not a wrapper failure';
843
+ case 'failed-boundary':
844
+ return boundaryKind
845
+ ? `review outcome: review-wrapper failure via ${boundaryKind}`
846
+ : 'review outcome: review-wrapper failure via explicit termination boundary';
847
+ case 'failed-other':
848
+ return 'review outcome: review command failed without termination-boundary classification; not an explicit wrapper-boundary failure';
849
+ }
850
+ }
851
+ function delay(ms) {
852
+ return new Promise((resolve) => setTimeout(resolve, ms));
853
+ }
285
854
  function runtimeSessionIdOrNull(value) {
286
855
  if (typeof value !== 'string') {
287
856
  return null;
@@ -454,9 +1023,12 @@ function streamEvent(writeEvent, event, hooks) {
454
1023
  break;
455
1024
  }
456
1025
  }
457
- function buildSummary(stage, exitCode, stdout, stderr, signal) {
458
- if (stage.summaryHint) {
459
- return stage.summaryHint;
1026
+ function buildSummary(stage, exitCode, stdout, stderr, signal, options = {}) {
1027
+ if (options.timedOut) {
1028
+ const timeoutLabel = typeof options.timeoutMs === 'number' && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0
1029
+ ? `${Math.trunc(options.timeoutMs)}ms`
1030
+ : 'configured timeout';
1031
+ return `Timed out after ${timeoutLabel}${stderr ? ` — ${truncate(stderr)}` : ''}`;
460
1032
  }
461
1033
  if (signal) {
462
1034
  return `Terminated with signal ${signal}${stderr ? ` — ${truncate(stderr)}` : ''}`;
@@ -464,6 +1036,9 @@ function buildSummary(stage, exitCode, stdout, stderr, signal) {
464
1036
  if (exitCode !== 0) {
465
1037
  return `Exited with code ${exitCode}${stderr ? ` — ${truncate(stderr)}` : ''}`;
466
1038
  }
1039
+ if (stage.summaryHint) {
1040
+ return stage.summaryHint;
1041
+ }
467
1042
  if (stdout) {
468
1043
  return truncate(stdout);
469
1044
  }
@@ -502,9 +1077,15 @@ function parseCollabToolCallLine(line, stageId, commandIndex) {
502
1077
  if (!item || item.type !== 'collab_tool_call') {
503
1078
  return null;
504
1079
  }
505
- const receiverThreadIds = Array.isArray(item.receiver_thread_ids)
506
- ? item.receiver_thread_ids.filter((entry) => typeof entry === 'string')
507
- : [];
1080
+ const receiverThreadIdSlots = parseStringSlots(item.receiver_thread_ids);
1081
+ const receiverThreadIds = receiverThreadIdSlots.filter((entry) => entry !== null);
1082
+ const senderAgentPath = normalizeOptionalString(item.sender_agent_path);
1083
+ const receiverAgentPathSlots = parseStringSlots(item.receiver_agent_paths);
1084
+ const receiverAgentPaths = receiverAgentPathSlots.filter((entry) => entry !== null);
1085
+ const receiverAgents = parseCollabReceiverAgents(item.receiver_agents, {
1086
+ receiverThreadIdSlots,
1087
+ receiverAgentPathSlots
1088
+ });
508
1089
  return {
509
1090
  observed_at: isoTimestamp(),
510
1091
  stage_id: stageId,
@@ -515,6 +1096,13 @@ function parseCollabToolCallLine(line, stageId, commandIndex) {
515
1096
  status: normalizeCollabStatus(item.status),
516
1097
  sender_thread_id: typeof item.sender_thread_id === 'string' ? item.sender_thread_id : 'unknown',
517
1098
  receiver_thread_ids: receiverThreadIds,
1099
+ sender_agent_path: senderAgentPath,
1100
+ receiver_agent_paths: receiverAgentPaths.length > 0
1101
+ ? receiverAgentPaths
1102
+ : receiverAgents
1103
+ ?.map((entry) => entry.agent_path)
1104
+ .filter((entry) => typeof entry === 'string' && entry.length > 0) ?? null,
1105
+ receiver_agents: receiverAgents,
518
1106
  prompt: typeof item.prompt === 'string' ? item.prompt : null,
519
1107
  fork_context: typeof item.fork_context === 'boolean' ? item.fork_context : null,
520
1108
  agents_states: item.agents_states && typeof item.agents_states === 'object'
@@ -522,9 +1110,70 @@ function parseCollabToolCallLine(line, stageId, commandIndex) {
522
1110
  : null
523
1111
  };
524
1112
  }
1113
+ function parseStringSlots(value) {
1114
+ return Array.isArray(value) ? value.map((entry) => normalizeOptionalString(entry)) : [];
1115
+ }
1116
+ function normalizeOptionalString(value) {
1117
+ if (typeof value !== 'string') {
1118
+ return null;
1119
+ }
1120
+ const trimmed = value.trim();
1121
+ return trimmed.length > 0 ? trimmed : null;
1122
+ }
1123
+ function parseCollabReceiverAgents(value, slots = {}) {
1124
+ if (!Array.isArray(value)) {
1125
+ return null;
1126
+ }
1127
+ const { receiverThreadIdSlots = [], receiverAgentPathSlots = [] } = slots;
1128
+ const parsed = [];
1129
+ for (const [index, entry] of value.entries()) {
1130
+ if (!entry || typeof entry !== 'object') {
1131
+ continue;
1132
+ }
1133
+ const record = entry;
1134
+ const threadId = normalizeOptionalString(record.thread_id) ?? receiverThreadIdSlots[index] ?? null;
1135
+ const agentNickname = normalizeOptionalString(record.agent_nickname);
1136
+ const agentRole = normalizeOptionalString(record.agent_role);
1137
+ const agentPath = normalizeOptionalString(record.agent_path) ?? receiverAgentPathSlots[index] ?? null;
1138
+ if (!threadId && !agentNickname && !agentRole && !agentPath) {
1139
+ continue;
1140
+ }
1141
+ parsed.push({
1142
+ thread_id: threadId,
1143
+ agent_nickname: agentNickname,
1144
+ agent_role: agentRole,
1145
+ agent_path: agentPath
1146
+ });
1147
+ }
1148
+ return parsed.length > 0 ? parsed : null;
1149
+ }
525
1150
  function normalizeCollabStatus(value) {
526
1151
  if (value === 'completed' || value === 'failed' || value === 'in_progress') {
527
1152
  return value;
528
1153
  }
529
1154
  return 'in_progress';
530
1155
  }
1156
+ function resolveStageTimeoutMs(stage, env) {
1157
+ const stageTimeout = normalizeTimeoutMs(stage.timeoutMs);
1158
+ if (stageTimeout !== null) {
1159
+ return stageTimeout;
1160
+ }
1161
+ return normalizeTimeoutMs(parseNumber(env.CODEX_ORCHESTRATOR_STAGE_TIMEOUT_MS));
1162
+ }
1163
+ function parseNumber(value) {
1164
+ if (!value || !value.trim()) {
1165
+ return undefined;
1166
+ }
1167
+ const parsed = Number(value);
1168
+ return Number.isFinite(parsed) ? parsed : undefined;
1169
+ }
1170
+ function normalizeTimeoutMs(value) {
1171
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
1172
+ return null;
1173
+ }
1174
+ const normalized = Math.trunc(value);
1175
+ if (normalized <= 0) {
1176
+ return null;
1177
+ }
1178
+ return normalized;
1179
+ }