@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.
- package/.agents/plugins/marketplace.json +20 -0
- package/README.md +46 -317
- package/bin/codex-orchestrator.js +161 -0
- package/codex.orchestrator.json +149 -13
- package/dist/bin/codex-orchestrator.js +797 -1154
- package/dist/orchestrator/src/cli/adapters/CommandBuilder.js +50 -0
- package/dist/orchestrator/src/cli/adapters/CommandPlanner.js +22 -4
- package/dist/orchestrator/src/cli/adapters/CommandReviewer.js +3 -3
- package/dist/orchestrator/src/cli/adapters/CommandTester.js +2 -2
- package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +295 -11
- package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +402 -0
- package/dist/orchestrator/src/cli/coStatusCliShell.js +451 -0
- package/dist/orchestrator/src/cli/coStatusOperatorAutopilotCliShell.js +120 -0
- package/dist/orchestrator/src/cli/codexCliShell.js +119 -0
- package/dist/orchestrator/src/cli/codexDefaultsSetup.js +265 -36
- package/dist/orchestrator/src/cli/config/delegationConfig.js +317 -5
- package/dist/orchestrator/src/cli/config/repoConfigPolicy.js +2 -3
- package/dist/orchestrator/src/cli/config/userConfig.js +28 -13
- package/dist/orchestrator/src/cli/control/authenticatedControlRouteGate.js +69 -0
- package/dist/orchestrator/src/cli/control/authenticatedRouteComposition.js +267 -0
- package/dist/orchestrator/src/cli/control/authenticatedRouteController.js +5 -0
- package/dist/orchestrator/src/cli/control/authenticatedRouteDispatcher.js +41 -0
- package/dist/orchestrator/src/cli/control/compatibilityIssuePresenter.js +1035 -0
- package/dist/orchestrator/src/cli/control/confirmationApproveController.js +62 -0
- package/dist/orchestrator/src/cli/control/confirmationCreateController.js +69 -0
- package/dist/orchestrator/src/cli/control/confirmationIssueConsumeController.js +43 -0
- package/dist/orchestrator/src/cli/control/confirmationListController.js +22 -0
- package/dist/orchestrator/src/cli/control/confirmationValidateController.js +58 -0
- package/dist/orchestrator/src/cli/control/confirmations.js +25 -3
- package/dist/orchestrator/src/cli/control/controlActionCancelConfirmation.js +65 -0
- package/dist/orchestrator/src/cli/control/controlActionController.js +77 -0
- package/dist/orchestrator/src/cli/control/controlActionControllerSequencing.js +161 -0
- package/dist/orchestrator/src/cli/control/controlActionExecution.js +142 -0
- package/dist/orchestrator/src/cli/control/controlActionFinalization.js +43 -0
- package/dist/orchestrator/src/cli/control/controlActionOutcome.js +60 -0
- package/dist/orchestrator/src/cli/control/controlActionPreflight.js +476 -0
- package/dist/orchestrator/src/cli/control/controlAuthenticatedRouteHandoff.js +57 -0
- package/dist/orchestrator/src/cli/control/controlBootstrapAssembly.js +39 -0
- package/dist/orchestrator/src/cli/control/controlBootstrapMetadataPersistence.js +16 -0
- package/dist/orchestrator/src/cli/control/controlEventTransport.js +49 -0
- package/dist/orchestrator/src/cli/control/controlExpiryLifecycle.js +102 -0
- package/dist/orchestrator/src/cli/control/controlHostOwnership.js +480 -0
- package/dist/orchestrator/src/cli/control/controlHostSupervision.js +630 -0
- package/dist/orchestrator/src/cli/control/controlOversightFacade.js +8 -0
- package/dist/orchestrator/src/cli/control/controlOversightReadContract.js +1 -0
- package/dist/orchestrator/src/cli/control/controlOversightReadService.js +16 -0
- package/dist/orchestrator/src/cli/control/controlOversightUpdateContract.js +1 -0
- package/dist/orchestrator/src/cli/control/controlPersistenceFiles.js +6 -0
- package/dist/orchestrator/src/cli/control/controlQuestionChildResolution.js +18 -0
- package/dist/orchestrator/src/cli/control/controlRequestContext.js +42 -0
- package/dist/orchestrator/src/cli/control/controlRequestController.js +9 -0
- package/dist/orchestrator/src/cli/control/controlRequestPredispatch.js +17 -0
- package/dist/orchestrator/src/cli/control/controlRequestRouteDispatch.js +44 -0
- package/dist/orchestrator/src/cli/control/controlRuntime.js +1003 -0
- package/dist/orchestrator/src/cli/control/controlServer.js +23 -1456
- package/dist/orchestrator/src/cli/control/controlServerAuditAndErrorHelpers.js +115 -0
- package/dist/orchestrator/src/cli/control/controlServerAuthenticatedRouteBranch.js +29 -0
- package/dist/orchestrator/src/cli/control/controlServerBootstrapLifecycle.js +30 -0
- package/dist/orchestrator/src/cli/control/controlServerBootstrapStartSequence.js +21 -0
- package/dist/orchestrator/src/cli/control/controlServerOwnedRuntimeLifecycle.js +67 -0
- package/dist/orchestrator/src/cli/control/controlServerPublicLifecycle.js +756 -0
- package/dist/orchestrator/src/cli/control/controlServerPublicRouteHelpers.js +86 -0
- package/dist/orchestrator/src/cli/control/controlServerReadyInstanceLifecycle.js +25 -0
- package/dist/orchestrator/src/cli/control/controlServerReadyInstanceStartup.js +18 -0
- package/dist/orchestrator/src/cli/control/controlServerRequestBodyHelpers.js +37 -0
- package/dist/orchestrator/src/cli/control/controlServerRequestShell.js +40 -0
- package/dist/orchestrator/src/cli/control/controlServerRequestShellBinding.js +17 -0
- package/dist/orchestrator/src/cli/control/controlServerSeedLoading.js +27 -0
- package/dist/orchestrator/src/cli/control/controlServerSeededRuntimeAssembly.js +186 -0
- package/dist/orchestrator/src/cli/control/controlServerStartupInputPreparation.js +31 -0
- package/dist/orchestrator/src/cli/control/controlServerStartupSequence.js +49 -0
- package/dist/orchestrator/src/cli/control/controlState.js +233 -2
- package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +1904 -0
- package/dist/orchestrator/src/cli/control/controlTelegramBridgeBootstrapLifecycle.js +22 -0
- package/dist/orchestrator/src/cli/control/controlTelegramBridgeLifecycle.js +67 -0
- package/dist/orchestrator/src/cli/control/controlTelegramBridgeOversightFacadeFactory.js +8 -0
- package/dist/orchestrator/src/cli/control/controlTelegramCommandController.js +49 -0
- package/dist/orchestrator/src/cli/control/controlTelegramDispatchRead.js +40 -0
- package/dist/orchestrator/src/cli/control/controlTelegramPollingController.js +89 -0
- package/dist/orchestrator/src/cli/control/controlTelegramProjectionNotificationController.js +29 -0
- package/dist/orchestrator/src/cli/control/controlTelegramPushState.js +63 -0
- package/dist/orchestrator/src/cli/control/controlTelegramQuestionRead.js +13 -0
- package/dist/orchestrator/src/cli/control/controlTelegramReadController.js +216 -0
- package/dist/orchestrator/src/cli/control/controlTelegramUpdateHandler.js +63 -0
- package/dist/orchestrator/src/cli/control/controlWatcher.js +73 -5
- package/dist/orchestrator/src/cli/control/delegationRegisterController.js +35 -0
- package/dist/orchestrator/src/cli/control/dynamicToolBridgePolicy.js +139 -0
- package/dist/orchestrator/src/cli/control/eventsSseController.js +12 -0
- package/dist/orchestrator/src/cli/control/linearBudgetState.js +1789 -0
- package/dist/orchestrator/src/cli/control/linearDispatchSource.js +1137 -0
- package/dist/orchestrator/src/cli/control/linearGraphqlClient.js +150 -0
- package/dist/orchestrator/src/cli/control/linearRateLimit.js +102 -0
- package/dist/orchestrator/src/cli/control/linearWebhookController.js +499 -0
- package/dist/orchestrator/src/cli/control/liveLinearAdvisoryRuntime.js +70 -0
- package/dist/orchestrator/src/cli/control/observabilityApiController.js +173 -0
- package/dist/orchestrator/src/cli/control/observabilityReadModel.js +500 -0
- package/dist/orchestrator/src/cli/control/observabilitySurface.js +284 -0
- package/dist/orchestrator/src/cli/control/observabilityUpdateNotifier.js +22 -0
- package/dist/orchestrator/src/cli/control/operatorDashboardPresenter.js +252 -0
- package/dist/orchestrator/src/cli/control/providerAgentCapacity.js +70 -0
- package/dist/orchestrator/src/cli/control/providerControlHostFreshnessGauge.js +1068 -0
- package/dist/orchestrator/src/cli/control/providerIntakeState.js +473 -0
- package/dist/orchestrator/src/cli/control/providerIssueHandoff.js +6811 -0
- package/dist/orchestrator/src/cli/control/providerIssueObservability.js +1348 -0
- package/dist/orchestrator/src/cli/control/providerIssueRetryQueue.js +84 -0
- package/dist/orchestrator/src/cli/control/providerLinearRuntimeProof.js +588 -0
- package/dist/orchestrator/src/cli/control/providerLinearScreenshotProof.js +473 -0
- package/dist/orchestrator/src/cli/control/providerLinearWorkerTruth.js +383 -0
- package/dist/orchestrator/src/cli/control/providerLinearWorkflowAudit.js +254 -0
- package/dist/orchestrator/src/cli/control/providerLinearWorkflowFacade.js +5573 -0
- package/dist/orchestrator/src/cli/control/providerLinearWorkflowStates.js +115 -0
- package/dist/orchestrator/src/cli/control/providerMergeCloseout.js +1868 -0
- package/dist/orchestrator/src/cli/control/providerOperatorAutopilot.js +1580 -0
- package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLifecycle.js +154 -0
- package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLocalRolloutExecution.js +1006 -0
- package/dist/orchestrator/src/cli/control/providerPollingHealth.js +435 -0
- package/dist/orchestrator/src/cli/control/providerTerminalCleanup.js +516 -0
- package/dist/orchestrator/src/cli/control/providerWorkerHosts.js +191 -0
- package/dist/orchestrator/src/cli/control/providerWorkflowConfigStore.js +515 -0
- package/dist/orchestrator/src/cli/control/questionChildResolutionAdapter.js +361 -0
- package/dist/orchestrator/src/cli/control/questionQueueController.js +181 -0
- package/dist/orchestrator/src/cli/control/questionReadRetryDeduplication.js +9 -0
- package/dist/orchestrator/src/cli/control/questionReadSequence.js +10 -0
- package/dist/orchestrator/src/cli/control/securityViolationController.js +27 -0
- package/dist/orchestrator/src/cli/control/selectedRunProjection.js +1885 -0
- package/dist/orchestrator/src/cli/control/telegramOversightApiClient.js +48 -0
- package/dist/orchestrator/src/cli/control/telegramOversightBridge.js +180 -0
- package/dist/orchestrator/src/cli/control/telegramOversightBridgeProjectionDeliveryQueue.js +25 -0
- package/dist/orchestrator/src/cli/control/telegramOversightBridgeRuntimeLifecycle.js +45 -0
- package/dist/orchestrator/src/cli/control/telegramOversightBridgeStateStore.js +77 -0
- package/dist/orchestrator/src/cli/control/telegramOversightControlActionApiClient.js +45 -0
- package/dist/orchestrator/src/cli/control/trackerDispatchPilot.js +439 -0
- package/dist/orchestrator/src/cli/control/uiDataController.js +34 -0
- package/dist/orchestrator/src/cli/control/uiSessionController.js +100 -0
- package/dist/orchestrator/src/cli/controlHostCliShell.js +860 -0
- package/dist/orchestrator/src/cli/controlHostFreshnessGaugeCliShell.js +129 -0
- package/dist/orchestrator/src/cli/controlHostSupervisionCliShell.js +2127 -0
- package/dist/orchestrator/src/cli/delegationCliShell.js +62 -0
- package/dist/orchestrator/src/cli/delegationServer.js +567 -678
- package/dist/orchestrator/src/cli/delegationServerCliShell.js +52 -0
- package/dist/orchestrator/src/cli/delegationServerQuestionFlowShell.js +228 -0
- package/dist/orchestrator/src/cli/delegationServerToolDispatchShell.js +411 -0
- package/dist/orchestrator/src/cli/delegationServerTransport.js +274 -0
- package/dist/orchestrator/src/cli/delegationSetup.js +51 -171
- package/dist/orchestrator/src/cli/devtoolsCliShell.js +34 -0
- package/dist/orchestrator/src/cli/doctor.js +678 -164
- package/dist/orchestrator/src/cli/doctorCliRequestShell.js +72 -0
- package/dist/orchestrator/src/cli/doctorCliShell.js +138 -0
- package/dist/orchestrator/src/cli/doctorUsage.js +119 -15
- package/dist/orchestrator/src/cli/exec/experience.js +16 -2
- package/dist/orchestrator/src/cli/exec/summary.js +3 -0
- package/dist/orchestrator/src/cli/execCliShell.js +51 -0
- package/dist/orchestrator/src/cli/flowCliRequestShell.js +44 -0
- package/dist/orchestrator/src/cli/flowCliShell.js +239 -0
- package/dist/orchestrator/src/cli/frontendTestCliRequestShell.js +80 -0
- package/dist/orchestrator/src/cli/frontendTestCliShell.js +41 -0
- package/dist/orchestrator/src/cli/init.js +95 -1
- package/dist/orchestrator/src/cli/initCliShell.js +50 -0
- package/dist/orchestrator/src/cli/linearCliShell.js +1200 -0
- package/dist/orchestrator/src/cli/mcpEnableCliShell.js +132 -0
- package/dist/orchestrator/src/cli/metrics/metricsAggregator.js +3 -2
- package/dist/orchestrator/src/cli/metrics/metricsRecorder.js +56 -0
- package/dist/orchestrator/src/cli/orchestrator.js +66 -1376
- package/dist/orchestrator/src/cli/planCliShell.js +19 -0
- package/dist/orchestrator/src/cli/prCliShell.js +41 -0
- package/dist/orchestrator/src/cli/providerLinearChildLanePhaseContract.js +204 -0
- package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +1835 -0
- package/dist/orchestrator/src/cli/providerLinearChildLaneShell.js +2420 -0
- package/dist/orchestrator/src/cli/providerLinearChildStreamShell.js +385 -0
- package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +6834 -0
- package/dist/orchestrator/src/cli/resumeCliShell.js +14 -0
- package/dist/orchestrator/src/cli/reviewCliLaunchShell.js +72 -0
- package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
- package/dist/orchestrator/src/cli/rlm/context.js +94 -7
- package/dist/orchestrator/src/cli/rlm/rlmCodexRuntimeShell.js +546 -0
- package/dist/orchestrator/src/cli/rlm/symbolic.js +4 -2
- package/dist/orchestrator/src/cli/rlmCliRequestShell.js +42 -0
- package/dist/orchestrator/src/cli/rlmCompletionCliShell.js +46 -0
- package/dist/orchestrator/src/cli/rlmLaunchCliShell.js +51 -0
- package/dist/orchestrator/src/cli/rlmRunner.js +83 -523
- package/dist/orchestrator/src/cli/run/blockMemory.js +500 -0
- package/dist/orchestrator/src/cli/run/manifest.js +410 -73
- package/dist/orchestrator/src/cli/run/manifestPersister.js +45 -14
- package/dist/orchestrator/src/cli/run/runMemoryController.js +216 -0
- package/dist/orchestrator/src/cli/run/source0.js +690 -0
- package/dist/orchestrator/src/cli/run/workspacePath.js +101 -0
- package/dist/orchestrator/src/cli/runtime/mode.js +2 -1
- package/dist/orchestrator/src/cli/runtime/provider.js +39 -2
- package/dist/orchestrator/src/cli/selfCheckCliShell.js +12 -0
- package/dist/orchestrator/src/cli/services/commandRunner.js +698 -18
- package/dist/orchestrator/src/cli/services/execRuntime.js +66 -1
- package/dist/orchestrator/src/cli/services/orchestratorAutoScoutEvidenceRecorder.js +71 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudBranchResolution.js +8 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudEnvironmentResolution.js +22 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudExecutionLifecycleShell.js +39 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudPromptBuilder.js +37 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudRouteFallbackContract.js +45 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudRouteShell.js +36 -0
- package/dist/orchestrator/src/cli/services/orchestratorCloudTargetExecutor.js +277 -0
- package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycle.js +98 -0
- package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycleShell.js +54 -0
- package/dist/orchestrator/src/cli/services/orchestratorExecutionLifecycle.js +112 -0
- package/dist/orchestrator/src/cli/services/orchestratorExecutionModePolicy.js +27 -0
- package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteAdapterShell.js +59 -0
- package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteDecisionShell.js +57 -0
- package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteState.js +21 -0
- package/dist/orchestrator/src/cli/services/orchestratorExecutionRouter.js +2 -0
- package/dist/orchestrator/src/cli/services/orchestratorLocalPipelineExecutor.js +149 -0
- package/dist/orchestrator/src/cli/services/orchestratorLocalRouteShell.js +63 -0
- package/dist/orchestrator/src/cli/services/orchestratorPlanShell.js +54 -0
- package/dist/orchestrator/src/cli/services/orchestratorPlanTargetTracker.js +16 -0
- package/dist/orchestrator/src/cli/services/orchestratorResumePreparationShell.js +84 -0
- package/dist/orchestrator/src/cli/services/orchestratorResumeTokenValidation.js +15 -0
- package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleCompletion.js +31 -0
- package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleExecutionRegistration.js +37 -0
- package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleOrchestrationShell.js +83 -0
- package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleTaskManagerShell.js +37 -0
- package/dist/orchestrator/src/cli/services/orchestratorRuntimeManifestMutation.js +20 -0
- package/dist/orchestrator/src/cli/services/orchestratorStartPreparationShell.js +56 -0
- package/dist/orchestrator/src/cli/services/orchestratorStatusShell.js +70 -0
- package/dist/orchestrator/src/cli/services/pipelineResolver.js +7 -3
- package/dist/orchestrator/src/cli/services/plannerMemory.js +119 -0
- package/dist/orchestrator/src/cli/services/runPreparation.js +7 -3
- package/dist/orchestrator/src/cli/services/runSummaryWriter.js +9 -0
- package/dist/orchestrator/src/cli/setupBootstrapShell.js +114 -0
- package/dist/orchestrator/src/cli/setupCliShell.js +51 -0
- package/dist/orchestrator/src/cli/skillsCliShell.js +56 -0
- package/dist/orchestrator/src/cli/startCliRequestShell.js +53 -0
- package/dist/orchestrator/src/cli/startCliShell.js +68 -0
- package/dist/orchestrator/src/cli/statusCliShell.js +22 -0
- package/dist/orchestrator/src/cli/utils/authProvenanceFingerprint.js +27 -0
- package/dist/orchestrator/src/cli/utils/cloudPreflight.js +285 -7
- package/dist/orchestrator/src/cli/utils/codexFeatures.js +60 -0
- package/dist/orchestrator/src/cli/utils/delegationConfigParser.js +250 -0
- package/dist/orchestrator/src/cli/utils/delegationMcpHealth.js +1382 -0
- package/dist/orchestrator/src/cli/utils/devtools.js +2 -54
- package/dist/orchestrator/src/cli/utils/mcpServerEntry.js +53 -0
- package/dist/orchestrator/src/cli/utils/packageProgramResolver.js +151 -0
- package/dist/orchestrator/src/cli/utils/providerOverrideEnv.js +71 -0
- package/dist/orchestrator/src/cli/utils/trailingJsonObject.js +59 -0
- package/dist/orchestrator/src/learning/crystalizer.js +2 -2
- package/dist/orchestrator/src/manager.js +74 -4
- package/dist/orchestrator/src/persistence/ExperienceStore.js +233 -49
- package/dist/orchestrator/src/persistence/TaskStateStore.js +6 -6
- package/dist/orchestrator/src/persistence/lockFile.js +70 -4
- package/dist/orchestrator/src/persistence/sanitizeIdentifier.js +39 -0
- package/dist/orchestrator/src/sync/createCloudSyncWorker.js +3 -2
- package/dist/orchestrator/src/utils/atomicWrite.js +17 -2
- package/dist/packages/orchestrator/src/exec/unified-exec.js +99 -6
- package/dist/packages/orchestrator/src/instructions/promptPacks.js +150 -19
- package/dist/packages/sdk-node/src/orchestrator.js +137 -13
- package/dist/packages/shared/config/designConfig.js +8 -1
- package/dist/packages/shared/streams/stdio.js +1 -1
- package/dist/scripts/design/pipeline/permit.js +15 -0
- package/dist/scripts/lib/docs-catalog.js +399 -0
- package/dist/scripts/lib/docs-helpers.js +87 -5
- package/dist/scripts/lib/pr-watch-merge.js +1088 -80
- package/dist/scripts/lib/provider-run-contract.js +26 -0
- package/dist/scripts/lib/review-command-intent-classification.js +532 -0
- package/dist/scripts/lib/review-command-probe-classification.js +385 -0
- package/dist/scripts/lib/review-execution-boundary-preflight.js +279 -0
- package/dist/scripts/lib/review-execution-runtime.js +753 -0
- package/dist/scripts/lib/review-execution-state.js +1144 -0
- package/dist/scripts/lib/review-execution-telemetry.js +215 -0
- package/dist/scripts/lib/review-inspection-target-parsing.js +78 -0
- package/dist/scripts/lib/review-launch-attempt.js +601 -0
- package/dist/scripts/lib/review-meta-surface-boundary-analysis.js +300 -0
- package/dist/scripts/lib/review-meta-surface-normalization.js +746 -0
- package/dist/scripts/lib/review-non-interactive-handoff.js +61 -0
- package/dist/scripts/lib/review-prompt-context.js +376 -0
- package/dist/scripts/lib/review-scope-advisory.js +286 -0
- package/dist/scripts/lib/review-scope-paths.js +123 -0
- package/dist/scripts/lib/review-shell-command-parser.js +389 -0
- package/dist/scripts/lib/review-shell-env-interpreter.js +340 -0
- package/dist/scripts/lib/run-manifests.js +192 -36
- package/dist/scripts/lib/spark-policy-classifier.js +593 -0
- package/dist/scripts/run-review.js +507 -1777
- package/docs/README.md +43 -20
- package/docs/book/README.md +19 -0
- package/docs/book/codex-cli-0124-adoption.md +68 -0
- package/docs/book/local-hook-impact.md +73 -0
- package/docs/book/operations.md +60 -0
- package/docs/book/public-posture.md +34 -0
- package/docs/book/setup.md +91 -0
- package/docs/book/skills.md +11 -0
- package/docs/guides/codex-version-policy.md +104 -0
- package/docs/public/downstream-setup.md +113 -0
- package/docs/public/provider-onboarding.md +173 -0
- package/package.json +23 -10
- package/plugins/codex-orchestrator/.codex-plugin/plugin.json +30 -0
- package/plugins/codex-orchestrator/.mcp.json +13 -0
- package/plugins/codex-orchestrator/launcher.mjs +361 -0
- package/schemas/manifest.json +411 -0
- package/skills/README.md +26 -0
- package/skills/collab-subagents-first/SKILL.md +1 -1
- package/skills/delegation-usage/DELEGATION_GUIDE.md +30 -12
- package/skills/delegation-usage/SKILL.md +25 -14
- package/skills/land/SKILL.md +77 -0
- package/skills/linear/SKILL.md +255 -0
- package/skills/release/SKILL.md +47 -3
- package/skills/standalone-review/SKILL.md +6 -1
- package/templates/README.md +4 -2
- package/templates/codex/.codex/agents/awaiter-high.toml +2 -2
- package/templates/codex/.codex/agents/worker-complex.toml +1 -1
- package/templates/codex/.codex/config.toml +3 -4
- package/templates/codex/.codex/providers/README.md +13 -0
- package/templates/codex/.codex/providers/control.example.json +18 -0
- package/templates/codex/.codex/providers/provider.env.example +15 -0
- package/templates/codex/AGENTS.md +15 -8
- package/templates/codex/mcp-client.json +5 -1
- 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:
|
|
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:
|
|
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
|
|
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 =
|
|
239
|
-
entry.summary =
|
|
240
|
-
entry.status =
|
|
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 === '
|
|
249
|
-
const
|
|
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, '
|
|
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:
|
|
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 (
|
|
459
|
-
|
|
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
|
|
506
|
-
|
|
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
|
+
}
|