@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
@@ -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,163 @@ 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
+ manifest.provider_linear_worker_tokens =
358
+ buildProviderLinearWorkerManifestTokenUsage(providerLinearWorkerProof?.tokens) ?? null;
359
+ if (result.status === 'succeeded' && providerLinearWorkerProofRecord === null) {
360
+ providerLinearWorkerFailureReason = 'provider_linear_worker_proof_missing_or_unreadable';
361
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
362
+ status: 'failed',
363
+ endReason: 'provider_linear_worker_proof_missing_or_unreadable'
364
+ });
365
+ forceProviderLinearWorkerFailure = true;
366
+ }
367
+ const proofTerminalStatus = resolveProviderLinearWorkerTerminalStatus(providerLinearWorkerProofRecord);
368
+ const proofTerminalReason = resolveProviderLinearWorkerTerminalReason(providerLinearWorkerProofRecord);
369
+ providerLinearWorkerTerminalStatus = proofTerminalStatus;
370
+ providerLinearWorkerTerminalReason = proofTerminalReason;
371
+ const proofAttemptStartedAt = resolveProviderLinearWorkerAttemptStartedAt(providerLinearWorkerProofRecord) ?? entry.started_at ?? null;
372
+ const reviewTelemetryStatus = coerceTelemetryStatusValue(providerReviewTelemetry?.status);
373
+ const reviewOutcomeSummary = formatReviewTelemetryOutcomeSummary(providerReviewTelemetry);
374
+ providerLinearWorkerReviewOutcomeSummary = reviewOutcomeSummary;
375
+ const mutationSuppressions = deriveDeterministicProviderMutationSuppressions(providerLinearWorkerProof?.linear_audit ?? null, {
376
+ recordedAtNotBefore: proofAttemptStartedAt,
377
+ issueId: providerLinearWorkerProof?.issue_id ?? null
378
+ });
379
+ const degradationSummary = formatDeterministicProviderMutationDegradationSummary(mutationSuppressions);
380
+ if (proofTerminalStatus === 'failed') {
381
+ providerLinearWorkerFailureReason = 'provider_linear_worker_terminal_failed';
382
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
383
+ status: 'failed',
384
+ endReason: proofTerminalReason,
385
+ reviewOutcomeSummary,
386
+ degradationSummary
387
+ });
388
+ forceProviderLinearWorkerFailure = true;
389
+ }
390
+ else if (providerLinearWorkerFailureReason === null && reviewTelemetryStatus === 'failed') {
391
+ providerLinearWorkerFailureReason = 'provider_linear_worker_review_failed';
392
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
393
+ status: 'failed',
394
+ endReason: null,
395
+ reviewOutcomeSummary: reviewOutcomeSummary ?? 'review telemetry reported terminal failure',
396
+ degradationSummary
397
+ });
398
+ forceProviderLinearWorkerFailure = true;
399
+ }
400
+ else if (proofTerminalStatus === 'succeeded' && result.status === 'succeeded') {
401
+ effectiveSummary = buildProviderLinearWorkerTerminalSummary({
402
+ status: 'succeeded',
403
+ endReason: proofTerminalReason,
404
+ reviewOutcomeSummary,
405
+ degradationSummary
406
+ });
407
+ }
408
+ else if (degradationSummary) {
409
+ effectiveSummary = `${effectiveSummary} (${degradationSummary})`;
410
+ }
411
+ }
412
+ const effectiveExitCode = (forceReviewEvidenceFailure || forceProviderLinearWorkerFailure) && normalizedExitCode === 0
413
+ ? 1
414
+ : normalizedExitCode;
237
415
  entry.completed_at = isoTimestamp();
