@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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { performance } from 'node:perf_hooks';
|
|
2
|
+
const RETRY_QUEUE_FIRE_FAILURE_DELAY_MS = 1_000;
|
|
3
|
+
export function createProviderIssueRetryQueue() {
|
|
4
|
+
const scheduled = new Map();
|
|
5
|
+
const schedule = (key, entry, minimumDelayMs = 0) => {
|
|
6
|
+
const delayMs = Math.max(minimumDelayMs, entry.dueAtMonotonicMs - performance.now(), 0);
|
|
7
|
+
const generation = entry.generation;
|
|
8
|
+
const timer = setTimeout(() => {
|
|
9
|
+
const current = scheduled.get(key);
|
|
10
|
+
if (!current || current.generation !== generation) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
current.timer = null;
|
|
14
|
+
current.firing = true;
|
|
15
|
+
void Promise.resolve()
|
|
16
|
+
.then(() => current.fire())
|
|
17
|
+
.then(() => {
|
|
18
|
+
const latest = scheduled.get(key);
|
|
19
|
+
if (latest && latest.generation === generation && latest.firing) {
|
|
20
|
+
scheduled.delete(key);
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
.catch(() => {
|
|
24
|
+
const latest = scheduled.get(key);
|
|
25
|
+
if (!latest || latest.generation !== generation || !latest.firing) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
latest.firing = false;
|
|
29
|
+
schedule(key, latest, RETRY_QUEUE_FIRE_FAILURE_DELAY_MS);
|
|
30
|
+
});
|
|
31
|
+
}, delayMs);
|
|
32
|
+
timer.unref?.();
|
|
33
|
+
entry.timer = timer;
|
|
34
|
+
};
|
|
35
|
+
const cancel = (key) => {
|
|
36
|
+
const existing = scheduled.get(key);
|
|
37
|
+
if (!existing) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (existing.timer) {
|
|
41
|
+
clearTimeout(existing.timer);
|
|
42
|
+
}
|
|
43
|
+
scheduled.delete(key);
|
|
44
|
+
};
|
|
45
|
+
const replace = (entry) => {
|
|
46
|
+
const dueTime = Date.parse(entry.dueAt);
|
|
47
|
+
if (!Number.isFinite(dueTime)) {
|
|
48
|
+
cancel(entry.key);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const existing = scheduled.get(entry.key);
|
|
52
|
+
if (existing && existing.dueAt === entry.dueAt) {
|
|
53
|
+
existing.fire = entry.fire;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (existing?.timer) {
|
|
57
|
+
clearTimeout(existing.timer);
|
|
58
|
+
}
|
|
59
|
+
const generation = (existing?.generation ?? 0) + 1;
|
|
60
|
+
const delayMs = Math.max(0, dueTime - Date.now());
|
|
61
|
+
const nextEntry = {
|
|
62
|
+
dueAt: entry.dueAt,
|
|
63
|
+
dueAtMonotonicMs: performance.now() + delayMs,
|
|
64
|
+
generation,
|
|
65
|
+
timer: null,
|
|
66
|
+
firing: false,
|
|
67
|
+
fire: entry.fire
|
|
68
|
+
};
|
|
69
|
+
scheduled.set(entry.key, nextEntry);
|
|
70
|
+
schedule(entry.key, nextEntry);
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
sync(entries) {
|
|
74
|
+
const desired = new Set(entries.map((entry) => entry.key));
|
|
75
|
+
for (const key of scheduled.keys()) {
|
|
76
|
+
if (!desired.has(key)) {
|
|
77
|
+
cancel(key);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
entries.forEach((entry) => replace(entry));
|
|
81
|
+
},
|
|
82
|
+
cancel
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
import { lookup as dnsLookup } from 'node:dns/promises';
|
|
2
|
+
import { BlockList, isIP } from 'node:net';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { findPermitEntry, loadPermitFile, resolveRuntimeProofCapabilities } from '../../../../scripts/design/pipeline/permit.js';
|
|
5
|
+
const ALL_RUNTIME_PROOF_KINDS = ['screenshot', 'external-link', 'video'];
|
|
6
|
+
const ALL_RUNTIME_PROOF_REACHABILITY_MODES = ['deterministic', 'dns-public'];
|
|
7
|
+
const BLOCKED_PROOF_HOSTS = createBlockedProofHostBlockList();
|
|
8
|
+
const BLOCKED_PROOF_TLDS = ['local', 'test', 'invalid', 'localhost', 'lan', 'example', 'home.arpa'];
|
|
9
|
+
const DEFAULT_REACHABILITY_CAVEAT = 'Reviewer reachability is not guaranteed across other networks, resolvers, or future DNS changes.';
|
|
10
|
+
const DEFAULT_DEPENDENCIES = {
|
|
11
|
+
dnsLookup: async (hostname) => (await dnsLookup(hostname, { all: true, verbatim: true })).map((result) => ({
|
|
12
|
+
address: result.address,
|
|
13
|
+
family: result.family
|
|
14
|
+
}))
|
|
15
|
+
};
|
|
16
|
+
export async function resolveProviderLinearRuntimeProof(input, overrides = {}) {
|
|
17
|
+
const dependencies = { ...DEFAULT_DEPENDENCIES, ...overrides };
|
|
18
|
+
const normalizedOrigin = normalizeOrigin(input.origin);
|
|
19
|
+
if (!normalizedOrigin) {
|
|
20
|
+
return failure('runtime_proof_origin_invalid', 'Runtime proof origin must be a valid URL.', 422);
|
|
21
|
+
}
|
|
22
|
+
const permitResult = await loadPermitFile(resolve(input.repoRoot));
|
|
23
|
+
if (permitResult.status === 'error') {
|
|
24
|
+
return failure('runtime_proof_permit_unreadable', permitResult.error ?? 'Unable to read compliance/permit.json.', 503, {
|
|
25
|
+
permit_path: permitResult.path,
|
|
26
|
+
origin: normalizedOrigin
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const permitEntry = permitResult.status === 'found' ? findPermitEntry(permitResult.permit, normalizedOrigin) : null;
|
|
30
|
+
const policy = buildRuntimeProofPolicy(normalizedOrigin, permitResult.path, permitResult.status, permitEntry);
|
|
31
|
+
const normalizedReachabilityMode = normalizeRuntimeProofReachabilityMode(input.reachabilityMode ?? null);
|
|
32
|
+
if (!normalizedReachabilityMode) {
|
|
33
|
+
return failure('runtime_proof_reachability_mode_invalid', 'Runtime proof reachability mode must be one of: deterministic, dns-public.', 422, {
|
|
34
|
+
requested_reachability_mode: input.reachabilityMode,
|
|
35
|
+
allowed_reachability_modes: ALL_RUNTIME_PROOF_REACHABILITY_MODES,
|
|
36
|
+
policy
|
|
37
|
+
}, policy);
|
|
38
|
+
}
|
|
39
|
+
const proofUrlInput = normalizeOptionalText(input.proofUrl ?? null);
|
|
40
|
+
const normalizedKind = normalizeRuntimeProofKind(input.kind ?? null);
|
|
41
|
+
const normalizedProofUrl = normalizeHttpUrl(input.proofUrl ?? null);
|
|
42
|
+
const normalizedTitle = normalizeOptionalText(input.title ?? null);
|
|
43
|
+
const normalizedSummary = normalizeOptionalText(input.summary ?? null);
|
|
44
|
+
const proofFieldsProvided = Boolean(proofUrlInput || normalizedTitle || normalizedSummary);
|
|
45
|
+
if (!normalizedKind) {
|
|
46
|
+
if (!input.kind && !proofFieldsProvided) {
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
policy,
|
|
50
|
+
proof: null,
|
|
51
|
+
handoff: null,
|
|
52
|
+
reachability: buildReachabilityWithoutProof(normalizedReachabilityMode)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (input.kind) {
|
|
56
|
+
return failure('runtime_proof_kind_invalid', 'Runtime proof kind must be one of: screenshot, external-link, video.', 422, {
|
|
57
|
+
requested_kind: input.kind,
|
|
58
|
+
allowed_kinds: ALL_RUNTIME_PROOF_KINDS,
|
|
59
|
+
policy
|
|
60
|
+
}, policy);
|
|
61
|
+
}
|
|
62
|
+
return failure('runtime_proof_kind_missing', 'Runtime proof kind is required when proof handoff fields are provided.', 422, {
|
|
63
|
+
allowed_kinds: ALL_RUNTIME_PROOF_KINDS,
|
|
64
|
+
policy
|
|
65
|
+
}, policy);
|
|
66
|
+
}
|
|
67
|
+
if (policy.permit_status === 'missing') {
|
|
68
|
+
return failure('runtime_proof_permit_missing', `No compliance permit is configured for ${normalizedOrigin}; runtime proof handoff is blocked.`, 422, {
|
|
69
|
+
origin: normalizedOrigin,
|
|
70
|
+
permit_path: policy.permit_path,
|
|
71
|
+
policy
|
|
72
|
+
}, policy);
|
|
73
|
+
}
|
|
74
|
+
if (policy.permit_status === 'origin_missing') {
|
|
75
|
+
return failure('runtime_proof_origin_unapproved', `Origin ${normalizedOrigin} is not listed in compliance/permit.json; runtime proof handoff is blocked.`, 422, {
|
|
76
|
+
origin: normalizedOrigin,
|
|
77
|
+
permit_path: policy.permit_path,
|
|
78
|
+
policy
|
|
79
|
+
}, policy);
|
|
80
|
+
}
|
|
81
|
+
if (!isKindAllowed(policy, normalizedKind)) {
|
|
82
|
+
return failure('runtime_proof_kind_not_permitted', `Runtime proof kind "${normalizedKind}" is not permitted for ${normalizedOrigin}. ${policy.summary}`, 422, {
|
|
83
|
+
requested_kind: normalizedKind,
|
|
84
|
+
allowed_kinds: policy.allowed_kinds,
|
|
85
|
+
blocked_kinds: policy.blocked_kinds,
|
|
86
|
+
origin: normalizedOrigin,
|
|
87
|
+
policy
|
|
88
|
+
}, policy);
|
|
89
|
+
}
|
|
90
|
+
if (!normalizedProofUrl) {
|
|
91
|
+
return failure('runtime_proof_url_missing', 'A reviewer-usable --proof-url is required to generate runtime proof handoff content. Local-only file paths are not supported.', 422, {
|
|
92
|
+
requested_kind: normalizedKind,
|
|
93
|
+
policy
|
|
94
|
+
}, policy);
|
|
95
|
+
}
|
|
96
|
+
const reachabilityResolution = await resolveRuntimeProofReachability(normalizedProofUrl, normalizedReachabilityMode, dependencies);
|
|
97
|
+
if (!reachabilityResolution.ok) {
|
|
98
|
+
return {
|
|
99
|
+
ok: false,
|
|
100
|
+
policy,
|
|
101
|
+
error: {
|
|
102
|
+
...reachabilityResolution.error,
|
|
103
|
+
details: {
|
|
104
|
+
...(reachabilityResolution.error.details ?? {}),
|
|
105
|
+
policy
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const proofTitle = normalizedTitle ?? buildDefaultProofTitle(normalizedKind);
|
|
111
|
+
const proof = {
|
|
112
|
+
kind: normalizedKind,
|
|
113
|
+
reviewer_url: normalizedProofUrl,
|
|
114
|
+
title: proofTitle,
|
|
115
|
+
summary: normalizedSummary
|
|
116
|
+
};
|
|
117
|
+
return {
|
|
118
|
+
ok: true,
|
|
119
|
+
policy,
|
|
120
|
+
proof,
|
|
121
|
+
handoff: {
|
|
122
|
+
workpad_markdown: buildWorkpadMarkdown(policy, proof, reachabilityResolution.reachability),
|
|
123
|
+
pr_markdown: buildPrMarkdown(policy, proof, reachabilityResolution.reachability)
|
|
124
|
+
},
|
|
125
|
+
reachability: reachabilityResolution.reachability
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function buildRuntimeProofPolicy(origin, permitPath, permitStatus, permitEntry) {
|
|
129
|
+
const resolvedPermitStatus = permitStatus === 'found' ? (permitEntry ? 'found' : 'origin_missing') : 'missing';
|
|
130
|
+
const capabilities = resolveRuntimeProofCapabilities(permitEntry);
|
|
131
|
+
const allowedKinds = ALL_RUNTIME_PROOF_KINDS.filter((kind) => capabilityForKind(capabilities, kind));
|
|
132
|
+
const blockedKinds = ALL_RUNTIME_PROOF_KINDS.filter((kind) => !allowedKinds.includes(kind));
|
|
133
|
+
return {
|
|
134
|
+
origin,
|
|
135
|
+
permit_path: permitPath,
|
|
136
|
+
permit_status: resolvedPermitStatus,
|
|
137
|
+
approval_id: normalizeOptionalText(permitEntry?.approval_id),
|
|
138
|
+
approver: normalizeOptionalText(permitEntry?.approver),
|
|
139
|
+
capabilities,
|
|
140
|
+
allowed_kinds: allowedKinds,
|
|
141
|
+
blocked_kinds: blockedKinds,
|
|
142
|
+
summary: buildPolicySummary(origin, resolvedPermitStatus, allowedKinds, blockedKinds)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function buildPolicySummary(origin, permitStatus, allowedKinds, blockedKinds) {
|
|
146
|
+
if (permitStatus === 'missing') {
|
|
147
|
+
return `No compliance permit file is configured for ${origin}; runtime proof handoff is blocked.`;
|
|
148
|
+
}
|
|
149
|
+
if (permitStatus === 'origin_missing') {
|
|
150
|
+
return `The compliance permit does not list ${origin}; runtime proof handoff is blocked.`;
|
|
151
|
+
}
|
|
152
|
+
if (allowedKinds.length === 0) {
|
|
153
|
+
return `The permit for ${origin} does not allow screenshot, external-link, or video runtime proof handoff.`;
|
|
154
|
+
}
|
|
155
|
+
if (blockedKinds.length === 0) {
|
|
156
|
+
return `Screenshot, external-link, and video runtime proof handoff are all permitted for ${origin}.`;
|
|
157
|
+
}
|
|
158
|
+
return `${formatKinds(allowedKinds)} proof ${allowedKinds.length === 1 ? 'is' : 'are'} permitted for ${origin}; ${formatKinds(blockedKinds)} ${blockedKinds.length === 1 ? 'is' : 'are'} blocked.`;
|
|
159
|
+
}
|
|
160
|
+
function buildWorkpadMarkdown(policy, proof, reachability) {
|
|
161
|
+
const activeProof = proof;
|
|
162
|
+
const inlineTitle = normalizeMarkdownInline(activeProof.title);
|
|
163
|
+
const inlineSummary = activeProof.summary ? normalizeMarkdownInline(activeProof.summary) : null;
|
|
164
|
+
return [
|
|
165
|
+
`- Runtime proof policy: ${policy.summary}`,
|
|
166
|
+
`- Runtime proof (${activeProof.kind}): [${escapeMarkdownLabel(inlineTitle)}](<${activeProof.reviewer_url}>)`,
|
|
167
|
+
inlineSummary ? `- Runtime proof summary: ${inlineSummary}` : null,
|
|
168
|
+
`- Runtime proof reachability: ${reachability.summary}`,
|
|
169
|
+
`- Runtime proof caveat: ${reachability.caveat}`
|
|
170
|
+
]
|
|
171
|
+
.filter((line) => Boolean(line))
|
|
172
|
+
.join('\n');
|
|
173
|
+
}
|
|
174
|
+
function buildPrMarkdown(policy, proof, reachability) {
|
|
175
|
+
const activeProof = proof;
|
|
176
|
+
const inlineTitle = normalizeMarkdownInline(activeProof.title);
|
|
177
|
+
const inlineSummary = activeProof.summary ? normalizeMarkdownInline(activeProof.summary) : null;
|
|
178
|
+
return [
|
|
179
|
+
'### Runtime Proof',
|
|
180
|
+
`- Policy: ${policy.summary}`,
|
|
181
|
+
`- Proof (${activeProof.kind}): [${escapeMarkdownLabel(inlineTitle)}](<${activeProof.reviewer_url}>)`,
|
|
182
|
+
inlineSummary ? `- Summary: ${inlineSummary}` : null,
|
|
183
|
+
`- Reachability: ${reachability.summary}`,
|
|
184
|
+
`- Caveat: ${reachability.caveat}`
|
|
185
|
+
]
|
|
186
|
+
.filter((line) => Boolean(line))
|
|
187
|
+
.join('\n');
|
|
188
|
+
}
|
|
189
|
+
async function resolveRuntimeProofReachability(proofUrl, mode, dependencies) {
|
|
190
|
+
const parsed = new URL(proofUrl);
|
|
191
|
+
const rawHostname = parsed.hostname.trim().toLowerCase().replaceAll(/^\[|\]$/g, '');
|
|
192
|
+
const hostname = normalizeHostname(rawHostname);
|
|
193
|
+
if (!rawHostname || !hostname) {
|
|
194
|
+
return {
|
|
195
|
+
ok: false,
|
|
196
|
+
error: {
|
|
197
|
+
code: 'runtime_proof_url_missing',
|
|
198
|
+
message: 'A reviewer-usable --proof-url is required to generate runtime proof handoff content. Local-only file paths are not supported.',
|
|
199
|
+
status: 422
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
if (mode === 'deterministic') {
|
|
204
|
+
return {
|
|
205
|
+
ok: true,
|
|
206
|
+
reachability: {
|
|
207
|
+
mode,
|
|
208
|
+
dns_ran: false,
|
|
209
|
+
hostname,
|
|
210
|
+
resolved_addresses: [],
|
|
211
|
+
summary: 'Deterministic URL validation accepted the reviewer proof URL without live DNS lookup.',
|
|
212
|
+
caveat: 'No live DNS lookup was performed. Reviewer reachability remains out of scope for the default deterministic path.'
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (isIP(hostname) > 0) {
|
|
217
|
+
return {
|
|
218
|
+
ok: true,
|
|
219
|
+
reachability: {
|
|
220
|
+
mode,
|
|
221
|
+
dns_ran: false,
|
|
222
|
+
hostname,
|
|
223
|
+
resolved_addresses: [hostname],
|
|
224
|
+
summary: `dns-public mode accepted the public IP literal ${hostname} without DNS lookup.`,
|
|
225
|
+
caveat: DEFAULT_REACHABILITY_CAVEAT
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
let answers;
|
|
230
|
+
try {
|
|
231
|
+
answers = await dependencies.dnsLookup(rawHostname);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
const dnsError = error;
|
|
235
|
+
return {
|
|
236
|
+
ok: false,
|
|
237
|
+
error: {
|
|
238
|
+
code: 'runtime_proof_dns_lookup_failed',
|
|
239
|
+
message: `dns-public reachability could not resolve ${hostname} with the worker-local DNS resolver; runtime proof handoff is blocked.`,
|
|
240
|
+
status: 503,
|
|
241
|
+
details: {
|
|
242
|
+
reachability_mode: mode,
|
|
243
|
+
reviewer_hostname: hostname,
|
|
244
|
+
dns_error_code: dnsError.code ?? null,
|
|
245
|
+
dns_error_message: dnsError.message ?? String(error),
|
|
246
|
+
proof_url: proofUrl
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const resolvedAddresses = uniqueAddresses(answers.map((answer) => answer.address));
|
|
252
|
+
if (resolvedAddresses.length === 0) {
|
|
253
|
+
return {
|
|
254
|
+
ok: false,
|
|
255
|
+
error: {
|
|
256
|
+
code: 'runtime_proof_dns_no_answers',
|
|
257
|
+
message: `dns-public reachability returned no answers for ${hostname}; runtime proof handoff is blocked.`,
|
|
258
|
+
status: 503,
|
|
259
|
+
details: {
|
|
260
|
+
reachability_mode: mode,
|
|
261
|
+
reviewer_hostname: hostname,
|
|
262
|
+
proof_url: proofUrl
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
const blockedAddresses = resolvedAddresses.filter((address) => isBlockedProofHostname(address));
|
|
268
|
+
if (blockedAddresses.length > 0) {
|
|
269
|
+
return {
|
|
270
|
+
ok: false,
|
|
271
|
+
error: {
|
|
272
|
+
code: 'runtime_proof_dns_non_public_resolution',
|
|
273
|
+
message: `dns-public reachability resolved ${hostname} to at least one non-public address; runtime proof handoff is blocked.`,
|
|
274
|
+
status: 422,
|
|
275
|
+
details: {
|
|
276
|
+
reachability_mode: mode,
|
|
277
|
+
reviewer_hostname: hostname,
|
|
278
|
+
proof_url: proofUrl,
|
|
279
|
+
resolved_addresses: resolvedAddresses,
|
|
280
|
+
blocked_addresses: blockedAddresses
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
ok: true,
|
|
287
|
+
reachability: {
|
|
288
|
+
mode,
|
|
289
|
+
dns_ran: true,
|
|
290
|
+
hostname,
|
|
291
|
+
resolved_addresses: resolvedAddresses,
|
|
292
|
+
summary: `Worker-local DNS resolved ${hostname} to public addresses only: ${resolvedAddresses.join(', ')}.`,
|
|
293
|
+
caveat: 'This is worker-local DNS evidence only. Reviewer reachability is not guaranteed across other networks, resolvers, or future DNS changes.'
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function buildReachabilityWithoutProof(mode) {
|
|
298
|
+
if (mode === 'dns-public') {
|
|
299
|
+
return {
|
|
300
|
+
mode,
|
|
301
|
+
dns_ran: false,
|
|
302
|
+
hostname: null,
|
|
303
|
+
resolved_addresses: [],
|
|
304
|
+
summary: 'No proof URL was provided, so dns-public reachability was not exercised.',
|
|
305
|
+
caveat: 'Reviewer reachability remains unevaluated until a reviewer-usable proof URL is supplied.'
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
mode,
|
|
310
|
+
dns_ran: false,
|
|
311
|
+
hostname: null,
|
|
312
|
+
resolved_addresses: [],
|
|
313
|
+
summary: 'No proof URL was provided; the deterministic path leaves reviewer reachability out of scope.',
|
|
314
|
+
caveat: 'No live DNS lookup was performed.'
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function uniqueAddresses(addresses) {
|
|
318
|
+
const seen = new Set();
|
|
319
|
+
const result = [];
|
|
320
|
+
for (const address of addresses) {
|
|
321
|
+
if (seen.has(address)) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
seen.add(address);
|
|
325
|
+
result.push(address);
|
|
326
|
+
}
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
function capabilityForKind(capabilities, kind) {
|
|
330
|
+
if (kind === 'external-link') {
|
|
331
|
+
return capabilities.external_link;
|
|
332
|
+
}
|
|
333
|
+
return capabilities[kind];
|
|
334
|
+
}
|
|
335
|
+
function isKindAllowed(policy, kind) {
|
|
336
|
+
return capabilityForKind(policy.capabilities, kind);
|
|
337
|
+
}
|
|
338
|
+
function normalizeRuntimeProofKind(value) {
|
|
339
|
+
const normalized = normalizeOptionalText(value)?.toLowerCase();
|
|
340
|
+
if (normalized === 'screenshot' || normalized === 'external-link' || normalized === 'video') {
|
|
341
|
+
return normalized;
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
function normalizeRuntimeProofReachabilityMode(value) {
|
|
346
|
+
const normalized = normalizeOptionalText(value)?.toLowerCase();
|
|
347
|
+
if (!normalized) {
|
|
348
|
+
return 'deterministic';
|
|
349
|
+
}
|
|
350
|
+
if (normalized === 'deterministic' || normalized === 'dns-public') {
|
|
351
|
+
return normalized;
|
|
352
|
+
}
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
function normalizeOrigin(value) {
|
|
356
|
+
const normalized = normalizeOptionalText(value);
|
|
357
|
+
if (!normalized) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const parsed = new URL(normalized);
|
|
362
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
return parsed.origin;
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function normalizeHttpUrl(value) {
|
|
372
|
+
const normalized = normalizeOptionalText(value);
|
|
373
|
+
if (!normalized) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
const parsed = new URL(normalized);
|
|
378
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
if (parsed.username || parsed.password) {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
if (isBlockedProofHostname(parsed.hostname)) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
return parsed.toString();
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function normalizeHostname(hostname) {
|
|
394
|
+
const normalized = hostname.trim().toLowerCase().replaceAll(/^\[|\]$/g, '').replace(/\.$/, '');
|
|
395
|
+
return normalized.length > 0 ? normalized : null;
|
|
396
|
+
}
|
|
397
|
+
function isBlockedProofHostname(hostname) {
|
|
398
|
+
const normalized = normalizeHostname(hostname);
|
|
399
|
+
if (!normalized) {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
if (normalized === 'localhost' || normalized.endsWith('.localhost')) {
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
if (isIP(normalized) > 0) {
|
|
406
|
+
return isBlockedProofIpAddress(normalized);
|
|
407
|
+
}
|
|
408
|
+
if (!normalized.includes('.')) {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
if (BLOCKED_PROOF_TLDS.some((tld) => normalized === tld || normalized.endsWith(`.${tld}`))) {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
function isBlockedProofIpAddress(address) {
|
|
417
|
+
const normalized = normalizeHostname(address);
|
|
418
|
+
if (!normalized) {
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
const embeddedIpv4 = extractEmbeddedIpv4Address(normalized);
|
|
422
|
+
if (embeddedIpv4) {
|
|
423
|
+
return BLOCKED_PROOF_HOSTS.check(embeddedIpv4, 'ipv4');
|
|
424
|
+
}
|
|
425
|
+
const ipVersion = isIP(normalized);
|
|
426
|
+
if (ipVersion === 4) {
|
|
427
|
+
return BLOCKED_PROOF_HOSTS.check(normalized, 'ipv4');
|
|
428
|
+
}
|
|
429
|
+
if (ipVersion === 6) {
|
|
430
|
+
return BLOCKED_PROOF_HOSTS.check(normalized, 'ipv6');
|
|
431
|
+
}
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
function extractEmbeddedIpv4Address(address) {
|
|
435
|
+
const hextets = expandIpv6Hextets(address);
|
|
436
|
+
if (!hextets) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
if (isIpv4MappedIpv6(hextets) || isIpv4TranslatedIpv6(hextets) || isWellKnownNat64Ipv6(hextets)) {
|
|
440
|
+
return formatEmbeddedIpv4(hextets[6], hextets[7]);
|
|
441
|
+
}
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
function expandIpv6Hextets(address) {
|
|
445
|
+
const normalized = normalizeHostname(address);
|
|
446
|
+
if (!normalized || isIP(normalized) !== 6) {
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
let source = normalized;
|
|
450
|
+
const zoneSeparator = source.indexOf('%');
|
|
451
|
+
if (zoneSeparator >= 0) {
|
|
452
|
+
source = source.slice(0, zoneSeparator);
|
|
453
|
+
}
|
|
454
|
+
if (source.includes('.')) {
|
|
455
|
+
const lastColon = source.lastIndexOf(':');
|
|
456
|
+
if (lastColon < 0) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
const ipv4Suffix = source.slice(lastColon + 1);
|
|
460
|
+
if (isIP(ipv4Suffix) !== 4) {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
const octets = ipv4Suffix.split('.').map((part) => Number.parseInt(part, 10));
|
|
464
|
+
source = `${source.slice(0, lastColon)}:${((octets[0] << 8) | octets[1]).toString(16)}:${((octets[2] << 8) | octets[3]).toString(16)}`;
|
|
465
|
+
}
|
|
466
|
+
const halves = source.split('::');
|
|
467
|
+
if (halves.length > 2) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
const head = halves[0] ? halves[0].split(':').filter((part) => part.length > 0) : [];
|
|
471
|
+
const tail = halves.length === 2 && halves[1] ? halves[1].split(':').filter((part) => part.length > 0) : [];
|
|
472
|
+
let parts;
|
|
473
|
+
if (halves.length === 1) {
|
|
474
|
+
if (head.length !== 8) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
parts = head;
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
const missing = 8 - (head.length + tail.length);
|
|
481
|
+
if (missing < 1) {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
parts = [...head, ...Array.from({ length: missing }, () => '0'), ...tail];
|
|
485
|
+
}
|
|
486
|
+
if (parts.length !== 8 || parts.some((part) => !/^[0-9a-f]{1,4}$/i.test(part))) {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
return parts.map((part) => Number.parseInt(part, 16));
|
|
490
|
+
}
|
|
491
|
+
function isIpv4MappedIpv6(hextets) {
|
|
492
|
+
return (hextets[0] === 0 &&
|
|
493
|
+
hextets[1] === 0 &&
|
|
494
|
+
hextets[2] === 0 &&
|
|
495
|
+
hextets[3] === 0 &&
|
|
496
|
+
hextets[4] === 0 &&
|
|
497
|
+
hextets[5] === 0xffff);
|
|
498
|
+
}
|
|
499
|
+
function isIpv4TranslatedIpv6(hextets) {
|
|
500
|
+
return (hextets[0] === 0 &&
|
|
501
|
+
hextets[1] === 0 &&
|
|
502
|
+
hextets[2] === 0 &&
|
|
503
|
+
hextets[3] === 0 &&
|
|
504
|
+
hextets[4] === 0xffff &&
|
|
505
|
+
hextets[5] === 0);
|
|
506
|
+
}
|
|
507
|
+
function isWellKnownNat64Ipv6(hextets) {
|
|
508
|
+
return (hextets[0] === 0x64 &&
|
|
509
|
+
hextets[1] === 0xff9b &&
|
|
510
|
+
hextets[2] === 0 &&
|
|
511
|
+
hextets[3] === 0 &&
|
|
512
|
+
hextets[4] === 0 &&
|
|
513
|
+
hextets[5] === 0);
|
|
514
|
+
}
|
|
515
|
+
function formatEmbeddedIpv4(left, right) {
|
|
516
|
+
return `${left >> 8}.${left & 0xff}.${right >> 8}.${right & 0xff}`;
|
|
517
|
+
}
|
|
518
|
+
function normalizeMarkdownInline(value) {
|
|
519
|
+
return value.replaceAll(/\s*[\r\n]+\s*/g, ' ').trim();
|
|
520
|
+
}
|
|
521
|
+
function normalizeOptionalText(value) {
|
|
522
|
+
if (typeof value !== 'string') {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
const trimmed = value.trim();
|
|
526
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
527
|
+
}
|
|
528
|
+
function buildDefaultProofTitle(kind) {
|
|
529
|
+
if (kind === 'external-link') {
|
|
530
|
+
return 'Runtime proof link';
|
|
531
|
+
}
|
|
532
|
+
return `Runtime proof ${kind}`;
|
|
533
|
+
}
|
|
534
|
+
function escapeMarkdownLabel(value) {
|
|
535
|
+
return value.replaceAll('[', '\\[').replaceAll(']', '\\]');
|
|
536
|
+
}
|
|
537
|
+
function formatKinds(kinds) {
|
|
538
|
+
if (kinds.length === 0) {
|
|
539
|
+
return 'No';
|
|
540
|
+
}
|
|
541
|
+
if (kinds.length === 1) {
|
|
542
|
+
return kinds[0];
|
|
543
|
+
}
|
|
544
|
+
if (kinds.length === 2) {
|
|
545
|
+
return `${kinds[0]} and ${kinds[1]}`;
|
|
546
|
+
}
|
|
547
|
+
return `${kinds.slice(0, -1).join(', ')}, and ${kinds.at(-1)}`;
|
|
548
|
+
}
|
|
549
|
+
function createBlockedProofHostBlockList() {
|
|
550
|
+
const blockList = new BlockList();
|
|
551
|
+
blockList.addSubnet('0.0.0.0', 8, 'ipv4');
|
|
552
|
+
blockList.addSubnet('10.0.0.0', 8, 'ipv4');
|
|
553
|
+
blockList.addSubnet('100.64.0.0', 10, 'ipv4');
|
|
554
|
+
blockList.addSubnet('127.0.0.0', 8, 'ipv4');
|
|
555
|
+
blockList.addSubnet('169.254.0.0', 16, 'ipv4');
|
|
556
|
+
blockList.addSubnet('172.16.0.0', 12, 'ipv4');
|
|
557
|
+
blockList.addSubnet('192.0.2.0', 24, 'ipv4');
|
|
558
|
+
blockList.addSubnet('192.88.99.0', 24, 'ipv4');
|
|
559
|
+
blockList.addSubnet('192.168.0.0', 16, 'ipv4');
|
|
560
|
+
blockList.addSubnet('198.18.0.0', 15, 'ipv4');
|
|
561
|
+
blockList.addSubnet('198.51.100.0', 24, 'ipv4');
|
|
562
|
+
blockList.addSubnet('203.0.113.0', 24, 'ipv4');
|
|
563
|
+
blockList.addSubnet('224.0.0.0', 4, 'ipv4');
|
|
564
|
+
blockList.addSubnet('240.0.0.0', 4, 'ipv4');
|
|
565
|
+
blockList.addSubnet('::', 96, 'ipv6');
|
|
566
|
+
blockList.addSubnet('100::', 64, 'ipv6');
|
|
567
|
+
blockList.addAddress('::', 'ipv6');
|
|
568
|
+
blockList.addAddress('::1', 'ipv6');
|
|
569
|
+
blockList.addSubnet('2001:db8::', 32, 'ipv6');
|
|
570
|
+
blockList.addSubnet('64:ff9b:1::', 48, 'ipv6');
|
|
571
|
+
blockList.addSubnet('fec0::', 10, 'ipv6');
|
|
572
|
+
blockList.addSubnet('fe80::', 10, 'ipv6');
|
|
573
|
+
blockList.addSubnet('fc00::', 7, 'ipv6');
|
|
574
|
+
blockList.addSubnet('ff00::', 8, 'ipv6');
|
|
575
|
+
return blockList;
|
|
576
|
+
}
|
|
577
|
+
function failure(code, message, status, details, policy) {
|
|
578
|
+
return {
|
|
579
|
+
ok: false,
|
|
580
|
+
policy: policy ?? null,
|
|
581
|
+
error: {
|
|
582
|
+
code,
|
|
583
|
+
message,
|
|
584
|
+
status,
|
|
585
|
+
...(details ? { details } : {})
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
}
|