@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.
Files changed (302) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/README.md +73 -291
  3. package/bin/codex-orchestrator.js +161 -0
  4. package/codex.orchestrator.json +149 -13
  5. package/dist/bin/codex-orchestrator.js +795 -1154
  6. package/dist/orchestrator/src/cli/adapters/CommandPlanner.js +22 -4
  7. package/dist/orchestrator/src/cli/adapters/CommandReviewer.js +3 -3
  8. package/dist/orchestrator/src/cli/adapters/CommandTester.js +2 -2
  9. package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +183 -11
  10. package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +402 -0
  11. package/dist/orchestrator/src/cli/coStatusCliShell.js +429 -0
  12. package/dist/orchestrator/src/cli/coStatusOperatorAutopilotCliShell.js +120 -0
  13. package/dist/orchestrator/src/cli/codexCliShell.js +72 -0
  14. package/dist/orchestrator/src/cli/codexDefaultsSetup.js +49 -11
  15. package/dist/orchestrator/src/cli/config/delegationConfig.js +317 -5
  16. package/dist/orchestrator/src/cli/config/repoConfigPolicy.js +2 -3
  17. package/dist/orchestrator/src/cli/config/userConfig.js +28 -13
  18. package/dist/orchestrator/src/cli/control/authenticatedControlRouteGate.js +69 -0
  19. package/dist/orchestrator/src/cli/control/authenticatedRouteComposition.js +267 -0
  20. package/dist/orchestrator/src/cli/control/authenticatedRouteController.js +5 -0
  21. package/dist/orchestrator/src/cli/control/authenticatedRouteDispatcher.js +41 -0
  22. package/dist/orchestrator/src/cli/control/compatibilityIssuePresenter.js +1035 -0
  23. package/dist/orchestrator/src/cli/control/confirmationApproveController.js +62 -0
  24. package/dist/orchestrator/src/cli/control/confirmationCreateController.js +69 -0
  25. package/dist/orchestrator/src/cli/control/confirmationIssueConsumeController.js +43 -0
  26. package/dist/orchestrator/src/cli/control/confirmationListController.js +22 -0
  27. package/dist/orchestrator/src/cli/control/confirmationValidateController.js +58 -0
  28. package/dist/orchestrator/src/cli/control/confirmations.js +25 -3
  29. package/dist/orchestrator/src/cli/control/controlActionCancelConfirmation.js +65 -0
  30. package/dist/orchestrator/src/cli/control/controlActionController.js +77 -0
  31. package/dist/orchestrator/src/cli/control/controlActionControllerSequencing.js +161 -0
  32. package/dist/orchestrator/src/cli/control/controlActionExecution.js +142 -0
  33. package/dist/orchestrator/src/cli/control/controlActionFinalization.js +43 -0
  34. package/dist/orchestrator/src/cli/control/controlActionOutcome.js +60 -0
  35. package/dist/orchestrator/src/cli/control/controlActionPreflight.js +476 -0
  36. package/dist/orchestrator/src/cli/control/controlAuthenticatedRouteHandoff.js +57 -0
  37. package/dist/orchestrator/src/cli/control/controlBootstrapAssembly.js +39 -0
  38. package/dist/orchestrator/src/cli/control/controlBootstrapMetadataPersistence.js +16 -0
  39. package/dist/orchestrator/src/cli/control/controlEventTransport.js +49 -0
  40. package/dist/orchestrator/src/cli/control/controlExpiryLifecycle.js +102 -0
  41. package/dist/orchestrator/src/cli/control/controlHostOwnership.js +480 -0
  42. package/dist/orchestrator/src/cli/control/controlHostSupervision.js +608 -0
  43. package/dist/orchestrator/src/cli/control/controlOversightFacade.js +8 -0
  44. package/dist/orchestrator/src/cli/control/controlOversightReadContract.js +1 -0
  45. package/dist/orchestrator/src/cli/control/controlOversightReadService.js +16 -0
  46. package/dist/orchestrator/src/cli/control/controlOversightUpdateContract.js +1 -0
  47. package/dist/orchestrator/src/cli/control/controlPersistenceFiles.js +6 -0
  48. package/dist/orchestrator/src/cli/control/controlQuestionChildResolution.js +18 -0
  49. package/dist/orchestrator/src/cli/control/controlRequestContext.js +42 -0
  50. package/dist/orchestrator/src/cli/control/controlRequestController.js +9 -0
  51. package/dist/orchestrator/src/cli/control/controlRequestPredispatch.js +17 -0
  52. package/dist/orchestrator/src/cli/control/controlRequestRouteDispatch.js +44 -0
  53. package/dist/orchestrator/src/cli/control/controlRuntime.js +992 -0
  54. package/dist/orchestrator/src/cli/control/controlServer.js +23 -1456
  55. package/dist/orchestrator/src/cli/control/controlServerAuditAndErrorHelpers.js +115 -0
  56. package/dist/orchestrator/src/cli/control/controlServerAuthenticatedRouteBranch.js +29 -0
  57. package/dist/orchestrator/src/cli/control/controlServerBootstrapLifecycle.js +30 -0
  58. package/dist/orchestrator/src/cli/control/controlServerBootstrapStartSequence.js +21 -0
  59. package/dist/orchestrator/src/cli/control/controlServerOwnedRuntimeLifecycle.js +67 -0
  60. package/dist/orchestrator/src/cli/control/controlServerPublicLifecycle.js +756 -0
  61. package/dist/orchestrator/src/cli/control/controlServerPublicRouteHelpers.js +86 -0
  62. package/dist/orchestrator/src/cli/control/controlServerReadyInstanceLifecycle.js +25 -0
  63. package/dist/orchestrator/src/cli/control/controlServerReadyInstanceStartup.js +18 -0
  64. package/dist/orchestrator/src/cli/control/controlServerRequestBodyHelpers.js +37 -0
  65. package/dist/orchestrator/src/cli/control/controlServerRequestShell.js +40 -0
  66. package/dist/orchestrator/src/cli/control/controlServerRequestShellBinding.js +17 -0
  67. package/dist/orchestrator/src/cli/control/controlServerSeedLoading.js +27 -0
  68. package/dist/orchestrator/src/cli/control/controlServerSeededRuntimeAssembly.js +186 -0
  69. package/dist/orchestrator/src/cli/control/controlServerStartupInputPreparation.js +31 -0
  70. package/dist/orchestrator/src/cli/control/controlServerStartupSequence.js +49 -0
  71. package/dist/orchestrator/src/cli/control/controlState.js +233 -2
  72. package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +1899 -0
  73. package/dist/orchestrator/src/cli/control/controlTelegramBridgeBootstrapLifecycle.js +22 -0
  74. package/dist/orchestrator/src/cli/control/controlTelegramBridgeLifecycle.js +67 -0
  75. package/dist/orchestrator/src/cli/control/controlTelegramBridgeOversightFacadeFactory.js +8 -0
  76. package/dist/orchestrator/src/cli/control/controlTelegramCommandController.js +49 -0
  77. package/dist/orchestrator/src/cli/control/controlTelegramDispatchRead.js +40 -0
  78. package/dist/orchestrator/src/cli/control/controlTelegramPollingController.js +89 -0
  79. package/dist/orchestrator/src/cli/control/controlTelegramProjectionNotificationController.js +29 -0
  80. package/dist/orchestrator/src/cli/control/controlTelegramPushState.js +63 -0
  81. package/dist/orchestrator/src/cli/control/controlTelegramQuestionRead.js +13 -0
  82. package/dist/orchestrator/src/cli/control/controlTelegramReadController.js +216 -0
  83. package/dist/orchestrator/src/cli/control/controlTelegramUpdateHandler.js +63 -0
  84. package/dist/orchestrator/src/cli/control/controlWatcher.js +73 -5
  85. package/dist/orchestrator/src/cli/control/delegationRegisterController.js +35 -0
  86. package/dist/orchestrator/src/cli/control/dynamicToolBridgePolicy.js +139 -0
  87. package/dist/orchestrator/src/cli/control/eventsSseController.js +12 -0
  88. package/dist/orchestrator/src/cli/control/linearBudgetState.js +1789 -0
  89. package/dist/orchestrator/src/cli/control/linearDispatchSource.js +1137 -0
  90. package/dist/orchestrator/src/cli/control/linearGraphqlClient.js +150 -0
  91. package/dist/orchestrator/src/cli/control/linearRateLimit.js +102 -0
  92. package/dist/orchestrator/src/cli/control/linearWebhookController.js +499 -0
  93. package/dist/orchestrator/src/cli/control/liveLinearAdvisoryRuntime.js +70 -0
  94. package/dist/orchestrator/src/cli/control/observabilityApiController.js +173 -0
  95. package/dist/orchestrator/src/cli/control/observabilityReadModel.js +500 -0
  96. package/dist/orchestrator/src/cli/control/observabilitySurface.js +284 -0
  97. package/dist/orchestrator/src/cli/control/observabilityUpdateNotifier.js +22 -0
  98. package/dist/orchestrator/src/cli/control/operatorDashboardPresenter.js +252 -0
  99. package/dist/orchestrator/src/cli/control/providerAgentCapacity.js +70 -0
  100. package/dist/orchestrator/src/cli/control/providerControlHostFreshnessGauge.js +1068 -0
  101. package/dist/orchestrator/src/cli/control/providerIntakeState.js +473 -0
  102. package/dist/orchestrator/src/cli/control/providerIssueHandoff.js +6811 -0
  103. package/dist/orchestrator/src/cli/control/providerIssueObservability.js +1348 -0
  104. package/dist/orchestrator/src/cli/control/providerIssueRetryQueue.js +84 -0
  105. package/dist/orchestrator/src/cli/control/providerLinearRuntimeProof.js +588 -0
  106. package/dist/orchestrator/src/cli/control/providerLinearScreenshotProof.js +473 -0
  107. package/dist/orchestrator/src/cli/control/providerLinearWorkerTruth.js +383 -0
  108. package/dist/orchestrator/src/cli/control/providerLinearWorkflowAudit.js +254 -0
  109. package/dist/orchestrator/src/cli/control/providerLinearWorkflowFacade.js +5573 -0
  110. package/dist/orchestrator/src/cli/control/providerLinearWorkflowStates.js +115 -0
  111. package/dist/orchestrator/src/cli/control/providerMergeCloseout.js +1868 -0
  112. package/dist/orchestrator/src/cli/control/providerOperatorAutopilot.js +1580 -0
  113. package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLifecycle.js +154 -0
  114. package/dist/orchestrator/src/cli/control/providerOperatorAutopilotLocalRolloutExecution.js +1006 -0
  115. package/dist/orchestrator/src/cli/control/providerPollingHealth.js +435 -0
  116. package/dist/orchestrator/src/cli/control/providerTerminalCleanup.js +516 -0
  117. package/dist/orchestrator/src/cli/control/providerWorkerHosts.js +191 -0
  118. package/dist/orchestrator/src/cli/control/providerWorkflowConfigStore.js +515 -0
  119. package/dist/orchestrator/src/cli/control/questionChildResolutionAdapter.js +361 -0
  120. package/dist/orchestrator/src/cli/control/questionQueueController.js +181 -0
  121. package/dist/orchestrator/src/cli/control/questionReadRetryDeduplication.js +9 -0
  122. package/dist/orchestrator/src/cli/control/questionReadSequence.js +10 -0
  123. package/dist/orchestrator/src/cli/control/securityViolationController.js +27 -0
  124. package/dist/orchestrator/src/cli/control/selectedRunProjection.js +1838 -0
  125. package/dist/orchestrator/src/cli/control/telegramOversightApiClient.js +48 -0
  126. package/dist/orchestrator/src/cli/control/telegramOversightBridge.js +180 -0
  127. package/dist/orchestrator/src/cli/control/telegramOversightBridgeProjectionDeliveryQueue.js +25 -0
  128. package/dist/orchestrator/src/cli/control/telegramOversightBridgeRuntimeLifecycle.js +45 -0
  129. package/dist/orchestrator/src/cli/control/telegramOversightBridgeStateStore.js +77 -0
  130. package/dist/orchestrator/src/cli/control/telegramOversightControlActionApiClient.js +45 -0
  131. package/dist/orchestrator/src/cli/control/trackerDispatchPilot.js +439 -0
  132. package/dist/orchestrator/src/cli/control/uiDataController.js +34 -0
  133. package/dist/orchestrator/src/cli/control/uiSessionController.js +100 -0
  134. package/dist/orchestrator/src/cli/controlHostCliShell.js +860 -0
  135. package/dist/orchestrator/src/cli/controlHostFreshnessGaugeCliShell.js +129 -0
  136. package/dist/orchestrator/src/cli/controlHostSupervisionCliShell.js +2127 -0
  137. package/dist/orchestrator/src/cli/delegationCliShell.js +62 -0
  138. package/dist/orchestrator/src/cli/delegationServer.js +567 -678
  139. package/dist/orchestrator/src/cli/delegationServerCliShell.js +52 -0
  140. package/dist/orchestrator/src/cli/delegationServerQuestionFlowShell.js +228 -0
  141. package/dist/orchestrator/src/cli/delegationServerToolDispatchShell.js +411 -0
  142. package/dist/orchestrator/src/cli/delegationServerTransport.js +274 -0
  143. package/dist/orchestrator/src/cli/delegationSetup.js +51 -171
  144. package/dist/orchestrator/src/cli/devtoolsCliShell.js +34 -0
  145. package/dist/orchestrator/src/cli/doctor.js +542 -122
  146. package/dist/orchestrator/src/cli/doctorCliRequestShell.js +72 -0
  147. package/dist/orchestrator/src/cli/doctorCliShell.js +138 -0
  148. package/dist/orchestrator/src/cli/doctorUsage.js +136 -16
  149. package/dist/orchestrator/src/cli/exec/experience.js +16 -2
  150. package/dist/orchestrator/src/cli/exec/summary.js +3 -0
  151. package/dist/orchestrator/src/cli/execCliShell.js +51 -0
  152. package/dist/orchestrator/src/cli/flowCliRequestShell.js +44 -0
  153. package/dist/orchestrator/src/cli/flowCliShell.js +239 -0
  154. package/dist/orchestrator/src/cli/frontendTestCliRequestShell.js +80 -0
  155. package/dist/orchestrator/src/cli/frontendTestCliShell.js +41 -0
  156. package/dist/orchestrator/src/cli/init.js +1 -0
  157. package/dist/orchestrator/src/cli/initCliShell.js +50 -0
  158. package/dist/orchestrator/src/cli/linearCliShell.js +1200 -0
  159. package/dist/orchestrator/src/cli/mcpEnableCliShell.js +132 -0
  160. package/dist/orchestrator/src/cli/metrics/metricsAggregator.js +3 -2
  161. package/dist/orchestrator/src/cli/metrics/metricsRecorder.js +56 -0
  162. package/dist/orchestrator/src/cli/orchestrator.js +66 -1376
  163. package/dist/orchestrator/src/cli/planCliShell.js +19 -0
  164. package/dist/orchestrator/src/cli/prCliShell.js +41 -0
  165. package/dist/orchestrator/src/cli/providerLinearChildLanePhaseContract.js +204 -0
  166. package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +1772 -0
  167. package/dist/orchestrator/src/cli/providerLinearChildLaneShell.js +2420 -0
  168. package/dist/orchestrator/src/cli/providerLinearChildStreamShell.js +385 -0
  169. package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +5738 -0
  170. package/dist/orchestrator/src/cli/resumeCliShell.js +14 -0
  171. package/dist/orchestrator/src/cli/reviewCliLaunchShell.js +72 -0
  172. package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
  173. package/dist/orchestrator/src/cli/rlm/context.js +94 -7
  174. package/dist/orchestrator/src/cli/rlm/rlmCodexRuntimeShell.js +546 -0
  175. package/dist/orchestrator/src/cli/rlm/symbolic.js +4 -2
  176. package/dist/orchestrator/src/cli/rlmCliRequestShell.js +42 -0
  177. package/dist/orchestrator/src/cli/rlmCompletionCliShell.js +46 -0
  178. package/dist/orchestrator/src/cli/rlmLaunchCliShell.js +51 -0
  179. package/dist/orchestrator/src/cli/rlmRunner.js +83 -523
  180. package/dist/orchestrator/src/cli/run/blockMemory.js +500 -0
  181. package/dist/orchestrator/src/cli/run/manifest.js +410 -73
  182. package/dist/orchestrator/src/cli/run/manifestPersister.js +45 -14
  183. package/dist/orchestrator/src/cli/run/runMemoryController.js +216 -0
  184. package/dist/orchestrator/src/cli/run/source0.js +690 -0
  185. package/dist/orchestrator/src/cli/run/workspacePath.js +101 -0
  186. package/dist/orchestrator/src/cli/runtime/mode.js +2 -1
  187. package/dist/orchestrator/src/cli/runtime/provider.js +39 -2
  188. package/dist/orchestrator/src/cli/selfCheckCliShell.js +12 -0
  189. package/dist/orchestrator/src/cli/services/commandRunner.js +668 -18
  190. package/dist/orchestrator/src/cli/services/execRuntime.js +66 -1
  191. package/dist/orchestrator/src/cli/services/orchestratorAutoScoutEvidenceRecorder.js +71 -0
  192. package/dist/orchestrator/src/cli/services/orchestratorCloudBranchResolution.js +8 -0
  193. package/dist/orchestrator/src/cli/services/orchestratorCloudEnvironmentResolution.js +22 -0
  194. package/dist/orchestrator/src/cli/services/orchestratorCloudExecutionLifecycleShell.js +39 -0
  195. package/dist/orchestrator/src/cli/services/orchestratorCloudPromptBuilder.js +37 -0
  196. package/dist/orchestrator/src/cli/services/orchestratorCloudRouteFallbackContract.js +45 -0
  197. package/dist/orchestrator/src/cli/services/orchestratorCloudRouteShell.js +36 -0
  198. package/dist/orchestrator/src/cli/services/orchestratorCloudTargetExecutor.js +277 -0
  199. package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycle.js +98 -0
  200. package/dist/orchestrator/src/cli/services/orchestratorControlPlaneLifecycleShell.js +54 -0
  201. package/dist/orchestrator/src/cli/services/orchestratorExecutionLifecycle.js +112 -0
  202. package/dist/orchestrator/src/cli/services/orchestratorExecutionModePolicy.js +27 -0
  203. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteAdapterShell.js +59 -0
  204. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteDecisionShell.js +57 -0
  205. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouteState.js +21 -0
  206. package/dist/orchestrator/src/cli/services/orchestratorExecutionRouter.js +2 -0
  207. package/dist/orchestrator/src/cli/services/orchestratorLocalPipelineExecutor.js +149 -0
  208. package/dist/orchestrator/src/cli/services/orchestratorLocalRouteShell.js +63 -0
  209. package/dist/orchestrator/src/cli/services/orchestratorPlanShell.js +54 -0
  210. package/dist/orchestrator/src/cli/services/orchestratorPlanTargetTracker.js +16 -0
  211. package/dist/orchestrator/src/cli/services/orchestratorResumePreparationShell.js +84 -0
  212. package/dist/orchestrator/src/cli/services/orchestratorResumeTokenValidation.js +15 -0
  213. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleCompletion.js +31 -0
  214. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleExecutionRegistration.js +37 -0
  215. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleOrchestrationShell.js +83 -0
  216. package/dist/orchestrator/src/cli/services/orchestratorRunLifecycleTaskManagerShell.js +37 -0
  217. package/dist/orchestrator/src/cli/services/orchestratorRuntimeManifestMutation.js +20 -0
  218. package/dist/orchestrator/src/cli/services/orchestratorStartPreparationShell.js +56 -0
  219. package/dist/orchestrator/src/cli/services/orchestratorStatusShell.js +70 -0
  220. package/dist/orchestrator/src/cli/services/pipelineResolver.js +7 -3
  221. package/dist/orchestrator/src/cli/services/plannerMemory.js +119 -0
  222. package/dist/orchestrator/src/cli/services/runPreparation.js +7 -3
  223. package/dist/orchestrator/src/cli/services/runSummaryWriter.js +9 -0
  224. package/dist/orchestrator/src/cli/setupBootstrapShell.js +114 -0
  225. package/dist/orchestrator/src/cli/setupCliShell.js +51 -0
  226. package/dist/orchestrator/src/cli/skillsCliShell.js +56 -0
  227. package/dist/orchestrator/src/cli/startCliRequestShell.js +53 -0
  228. package/dist/orchestrator/src/cli/startCliShell.js +68 -0
  229. package/dist/orchestrator/src/cli/statusCliShell.js +22 -0
  230. package/dist/orchestrator/src/cli/utils/authProvenanceFingerprint.js +27 -0
  231. package/dist/orchestrator/src/cli/utils/cloudPreflight.js +83 -1
  232. package/dist/orchestrator/src/cli/utils/delegationConfigParser.js +250 -0
  233. package/dist/orchestrator/src/cli/utils/delegationMcpHealth.js +1382 -0
  234. package/dist/orchestrator/src/cli/utils/devtools.js +2 -54
  235. package/dist/orchestrator/src/cli/utils/mcpServerEntry.js +53 -0
  236. package/dist/orchestrator/src/cli/utils/packageProgramResolver.js +151 -0
  237. package/dist/orchestrator/src/cli/utils/providerOverrideEnv.js +71 -0
  238. package/dist/orchestrator/src/cli/utils/trailingJsonObject.js +59 -0
  239. package/dist/orchestrator/src/learning/crystalizer.js +2 -2
  240. package/dist/orchestrator/src/persistence/ExperienceStore.js +233 -49
  241. package/dist/orchestrator/src/persistence/TaskStateStore.js +6 -6
  242. package/dist/orchestrator/src/persistence/lockFile.js +70 -4
  243. package/dist/orchestrator/src/persistence/sanitizeIdentifier.js +39 -0
  244. package/dist/orchestrator/src/sync/createCloudSyncWorker.js +3 -2
  245. package/dist/orchestrator/src/utils/atomicWrite.js +17 -2
  246. package/dist/packages/orchestrator/src/exec/unified-exec.js +99 -6
  247. package/dist/packages/orchestrator/src/instructions/promptPacks.js +150 -19
  248. package/dist/packages/sdk-node/src/orchestrator.js +137 -13
  249. package/dist/packages/shared/config/designConfig.js +8 -1
  250. package/dist/packages/shared/streams/stdio.js +1 -1
  251. package/dist/scripts/design/pipeline/permit.js +15 -0
  252. package/dist/scripts/lib/docs-catalog.js +365 -0
  253. package/dist/scripts/lib/docs-helpers.js +87 -5
  254. package/dist/scripts/lib/pr-watch-merge.js +1088 -80
  255. package/dist/scripts/lib/provider-run-contract.js +26 -0
  256. package/dist/scripts/lib/review-command-intent-classification.js +532 -0
  257. package/dist/scripts/lib/review-command-probe-classification.js +385 -0
  258. package/dist/scripts/lib/review-execution-boundary-preflight.js +279 -0
  259. package/dist/scripts/lib/review-execution-runtime.js +753 -0
  260. package/dist/scripts/lib/review-execution-state.js +1144 -0
  261. package/dist/scripts/lib/review-execution-telemetry.js +215 -0
  262. package/dist/scripts/lib/review-inspection-target-parsing.js +78 -0
  263. package/dist/scripts/lib/review-launch-attempt.js +601 -0
  264. package/dist/scripts/lib/review-meta-surface-boundary-analysis.js +300 -0
  265. package/dist/scripts/lib/review-meta-surface-normalization.js +746 -0
  266. package/dist/scripts/lib/review-non-interactive-handoff.js +61 -0
  267. package/dist/scripts/lib/review-prompt-context.js +376 -0
  268. package/dist/scripts/lib/review-scope-advisory.js +286 -0
  269. package/dist/scripts/lib/review-scope-paths.js +123 -0
  270. package/dist/scripts/lib/review-shell-command-parser.js +389 -0
  271. package/dist/scripts/lib/review-shell-env-interpreter.js +340 -0
  272. package/dist/scripts/lib/run-manifests.js +192 -36
  273. package/dist/scripts/lib/spark-policy-classifier.js +593 -0
  274. package/dist/scripts/run-review.js +507 -1777
  275. package/docs/public/downstream-setup.md +106 -0
  276. package/docs/public/provider-onboarding.md +173 -0
  277. package/package.json +30 -11
  278. package/plugins/codex-orchestrator/.codex-plugin/plugin.json +30 -0
  279. package/plugins/codex-orchestrator/.mcp.json +13 -0
  280. package/plugins/codex-orchestrator/launcher.mjs +359 -0
  281. package/schemas/manifest.json +395 -0
  282. package/skills/chrome-devtools/SKILL.md +1 -1
  283. package/skills/codex-orchestrator/SKILL.md +83 -0
  284. package/skills/collab-subagents-first/SKILL.md +2 -1
  285. package/skills/delegation-usage/DELEGATION_GUIDE.md +24 -11
  286. package/skills/delegation-usage/SKILL.md +20 -13
  287. package/skills/land/SKILL.md +77 -0
  288. package/skills/linear/SKILL.md +255 -0
  289. package/skills/release/SKILL.md +47 -3
  290. package/skills/standalone-review/SKILL.md +6 -1
  291. package/templates/README.md +4 -2
  292. package/templates/codex/.codex/agents/awaiter-high.toml +2 -2
  293. package/templates/codex/.codex/agents/explorer-fast.toml +1 -0
  294. package/templates/codex/.codex/agents/worker-complex.toml +1 -1
  295. package/templates/codex/.codex/config.toml +3 -4
  296. package/templates/codex/.codex/providers/README.md +13 -0
  297. package/templates/codex/.codex/providers/control.example.json +18 -0
  298. package/templates/codex/.codex/providers/provider.env.example +15 -0
  299. package/templates/codex/AGENTS.md +12 -7
  300. package/templates/codex/mcp-client.json +5 -1
  301. package/docs/README.md +0 -307
  302. 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.guardrailsRequired !== false,
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 experienceSnippets = await Promise.all(instructions.promptPacks.map(async (pack) => {
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 minReward = resolveExperienceMinReward();
101
- const records = await experienceStore.fetchTop({
140
+ const selection = await experienceStore.selectTop({
102
141
  domain: pack.domain,
103
142
  limit: pack.experienceSlots,
104
- minReward,
105
- taskId: env.taskId
143
+ taskId: env.taskId,
144
+ policy
106
145
  });
107
- return formatExperienceInjections(records, pack.experienceSlots);
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 experiences = experienceSnippets[index] ?? [];
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
- manifest.resume_events.push({ ...event, timestamp: isoTimestamp() });
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 summary = buildGuardrailSummary(manifest);
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
- filtered.push(summary);
236
- manifest.summary = filtered.join('\n').trim();
237
- if (manifest.summary.length === 0) {
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.guardrails_required ?? true;
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
- return manifest.commands.filter((entry) => {
289
- const id = entry.id?.toLowerCase() ?? '';
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 formatGuardrailSummary(counts) {
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 'Guardrails: spec-guard command not found.';
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
- async function resolveManifestPathForRunId(env, runId) {
399
- const expectedPaths = resolveRunPaths(env, runId);
400
- try {
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
- try {
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
- try {
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
- try {
529
- await access(cliManifestPath);
530
- return cliManifestPath;
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
- try {
539
- await access(legacyManifestPath);
540
- return legacyManifestPath;
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) {