238
- entry.exit_code = normalizedExitCode;
239
- entry.summary = summary;
240
- entry.status = result.status === 'succeeded' ? 'succeeded' : stage.allowFailure ? 'skipped' : 'failed';
416
+ entry.exit_code = effectiveExitCode;
417
+ entry.summary = effectiveSummary;
418
+ entry.status = forceReviewEvidenceFailure || forceProviderLinearWorkerFailure
419
+ ? 'failed'
420
+ : result.status === 'succeeded'
421
+ ? 'succeeded'
422
+ : stage.allowFailure
423
+ ? 'skipped'
424
+ : 'failed';
241
425
  if (collabBuffer.trim()) {
242
426
  const record = parseCollabToolCallLine(collabBuffer, stage.id, entry.index);
243
427
  if (record) {
@@ -245,22 +429,113 @@ export async function runCommandStage(context, hooks = {}) {
245
429
  }
246
430
  collabBuffer = '';
247
431
  }
248
- if (entry.status === 'failed') {
249
- const errorDetails = {
432
+ if (result.status !== 'succeeded' && entry.status === 'skipped') {
433
+ const fallbackReason = timedOut ? 'timed_out' : 'command_failed';
434
+ writeEvent({
435
+ type: 'command:fallback',
436
+ fallback: 'allow_failure',
437
+ reason: fallbackReason,
250
438
  exit_code: normalizedExitCode,
439
+ signal: result.signal,
440
+ timeout_ms: timeoutBoundMs
441
+ });
442
+ events?.log({
443
+ stageId: stage.id,
444
+ stageIndex: index,
445
+ level: 'warn',
446
+ source: 'system',
447
+ message: timedOut
448
+ ? `Non-fatal fallback applied after timeout (${timeoutBoundMs !== null ? `${timeoutBoundMs}ms` : 'configured timeout'}).`
449
+ : 'Non-fatal fallback applied after command failure.'
450
+ });
451
+ }
452
+ if (result.status !== 'succeeded') {
453
+ const failureReason = timedOut ? 'timed_out' : 'command_failed';
454
+ const errorDetails = {
455
+ exit_code: effectiveExitCode,
251
456
  sandbox_state: result.sandboxState,
252
- stderr: stderrText
457
+ stderr: stderrText,
458
+ failure_reason: failureReason
253
459
  };
460
+ if (effectiveExitCode !== normalizedExitCode) {
461
+ errorDetails.command_exit_code = normalizedExitCode;
462
+ }
254
463
  if (result.signal) {
255
464
  errorDetails.signal = result.signal;
256
465
  }
466
+ if (timeoutBoundMs !== null) {
467
+ errorDetails.timeout_ms = timeoutBoundMs;
468
+ }
469
+ if (timedOut) {
470
+ errorDetails.timed_out = true;
471
+ }
472
+ if (entry.status === 'skipped') {
473
+ errorDetails.non_fatal_fallback = true;
474
+ }
475
+ if (stdoutTruncated) {
476
+ errorDetails.stdout_truncated = true;
477
+ }
478
+ if (stderrTruncated) {
479
+ errorDetails.stderr_truncated = true;
480
+ }
481
+ entry.error_file = await appendCommandError(env, paths, manifest, entry, entry.status === 'skipped' ? 'command-allow-failure' : 'command-failed', errorDetails);
482
+ }
483
+ if (forceProviderLinearWorkerFailure && result.status === 'succeeded' && !entry.error_file) {
484
+ const errorDetails = {
485
+ exit_code: effectiveExitCode,
486
+ command_exit_code: normalizedExitCode,
487
+ sandbox_state: result.sandboxState,
488
+ failure_reason: providerLinearWorkerFailureReason ?? 'provider_linear_worker_authoritative_failure',
489
+ detail: effectiveSummary
490
+ };
491
+ if (providerLinearWorkerTerminalStatus) {
492
+ errorDetails.provider_linear_worker_terminal_status = providerLinearWorkerTerminalStatus;
493
+ }
494
+ if (providerLinearWorkerTerminalReason) {
495
+ errorDetails.provider_linear_worker_end_reason = providerLinearWorkerTerminalReason;
496
+ }
497
+ if (providerLinearWorkerReviewOutcomeSummary) {
498
+ errorDetails.review_outcome_summary = providerLinearWorkerReviewOutcomeSummary;
499
+ }
257
500
  if (stdoutTruncated) {
258
501
  errorDetails.stdout_truncated = true;
259
502
  }
260
503
  if (stderrTruncated) {
261
504
  errorDetails.stderr_truncated = true;
262
505
  }
263
- entry.error_file = await appendCommandError(env, paths, manifest, entry, 'command-failed', errorDetails);
506
+ entry.error_file = await appendCommandError(env, paths, manifest, entry, 'provider-linear-worker-authoritative-failed', errorDetails);
507
+ }
508
+ if (forceReviewEvidenceFailure && reviewEvidenceMismatch) {
509
+ if (entry.error_file) {
510
+ writeEvent({
511
+ type: 'command:warning',
512
+ warning: 'review-evidence-inconsistent',
513
+ preserved_error_file: entry.error_file,
514
+ telemetry_path: relativeToRepo(env, reviewEvidenceMismatch.telemetryPath),
515
+ detail: reviewEvidenceMismatch.message
516
+ });
517
+ events?.log({
518
+ stageId: stage.id,
519
+ stageIndex: index,
520
+ level: 'warn',
521
+ source: 'system',
522
+ message: `Review evidence mismatch preserved alongside the original command failure: ${reviewEvidenceMismatch.message}`
523
+ });
524
+ }
525
+ else {
526
+ entry.error_file = await appendCommandError(env, paths, manifest, entry, 'review-evidence-inconsistent', {
527
+ exit_code: effectiveExitCode,
528
+ command_exit_code: normalizedExitCode,
529
+ sandbox_state: result.sandboxState,
530
+ expected_review_status: result.status === 'succeeded' ? 'succeeded' : 'failed',
531
+ telemetry_status: reviewEvidenceMismatch.telemetryStatus,
532
+ telemetry_generated_at: reviewEvidenceMismatch.telemetryGeneratedAt,
533
+ telemetry_output_log_path: reviewEvidenceMismatch.telemetryOutputLogPath,
534
+ telemetry_path: relativeToRepo(env, reviewEvidenceMismatch.telemetryPath),
535
+ failure_reason: 'review_evidence_inconsistent',
536
+ detail: reviewEvidenceMismatch.message
537
+ });
538
+ }
264
539
  }
265
540
  await persistManifest(paths, manifest, persister, { force: true });
266
541
  events?.stageCompleted({
@@ -273,7 +548,7 @@ export async function runCommandStage(context, hooks = {}) {
273
548
  summary: entry.summary,
274
549
  logPath: entry.log_path
275
550
  });
276
- return { exitCode: normalizedExitCode, summary };
551
+ return { exitCode: effectiveExitCode, summary: effectiveSummary };
277
552
  }
278
553
  finally {
279
554
  unsubscribe();
@@ -282,6 +557,331 @@ export async function runCommandStage(context, hooks = {}) {
282
557
  privacyLog.end();
283
558
  }
284
559
  }
560
+ function shouldEnforceReviewEvidenceConsistency(stage) {
561
+ return (parseBooleanEnvFlag(stage.env?.[REVIEW_EVIDENCE_CONSISTENCY_ENV_KEY]) &&
562
+ isReviewCommandStage(stage));
563
+ }
564
+ function shouldAwaitReviewTelemetryEvidence(execEnv, enforceReviewEvidenceConsistency) {
565
+ if (enforceReviewEvidenceConsistency) {
566
+ return true;
567
+ }
568
+ const forced = parseBooleanEnvFlag(execEnv.FORCE_CODEX_REVIEW);
569
+ const nonInteractive = process.stdin.isTTY !== true ||
570
+ parseBooleanEnvFlag(execEnv.CODEX_REVIEW_NON_INTERACTIVE) ||
571
+ parseBooleanEnvFlag(execEnv.CODEX_NON_INTERACTIVE) ||
572
+ parseBooleanEnvFlag(execEnv.CODEX_NO_INTERACTIVE);
573
+ return forced || !nonInteractive;
574
+ }
575
+ function isReviewCommandStage(stage) {
576
+ const stageId = stage.id.trim().toLowerCase();
577
+ if (stageId === 'review') {
578
+ return true;
579
+ }
580
+ const haystack = `${stage.title} ${stage.command}`.toLowerCase();
581
+ return (haystack.includes('npm run review') ||
582
+ haystack.includes('codex review') ||
583
+ haystack.includes('codex-orchestrator review') ||
584
+ haystack.includes('run-review.ts') ||
585
+ haystack.includes('run-review.js'));
586
+ }
587
+ function isProviderLinearWorkerCommandStage(stage) {
588
+ const stageId = stage.id.trim().toLowerCase();
589
+ if (stageId === 'provider-linear-worker') {
590
+ return true;
591
+ }
592
+ const haystack = `${stage.title} ${stage.command}`.toLowerCase();
593
+ return haystack.includes('providerlinearworkerrunner');
594
+ }
595
+ function resolveStageInvocation(stage, env) {
596
+ if (isProviderLinearWorkerCommandStage(stage)) {
597
+ const providerWorkerPackageRoot = normalizeOptionalString(env.CODEX_ORCHESTRATOR_PACKAGE_ROOT) ?? PACKAGE_ROOT;
598
+ const invocation = resolveProviderLinearWorkerProgramInvocation({
599
+ allowConfiguredForeignPackageRoot: true,
600
+ env,
601
+ execPath: normalizeOptionalString(env.CODEX_ORCHESTRATOR_NODE_BIN) ?? process.execPath,
602
+ packageRoot: providerWorkerPackageRoot
603
+ });
604
+ return {
605
+ command: invocation.command,
606
+ args: invocation.args,
607
+ preview: buildCommandPreview(invocation.command, invocation.args),
608
+ warning: invocation.warning,
609
+ envOverrides: invocation.envOverrides
610
+ };
611
+ }
612
+ const packageRootInvocation = resolvePackageRootDistStageInvocation(stage.command, env);
613
+ if (packageRootInvocation) {
614
+ return packageRootInvocation;
615
+ }
616
+ return {
617
+ command: stage.command,
618
+ preview: stage.command
619
+ };
620
+ }
621
+ function resolvePackageRootDistStageInvocation(commandLine, env) {
622
+ const match = commandLine.match(/^\s*node\s+["']?\$CODEX_ORCHESTRATOR_PACKAGE_ROOT\/dist\/([^"'\s]+?\.js)["']?(.*)$/u);
623
+ if (!match) {
624
+ return null;
625
+ }
626
+ const [, distRelativePath, trailingArgsRaw] = match;
627
+ const invocation = resolvePackageProgramInvocation({
628
+ allowConfiguredForeignPackageRoot: true,
629
+ env,
630
+ packageRoot: PACKAGE_ROOT,
631
+ execPath: normalizeOptionalString(env.CODEX_ORCHESTRATOR_NODE_BIN) ?? process.execPath,
632
+ distRelativePath
633
+ });
634
+ const command = `${buildCommandPreview(invocation.command, invocation.args)}${trailingArgsRaw}`;
635
+ return {
636
+ command,
637
+ preview: command,
638
+ warning: invocation.warning,
639
+ envOverrides: invocation.envOverrides
640
+ };
641
+ }
642
+ function resolveReviewEvidenceWaiverReason(env) {
643
+ const reason = env?.[REVIEW_EVIDENCE_WAIVER_REASON_ENV_KEY]?.trim();
644
+ return reason && reason.length > 0 ? reason : null;
645
+ }
646
+ function parseBooleanEnvFlag(value) {
647
+ if (!value) {
648
+ return false;
649
+ }
650
+ const normalized = value.trim().toLowerCase();
651
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
652
+ }
653
+ async function verifyReviewEvidenceConsistency(options) {
654
+ const telemetryPath = options.telemetryPath ?? join(options.paths.runDir, 'review', 'telemetry.json');
655
+ const telemetry = options.telemetryPreloaded === true
656
+ ? options.telemetry ?? null
657
+ : options.telemetry ?? (await waitForReviewTelemetryEvidence(telemetryPath));
658
+ if (!telemetry) {
659
+ return {
660
+ message: 'review telemetry is missing, unreadable, or incomplete at terminal stage closeout.',
661
+ telemetryPath,
662
+ telemetryStatus: null,
663
+ telemetryGeneratedAt: null,
664
+ telemetryOutputLogPath: null
665
+ };
666
+ }
667
+ const freshnessMismatch = verifyReviewTelemetryFreshness({
668
+ env: options.env,
669
+ paths: options.paths,
670
+ startedAt: options.startedAt,
671
+ telemetry,
672
+ telemetryPath
673
+ });
674
+ if (freshnessMismatch) {
675
+ return freshnessMismatch;
676
+ }
677
+ const generatedAt = coerceTelemetryString(telemetry.generated_at);
678
+ const telemetryStatus = coerceTelemetryString(telemetry.status);
679
+ const telemetryOutputLogPath = coerceTelemetryString(telemetry.output_log_path);
680
+ if (telemetryStatus !== options.expectedStatus) {
681
+ return {
682
+ message: `review telemetry status ${telemetryStatus ?? '<missing>'} does not match terminal stage result ${options.expectedStatus}.`,
683
+ telemetryPath,
684
+ telemetryStatus,
685
+ telemetryGeneratedAt: generatedAt,
686
+ telemetryOutputLogPath
687
+ };
688
+ }
689
+ return null;
690
+ }
691
+ function verifyReviewTelemetryFreshness(options) {
692
+ const { env, paths, startedAt, telemetry, telemetryPath } = options;
693
+ const generatedAt = typeof telemetry.generated_at === 'string' && telemetry.generated_at.trim().length > 0
694
+ ? telemetry.generated_at
695
+ : null;
696
+ if (!generatedAt) {
697
+ return {
698
+ message: 'review telemetry is missing generated_at, so terminal evidence freshness cannot be verified.',
699
+ telemetryPath,
700
+ telemetryStatus: coerceTelemetryString(telemetry.status),
701
+ telemetryGeneratedAt: null,
702
+ telemetryOutputLogPath: coerceTelemetryString(telemetry.output_log_path)
703
+ };
704
+ }
705
+ const generatedAtMs = Date.parse(generatedAt);
706
+ if (!Number.isFinite(generatedAtMs)) {
707
+ return {
708
+ message: `review telemetry generated_at is invalid (${generatedAt}).`,
709
+ telemetryPath,
710
+ telemetryStatus: coerceTelemetryString(telemetry.status),
711
+ telemetryGeneratedAt: generatedAt,
712
+ telemetryOutputLogPath: coerceTelemetryString(telemetry.output_log_path)
713
+ };
714
+ }
715
+ const startedAtMs = typeof startedAt === 'string' ? Date.parse(startedAt) : Number.NaN;
716
+ if (Number.isFinite(startedAtMs) && generatedAtMs < startedAtMs) {
717
+ return {
718
+ message: `review telemetry is stale (generated_at ${generatedAt} precedes stage start ${startedAt}).`,
719
+ telemetryPath,
720
+ telemetryStatus: coerceTelemetryString(telemetry.status),
721
+ telemetryGeneratedAt: generatedAt,
722
+ telemetryOutputLogPath: coerceTelemetryString(telemetry.output_log_path)
723
+ };
724
+ }
725
+ const expectedOutputLogPath = relativeToRepo(env, join(paths.runDir, 'review', 'output.log'));
726
+ const telemetryStatus = coerceTelemetryString(telemetry.status);
727
+ const telemetryOutputLogPath = coerceTelemetryString(telemetry.output_log_path);
728
+ if (telemetryOutputLogPath !== expectedOutputLogPath) {
729
+ return {
730
+ message: `review telemetry output_log_path ${telemetryOutputLogPath ?? '<missing>'} does not match the active run artifact ${expectedOutputLogPath}.`,
731
+ telemetryPath,
732
+ telemetryStatus,
733
+ telemetryGeneratedAt: generatedAt,
734
+ telemetryOutputLogPath
735
+ };
736
+ }
737
+ return null;
738
+ }
739
+ async function loadReviewTelemetryEvidence(telemetryPath, options) {
740
+ if (options.waitForEvidence) {
741
+ return await waitForReviewTelemetryEvidence(telemetryPath);
742
+ }
743
+ return await readReviewTelemetryEvidence(telemetryPath);
744
+ }
745
+ async function waitForReviewTelemetryEvidence(telemetryPath) {
746
+ const deadline = Date.now() + REVIEW_TELEMETRY_WAIT_TIMEOUT_MS;
747
+ for (;;) {
748
+ const telemetry = await readReviewTelemetryEvidence(telemetryPath);
749
+ if (telemetry) {
750
+ return telemetry;
751
+ }
752
+ if (Date.now() >= deadline) {
753
+ return null;
754
+ }
755
+ await delay(REVIEW_TELEMETRY_POLL_INTERVAL_MS);
756
+ }
757
+ }
758
+ async function readReviewTelemetryEvidence(telemetryPath) {
759
+ try {
760
+ const raw = await readFile(telemetryPath, 'utf8');
761
+ const parsed = JSON.parse(raw);
762
+ return parsed && typeof parsed === 'object' ? parsed : null;
763
+ }
764
+ catch {
765
+ return null;
766
+ }
767
+ }
768
+ async function loadProviderLinearWorkerProof(proofPath) {
769
+ try {
770
+ const raw = await readFile(proofPath, 'utf8');
771
+ const parsed = JSON.parse(raw);
772
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
773
+ }
774
+ catch {
775
+ return null;
776
+ }
777
+ }
778
+ function buildProviderLinearWorkerManifestTokenUsage(tokens) {
779
+ if (!tokens || typeof tokens !== 'object') {
780
+ return null;
781
+ }
782
+ const inputTokens = normalizeManifestTokenCount(tokens.input_tokens);
783
+ const outputTokens = normalizeManifestTokenCount(tokens.output_tokens);
784
+ const totalTokens = normalizeManifestTokenCount(tokens.total_tokens);
785
+ const reasoningOutputTokens = normalizeManifestTokenCount(tokens.reasoning_output_tokens);
786
+ if (inputTokens === null &&
787
+ outputTokens === null &&
788
+ totalTokens === null &&
789
+ reasoningOutputTokens === null) {
790
+ return null;
791
+ }
792
+ const usage = {
793
+ input_tokens: inputTokens,
794
+ output_tokens: outputTokens,
795
+ total_tokens: totalTokens
796
+ };
797
+ if (reasoningOutputTokens !== null) {
798
+ usage.reasoning_output_tokens = reasoningOutputTokens;
799
+ }
800
+ return usage;
801
+ }
802
+ function normalizeManifestTokenCount(value) {
803
+ return typeof value === 'number' && Number.isFinite(value)
804
+ ? Math.max(0, Math.trunc(value))
805
+ : null;
806
+ }
807
+ function coerceTelemetryString(value) {
808
+ if (typeof value !== 'string') {
809
+ return null;
810
+ }
811
+ const trimmed = value.trim();
812
+ return trimmed.length > 0 ? trimmed : null;
813
+ }
814
+ function coerceTelemetryStatusValue(value) {
815
+ if (value === 'succeeded' || value === 'failed') {
816
+ return value;
817
+ }
818
+ return null;
819
+ }
820
+ function coerceReviewOutcomeDisposition(value) {
821
+ switch (value) {
822
+ case 'clean-success':
823
+ case 'bounded-success':
824
+ case 'failed-boundary':
825
+ case 'failed-other':
826
+ return value;
827
+ default:
828
+ return null;
829
+ }
830
+ }
831
+ function hasTelemetryTerminationBoundary(telemetry) {
832
+ return coerceTelemetryTerminationBoundaryKind(telemetry) !== null;
833
+ }
834
+ function coerceTelemetryTerminationBoundaryKind(telemetry) {
835
+ if (!telemetry) {
836
+ return null;
837
+ }
838
+ const boundary = telemetry.termination_boundary;
839
+ if (boundary === null || typeof boundary !== 'object' || Array.isArray(boundary)) {
840
+ return null;
841
+ }
842
+ return coerceTelemetryString(boundary.kind);
843
+ }
844
+ function resolveReviewTelemetryOutcomeDisposition(telemetry) {
845
+ if (!telemetry) {
846
+ return null;
847
+ }
848
+ const explicitDisposition = coerceReviewOutcomeDisposition(telemetry.review_outcome);
849
+ const telemetryStatus = coerceTelemetryStatusValue(telemetry.status);
850
+ if (!telemetryStatus) {
851
+ return null;
852
+ }
853
+ const derivedDisposition = deriveReviewOutcomeDisposition({
854
+ status: telemetryStatus,
855
+ terminationBoundary: hasTelemetryTerminationBoundary(telemetry)
856
+ ? REVIEW_OUTCOME_BOUNDARY_PRESENCE_SENTINEL
857
+ : null
858
+ });
859
+ return explicitDisposition === derivedDisposition ? explicitDisposition : derivedDisposition;
860
+ }
861
+ function formatReviewTelemetryOutcomeSummary(telemetry) {
862
+ const disposition = resolveReviewTelemetryOutcomeDisposition(telemetry);
863
+ if (!disposition) {
864
+ return null;
865
+ }
866
+ const boundaryKind = coerceTelemetryTerminationBoundaryKind(telemetry);
867
+ switch (disposition) {
868
+ case 'clean-success':
869
+ return 'review outcome: clean success';
870
+ case 'bounded-success':
871
+ return boundaryKind
872
+ ? `review outcome: bounded success via ${boundaryKind}; not a wrapper failure`
873
+ : 'review outcome: bounded success with preserved termination boundary; not a wrapper failure';
874
+ case 'failed-boundary':
875
+ return boundaryKind
876
+ ? `review outcome: review-wrapper failure via ${boundaryKind}`
877
+ : 'review outcome: review-wrapper failure via explicit termination boundary';
878
+ case 'failed-other':
879
+ return 'review outcome: review command failed without termination-boundary classification; not an explicit wrapper-boundary failure';
880
+ }
881
+ }
882
+ function delay(ms) {
883
+ return new Promise((resolve) => setTimeout(resolve, ms));
884
+ }
285
885
  function runtimeSessionIdOrNull(value) {
286
886
  if (typeof value !== 'string') {
287
887
  return null;
@@ -454,9 +1054,12 @@ function streamEvent(writeEvent, event, hooks) {
454
1054
  break;
455
1055
  }
456
1056
  }
457
- function buildSummary(stage, exitCode, stdout, stderr, signal) {
458
- if (stage.summaryHint) {
459
- return stage.summaryHint;
1057
+ function buildSummary(stage, exitCode, stdout, stderr, signal, options = {}) {
1058
+ if (options.timedOut) {
1059
+ const timeoutLabel = typeof options.timeoutMs === 'number' && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0
1060
+ ? `${Math.trunc(options.timeoutMs)}ms`
1061
+ : 'configured timeout';
1062
+ return `Timed out after ${timeoutLabel}${stderr ? ` — ${truncate(stderr)}` : ''}`;
460
1063
  }
461
1064
  if (signal) {
462
1065
  return `Terminated with signal ${signal}${stderr ? ` — ${truncate(stderr)}` : ''}`;
@@ -464,6 +1067,9 @@ function buildSummary(stage, exitCode, stdout, stderr, signal) {
464
1067
  if (exitCode !== 0) {
465
1068
  return `Exited with code ${exitCode}${stderr ? ` — ${truncate(stderr)}` : ''}`;
466
1069
  }
1070
+ if (stage.summaryHint) {
1071
+ return stage.summaryHint;
1072
+ }
467
1073
  if (stdout) {
468
1074
  return truncate(stdout);
469
1075
  }
@@ -502,9 +1108,15 @@ function parseCollabToolCallLine(line, stageId, commandIndex) {
502
1108
  if (!item || item.type !== 'collab_tool_call') {
503
1109
  return null;
504
1110
  }
505
- const receiverThreadIds = Array.isArray(item.receiver_thread_ids)
506
- ? item.receiver_thread_ids.filter((entry) => typeof entry === 'string')
507
- : [];
1111
+ const receiverThreadIdSlots = parseStringSlots(item.receiver_thread_ids);
1112
+ const receiverThreadIds = receiverThreadIdSlots.filter((entry) => entry !== null);
1113
+ const senderAgentPath = normalizeOptionalString(item.sender_agent_path);
1114
+ const receiverAgentPathSlots = parseStringSlots(item.receiver_agent_paths);
1115
+ const receiverAgentPaths = receiverAgentPathSlots.filter((entry) => entry !== null);
1116
+ const receiverAgents = parseCollabReceiverAgents(item.receiver_agents, {
1117
+ receiverThreadIdSlots,
1118
+ receiverAgentPathSlots
1119
+ });
508
1120
  return {
509
1121
  observed_at: isoTimestamp(),
510
1122
  stage_id: stageId,
@@ -515,6 +1127,13 @@ function parseCollabToolCallLine(line, stageId, commandIndex) {
515
1127
  status: normalizeCollabStatus(item.status),
516
1128
  sender_thread_id: typeof item.sender_thread_id === 'string' ? item.sender_thread_id : 'unknown',
517
1129
  receiver_thread_ids: receiverThreadIds,
1130
+ sender_agent_path: senderAgentPath,
1131
+ receiver_agent_paths: receiverAgentPaths.length > 0
1132
+ ? receiverAgentPaths
1133
+ : receiverAgents
1134
+ ?.map((entry) => entry.agent_path)
1135
+ .filter((entry) => typeof entry === 'string' && entry.length > 0) ?? null,
1136
+ receiver_agents: receiverAgents,
518
1137
  prompt: typeof item.prompt === 'string' ? item.prompt : null,
519
1138
  fork_context: typeof item.fork_context === 'boolean' ? item.fork_context : null,
520
1139
  agents_states: item.agents_states && typeof item.agents_states === 'object'
@@ -522,9 +1141,70 @@ function parseCollabToolCallLine(line, stageId, commandIndex) {
522
1141
  : null
523
1142
  };
524
1143
  }
1144
+ function parseStringSlots(value) {
1145
+ return Array.isArray(value) ? value.map((entry) => normalizeOptionalString(entry)) : [];
1146
+ }
1147
+ function normalizeOptionalString(value) {
1148
+ if (typeof value !== 'string') {
1149
+ return null;
1150
+ }
1151
+ const trimmed = value.trim();
1152
+ return trimmed.length > 0 ? trimmed : null;
1153
+ }
1154
+ function parseCollabReceiverAgents(value, slots = {}) {
1155
+ if (!Array.isArray(value)) {
1156
+ return null;
1157
+ }
1158
+ const { receiverThreadIdSlots = [], receiverAgentPathSlots = [] } = slots;
1159
+ const parsed = [];
1160
+ for (const [index, entry] of value.entries()) {
1161
+ if (!entry || typeof entry !== 'object') {
1162
+ continue;
1163
+ }
1164
+ const record = entry;
1165
+ const threadId = normalizeOptionalString(record.thread_id) ?? receiverThreadIdSlots[index] ?? null;
1166
+ const agentNickname = normalizeOptionalString(record.agent_nickname);
1167
+ const agentRole = normalizeOptionalString(record.agent_role);
1168
+ const agentPath = normalizeOptionalString(record.agent_path) ?? receiverAgentPathSlots[index] ?? null;
1169
+ if (!threadId && !agentNickname && !agentRole && !agentPath) {
1170
+ continue;
1171
+ }
1172
+ parsed.push({
1173
+ thread_id: threadId,
1174
+ agent_nickname: agentNickname,
1175
+ agent_role: agentRole,
1176
+ agent_path: agentPath
1177
+ });
1178
+ }
1179
+ return parsed.length > 0 ? parsed : null;
1180
+ }
525
1181
  function normalizeCollabStatus(value) {
526
1182
  if (value === 'completed' || value === 'failed' || value === 'in_progress') {
527
1183
  return value;
528
1184
  }
529
1185
  return 'in_progress';
530
1186
  }
1187
+ function resolveStageTimeoutMs(stage, env) {
1188
+ const stageTimeout = normalizeTimeoutMs(stage.timeoutMs);
1189
+ if (stageTimeout !== null) {
1190
+ return stageTimeout;
1191
+ }
1192
+ return normalizeTimeoutMs(parseNumber(env.CODEX_ORCHESTRATOR_STAGE_TIMEOUT_MS));
1193
+ }
1194
+ function parseNumber(value) {
1195
+ if (!value || !value.trim()) {
1196
+ return undefined;
1197
+ }
1198
+ const parsed = Number(value);
1199
+ return Number.isFinite(parsed) ? parsed : undefined;
1200
+ }
1201
+ function normalizeTimeoutMs(value) {
1202
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
1203
+ return null;
1204
+ }
1205
+ const normalized = Math.trunc(value);
1206
+ if (normalized <= 0) {
1207
+ return null;
1208
+ }
1209
+ return normalized;
1210
+ }