@kbediako/codex-orchestrator 0.1.37 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +20 -0
- package/README.md +73 -291
- package/bin/codex-orchestrator.js +161 -0
- package/codex.orchestrator.json +149 -13
- package/dist/bin/codex-orchestrator.js +795 -1154
- 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 +183 -11
- package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +402 -0
- package/dist/orchestrator/src/cli/coStatusCliShell.js +429 -0
- package/dist/orchestrator/src/cli/coStatusOperatorAutopilotCliShell.js +120 -0
- package/dist/orchestrator/src/cli/codexCliShell.js +72 -0
- package/dist/orchestrator/src/cli/codexDefaultsSetup.js +49 -11
- 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 +608 -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 +992 -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 +1899 -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 +1838 -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 +542 -122
- 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 +136 -16
- 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 +1 -0
- 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 +1772 -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 +5738 -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 +668 -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 +83 -1
- 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/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 +365 -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/public/downstream-setup.md +106 -0
- package/docs/public/provider-onboarding.md +173 -0
- package/package.json +30 -11
- package/plugins/codex-orchestrator/.codex-plugin/plugin.json +30 -0
- package/plugins/codex-orchestrator/.mcp.json +13 -0
- package/plugins/codex-orchestrator/launcher.mjs +359 -0
- package/schemas/manifest.json +395 -0
- package/skills/chrome-devtools/SKILL.md +1 -1
- package/skills/codex-orchestrator/SKILL.md +83 -0
- package/skills/collab-subagents-first/SKILL.md +2 -1
- package/skills/delegation-usage/DELEGATION_GUIDE.md +24 -11
- package/skills/delegation-usage/SKILL.md +20 -13
- 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/explorer-fast.toml +1 -0
- 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 +12 -7
- package/templates/codex/mcp-client.json +5 -1
- package/docs/README.md +0 -307
- package/docs/assets/setup.gif +0 -0
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
2
|
import { access, lstat, mkdir, readdir, readFile, realpath, symlink, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import process from 'node:process';
|
|
4
5
|
import { writeJsonAtomic } from '../utils/fs.js';
|
|
5
6
|
import { slugify } from '../utils/strings.js';
|
|
6
7
|
import { isoTimestamp } from '../utils/time.js';
|
|
7
8
|
import { loadInstructionSet } from '../../../../packages/orchestrator/src/instructions/loader.js';
|
|
8
9
|
import { resolveRunPaths, relativeToRepo } from './runPaths.js';
|
|
10
|
+
import { materializeRunSource0, refreshRunMemoryObservability } from './source0.js';
|
|
11
|
+
import { normalizeWorkspacePath } from './workspacePath.js';
|
|
9
12
|
import { ExperienceStore } from '../../persistence/ExperienceStore.js';
|
|
10
13
|
import { formatExperienceInjections } from '../exec/experience.js';
|
|
11
14
|
import { sanitizeRunId } from '../../persistence/sanitizeRunId.js';
|
|
15
|
+
import { PROVIDER_CONTROL_HOST_RUN_ID_ENV, PROVIDER_CONTROL_HOST_TASK_ID_ENV, PROVIDER_LAUNCH_SOURCE_CONTROL_HOST, PROVIDER_LAUNCH_SOURCE_ENV } from '../../../../scripts/lib/provider-run-contract.js';
|
|
12
16
|
const HEARTBEAT_INTERVAL_SECONDS = 5;
|
|
13
17
|
const HEARTBEAT_STALE_AFTER_SECONDS = 30;
|
|
14
18
|
const MAX_ERROR_DETAIL_CHARS = 8 * 1024;
|
|
15
19
|
const DEFAULT_MIN_EXPERIENCE_REWARD = 0.1;
|
|
20
|
+
const KNOWN_NON_GUARDRAIL_PIPELINE_IDS = new Set([
|
|
21
|
+
'provider-linear-worker',
|
|
22
|
+
'provider-linear-child-lane'
|
|
23
|
+
]);
|
|
16
24
|
function createDefaultRuntimeFallback() {
|
|
17
25
|
return {
|
|
18
26
|
occurred: false,
|
|
@@ -26,6 +34,22 @@ function createDefaultRuntimeFallback() {
|
|
|
26
34
|
function runtimeProviderForMode(mode) {
|
|
27
35
|
return mode === 'appserver' ? 'AppServerRuntimeProvider' : 'CliRuntimeProvider';
|
|
28
36
|
}
|
|
37
|
+
function resolveProviderControlHostLocatorFromEnv(env = process.env) {
|
|
38
|
+
const launchSource = normalizeOptionalString(env[PROVIDER_LAUNCH_SOURCE_ENV]);
|
|
39
|
+
const taskId = normalizeOptionalString(env[PROVIDER_CONTROL_HOST_TASK_ID_ENV]);
|
|
40
|
+
const runId = normalizeOptionalString(env[PROVIDER_CONTROL_HOST_RUN_ID_ENV]);
|
|
41
|
+
if (launchSource !== PROVIDER_LAUNCH_SOURCE_CONTROL_HOST || !taskId || !runId) {
|
|
42
|
+
return { launchSource: null, taskId: null, runId: null };
|
|
43
|
+
}
|
|
44
|
+
return { launchSource, taskId, runId };
|
|
45
|
+
}
|
|
46
|
+
function normalizeOptionalString(value) {
|
|
47
|
+
if (typeof value !== 'string') {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const trimmed = value.trim();
|
|
51
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
52
|
+
}
|
|
29
53
|
export async function bootstrapManifest(runId, options) {
|
|
30
54
|
const { env, pipeline, parentRunId = null, taskSlug, approvalPolicy = null } = options;
|
|
31
55
|
const paths = resolveRunPaths(env, runId);
|
|
@@ -35,6 +59,7 @@ export async function bootstrapManifest(runId, options) {
|
|
|
35
59
|
const now = isoTimestamp();
|
|
36
60
|
const resumeToken = randomBytes(32).toString('hex');
|
|
37
61
|
const commands = buildCommandEntries(pipeline);
|
|
62
|
+
const providerControlHostLocator = resolveProviderControlHostLocatorFromEnv();
|
|
38
63
|
const manifest = {
|
|
39
64
|
version: 1,
|
|
40
65
|
task_id: env.taskId,
|
|
@@ -56,6 +81,14 @@ export async function bootstrapManifest(runId, options) {
|
|
|
56
81
|
artifact_root: relativeToRepo(env, paths.runDir),
|
|
57
82
|
compat_path: relative(env.repoRoot, dirname(paths.compatManifestPath)),
|
|
58
83
|
log_path: relativeToRepo(env, paths.logPath),
|
|
84
|
+
issue_provider: options.issueProvider ?? null,
|
|
85
|
+
issue_id: options.issueId ?? null,
|
|
86
|
+
issue_identifier: options.issueIdentifier ?? null,
|
|
87
|
+
issue_updated_at: options.issueUpdatedAt ?? null,
|
|
88
|
+
workspace_path: normalizeWorkspacePath(env.repoRoot),
|
|
89
|
+
provider_launch_source: providerControlHostLocator.launchSource,
|
|
90
|
+
provider_control_host_task_id: providerControlHostLocator.taskId,
|
|
91
|
+
provider_control_host_run_id: providerControlHostLocator.runId,
|
|
59
92
|
summary: null,
|
|
60
93
|
metrics_recorded: false,
|
|
61
94
|
resume_token: resumeToken,
|
|
@@ -69,7 +102,8 @@ export async function bootstrapManifest(runId, options) {
|
|
|
69
102
|
instructions_hash: null,
|
|
70
103
|
instructions_sources: [],
|
|
71
104
|
prompt_packs: [],
|
|
72
|
-
guardrails_required: pipeline
|
|
105
|
+
guardrails_required: resolveGuardrailsRequiredForPipeline(pipeline),
|
|
106
|
+
guardrails_required_source: resolveGuardrailsRequiredSourceForPipeline(pipeline),
|
|
73
107
|
runtime_mode_requested: 'appserver',
|
|
74
108
|
runtime_mode: 'appserver',
|
|
75
109
|
runtime_provider: runtimeProviderForMode('appserver'),
|
|
@@ -93,32 +127,72 @@ export async function bootstrapManifest(runId, options) {
|
|
|
93
127
|
runsDir: env.runsRoot,
|
|
94
128
|
maxSummaryWords: instructions.experienceMaxWords
|
|
95
129
|
});
|
|
96
|
-
const
|
|
130
|
+
const promptPackSelections = await Promise.all(instructions.promptPacks.map(async (pack, index) => {
|
|
131
|
+
const policy = toExperienceSelectionPolicy(pack.retrievalPolicy, resolveExperienceMinReward());
|
|
97
132
|
if (!pack.experienceSlots) {
|
|
98
|
-
return
|
|
133
|
+
return {
|
|
134
|
+
policy,
|
|
135
|
+
experiences: [],
|
|
136
|
+
selection: null,
|
|
137
|
+
diagnosticsPath: null
|
|
138
|
+
};
|
|
99
139
|
}
|
|
100
|
-
const
|
|
101
|
-
const records = await experienceStore.fetchTop({
|
|
140
|
+
const selection = await experienceStore.selectTop({
|
|
102
141
|
domain: pack.domain,
|
|
103
142
|
limit: pack.experienceSlots,
|
|
104
|
-
|
|
105
|
-
|
|
143
|
+
taskId: env.taskId,
|
|
144
|
+
policy
|
|
106
145
|
});
|
|
107
|
-
|
|
146
|
+
const diagnosticsPath = await writePromptPackRetrievalDiagnostics({
|
|
147
|
+
env,
|
|
148
|
+
paths,
|
|
149
|
+
packDomain: pack.domain,
|
|
150
|
+
packId: pack.id,
|
|
151
|
+
packIndex: index,
|
|
152
|
+
diagnostics: selection.diagnostics
|
|
153
|
+
});
|
|
154
|
+
return {
|
|
155
|
+
policy,
|
|
156
|
+
experiences: formatExperienceInjections(selection.records, pack.experienceSlots, selection.diagnostics),
|
|
157
|
+
selection,
|
|
158
|
+
diagnosticsPath
|
|
159
|
+
};
|
|
108
160
|
}));
|
|
109
161
|
manifest.instructions_hash = instructions.hash || null;
|
|
110
162
|
manifest.instructions_sources = instructions.sources.map((source) => source.path);
|
|
111
163
|
manifest.prompt_packs = instructions.promptPacks.map((pack, index) => {
|
|
112
|
-
const
|
|
164
|
+
const selectionArtifact = promptPackSelections[index];
|
|
165
|
+
const experiences = selectionArtifact?.experiences ?? [];
|
|
113
166
|
return {
|
|
114
167
|
id: pack.id,
|
|
115
168
|
domain: pack.domain,
|
|
116
169
|
stamp: pack.stamp,
|
|
117
170
|
experience_slots: pack.experienceSlots,
|
|
118
171
|
sources: pack.sources.map((source) => source.path),
|
|
172
|
+
retrieval_policy: serializePromptPackRetrievalPolicy(selectionArtifact?.policy),
|
|
173
|
+
...(selectionArtifact?.selection
|
|
174
|
+
? {
|
|
175
|
+
retrieval_selection: serializePromptPackRetrievalSelection(selectionArtifact.selection.diagnostics, selectionArtifact.diagnosticsPath)
|
|
176
|
+
}
|
|
177
|
+
: {}),
|
|
119
178
|
...(experiences.length > 0 ? { experiences } : {})
|
|
120
179
|
};
|
|
121
180
|
});
|
|
181
|
+
let inheritedSource0 = null;
|
|
182
|
+
if (parentRunId) {
|
|
183
|
+
try {
|
|
184
|
+
inheritedSource0 = await loadManifest(env, parentRunId);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
inheritedSource0 = null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
manifest.memory = await materializeRunSource0({
|
|
191
|
+
env,
|
|
192
|
+
paths,
|
|
193
|
+
manifest,
|
|
194
|
+
inheritedFrom: inheritedSource0
|
|
195
|
+
});
|
|
122
196
|
await writeJsonAtomic(paths.manifestPath, manifest);
|
|
123
197
|
await writeFile(paths.resumeTokenPath, `${resumeToken}\n`, 'utf8');
|
|
124
198
|
await writeFile(paths.heartbeatPath, `${now}\n`, 'utf8');
|
|
@@ -126,6 +200,10 @@ export async function bootstrapManifest(runId, options) {
|
|
|
126
200
|
return { manifest, paths };
|
|
127
201
|
}
|
|
128
202
|
export async function saveManifest(paths, manifest) {
|
|
203
|
+
const pipelineId = normalizeOptionalString(manifest.pipeline_id);
|
|
204
|
+
if (pipelineId === 'provider-linear-worker') {
|
|
205
|
+
backfillProviderControlHostLocatorFromEnv(manifest);
|
|
206
|
+
}
|
|
129
207
|
manifest.updated_at = isoTimestamp();
|
|
130
208
|
await writeJsonAtomic(paths.manifestPath, manifest);
|
|
131
209
|
}
|
|
@@ -140,6 +218,30 @@ export async function loadManifest(env, runId) {
|
|
|
140
218
|
const paths = resolveRunPathsForManifestPath(resolvedEnv, runId, manifestPath);
|
|
141
219
|
return { manifest, paths };
|
|
142
220
|
}
|
|
221
|
+
export function backfillProviderControlHostLocatorFromEnv(manifest, env = process.env, options = {}) {
|
|
222
|
+
const locator = resolveProviderControlHostLocatorFromEnv(env);
|
|
223
|
+
if (!locator.launchSource || !locator.taskId || !locator.runId) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
const manifestLaunchSource = normalizeOptionalString(manifest.provider_launch_source);
|
|
227
|
+
const manifestTaskId = normalizeOptionalString(manifest.provider_control_host_task_id);
|
|
228
|
+
const manifestRunId = normalizeOptionalString(manifest.provider_control_host_run_id);
|
|
229
|
+
if (!options.overwriteConflicts &&
|
|
230
|
+
((manifestLaunchSource && manifestLaunchSource !== locator.launchSource) ||
|
|
231
|
+
(manifestTaskId && manifestTaskId !== locator.taskId) ||
|
|
232
|
+
(manifestRunId && manifestRunId !== locator.runId))) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
if (manifestLaunchSource === locator.launchSource &&
|
|
236
|
+
manifestTaskId === locator.taskId &&
|
|
237
|
+
manifestRunId === locator.runId) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
manifest.provider_launch_source = locator.launchSource;
|
|
241
|
+
manifest.provider_control_host_task_id = locator.taskId;
|
|
242
|
+
manifest.provider_control_host_run_id = locator.runId;
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
143
245
|
export function updateCommandStatus(manifest, commandIndex, changes) {
|
|
144
246
|
const entry = manifest.commands[commandIndex];
|
|
145
247
|
if (!entry) {
|
|
@@ -197,6 +299,63 @@ function resolveExperienceMinReward(env = process.env) {
|
|
|
197
299
|
}
|
|
198
300
|
return Math.max(0, parsed);
|
|
199
301
|
}
|
|
302
|
+
function toExperienceSelectionPolicy(policy, fallbackMinScore) {
|
|
303
|
+
return {
|
|
304
|
+
kind: 'competitive_scoring_v1',
|
|
305
|
+
minScore: policy.minScore ?? fallbackMinScore,
|
|
306
|
+
scoreWeights: {
|
|
307
|
+
gtScore: policy.scoreWeights.gtScore,
|
|
308
|
+
relativeRank: policy.scoreWeights.relativeRank
|
|
309
|
+
},
|
|
310
|
+
antiDominanceNormalization: {
|
|
311
|
+
enabled: policy.antiDominanceNormalization.enabled,
|
|
312
|
+
strength: policy.antiDominanceNormalization.strength,
|
|
313
|
+
sourceGrouping: policy.antiDominanceNormalization.sourceGrouping
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function serializePromptPackRetrievalPolicy(policy) {
|
|
318
|
+
if (!policy) {
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
kind: policy.kind,
|
|
323
|
+
min_score: policy.minScore,
|
|
324
|
+
score_weights: {
|
|
325
|
+
gt_score: policy.scoreWeights.gtScore,
|
|
326
|
+
relative_rank: policy.scoreWeights.relativeRank
|
|
327
|
+
},
|
|
328
|
+
anti_dominance_normalization: {
|
|
329
|
+
enabled: policy.antiDominanceNormalization.enabled,
|
|
330
|
+
strength: policy.antiDominanceNormalization.strength,
|
|
331
|
+
source_grouping: policy.antiDominanceNormalization.sourceGrouping
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function serializePromptPackRetrievalSelection(diagnostics, diagnosticsPath) {
|
|
336
|
+
return {
|
|
337
|
+
candidate_count: diagnostics.candidate_count,
|
|
338
|
+
selected_count: diagnostics.selected_count,
|
|
339
|
+
diagnostics_path: diagnosticsPath,
|
|
340
|
+
selected_ids: diagnostics.selected_ids,
|
|
341
|
+
suppressed_source_keys: diagnostics.suppressed_source_keys,
|
|
342
|
+
selected: diagnostics.selected.map((entry) => ({
|
|
343
|
+
id: entry.id,
|
|
344
|
+
source_key: entry.source_key,
|
|
345
|
+
source_kind: entry.source_kind,
|
|
346
|
+
raw_score: entry.raw_score,
|
|
347
|
+
competitive_score: entry.competitive_score,
|
|
348
|
+
dominance_penalty: entry.dominance_penalty
|
|
349
|
+
}))
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
async function writePromptPackRetrievalDiagnostics(params) {
|
|
353
|
+
const diagnosticsDir = join(params.paths.runDir, 'prompt-packs');
|
|
354
|
+
await mkdir(diagnosticsDir, { recursive: true });
|
|
355
|
+
const filePath = join(diagnosticsDir, `${slugify(`${params.packDomain}-${params.packId}`)}-${String(params.packIndex + 1).padStart(2, '0')}-retrieval.json`);
|
|
356
|
+
await writeJsonAtomic(filePath, params.diagnostics);
|
|
357
|
+
return relativeToRepo(params.env, filePath);
|
|
358
|
+
}
|
|
200
359
|
export function updateHeartbeat(manifest) {
|
|
201
360
|
manifest.heartbeat_at = isoTimestamp();
|
|
202
361
|
if (manifest.status === 'in_progress') {
|
|
@@ -215,7 +374,9 @@ export function resetForResume(manifest) {
|
|
|
215
374
|
manifest.cloud_fallback = null;
|
|
216
375
|
}
|
|
217
376
|
export function recordResumeEvent(manifest, event) {
|
|
218
|
-
|
|
377
|
+
const recordedAt = isoTimestamp();
|
|
378
|
+
manifest.resume_events.push({ ...event, timestamp: recordedAt });
|
|
379
|
+
refreshRunMemoryObservability(manifest, recordedAt);
|
|
219
380
|
}
|
|
220
381
|
export function ensureGuardrailStatus(manifest) {
|
|
221
382
|
if (manifest.guardrail_status) {
|
|
@@ -228,19 +389,74 @@ export function ensureGuardrailStatus(manifest) {
|
|
|
228
389
|
export function buildGuardrailSummary(manifest) {
|
|
229
390
|
return ensureGuardrailStatus(manifest).summary;
|
|
230
391
|
}
|
|
392
|
+
export function resolveGuardrailsRequiredForPipeline(pipeline) {
|
|
393
|
+
if (typeof pipeline.guardrailsRequired === 'boolean') {
|
|
394
|
+
return pipeline.guardrailsRequired;
|
|
395
|
+
}
|
|
396
|
+
return pipeline.stages.some((stage) => isGuardrailPipelineStage(stage));
|
|
397
|
+
}
|
|
398
|
+
export function resolveGuardrailsRequiredSourceForPipeline(pipeline) {
|
|
399
|
+
return typeof pipeline.guardrailsRequired === 'boolean' ? 'explicit' : 'stage_detection';
|
|
400
|
+
}
|
|
401
|
+
export function resolveGuardrailsRequiredSourceForManifest(manifest) {
|
|
402
|
+
return normalizeGuardrailsRequiredSource(manifest.guardrails_required_source);
|
|
403
|
+
}
|
|
404
|
+
export function resolveGuardrailsRequiredForManifest(manifest) {
|
|
405
|
+
const guardrailCommands = selectGuardrailCommands(manifest);
|
|
406
|
+
if (typeof manifest.guardrails_required === 'boolean') {
|
|
407
|
+
const source = resolveGuardrailsRequiredSourceForManifest(manifest);
|
|
408
|
+
if (manifest.guardrails_required &&
|
|
409
|
+
guardrailCommands.length === 0 &&
|
|
410
|
+
isKnownNonGuardrailPipelineManifest(manifest) &&
|
|
411
|
+
source === 'stage_detection') {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
return manifest.guardrails_required;
|
|
415
|
+
}
|
|
416
|
+
return guardrailCommands.length > 0;
|
|
417
|
+
}
|
|
418
|
+
export function stripNonApplicableGuardrailSummaryLines(manifest, summary) {
|
|
419
|
+
const normalized = summary?.trim();
|
|
420
|
+
if (!normalized) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
const lines = normalized.split('\n');
|
|
424
|
+
const guardrailCommands = selectGuardrailCommands(manifest);
|
|
425
|
+
if (guardrailCommands.length > 0) {
|
|
426
|
+
return normalized;
|
|
427
|
+
}
|
|
428
|
+
const source = resolveGuardrailsRequiredSourceForManifest(manifest);
|
|
429
|
+
const canStripLegacyMixedSummary = source === 'stage_detection' &&
|
|
430
|
+
isKnownNonGuardrailPipelineManifest(manifest) &&
|
|
431
|
+
lines.some((line) => !isGuardrailSummaryOrRecommendationLine(line));
|
|
432
|
+
if (resolveGuardrailsRequiredForManifest(manifest) && !canStripLegacyMixedSummary) {
|
|
433
|
+
return normalized;
|
|
434
|
+
}
|
|
435
|
+
const filtered = lines
|
|
436
|
+
.filter((line) => {
|
|
437
|
+
return !isGuardrailSummaryOrRecommendationLine(line);
|
|
438
|
+
})
|
|
439
|
+
.join('\n')
|
|
440
|
+
.trim();
|
|
441
|
+
return filtered || null;
|
|
442
|
+
}
|
|
231
443
|
export function upsertGuardrailSummary(manifest) {
|
|
232
|
-
const
|
|
444
|
+
const guardrailStatus = ensureGuardrailStatus(manifest);
|
|
233
445
|
const existing = manifest.summary ? manifest.summary.split('\n') : [];
|
|
234
|
-
const filtered = existing.filter((line) => !line.toLowerCase().startsWith('guardrails:'));
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
manifest.summary = summary;
|
|
446
|
+
const filtered = existing.filter((line) => !line.toLowerCase().startsWith('guardrails:') && !isGuardrailRecommendationLine(line));
|
|
447
|
+
if (!shouldEmitGuardrailSummary(manifest, guardrailStatus)) {
|
|
448
|
+
manifest.summary = filtered.join('\n').trim() || null;
|
|
449
|
+
return;
|
|
239
450
|
}
|
|
451
|
+
if (guardrailStatus.recommendation) {
|
|
452
|
+
filtered.push(guardrailStatus.recommendation);
|
|
453
|
+
}
|
|
454
|
+
filtered.push(guardrailStatus.summary);
|
|
455
|
+
manifest.summary = filtered.join('\n').trim() || guardrailStatus.summary;
|
|
240
456
|
}
|
|
241
457
|
function computeGuardrailStatus(manifest) {
|
|
242
458
|
const guardrailCommands = selectGuardrailCommands(manifest);
|
|
243
|
-
const guardrailsRequired = manifest
|
|
459
|
+
const guardrailsRequired = resolveGuardrailsRequiredForManifest(manifest);
|
|
244
460
|
const counts = {
|
|
245
461
|
total: guardrailCommands.length,
|
|
246
462
|
succeeded: 0,
|
|
@@ -275,7 +491,7 @@ function computeGuardrailStatus(manifest) {
|
|
|
275
491
|
recommendation =
|
|
276
492
|
'Guardrail command failed; re-run "codex-orchestrator start diagnostics --approval-policy never --format json --no-interactive" to gather failure artifacts.';
|
|
277
493
|
}
|
|
278
|
-
const summary = formatGuardrailSummary(counts);
|
|
494
|
+
const summary = formatGuardrailSummary(counts, guardrailsRequired);
|
|
279
495
|
return {
|
|
280
496
|
present,
|
|
281
497
|
recommendation,
|
|
@@ -284,14 +500,12 @@ function computeGuardrailStatus(manifest) {
|
|
|
284
500
|
counts
|
|
285
501
|
};
|
|
286
502
|
}
|
|
503
|
+
export function countGuardrailCommands(manifest) {
|
|
504
|
+
return selectGuardrailCommands(manifest).length;
|
|
505
|
+
}
|
|
287
506
|
function selectGuardrailCommands(manifest) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const title = entry.title?.toLowerCase() ?? '';
|
|
291
|
-
const command = entry.command?.toLowerCase() ?? '';
|
|
292
|
-
const haystack = `${id} ${title} ${command}`;
|
|
293
|
-
return haystack.includes('spec-guard') || haystack.includes('specguardrunner');
|
|
294
|
-
});
|
|
507
|
+
const commands = Array.isArray(manifest.commands) ? manifest.commands : [];
|
|
508
|
+
return commands.filter((entry) => isGuardrailCommandEntry(entry));
|
|
295
509
|
}
|
|
296
510
|
function classifyGuardrailCommand(entry) {
|
|
297
511
|
if (entry.status === 'failed') {
|
|
@@ -314,9 +528,17 @@ function isExplicitGuardrailSkip(summary) {
|
|
|
314
528
|
normalized.includes('spec-guard skipped') ||
|
|
315
529
|
normalized.includes('spec guard skipped'));
|
|
316
530
|
}
|
|
317
|
-
function
|
|
531
|
+
function shouldEmitGuardrailSummary(manifest, snapshot) {
|
|
532
|
+
if (snapshot.counts.total > 0) {
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
return resolveGuardrailsRequiredForManifest(manifest);
|
|
536
|
+
}
|
|
537
|
+
function formatGuardrailSummary(counts, guardrailsRequired) {
|
|
318
538
|
if (counts.total === 0) {
|
|
319
|
-
return
|
|
539
|
+
return guardrailsRequired
|
|
540
|
+
? 'Guardrails: spec-guard command not found.'
|
|
541
|
+
: 'Guardrails: spec-guard not configured for this pipeline.';
|
|
320
542
|
}
|
|
321
543
|
if (counts.failed > 0) {
|
|
322
544
|
return `Guardrails: spec-guard failed (${counts.failed}/${counts.total} failed).`;
|
|
@@ -339,6 +561,40 @@ function formatGuardrailSummary(counts) {
|
|
|
339
561
|
}
|
|
340
562
|
return `Guardrails: spec-guard partial (${parts.join(', ')} of ${counts.total}).`;
|
|
341
563
|
}
|
|
564
|
+
function isGuardrailRecommendationLine(line) {
|
|
565
|
+
const trimmed = line.trim();
|
|
566
|
+
return (trimmed.startsWith('Guardrail command missing;') ||
|
|
567
|
+
trimmed.startsWith('Guardrail command failed;'));
|
|
568
|
+
}
|
|
569
|
+
function isGuardrailSummaryOrRecommendationLine(line) {
|
|
570
|
+
const trimmed = line.trim();
|
|
571
|
+
return trimmed.toLowerCase().startsWith('guardrails:') || isGuardrailRecommendationLine(trimmed);
|
|
572
|
+
}
|
|
573
|
+
function normalizeGuardrailsRequiredSource(value) {
|
|
574
|
+
return value === 'explicit' || value === 'stage_detection' ? value : null;
|
|
575
|
+
}
|
|
576
|
+
function isKnownNonGuardrailPipelineManifest(manifest) {
|
|
577
|
+
return (typeof manifest.pipeline_id === 'string' &&
|
|
578
|
+
KNOWN_NON_GUARDRAIL_PIPELINE_IDS.has(manifest.pipeline_id.trim().toLowerCase()));
|
|
579
|
+
}
|
|
580
|
+
function isGuardrailPipelineStage(stage) {
|
|
581
|
+
const command = stage.kind === 'command' ? stage.command : stage.pipeline;
|
|
582
|
+
return containsGuardrailNeedle(stage.id, stage.title, command);
|
|
583
|
+
}
|
|
584
|
+
function isGuardrailCommandEntry(entry) {
|
|
585
|
+
if (!entry || typeof entry !== 'object') {
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
const record = entry;
|
|
589
|
+
return containsGuardrailNeedle(record.id, record.title, record.command);
|
|
590
|
+
}
|
|
591
|
+
function containsGuardrailNeedle(...values) {
|
|
592
|
+
const haystack = values
|
|
593
|
+
.filter((value) => typeof value === 'string')
|
|
594
|
+
.join(' ')
|
|
595
|
+
.toLowerCase();
|
|
596
|
+
return haystack.includes('spec-guard') || haystack.includes('specguardrunner');
|
|
597
|
+
}
|
|
342
598
|
export function appendSummary(manifest, message) {
|
|
343
599
|
if (!message) {
|
|
344
600
|
return;
|
|
@@ -352,6 +608,12 @@ export function appendSummary(manifest, message) {
|
|
|
352
608
|
}
|
|
353
609
|
manifest.summary = `${manifest.summary}\n${message}`;
|
|
354
610
|
}
|
|
611
|
+
export function removeStageFailureSummary(manifest, stageTitle) {
|
|
612
|
+
removeSummaryLines(manifest, (line) => line.trim().startsWith(`Stage '${stageTitle}' failed with exit code `) && line.trim().endsWith('.'));
|
|
613
|
+
}
|
|
614
|
+
export function removeSubpipelineFailureSummary(manifest, pipelineId) {
|
|
615
|
+
removeSummaryLines(manifest, (line) => line.trim() === `Sub-pipeline '${pipelineId}' failed.`);
|
|
616
|
+
}
|
|
355
617
|
export function finalizeStatus(manifest, status, detail) {
|
|
356
618
|
manifest.status = status;
|
|
357
619
|
manifest.status_detail = detail ?? null;
|
|
@@ -395,18 +657,20 @@ async function createCompatibilityPointer(env, paths) {
|
|
|
395
657
|
});
|
|
396
658
|
}
|
|
397
659
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
await access(expectedPaths.manifestPath);
|
|
402
|
-
return expectedPaths.manifestPath;
|
|
403
|
-
}
|
|
404
|
-
catch (error) {
|
|
405
|
-
if (error.code !== 'ENOENT') {
|
|
406
|
-
throw error;
|
|
407
|
-
}
|
|
660
|
+
function removeSummaryLines(manifest, predicate) {
|
|
661
|
+
if (!manifest.summary) {
|
|
662
|
+
return;
|
|
408
663
|
}
|
|
664
|
+
const retainedLines = manifest.summary.split('\n').filter((line) => !predicate(line));
|
|
665
|
+
manifest.summary = retainedLines.join('\n').trim() || null;
|
|
666
|
+
}
|
|
667
|
+
async function resolveManifestPathForRunId(env, runId) {
|
|
409
668
|
const safeRunId = sanitizeRunId(runId);
|
|
669
|
+
const expectedPaths = resolveRunPaths(env, safeRunId);
|
|
670
|
+
const expectedManifestPath = await validateRunManifestCandidate(expectedPaths.manifestPath, env.runsRoot, safeRunId);
|
|
671
|
+
if (expectedManifestPath) {
|
|
672
|
+
return expectedManifestPath;
|
|
673
|
+
}
|
|
410
674
|
const localCompatResolved = await resolveLocalCompatManifestPath(env, safeRunId);
|
|
411
675
|
if (localCompatResolved) {
|
|
412
676
|
return localCompatResolved;
|
|
@@ -439,30 +703,13 @@ async function resolveLocalCompatManifestPath(env, safeRunId) {
|
|
|
439
703
|
throw error;
|
|
440
704
|
}
|
|
441
705
|
if (stats.isSymbolicLink()) {
|
|
442
|
-
|
|
443
|
-
return await realpath(localCompatManifestPath);
|
|
444
|
-
}
|
|
445
|
-
catch (error) {
|
|
446
|
-
if (error.code === 'ENOENT') {
|
|
447
|
-
return null;
|
|
448
|
-
}
|
|
449
|
-
throw error;
|
|
450
|
-
}
|
|
706
|
+
return await validateRunManifestCandidate(localCompatManifestPath, env.runsRoot, safeRunId);
|
|
451
707
|
}
|
|
452
708
|
const redirectPath = await resolveRedirectManifestPath(env, localCompatManifestPath);
|
|
453
709
|
if (!redirectPath) {
|
|
454
710
|
return null;
|
|
455
711
|
}
|
|
456
|
-
|
|
457
|
-
await access(redirectPath);
|
|
458
|
-
return redirectPath;
|
|
459
|
-
}
|
|
460
|
-
catch (error) {
|
|
461
|
-
if (error.code === 'ENOENT') {
|
|
462
|
-
return null;
|
|
463
|
-
}
|
|
464
|
-
throw error;
|
|
465
|
-
}
|
|
712
|
+
return await validateRunManifestCandidate(redirectPath, env.runsRoot, safeRunId);
|
|
466
713
|
}
|
|
467
714
|
async function resolveRedirectManifestPath(env, localCompatManifestPath) {
|
|
468
715
|
let raw;
|
|
@@ -525,28 +772,118 @@ async function findManifestPathAcrossTasks(runsRoot, safeRunId) {
|
|
|
525
772
|
}
|
|
526
773
|
const taskRoot = join(runsRoot, entry.name);
|
|
527
774
|
const cliManifestPath = join(taskRoot, 'cli', safeRunId, 'manifest.json');
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
return
|
|
531
|
-
}
|
|
532
|
-
catch (error) {
|
|
533
|
-
if (error.code !== 'ENOENT') {
|
|
534
|
-
throw error;
|
|
535
|
-
}
|
|
775
|
+
const validatedCliManifest = await validateRunManifestCandidate(cliManifestPath, runsRoot, safeRunId);
|
|
776
|
+
if (validatedCliManifest) {
|
|
777
|
+
return validatedCliManifest;
|
|
536
778
|
}
|
|
537
779
|
const legacyManifestPath = join(taskRoot, safeRunId, 'manifest.json');
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
return
|
|
541
|
-
}
|
|
542
|
-
catch (error) {
|
|
543
|
-
if (error.code !== 'ENOENT') {
|
|
544
|
-
throw error;
|
|
545
|
-
}
|
|
780
|
+
const validatedLegacyManifest = await validateRunManifestCandidate(legacyManifestPath, runsRoot, safeRunId);
|
|
781
|
+
if (validatedLegacyManifest) {
|
|
782
|
+
return validatedLegacyManifest;
|
|
546
783
|
}
|
|
547
784
|
}
|
|
548
785
|
return null;
|
|
549
786
|
}
|
|
787
|
+
async function validateRunManifestCandidate(candidatePath, runsRoot, safeRunId) {
|
|
788
|
+
try {
|
|
789
|
+
await access(candidatePath);
|
|
790
|
+
}
|
|
791
|
+
catch (error) {
|
|
792
|
+
if (error.code === 'ENOENT') {
|
|
793
|
+
return null;
|
|
794
|
+
}
|
|
795
|
+
throw error;
|
|
796
|
+
}
|
|
797
|
+
const canonicalPath = await canonicalizePath(candidatePath);
|
|
798
|
+
const canonicalRunsRoot = await canonicalizePath(runsRoot);
|
|
799
|
+
if (!(await isPathWithinRoots(canonicalPath, [canonicalRunsRoot]))) {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
assertRunManifestPath(canonicalPath, canonicalRunsRoot, 'manifest_path');
|
|
804
|
+
}
|
|
805
|
+
catch {
|
|
806
|
+
return null;
|
|
807
|
+
}
|
|
808
|
+
const runDir = dirname(canonicalPath);
|
|
809
|
+
if (basename(runDir) !== safeRunId) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
return canonicalPath;
|
|
813
|
+
}
|
|
814
|
+
function assertRunManifestPath(pathname, runsRoot, label) {
|
|
815
|
+
try {
|
|
816
|
+
assertCliRunManifestPath(pathname, runsRoot, label);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
catch {
|
|
820
|
+
assertLegacyRunManifestPath(pathname, runsRoot, label);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
function assertCliRunManifestPath(pathname, runsRoot, label) {
|
|
824
|
+
if (basename(pathname) !== 'manifest.json') {
|
|
825
|
+
throw new Error(`${label} invalid`);
|
|
826
|
+
}
|
|
827
|
+
const runDir = dirname(pathname);
|
|
828
|
+
const cliDir = dirname(runDir);
|
|
829
|
+
if (basename(cliDir) !== 'cli') {
|
|
830
|
+
throw new Error(`${label} invalid`);
|
|
831
|
+
}
|
|
832
|
+
const taskDir = dirname(cliDir);
|
|
833
|
+
const runsDir = dirname(taskDir);
|
|
834
|
+
const normalizedRunsDir = normalizePath(resolve(runsDir));
|
|
835
|
+
const normalizedRunsRoot = normalizePath(resolve(runsRoot));
|
|
836
|
+
if (!basename(runDir) || !basename(taskDir) || normalizedRunsDir !== normalizedRunsRoot) {
|
|
837
|
+
throw new Error(`${label} invalid`);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
function assertLegacyRunManifestPath(pathname, runsRoot, label) {
|
|
841
|
+
if (basename(pathname) !== 'manifest.json') {
|
|
842
|
+
throw new Error(`${label} invalid`);
|
|
843
|
+
}
|
|
844
|
+
const runDir = dirname(pathname);
|
|
845
|
+
const taskDir = dirname(runDir);
|
|
846
|
+
const runsDir = dirname(taskDir);
|
|
847
|
+
const normalizedRunsDir = normalizePath(resolve(runsDir));
|
|
848
|
+
const normalizedRunsRoot = normalizePath(resolve(runsRoot));
|
|
849
|
+
if (!basename(runDir) ||
|
|
850
|
+
!basename(taskDir) ||
|
|
851
|
+
basename(taskDir) === 'local-mcp' ||
|
|
852
|
+
normalizedRunsDir !== normalizedRunsRoot) {
|
|
853
|
+
throw new Error(`${label} invalid`);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
async function isPathWithinRoots(pathname, roots) {
|
|
857
|
+
const normalizedPath = normalizePath(await canonicalizePath(pathname));
|
|
858
|
+
for (const root of roots) {
|
|
859
|
+
const normalizedRoot = normalizePath(await canonicalizePath(root));
|
|
860
|
+
if (normalizedRoot === normalizedPath) {
|
|
861
|
+
return true;
|
|
862
|
+
}
|
|
863
|
+
const relativePath = relative(normalizedRoot, normalizedPath);
|
|
864
|
+
if (!relativePath) {
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
867
|
+
if (isAbsolute(relativePath)) {
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
870
|
+
if (!relativePath.startsWith(`..${sep}`) && relativePath !== '..') {
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return false;
|
|
875
|
+
}
|
|
876
|
+
async function canonicalizePath(pathname) {
|
|
877
|
+
try {
|
|
878
|
+
return await realpath(pathname);
|
|
879
|
+
}
|
|
880
|
+
catch {
|
|
881
|
+
return resolve(pathname);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function normalizePath(pathname) {
|
|
885
|
+
return process.platform === 'win32' ? pathname.toLowerCase() : pathname;
|
|
886
|
+
}
|
|
550
887
|
function resolveRunPathsForManifestPath(env, runId, manifestPath) {
|
|
551
888
|
const resolved = resolveRunPaths(env, runId);
|
|
552
889
|
if (resolved.manifestPath === manifestPath) {
|