@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
@@ -0,0 +1,1382 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
3
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
+ import process from 'node:process';
5
+ import { buildCommandPreview } from './commandPreview.js';
6
+ import { resolveCodexCliBin } from './codexCli.js';
7
+ import { resolveCodexHome } from './codexPaths.js';
8
+ import { readDelegationFallbackConfig } from './delegationConfigParser.js';
9
+ import { findPackageRoot } from './packageInfo.js';
10
+ import { resolveCodexOrchestratorBootstrapInvocation } from './packageProgramResolver.js';
11
+ const DEFAULT_STARTUP_TIMEOUT_MS = 3000;
12
+ const DEFAULT_STARTUP_SLOW_THRESHOLD_MS = 1000;
13
+ const DEFAULT_STALE_THRESHOLD_SECONDS = 10 * 60;
14
+ export function formatDelegateServerProcessSummary(detail) {
15
+ return `pid ${detail.pid} (${detail.classification}), parent ${detail.rootCodexParentPid ?? detail.parentPid ?? 'none'}, cwd ${detail.rootCodexParentCwd ?? detail.parentCwd ?? detail.cwd ?? '<unknown>'}, manifest ${detail.manifestPath ?? '<none>'}`;
16
+ }
17
+ const DEFAULT_DELEGATE_SERVER_CLEANUP_DEPENDENCIES = {
18
+ inspect: inspectDelegateServerProcessBundle,
19
+ readProcessRecord: readDelegateServerProcessRecord,
20
+ tryKillProcess,
21
+ isProcessAlive,
22
+ waitForMs
23
+ };
24
+ export function resolveDelegationServerInvocation(options = {}) {
25
+ const command = options.execPath ?? process.execPath;
26
+ const distPath = resolveDelegationDistPath({
27
+ allowMissingDist: options.allowMissingDist === true,
28
+ command,
29
+ env: options.env
30
+ });
31
+ if (!options.allowMissingDist && !existsSync(distPath)) {
32
+ throw new Error(`Delegation MCP requires a built dist entrypoint for stdio startup; missing ${distPath}.`);
33
+ }
34
+ const args = [distPath, 'delegate-server'];
35
+ return {
36
+ command,
37
+ args,
38
+ distPath,
39
+ commandLine: buildCommandPreview(command, args)
40
+ };
41
+ }
42
+ function resolveDelegationDistPath(options) {
43
+ try {
44
+ return resolveCodexOrchestratorBootstrapInvocation({
45
+ env: options.env,
46
+ execPath: options.command
47
+ }).distPath;
48
+ }
49
+ catch (error) {
50
+ if (!options.allowMissingDist || !isSourceFallbackBootstrapDistError(error)) {
51
+ throw error;
52
+ }
53
+ return join(findPackageRoot(import.meta.url), 'dist', 'bin', 'codex-orchestrator.js');
54
+ }
55
+ }
56
+ function isSourceFallbackBootstrapDistError(error) {
57
+ const detail = error instanceof Error ? error.message : String(error);
58
+ return detail.includes('Unable to run ')
59
+ && detail.includes('ts-node/esm is unavailable')
60
+ && /dist(?:\/|\\)bin(?:\/|\\)codex-orchestrator\.js/u.test(detail);
61
+ }
62
+ export function inspectDelegationMcpConfig(env = process.env) {
63
+ const codexBin = resolveCodexCliBin(env);
64
+ const codexHome = resolveCodexHome(env);
65
+ const configPath = join(codexHome, 'config.toml');
66
+ const cliEntry = readDelegationMcpServer(codexBin, env);
67
+ if (cliEntry) {
68
+ return {
69
+ status: 'ok',
70
+ path: configPath,
71
+ entry: {
72
+ source: 'codex-cli',
73
+ ...cliEntry,
74
+ commandLine: buildCommandPreview(cliEntry.command ?? '<missing>', cliEntry.args)
75
+ }
76
+ };
77
+ }
78
+ const fallback = readDelegationFallbackConfig(configPath);
79
+ if (!fallback) {
80
+ if (!existsSync(configPath)) {
81
+ return { status: 'missing', path: configPath, entry: null, detail: 'config.toml not found' };
82
+ }
83
+ return { status: 'missing', path: configPath, entry: null, detail: 'mcp_servers.delegation entry not found' };
84
+ }
85
+ return {
86
+ status: 'ok',
87
+ path: configPath,
88
+ entry: {
89
+ source: 'fallback',
90
+ command: fallback.command,
91
+ args: fallback.args,
92
+ envVars: fallback.envVars,
93
+ pinnedRepo: readPinnedRepo(fallback.args),
94
+ commandLine: buildCommandPreview(fallback.command ?? '<missing>', fallback.args)
95
+ }
96
+ };
97
+ }
98
+ export function classifyDelegationTransport(entry) {
99
+ if (!entry) {
100
+ return {
101
+ status: 'missing',
102
+ kind: 'missing',
103
+ commandLine: null,
104
+ detail: 'Delegation MCP entry is not configured.'
105
+ };
106
+ }
107
+ const delegateIndex = findDelegateServerIndex(entry.args);
108
+ if (delegateIndex === -1) {
109
+ return {
110
+ status: 'unsafe',
111
+ kind: 'not-delegation',
112
+ commandLine: entry.commandLine,
113
+ detail: 'Delegation MCP entry does not invoke delegate-server.'
114
+ };
115
+ }
116
+ if (isDirectDistDelegateServer(entry.command, entry.args, delegateIndex)) {
117
+ return {
118
+ status: 'safe',
119
+ kind: 'direct-dist',
120
+ commandLine: entry.commandLine,
121
+ detail: 'Delegation MCP uses the direct dist entrypoint, which is safe for stdio initialize latency.'
122
+ };
123
+ }
124
+ if (isWrapperDelegateServer(entry.command, entry.args, delegateIndex)) {
125
+ return {
126
+ status: 'unsafe',
127
+ kind: 'wrapper',
128
+ commandLine: entry.commandLine,
129
+ detail: 'Delegation MCP still routes through the codex-orchestrator wrapper; re-register with the direct dist entrypoint.'
130
+ };
131
+ }
132
+ return {
133
+ status: 'unsafe',
134
+ kind: 'other',
135
+ commandLine: entry.commandLine,
136
+ detail: 'Delegation MCP uses a non-standard delegate-server command; verify a direct dist entrypoint before relying on startup timing.'
137
+ };
138
+ }
139
+ export function probeDelegationInitialize(entry, options = {}) {
140
+ const thresholdMs = options.slowThresholdMs ?? DEFAULT_STARTUP_SLOW_THRESHOLD_MS;
141
+ const transport = classifyDelegationTransport(entry);
142
+ if (!entry || transport.status !== 'safe' || !entry.command) {
143
+ return {
144
+ status: 'skipped',
145
+ latencyMs: null,
146
+ thresholdMs,
147
+ detail: transport.status === 'missing'
148
+ ? 'Startup probe skipped because delegation MCP is not configured.'
149
+ : 'Startup probe skipped until the configured transport is re-registered to the direct dist entrypoint.'
150
+ };
151
+ }
152
+ const payload = `${JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize' })}\n`;
153
+ const start = Date.now();
154
+ const result = spawnSync(entry.command, entry.args, {
155
+ encoding: 'utf8',
156
+ stdio: ['pipe', 'pipe', 'pipe'],
157
+ timeout: options.timeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS,
158
+ input: payload,
159
+ env: {
160
+ ...(options.env ?? process.env),
161
+ ...entry.envVars
162
+ }
163
+ });
164
+ const latencyMs = Date.now() - start;
165
+ if (result.error) {
166
+ const message = result.error.message || `spawn failed for ${entry.commandLine}`;
167
+ return { status: 'failed', latencyMs: null, thresholdMs, detail: message };
168
+ }
169
+ if (typeof result.signal === 'string' && result.signal.length > 0) {
170
+ return {
171
+ status: 'failed',
172
+ latencyMs,
173
+ thresholdMs,
174
+ detail: `Initialize probe timed out or terminated with signal ${result.signal}.`
175
+ };
176
+ }
177
+ const response = parseInitializeResponse(String(result.stdout ?? ''));
178
+ if (!response.ok) {
179
+ const stderr = String(result.stderr ?? '').trim();
180
+ const detail = stderr.length > 0 ? `${response.detail} stderr=${stderr}` : response.detail;
181
+ return { status: 'failed', latencyMs, thresholdMs, detail };
182
+ }
183
+ return {
184
+ status: latencyMs > thresholdMs ? 'slow' : 'ok',
185
+ latencyMs,
186
+ thresholdMs,
187
+ detail: latencyMs > thresholdMs
188
+ ? `Initialize succeeded in ${latencyMs} ms, slower than the ${thresholdMs} ms threshold.`
189
+ : `Initialize succeeded in ${latencyMs} ms.`
190
+ };
191
+ }
192
+ export function inspectDelegateServerProcesses(options = {}) {
193
+ return inspectDelegateServerProcessBundle(options).inspection;
194
+ }
195
+ function inspectDelegateServerProcessBundle(options = {}) {
196
+ const thresholdSeconds = options.staleThresholdSeconds ?? DEFAULT_STALE_THRESHOLD_SECONDS;
197
+ const snapshotResult = options.snapshot === undefined ? readDelegateServerProcessSnapshot() : { ok: true, output: options.snapshot };
198
+ if (!snapshotResult.ok) {
199
+ return {
200
+ inspection: {
201
+ status: 'unavailable',
202
+ activeCount: 0,
203
+ staleCount: 0,
204
+ activePids: [],
205
+ stalePids: [],
206
+ staleRssKb: 0,
207
+ thresholdSeconds,
208
+ detail: snapshotResult.detail,
209
+ details: []
210
+ },
211
+ staleRecords: []
212
+ };
213
+ }
214
+ const allProcesses = parseDelegateServerProcessSnapshot(snapshotResult.output);
215
+ const processes = allProcesses.filter((record) => isDelegateServerCommand(record.command));
216
+ const processMap = new Map(allProcesses.map((record) => [record.pid, record]));
217
+ const preloadPids = resolveDelegateServerRelatedPids(processes, processMap);
218
+ const lookupProcessCwd = createProcessCwdReader(options.processCwdLookup, preloadPids);
219
+ if (processes.length === 0) {
220
+ return {
221
+ inspection: {
222
+ status: 'ok',
223
+ activeCount: 0,
224
+ staleCount: 0,
225
+ activePids: [],
226
+ stalePids: [],
227
+ staleRssKb: 0,
228
+ thresholdSeconds,
229
+ detail: 'No delegate-server processes detected.',
230
+ details: []
231
+ },
232
+ staleRecords: []
233
+ };
234
+ }
235
+ const manifestCatalog = options.manifestCatalog ?? loadDelegateServerManifestCatalog(resolveDelegateServerInspectionRepoRoot(options.repoRoot));
236
+ const manifestCatalogByWorkspace = buildManifestCatalogByWorkspace(manifestCatalog);
237
+ const drafts = processes.map((record) => buildDelegateServerProcessDraft(record, processMap, lookupProcessCwd, manifestCatalogByWorkspace));
238
+ const freshestUnassociatedPidByRootParent = resolveFreshestUnassociatedPidByRootParent(drafts);
239
+ const details = drafts.map((draft) => finalizeDelegateServerProcessDetail(draft, freshestUnassociatedPidByRootParent, thresholdSeconds));
240
+ const activePids = details
241
+ .filter((detail) => detail.classification === 'active-associated' || detail.classification === 'active-unassociated')
242
+ .map((detail) => detail.pid);
243
+ const idleDetails = details.filter((detail) => detail.classification === 'idle-parent-session' || detail.classification === 'idle-orphan');
244
+ const staleDetails = details.filter((detail) => detail.classification === 'stale-parent-session' || detail.classification === 'stale-orphan');
245
+ const stalePids = staleDetails.map((detail) => detail.pid);
246
+ const staleRecords = processes.filter((record) => stalePids.includes(record.pid));
247
+ const staleRssKb = staleDetails.reduce((sum, detail) => sum + detail.rssKb, 0);
248
+ const detail = processes.length === 0
249
+ ? 'No delegate-server processes detected.'
250
+ : stalePids.length > 0
251
+ ? buildDelegateServerInspectionDetail(idleDetails, staleDetails)
252
+ : idleDetails.length > 0
253
+ ? buildDelegateServerInspectionDetail(idleDetails, [])
254
+ : 'No stale delegate-server processes detected.';
255
+ return {
256
+ inspection: {
257
+ status: stalePids.length > 0 ? 'stale' : 'ok',
258
+ activeCount: activePids.length,
259
+ staleCount: stalePids.length,
260
+ activePids,
261
+ stalePids,
262
+ staleRssKb,
263
+ thresholdSeconds,
264
+ detail,
265
+ details
266
+ },
267
+ staleRecords
268
+ };
269
+ }
270
+ export async function cleanupStaleDelegateServerProcesses(options = {}, dependencies = {}) {
271
+ const cleanupDependencies = { ...DEFAULT_DELEGATE_SERVER_CLEANUP_DEPENDENCIES, ...dependencies };
272
+ const { inspection, staleRecords } = cleanupDependencies.inspect({
273
+ staleThresholdSeconds: options.staleThresholdSeconds,
274
+ repoRoot: options.repoRoot
275
+ });
276
+ if (!options.apply || inspection.status === 'unavailable' || inspection.stalePids.length === 0) {
277
+ return {
278
+ ...inspection,
279
+ dryRun: !options.apply,
280
+ replacedPids: [],
281
+ terminatedPids: [],
282
+ forcedPids: [],
283
+ remainingPids: inspection.stalePids
284
+ };
285
+ }
286
+ const stalePidRecords = [...staleRecords].sort((left, right) => right.pid - left.pid);
287
+ const replacedSet = new Set();
288
+ const terminatedSet = new Set();
289
+ const remainingSet = new Set();
290
+ const forcedSet = new Set();
291
+ for (const record of stalePidRecords) {
292
+ const revalidation = classifyCleanupCandidate(record, cleanupDependencies);
293
+ if (revalidation === 'missing') {
294
+ terminatedSet.add(record.pid);
295
+ continue;
296
+ }
297
+ if (revalidation === 'replaced') {
298
+ replacedSet.add(record.pid);
299
+ continue;
300
+ }
301
+ if (revalidation === 'remaining') {
302
+ remainingSet.add(record.pid);
303
+ continue;
304
+ }
305
+ const killResult = cleanupDependencies.tryKillProcess(record.pid, 'SIGTERM');
306
+ if (killResult.status === 'missing') {
307
+ terminatedSet.add(record.pid);
308
+ continue;
309
+ }
310
+ if (killResult.status === 'blocked') {
311
+ remainingSet.add(record.pid);
312
+ }
313
+ }
314
+ await cleanupDependencies.waitForMs(250);
315
+ for (const record of stalePidRecords) {
316
+ if (replacedSet.has(record.pid) || terminatedSet.has(record.pid)) {
317
+ continue;
318
+ }
319
+ const revalidation = classifyCleanupCandidate(record, cleanupDependencies);
320
+ if (revalidation === 'missing') {
321
+ remainingSet.delete(record.pid);
322
+ terminatedSet.add(record.pid);
323
+ continue;
324
+ }
325
+ if (revalidation === 'replaced') {
326
+ remainingSet.delete(record.pid);
327
+ replacedSet.add(record.pid);
328
+ continue;
329
+ }
330
+ if (revalidation === 'remaining') {
331
+ remainingSet.add(record.pid);
332
+ continue;
333
+ }
334
+ if (remainingSet.has(record.pid)) {
335
+ continue;
336
+ }
337
+ const killResult = cleanupDependencies.tryKillProcess(record.pid, 'SIGKILL');
338
+ if (killResult.status === 'signaled') {
339
+ forcedSet.add(record.pid);
340
+ continue;
341
+ }
342
+ if (killResult.status === 'missing') {
343
+ terminatedSet.add(record.pid);
344
+ continue;
345
+ }
346
+ remainingSet.add(record.pid);
347
+ }
348
+ if (forcedSet.size > 0) {
349
+ await cleanupDependencies.waitForMs(250);
350
+ }
351
+ for (const record of stalePidRecords) {
352
+ if (replacedSet.has(record.pid) || terminatedSet.has(record.pid)) {
353
+ continue;
354
+ }
355
+ const revalidation = classifyCleanupCandidate(record, cleanupDependencies);
356
+ if (revalidation === 'missing') {
357
+ remainingSet.delete(record.pid);
358
+ terminatedSet.add(record.pid);
359
+ continue;
360
+ }
361
+ if (revalidation === 'replaced') {
362
+ remainingSet.delete(record.pid);
363
+ replacedSet.add(record.pid);
364
+ continue;
365
+ }
366
+ remainingSet.add(record.pid);
367
+ }
368
+ const stalePids = stalePidRecords.map((record) => record.pid);
369
+ const forcedPids = stalePids.filter((pid) => forcedSet.has(pid));
370
+ const terminatedPids = stalePids.filter((pid) => !forcedSet.has(pid) && terminatedSet.has(pid));
371
+ const replacedPids = stalePids.filter((pid) => !forcedSet.has(pid) && !terminatedSet.has(pid) && replacedSet.has(pid));
372
+ const remainingPids = stalePids.filter((pid) => !forcedSet.has(pid) && !terminatedSet.has(pid) && !replacedSet.has(pid) && remainingSet.has(pid));
373
+ return {
374
+ ...inspection,
375
+ dryRun: false,
376
+ replacedPids,
377
+ terminatedPids,
378
+ forcedPids,
379
+ remainingPids
380
+ };
381
+ }
382
+ export function formatDelegateServerCleanupSummary(result) {
383
+ const lines = [];
384
+ const operationLabel = result.status === 'unavailable'
385
+ ? 'unavailable'
386
+ : result.dryRun
387
+ ? 'planned'
388
+ : result.staleCount === 0
389
+ ? 'clean'
390
+ : result.remainingPids.length === 0
391
+ ? 'applied'
392
+ : 'partial';
393
+ lines.push(`Delegation cleanup: ${operationLabel}`);
394
+ lines.push(`- Active delegate-server processes: ${result.activeCount}`);
395
+ lines.push(`- Stale delegate-server processes: ${result.staleCount} (threshold ${(result.thresholdSeconds / 60).toFixed(0)}m, rss ${(result.staleRssKb / 1024).toFixed(1)} MB)`);
396
+ if (result.stalePids.length > 0) {
397
+ lines.push(`- Stale pids: ${result.stalePids.join(', ')}`);
398
+ }
399
+ if (result.replacedPids.length > 0) {
400
+ lines.push(`- Replaced pids: ${result.replacedPids.join(', ')}`);
401
+ }
402
+ if (result.terminatedPids.length > 0) {
403
+ lines.push(`- Terminated pids: ${result.terminatedPids.join(', ')}`);
404
+ }
405
+ if (result.forcedPids.length > 0) {
406
+ lines.push(`- Force-killed pids: ${result.forcedPids.join(', ')}`);
407
+ }
408
+ if (result.remainingPids.length > 0) {
409
+ lines.push(`- Remaining pids: ${result.remainingPids.join(', ')}`);
410
+ }
411
+ lines.push(`- Detail: ${result.detail}`);
412
+ const staleDetails = result.details.filter((detail) => detail.classification === 'stale-parent-session' || detail.classification === 'stale-orphan');
413
+ for (const detail of staleDetails.slice(0, 3)) {
414
+ lines.push(`- Stale detail: ${formatDelegateServerProcessSummary({
415
+ pid: detail.pid,
416
+ classification: detail.classification,
417
+ cwd: detail.cwd,
418
+ parentPid: detail.parentPid,
419
+ parentCwd: detail.parentCwd,
420
+ rootCodexParentPid: detail.rootCodexParentPid,
421
+ rootCodexParentCwd: detail.rootCodexParentCwd,
422
+ manifestPath: detail.manifestAssociation?.manifestPath ?? null
423
+ })}`);
424
+ }
425
+ if (result.dryRun && result.status !== 'unavailable') {
426
+ lines.push('Run with --yes to terminate stale delegate-server processes.');
427
+ }
428
+ return lines;
429
+ }
430
+ export function readPinnedRepo(args) {
431
+ const index = args.indexOf('--repo');
432
+ if (index === -1) {
433
+ return null;
434
+ }
435
+ const candidate = args[index + 1];
436
+ return typeof candidate === 'string' && candidate.trim().length > 0 ? candidate.trim() : null;
437
+ }
438
+ function readDelegationMcpServer(codexBin, env) {
439
+ const result = spawnSync(codexBin, ['mcp', 'get', 'delegation', '--json'], {
440
+ encoding: 'utf8',
441
+ stdio: ['ignore', 'pipe', 'pipe'],
442
+ timeout: 5000,
443
+ env
444
+ });
445
+ if (result.error || result.status !== 0) {
446
+ return null;
447
+ }
448
+ const stdout = String(result.stdout ?? '').trim();
449
+ if (!stdout) {
450
+ return null;
451
+ }
452
+ try {
453
+ const parsed = JSON.parse(stdout);
454
+ const transport = parsed.transport;
455
+ const command = typeof transport?.command === 'string' ? transport.command : null;
456
+ const args = Array.isArray(transport?.args)
457
+ ? transport.args.filter((value) => typeof value === 'string')
458
+ : [];
459
+ const envVars = {};
460
+ const envRecord = transport?.env;
461
+ if (envRecord && typeof envRecord === 'object' && !Array.isArray(envRecord)) {
462
+ for (const [key, value] of Object.entries(envRecord)) {
463
+ if (typeof value === 'string') {
464
+ envVars[key] = value;
465
+ }
466
+ }
467
+ }
468
+ return { command, args, envVars, pinnedRepo: readPinnedRepo(args) };
469
+ }
470
+ catch {
471
+ return null;
472
+ }
473
+ }
474
+ function findDelegateServerIndex(args) {
475
+ return args.findIndex((arg) => arg === 'delegate-server' || arg === 'delegation-server');
476
+ }
477
+ function isDirectDistDelegateServer(command, args, delegateIndex) {
478
+ if (command && isDistCodexOrchestratorPath(command) && delegateIndex === 0) {
479
+ return true;
480
+ }
481
+ const precedingToken = delegateIndex > 0 ? args[delegateIndex - 1] : null;
482
+ return precedingToken ? isDistCodexOrchestratorPath(precedingToken) : false;
483
+ }
484
+ function isWrapperDelegateServer(command, args, delegateIndex) {
485
+ if (command && isCodexOrchestratorWrapperPath(command) && delegateIndex === 0) {
486
+ return true;
487
+ }
488
+ const precedingToken = delegateIndex > 0 ? args[delegateIndex - 1] : null;
489
+ return precedingToken ? isCodexOrchestratorWrapperPath(precedingToken) : false;
490
+ }
491
+ function isDistCodexOrchestratorPath(candidate) {
492
+ return /(?:^|[/\\])dist[/\\]bin[/\\]codex-orchestrator\.js$/u.test(candidate);
493
+ }
494
+ function isCodexOrchestratorWrapperPath(candidate) {
495
+ if (isDistCodexOrchestratorPath(candidate)) {
496
+ return false;
497
+ }
498
+ const token = basenameFromCommandToken(candidate);
499
+ return token === 'codex-orchestrator' || token === 'codex-orchestrator.js';
500
+ }
501
+ function basenameFromCommandToken(token) {
502
+ return basename(token.replace(/\\/gu, '/'));
503
+ }
504
+ function parseInitializeResponse(stdout) {
505
+ const lines = stdout
506
+ .split(/\r?\n/u)
507
+ .map((line) => line.trim())
508
+ .filter((line) => line.length > 0);
509
+ const responseLine = [...lines].reverse().find((line) => line.startsWith('{'));
510
+ if (!responseLine) {
511
+ return { ok: false, detail: 'Initialize probe did not emit a JSON-RPC response.' };
512
+ }
513
+ try {
514
+ const parsed = JSON.parse(responseLine);
515
+ const result = parsed.result;
516
+ if (parsed.id !== 1 || !result || typeof result.protocolVersion !== 'string') {
517
+ return { ok: false, detail: 'Initialize probe returned an unexpected JSON-RPC payload.' };
518
+ }
519
+ return { ok: true };
520
+ }
521
+ catch (error) {
522
+ return {
523
+ ok: false,
524
+ detail: error instanceof Error ? error.message : 'Failed to parse initialize probe response.'
525
+ };
526
+ }
527
+ }
528
+ function readDelegateServerProcessSnapshot() {
529
+ const result = spawnSync('ps', ['-ax', '-o', 'pid=,ppid=,etime=,rss=,args='], {
530
+ encoding: 'utf8',
531
+ stdio: ['ignore', 'pipe', 'pipe'],
532
+ timeout: 5000
533
+ });
534
+ if (result.error) {
535
+ return { ok: false, detail: result.error.message };
536
+ }
537
+ if (result.status !== 0) {
538
+ const stderr = String(result.stderr ?? '').trim();
539
+ return { ok: false, detail: stderr || `ps exited with code ${result.status ?? 'unknown'}` };
540
+ }
541
+ return { ok: true, output: String(result.stdout ?? '') };
542
+ }
543
+ function readDelegateServerProcessRecord(pid) {
544
+ const result = spawnSync('ps', ['-p', String(pid), '-o', 'pid=,ppid=,etime=,rss=,args='], {
545
+ encoding: 'utf8',
546
+ stdio: ['ignore', 'pipe', 'pipe'],
547
+ timeout: 5000
548
+ });
549
+ if (result.error || result.status !== 0) {
550
+ return null;
551
+ }
552
+ return parseDelegateServerProcessSnapshot(String(result.stdout ?? ''))[0] ?? null;
553
+ }
554
+ function parseDelegateServerProcessSnapshot(snapshot) {
555
+ const records = [];
556
+ for (const line of snapshot.split(/\r?\n/u)) {
557
+ const match = line.match(/^\s*(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+(.*)$/u);
558
+ if (!match) {
559
+ continue;
560
+ }
561
+ const pid = Number(match[1]);
562
+ const ppid = Number(match[2]);
563
+ const elapsedSeconds = parseElapsedSeconds(match[3] ?? '');
564
+ const rssKb = Number(match[4] ?? '0');
565
+ const command = (match[5] ?? '').trim();
566
+ if (!Number.isInteger(pid) || !Number.isInteger(ppid) || !command) {
567
+ continue;
568
+ }
569
+ records.push({ pid, ppid, elapsedSeconds, rssKb: Number.isFinite(rssKb) ? rssKb : 0, command });
570
+ }
571
+ return records;
572
+ }
573
+ function isDelegateServerCommand(command) {
574
+ if (command.includes('mcp add delegation') || command.includes('mcp get delegation')) {
575
+ return false;
576
+ }
577
+ const args = parseShellStyleArguments(command);
578
+ const delegateIndex = findDelegateServerIndex(args);
579
+ if (delegateIndex === -1) {
580
+ return false;
581
+ }
582
+ if (args.some((arg) => arg === 'mcp') && args.some((arg) => arg === 'add')) {
583
+ return false;
584
+ }
585
+ const precedingToken = delegateIndex > 0 ? args[delegateIndex - 1] ?? null : null;
586
+ if (precedingToken && (isDistCodexOrchestratorPath(precedingToken) || isCodexOrchestratorWrapperPath(precedingToken))) {
587
+ return delegateIndex === 1 || args.slice(0, delegateIndex - 1).some((arg) => isNodeLauncherToken(arg));
588
+ }
589
+ return delegateIndex === 1 && isCodexOrchestratorWrapperPath(args[0] ?? '');
590
+ }
591
+ function resolveDelegateServerRootCodexParent(record, processMap) {
592
+ let current = record;
593
+ const visited = new Set();
594
+ while (current && !visited.has(current.pid)) {
595
+ visited.add(current.pid);
596
+ if (isCodexClientCommand(current.command)) {
597
+ return current;
598
+ }
599
+ if (current.ppid <= 1) {
600
+ return null;
601
+ }
602
+ current = processMap.get(current.ppid);
603
+ }
604
+ return null;
605
+ }
606
+ function isCodexClientCommand(command) {
607
+ const args = parseShellStyleArguments(command);
608
+ const recognizedBasenames = buildRecognizedCodexClientBasenames();
609
+ return args.some((arg) => recognizedBasenames.has(basenameFromCommandToken(arg).toLowerCase()));
610
+ }
611
+ function buildRecognizedCodexClientBasenames(env = process.env) {
612
+ const basenames = new Set(['codex', 'codex.exe', 'codex.cmd']);
613
+ try {
614
+ basenames.add(basenameFromCommandToken(resolveCodexCliBin(env)).toLowerCase());
615
+ }
616
+ catch {
617
+ // Ignore local codex binary resolution failures and keep the default names.
618
+ }
619
+ return basenames;
620
+ }
621
+ function isNodeLauncherToken(token) {
622
+ const normalized = basenameFromCommandToken(token).toLowerCase();
623
+ return normalized === 'node'
624
+ || normalized === 'node.exe'
625
+ || normalized === 'nodejs'
626
+ || normalized === 'nodejs.exe';
627
+ }
628
+ function createProcessCwdReader(seed, preloadPids = []) {
629
+ const cache = new Map();
630
+ if (seed) {
631
+ for (const [key, value] of Object.entries(seed)) {
632
+ const pid = Number.parseInt(key, 10);
633
+ if (Number.isInteger(pid)) {
634
+ cache.set(pid, value);
635
+ }
636
+ }
637
+ }
638
+ const missingPids = preloadPids.filter((pid, index, values) => {
639
+ return Number.isInteger(pid) && pid > 0 && !cache.has(pid) && values.indexOf(pid) === index;
640
+ });
641
+ if (missingPids.length > 0) {
642
+ for (const [pid, cwd] of readProcessCwds(missingPids)) {
643
+ cache.set(pid, cwd);
644
+ }
645
+ }
646
+ return (pid) => {
647
+ if (cache.has(pid)) {
648
+ return cache.get(pid) ?? null;
649
+ }
650
+ const cwd = readProcessCwd(pid);
651
+ cache.set(pid, cwd);
652
+ return cwd;
653
+ };
654
+ }
655
+ function resolveDelegateServerRelatedPids(processes, processMap) {
656
+ const related = new Set();
657
+ for (const record of processes) {
658
+ let current = record;
659
+ const seen = new Set();
660
+ while (current && !seen.has(current.pid)) {
661
+ seen.add(current.pid);
662
+ related.add(current.pid);
663
+ current = processMap.get(current.ppid) ?? null;
664
+ }
665
+ }
666
+ return [...related];
667
+ }
668
+ function readProcessCwds(pids) {
669
+ const results = new Map();
670
+ for (const chunk of chunkProcessIds(pids, 128)) {
671
+ const result = spawnSync('lsof', ['-a', '-d', 'cwd', '-Fpfn', '-p', chunk.join(',')], {
672
+ encoding: 'utf8',
673
+ stdio: ['ignore', 'pipe', 'pipe'],
674
+ timeout: 1000
675
+ });
676
+ if (result.error || result.status !== 0) {
677
+ continue;
678
+ }
679
+ let currentPid = null;
680
+ for (const rawLine of String(result.stdout ?? '').split(/\r?\n/u)) {
681
+ const line = rawLine.trim();
682
+ if (!line) {
683
+ continue;
684
+ }
685
+ if (line.startsWith('p')) {
686
+ const parsedPid = Number.parseInt(line.slice(1), 10);
687
+ currentPid = Number.isInteger(parsedPid) ? parsedPid : null;
688
+ continue;
689
+ }
690
+ if (line.startsWith('n') && currentPid !== null) {
691
+ const cwd = line.slice(1).trim();
692
+ results.set(currentPid, cwd.length > 0 ? cwd : null);
693
+ }
694
+ }
695
+ }
696
+ return results;
697
+ }
698
+ function chunkProcessIds(pids, chunkSize) {
699
+ const chunks = [];
700
+ for (let index = 0; index < pids.length; index += chunkSize) {
701
+ chunks.push(pids.slice(index, index + chunkSize));
702
+ }
703
+ return chunks;
704
+ }
705
+ function resolveDelegateServerInspectionRepoRoot(repoRoot) {
706
+ const configuredRoot = normalizeRepoRootHint(repoRoot);
707
+ if (configuredRoot) {
708
+ return collapseWorkspaceRepoRoot(resolveRepoRootFromHint(configuredRoot));
709
+ }
710
+ const envRoot = normalizeRepoRootHint(process.env.CODEX_ORCHESTRATOR_ROOT);
711
+ if (envRoot) {
712
+ return collapseWorkspaceRepoRoot(resolveRepoRootFromHint(envRoot));
713
+ }
714
+ const cwd = normalizeRepoRootHint(process.cwd());
715
+ if (cwd) {
716
+ return collapseWorkspaceRepoRoot(resolveRepoRootFromHint(cwd));
717
+ }
718
+ try {
719
+ return collapseWorkspaceRepoRoot(findPackageRoot(import.meta.url));
720
+ }
721
+ catch {
722
+ return collapseWorkspaceRepoRoot(process.cwd());
723
+ }
724
+ }
725
+ function normalizeRepoRootHint(value) {
726
+ if (typeof value !== 'string') {
727
+ return null;
728
+ }
729
+ const trimmed = value.trim();
730
+ return trimmed.length > 0 ? trimmed : null;
731
+ }
732
+ function resolveRepoRootFromHint(rootHint) {
733
+ const normalizedHint = resolve(rootHint);
734
+ const gitBoundary = findNearestGitBoundary(normalizedHint);
735
+ let current = normalizedHint;
736
+ while (current) {
737
+ if (existsSync(join(current, 'tasks', 'index.json'))) {
738
+ return current;
739
+ }
740
+ if (gitBoundary && current === gitBoundary) {
741
+ break;
742
+ }
743
+ const parent = dirname(current);
744
+ if (parent === current) {
745
+ break;
746
+ }
747
+ current = parent;
748
+ }
749
+ return gitBoundary ?? normalizedHint;
750
+ }
751
+ function findNearestGitBoundary(start) {
752
+ let current = resolve(start);
753
+ while (current) {
754
+ if (existsSync(join(current, '.git'))) {
755
+ return current;
756
+ }
757
+ const parent = dirname(current);
758
+ if (parent === current) {
759
+ break;
760
+ }
761
+ current = parent;
762
+ }
763
+ return null;
764
+ }
765
+ function collapseWorkspaceRepoRoot(candidate) {
766
+ const resolved = resolve(candidate);
767
+ const normalized = resolved.replace(/\\/gu, '/');
768
+ const marker = '/.workspaces/';
769
+ const markerIndex = normalized.indexOf(marker);
770
+ if (markerIndex === -1) {
771
+ return resolved;
772
+ }
773
+ return resolved.slice(0, markerIndex) || resolved;
774
+ }
775
+ function isPathWithinRoot(root, candidate) {
776
+ const relativePath = relative(root, candidate);
777
+ return relativePath === ''
778
+ || (!relativePath.startsWith('..') && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath));
779
+ }
780
+ function readProcessCwd(pid) {
781
+ const result = spawnSync('lsof', ['-a', '-d', 'cwd', '-Fn', '-p', String(pid)], {
782
+ encoding: 'utf8',
783
+ stdio: ['ignore', 'pipe', 'pipe'],
784
+ timeout: 3000
785
+ });
786
+ if (result.error || result.status !== 0) {
787
+ return null;
788
+ }
789
+ const line = String(result.stdout ?? '')
790
+ .split(/\r?\n/u)
791
+ .map((value) => value.trim())
792
+ .find((value) => value.startsWith('n'));
793
+ if (!line) {
794
+ return null;
795
+ }
796
+ const cwd = line.slice(1).trim();
797
+ return cwd.length > 0 ? cwd : null;
798
+ }
799
+ function loadDelegateServerManifestCatalog(repoRoot) {
800
+ const catalog = [];
801
+ for (const runsRoot of resolveDelegateServerManifestCatalogRunsRoots(repoRoot, repoRoot)) {
802
+ collectManifestCatalogFromRunsRoot(runsRoot, catalog);
803
+ }
804
+ const workspacesRoot = join(repoRoot, '.workspaces');
805
+ if (existsSync(workspacesRoot)) {
806
+ for (const entry of readDirectoryEntriesSafe(workspacesRoot)) {
807
+ if (!entry.isDirectory()) {
808
+ continue;
809
+ }
810
+ const workspaceRoot = join(workspacesRoot, entry.name);
811
+ for (const runsRoot of resolveDelegateServerManifestCatalogRunsRoots(repoRoot, workspaceRoot)) {
812
+ collectManifestCatalogFromRunsRoot(runsRoot, catalog);
813
+ }
814
+ const childLanesRoot = join(workspaceRoot, '.child-lanes');
815
+ if (!existsSync(childLanesRoot)) {
816
+ continue;
817
+ }
818
+ for (const childLaneEntry of readDirectoryEntriesSafe(childLanesRoot)) {
819
+ if (!childLaneEntry.isDirectory()) {
820
+ continue;
821
+ }
822
+ const childLaneRoot = join(childLanesRoot, childLaneEntry.name);
823
+ for (const runsRoot of resolveDelegateServerManifestCatalogRunsRoots(repoRoot, childLaneRoot)) {
824
+ collectManifestCatalogFromRunsRoot(runsRoot, catalog);
825
+ }
826
+ }
827
+ }
828
+ }
829
+ return catalog;
830
+ }
831
+ function resolveDelegateServerManifestCatalogRunsRoots(sharedRoot, ownerRoot) {
832
+ const runsRoots = new Set([join(ownerRoot, '.runs')]);
833
+ const configured = normalizeRepoRootHint(process.env.CODEX_ORCHESTRATOR_RUNS_DIR);
834
+ if (!configured) {
835
+ return [...runsRoots];
836
+ }
837
+ const configuredRunsRoot = isAbsolute(configured) ? resolve(configured) : resolve(sharedRoot, configured);
838
+ if (ownerRoot === sharedRoot) {
839
+ runsRoots.add(configuredRunsRoot);
840
+ return [...runsRoots];
841
+ }
842
+ if (isPathWithinRoot(sharedRoot, configuredRunsRoot)) {
843
+ runsRoots.add(resolve(ownerRoot, relative(sharedRoot, configuredRunsRoot)));
844
+ }
845
+ return [...runsRoots];
846
+ }
847
+ function collectManifestCatalogFromRunsRoot(root, catalog) {
848
+ if (!existsSync(root)) {
849
+ return;
850
+ }
851
+ for (const taskEntry of readDirectoryEntriesSafe(root)) {
852
+ if (!taskEntry.isDirectory()) {
853
+ continue;
854
+ }
855
+ const taskRoot = join(root, taskEntry.name);
856
+ const cliRoot = join(taskRoot, 'cli');
857
+ if (existsSync(cliRoot)) {
858
+ for (const runEntry of readDirectoryEntriesSafe(cliRoot)) {
859
+ if (!runEntry.isDirectory()) {
860
+ continue;
861
+ }
862
+ const manifestPath = join(cliRoot, runEntry.name, 'manifest.json');
863
+ const association = readManifestAssociation(manifestPath);
864
+ if (association) {
865
+ catalog.push(association);
866
+ }
867
+ }
868
+ continue;
869
+ }
870
+ for (const runEntry of readDirectoryEntriesSafe(taskRoot)) {
871
+ if (!runEntry.isDirectory()) {
872
+ continue;
873
+ }
874
+ const manifestPath = join(taskRoot, runEntry.name, 'manifest.json');
875
+ const association = readManifestAssociation(manifestPath);
876
+ if (association) {
877
+ catalog.push(association);
878
+ }
879
+ }
880
+ }
881
+ }
882
+ function readDirectoryEntriesSafe(root) {
883
+ try {
884
+ return readdirSync(root, { withFileTypes: true });
885
+ }
886
+ catch {
887
+ return [];
888
+ }
889
+ }
890
+ function readManifestAssociation(manifestPath) {
891
+ if (!existsSync(manifestPath)) {
892
+ return null;
893
+ }
894
+ try {
895
+ const parsed = JSON.parse(readFileSync(manifestPath, 'utf8'));
896
+ return {
897
+ manifestPath,
898
+ workspacePath: normalizeOptionalString(parsed.workspace_path),
899
+ status: normalizeOptionalString(parsed.status),
900
+ pipelineId: normalizeOptionalString(parsed.pipeline_id),
901
+ taskId: normalizeOptionalString(parsed.task_id),
902
+ runId: normalizeOptionalString(parsed.run_id),
903
+ issueId: normalizeOptionalString(parsed.issue_id),
904
+ issueIdentifier: normalizeOptionalString(parsed.issue_identifier),
905
+ proofPid: readManifestProofPid(manifestPath)
906
+ };
907
+ }
908
+ catch {
909
+ return null;
910
+ }
911
+ }
912
+ function readManifestProofPid(manifestPath) {
913
+ const runRoot = dirname(manifestPath);
914
+ const proofPath = join(runRoot, 'provider-linear-worker-proof.json');
915
+ if (!existsSync(proofPath)) {
916
+ return null;
917
+ }
918
+ try {
919
+ const parsed = JSON.parse(readFileSync(proofPath, 'utf8'));
920
+ return parsePositiveInteger(parsed.pid);
921
+ }
922
+ catch {
923
+ return null;
924
+ }
925
+ }
926
+ function parsePositiveInteger(value) {
927
+ if (typeof value === 'number') {
928
+ return Number.isInteger(value) && value > 0 ? value : null;
929
+ }
930
+ if (typeof value !== 'string') {
931
+ return null;
932
+ }
933
+ const trimmed = value.trim();
934
+ if (!/^\d+$/u.test(trimmed)) {
935
+ return null;
936
+ }
937
+ const parsed = Number.parseInt(trimmed, 10);
938
+ return parsed > 0 ? parsed : null;
939
+ }
940
+ function buildManifestCatalogByWorkspace(catalog) {
941
+ const byWorkspace = new Map();
942
+ for (const association of catalog) {
943
+ if (!association.workspacePath) {
944
+ continue;
945
+ }
946
+ const existing = byWorkspace.get(association.workspacePath) ?? [];
947
+ existing.push(association);
948
+ byWorkspace.set(association.workspacePath, existing);
949
+ }
950
+ return byWorkspace;
951
+ }
952
+ function resolveManifestCandidatesForWorkspace(workspacePath, manifestCatalogByWorkspace) {
953
+ const exactCandidates = manifestCatalogByWorkspace.get(workspacePath);
954
+ if (exactCandidates && exactCandidates.length > 0) {
955
+ return exactCandidates;
956
+ }
957
+ const fallbackWorkspaceRoot = [...manifestCatalogByWorkspace.keys()]
958
+ .filter((candidateWorkspacePath) => isPathWithinWorkspaceRoot(candidateWorkspacePath, workspacePath))
959
+ .sort((left, right) => right.length - left.length)[0];
960
+ if (!fallbackWorkspaceRoot) {
961
+ return [];
962
+ }
963
+ return manifestCatalogByWorkspace.get(fallbackWorkspaceRoot) ?? [];
964
+ }
965
+ function resolveScopedManifestCandidatesForWorkspace(workspacePath, manifestCatalogByWorkspace) {
966
+ const exactCandidates = manifestCatalogByWorkspace.get(workspacePath);
967
+ if (exactCandidates && exactCandidates.length > 0) {
968
+ return exactCandidates;
969
+ }
970
+ const fallbackWorkspaceRoot = [...manifestCatalogByWorkspace.keys()]
971
+ .filter((candidateWorkspacePath) => candidateWorkspacePath !== workspacePath
972
+ && isScopedWorkspacePath(candidateWorkspacePath)
973
+ && isPathWithinWorkspaceRoot(candidateWorkspacePath, workspacePath))
974
+ .sort((left, right) => right.length - left.length)[0];
975
+ if (!fallbackWorkspaceRoot) {
976
+ return [];
977
+ }
978
+ return manifestCatalogByWorkspace.get(fallbackWorkspaceRoot) ?? [];
979
+ }
980
+ function buildDelegateServerProcessDraft(record, processMap, readProcessCwdValue, manifestCatalogByWorkspace) {
981
+ const parentRecord = processMap.get(record.ppid) ?? null;
982
+ const rootCodexParent = resolveDelegateServerRootCodexParent(record, processMap);
983
+ const cwd = readProcessCwdValue(record.pid);
984
+ const parentCwd = parentRecord ? readProcessCwdValue(parentRecord.pid) : null;
985
+ const rootCodexParentCwd = rootCodexParent ? readProcessCwdValue(rootCodexParent.pid) : null;
986
+ const ancestryPids = resolveProcessAncestryPids(record, processMap);
987
+ const candidateWorkspaces = [cwd, parentCwd, rootCodexParentCwd];
988
+ const cwdLookupAvailable = candidateWorkspaces.some((workspacePath) => workspacePath !== null);
989
+ return {
990
+ record,
991
+ cwd,
992
+ parentRecord,
993
+ parentCwd,
994
+ rootCodexParent,
995
+ rootCodexParentCwd,
996
+ cwdLookupAvailable,
997
+ ancestryPids,
998
+ manifestAssociation: cwdLookupAvailable
999
+ ? resolveManifestAssociationForProcess(candidateWorkspaces, ancestryPids, manifestCatalogByWorkspace)
1000
+ : resolveManifestAssociationByAncestry(ancestryPids, manifestCatalogByWorkspace)
1001
+ };
1002
+ }
1003
+ function resolveProcessAncestryPids(record, processMap) {
1004
+ const ancestry = [];
1005
+ const seen = new Set();
1006
+ let current = record;
1007
+ while (current && !seen.has(current.pid)) {
1008
+ ancestry.push(current.pid);
1009
+ seen.add(current.pid);
1010
+ current = processMap.get(current.ppid) ?? null;
1011
+ }
1012
+ return ancestry;
1013
+ }
1014
+ function resolveManifestAssociationForProcess(candidateWorkspaces, ancestryPids, manifestCatalogByWorkspace) {
1015
+ const ancestryPidSet = new Set(ancestryPids);
1016
+ for (const workspacePath of candidateWorkspaces) {
1017
+ if (!workspacePath) {
1018
+ continue;
1019
+ }
1020
+ const scopedCandidates = isScopedWorkspacePath(workspacePath)
1021
+ ? resolveScopedManifestCandidatesForWorkspace(workspacePath, manifestCatalogByWorkspace)
1022
+ : [];
1023
+ const candidates = scopedCandidates.length > 0
1024
+ ? scopedCandidates
1025
+ : resolveManifestCandidatesForWorkspace(workspacePath, manifestCatalogByWorkspace);
1026
+ if (!candidates || candidates.length === 0) {
1027
+ continue;
1028
+ }
1029
+ const exactAncestryMatch = candidates
1030
+ .filter((candidate) => candidate.proofPid !== null && ancestryPidSet.has(candidate.proofPid))
1031
+ .sort(compareManifestAssociations)[0];
1032
+ if (exactAncestryMatch) {
1033
+ return exactAncestryMatch;
1034
+ }
1035
+ if (isScopedWorkspacePath(workspacePath) && scopedCandidates.length > 0) {
1036
+ const scopedFallback = resolveScopedWorkspaceFallbackAssociation(scopedCandidates);
1037
+ if (scopedFallback) {
1038
+ return scopedFallback;
1039
+ }
1040
+ }
1041
+ }
1042
+ return null;
1043
+ }
1044
+ function resolveManifestAssociationByAncestry(ancestryPids, manifestCatalogByWorkspace) {
1045
+ const ancestryPidSet = new Set(ancestryPids);
1046
+ const matches = [...manifestCatalogByWorkspace.values()]
1047
+ .flat()
1048
+ .filter((candidate) => candidate.proofPid !== null && ancestryPidSet.has(candidate.proofPid))
1049
+ .sort(compareManifestAssociations);
1050
+ if (matches.length === 0) {
1051
+ return null;
1052
+ }
1053
+ const workspaceKeys = new Set(matches.map((candidate) => candidate.workspacePath ?? `manifest:${candidate.manifestPath}`));
1054
+ if (workspaceKeys.size > 1) {
1055
+ return null;
1056
+ }
1057
+ return matches[0] ?? null;
1058
+ }
1059
+ function isScopedWorkspacePath(workspacePath) {
1060
+ const normalized = workspacePath.replace(/\\/gu, '/');
1061
+ return normalized.includes('/.workspaces/') || normalized.includes('/.child-lanes/');
1062
+ }
1063
+ function isPathWithinWorkspaceRoot(root, candidate) {
1064
+ const normalizedRoot = normalizePathForComparison(root);
1065
+ const normalizedCandidate = normalizePathForComparison(candidate);
1066
+ return normalizedCandidate === normalizedRoot || normalizedCandidate.startsWith(`${normalizedRoot}/`);
1067
+ }
1068
+ function normalizePathForComparison(value) {
1069
+ return value.replace(/\\/gu, '/').replace(/\/+$/u, '');
1070
+ }
1071
+ function resolveScopedWorkspaceFallbackAssociation(candidates) {
1072
+ if (candidates.length === 0) {
1073
+ return null;
1074
+ }
1075
+ const liveCandidates = candidates.filter((candidate) => !isTerminalManifestStatus(candidate.status));
1076
+ const terminalCandidates = candidates.filter((candidate) => isTerminalManifestStatus(candidate.status));
1077
+ if (liveCandidates.length === 0) {
1078
+ return [...terminalCandidates].sort(compareManifestAssociations)[0] ?? null;
1079
+ }
1080
+ if (terminalCandidates.length === 0) {
1081
+ return [...liveCandidates].sort(compareManifestAssociations)[0] ?? null;
1082
+ }
1083
+ if (liveCandidates.every((candidate) => candidate.proofPid !== null)) {
1084
+ return [...terminalCandidates].sort(compareManifestAssociations)[0] ?? null;
1085
+ }
1086
+ return null;
1087
+ }
1088
+ function compareManifestAssociations(left, right) {
1089
+ const leftTerminal = isTerminalManifestStatus(left.status);
1090
+ const rightTerminal = isTerminalManifestStatus(right.status);
1091
+ if (leftTerminal !== rightTerminal) {
1092
+ return leftTerminal ? 1 : -1;
1093
+ }
1094
+ return (right.runId ?? '').localeCompare(left.runId ?? '');
1095
+ }
1096
+ function isTerminalManifestStatus(status) {
1097
+ return status === 'succeeded'
1098
+ || status === 'failed'
1099
+ || status === 'cancelled'
1100
+ || status === 'canceled'
1101
+ || status === 'done';
1102
+ }
1103
+ function resolveFreshestUnassociatedPidByRootParent(drafts) {
1104
+ const freshest = new Map();
1105
+ for (const draft of drafts) {
1106
+ if (!draft.rootCodexParent || draft.manifestAssociation) {
1107
+ continue;
1108
+ }
1109
+ const rootPid = draft.rootCodexParent.pid;
1110
+ const currentPid = freshest.get(rootPid);
1111
+ if (currentPid === undefined) {
1112
+ freshest.set(rootPid, draft.record.pid);
1113
+ continue;
1114
+ }
1115
+ const currentDraft = drafts.find((candidate) => candidate.record.pid === currentPid) ?? null;
1116
+ if (!currentDraft) {
1117
+ freshest.set(rootPid, draft.record.pid);
1118
+ continue;
1119
+ }
1120
+ const currentAge = currentDraft.record.elapsedSeconds ?? Number.MAX_SAFE_INTEGER;
1121
+ const nextAge = draft.record.elapsedSeconds ?? Number.MAX_SAFE_INTEGER;
1122
+ if (nextAge < currentAge || (nextAge === currentAge && draft.record.pid > currentDraft.record.pid)) {
1123
+ freshest.set(rootPid, draft.record.pid);
1124
+ }
1125
+ }
1126
+ return freshest;
1127
+ }
1128
+ function finalizeDelegateServerProcessDetail(draft, freshestUnassociatedPidByRootParent, thresholdSeconds) {
1129
+ const association = draft.manifestAssociation;
1130
+ let classification = 'active-unassociated';
1131
+ let classificationDetail = 'delegate-server is still rooted in a live codex session.';
1132
+ if (!draft.rootCodexParent) {
1133
+ if (draft.record.elapsedSeconds !== null && draft.record.elapsedSeconds >= thresholdSeconds) {
1134
+ classification = 'stale-orphan';
1135
+ classificationDetail = 'delegate-server is no longer rooted in a live codex parent and exceeded the stale threshold.';
1136
+ }
1137
+ else {
1138
+ classification = 'idle-orphan';
1139
+ classificationDetail = 'delegate-server is not rooted in a live codex parent and is still within the stale threshold.';
1140
+ }
1141
+ }
1142
+ else if (association && !isTerminalManifestStatus(association.status)) {
1143
+ classification = 'active-associated';
1144
+ classificationDetail = `delegate-server is rooted in codex parent ${draft.rootCodexParent.pid} and matches live manifest ${association.manifestPath}.`;
1145
+ }
1146
+ else if (association && isTerminalManifestStatus(association.status)) {
1147
+ if (draft.record.elapsedSeconds !== null && draft.record.elapsedSeconds >= thresholdSeconds) {
1148
+ classification = 'stale-parent-session';
1149
+ classificationDetail = `delegate-server is still parented by codex pid ${draft.rootCodexParent.pid}, but the matched manifest ${association.manifestPath} is terminal (${association.status ?? 'unknown'}).`;
1150
+ }
1151
+ else {
1152
+ classification = 'idle-parent-session';
1153
+ classificationDetail = `delegate-server matches terminal manifest ${association.manifestPath} but is still below the stale threshold.`;
1154
+ }
1155
+ }
1156
+ else if (!draft.cwdLookupAvailable) {
1157
+ classificationDetail =
1158
+ `delegate-server is rooted in live codex parent ${draft.rootCodexParent.pid}, but cwd lookup was unavailable so manifest association could not be determined.`;
1159
+ }
1160
+ else {
1161
+ const freshestPid = freshestUnassociatedPidByRootParent.get(draft.rootCodexParent.pid) ?? null;
1162
+ if (freshestPid !== null && freshestPid !== draft.record.pid) {
1163
+ if (draft.record.elapsedSeconds !== null && draft.record.elapsedSeconds >= thresholdSeconds) {
1164
+ classification = 'stale-parent-session';
1165
+ classificationDetail =
1166
+ `delegate-server is an older sibling under live codex parent ${draft.rootCodexParent.pid}; pid ${freshestPid} is the freshest unassociated sibling kept active.`;
1167
+ }
1168
+ else {
1169
+ classification = 'idle-parent-session';
1170
+ classificationDetail =
1171
+ `delegate-server is an older sibling under live codex parent ${draft.rootCodexParent.pid} and remains below the stale threshold while pid ${freshestPid} stays active.`;
1172
+ }
1173
+ }
1174
+ else if (draft.record.elapsedSeconds !== null && draft.record.elapsedSeconds >= thresholdSeconds) {
1175
+ classification = 'idle-parent-session';
1176
+ classificationDetail =
1177
+ `delegate-server is the freshest unassociated sibling under live codex parent ${draft.rootCodexParent.pid}; it exceeded the stale threshold without a live manifest association, but no fresher sibling displaced it.`;
1178
+ }
1179
+ else {
1180
+ classificationDetail =
1181
+ `delegate-server is the freshest unassociated sibling under live codex parent ${draft.rootCodexParent.pid} and remains below the stale threshold.`;
1182
+ }
1183
+ }
1184
+ return {
1185
+ pid: draft.record.pid,
1186
+ ppid: draft.record.ppid,
1187
+ elapsedSeconds: draft.record.elapsedSeconds,
1188
+ rssKb: draft.record.rssKb,
1189
+ command: draft.record.command,
1190
+ cwd: draft.cwd,
1191
+ parentPid: draft.parentRecord?.pid ?? null,
1192
+ parentCommand: draft.parentRecord?.command ?? null,
1193
+ parentCwd: draft.parentCwd,
1194
+ rootCodexParentPid: draft.rootCodexParent?.pid ?? null,
1195
+ rootCodexParentCommand: draft.rootCodexParent?.command ?? null,
1196
+ rootCodexParentCwd: draft.rootCodexParentCwd,
1197
+ manifestAssociation: draft.manifestAssociation,
1198
+ classification,
1199
+ classificationDetail
1200
+ };
1201
+ }
1202
+ function buildDelegateServerInspectionDetail(idleDetails, staleDetails) {
1203
+ const idleParentSessionCount = idleDetails.filter((detail) => detail.classification === 'idle-parent-session').length;
1204
+ const idleOrphanCount = idleDetails.length - idleParentSessionCount;
1205
+ const staleParentSessionCount = staleDetails.filter((detail) => detail.classification === 'stale-parent-session').length;
1206
+ const staleOrphanCount = staleDetails.length - staleParentSessionCount;
1207
+ const parts = [];
1208
+ if (idleDetails.length > 0) {
1209
+ parts.push(`Detected ${idleDetails.length} idle delegate-server processes`);
1210
+ }
1211
+ if (idleParentSessionCount > 0) {
1212
+ parts.push(`${idleParentSessionCount} idle parent-session`);
1213
+ }
1214
+ if (idleOrphanCount > 0) {
1215
+ parts.push(`${idleOrphanCount} idle orphan`);
1216
+ }
1217
+ if (staleDetails.length > 0) {
1218
+ parts.push(`Detected ${staleDetails.length} stale delegate-server processes`);
1219
+ }
1220
+ if (staleParentSessionCount > 0) {
1221
+ parts.push(`${staleParentSessionCount} stale parent-session`);
1222
+ }
1223
+ if (staleOrphanCount > 0) {
1224
+ parts.push(`${staleOrphanCount} orphaned`);
1225
+ }
1226
+ return `${parts.join(' / ')}.`;
1227
+ }
1228
+ function normalizeOptionalString(value) {
1229
+ if (typeof value !== 'string') {
1230
+ return null;
1231
+ }
1232
+ const trimmed = value.trim();
1233
+ return trimmed.length > 0 ? trimmed : null;
1234
+ }
1235
+ function parseShellStyleArguments(command) {
1236
+ const args = [];
1237
+ let current = '';
1238
+ let quote = null;
1239
+ let escaped = false;
1240
+ const flushCurrent = () => {
1241
+ if (current.length === 0) {
1242
+ return;
1243
+ }
1244
+ args.push(current);
1245
+ current = '';
1246
+ };
1247
+ for (let index = 0; index < command.length; index += 1) {
1248
+ const character = command[index];
1249
+ if (escaped) {
1250
+ current += character;
1251
+ escaped = false;
1252
+ continue;
1253
+ }
1254
+ if (quote === "'") {
1255
+ if (character === "'") {
1256
+ quote = null;
1257
+ }
1258
+ else {
1259
+ current += character;
1260
+ }
1261
+ continue;
1262
+ }
1263
+ if (quote === '"') {
1264
+ if (character === '"') {
1265
+ quote = null;
1266
+ continue;
1267
+ }
1268
+ if (character === '\\') {
1269
+ const nextCharacter = command[index + 1];
1270
+ if (nextCharacter && ['\\', '"', '$', '`'].includes(nextCharacter)) {
1271
+ current += nextCharacter;
1272
+ index += 1;
1273
+ continue;
1274
+ }
1275
+ }
1276
+ current += character;
1277
+ continue;
1278
+ }
1279
+ if (/\s/u.test(character)) {
1280
+ flushCurrent();
1281
+ continue;
1282
+ }
1283
+ if (character === '"' || character === "'") {
1284
+ quote = character;
1285
+ continue;
1286
+ }
1287
+ if (character === '\\') {
1288
+ escaped = true;
1289
+ continue;
1290
+ }
1291
+ current += character;
1292
+ }
1293
+ if (escaped) {
1294
+ current += '\\';
1295
+ }
1296
+ flushCurrent();
1297
+ return args;
1298
+ }
1299
+ function parseElapsedSeconds(value) {
1300
+ if (!value) {
1301
+ return null;
1302
+ }
1303
+ const daySplit = value.split('-');
1304
+ let days = 0;
1305
+ let timePart = value;
1306
+ if (daySplit.length === 2) {
1307
+ days = Number(daySplit[0]);
1308
+ timePart = daySplit[1] ?? '';
1309
+ }
1310
+ const segments = timePart.split(':').map((part) => Number(part));
1311
+ if (segments.some((part) => !Number.isFinite(part))) {
1312
+ return null;
1313
+ }
1314
+ if (segments.length === 2) {
1315
+ return days * 86400 + segments[0] * 60 + segments[1];
1316
+ }
1317
+ if (segments.length === 3) {
1318
+ return days * 86400 + segments[0] * 3600 + segments[1] * 60 + segments[2];
1319
+ }
1320
+ return null;
1321
+ }
1322
+ function classifyCleanupCandidate(original, dependencies) {
1323
+ const current = dependencies.readProcessRecord(original.pid);
1324
+ if (!current) {
1325
+ return dependencies.isProcessAlive(original.pid) ? 'remaining' : 'missing';
1326
+ }
1327
+ const status = classifyMatchingDelegateServerProcess(original, current);
1328
+ if (status === 'replaced') {
1329
+ return 'replaced';
1330
+ }
1331
+ if (status === 'different') {
1332
+ return 'remaining';
1333
+ }
1334
+ return 'ready';
1335
+ }
1336
+ function classifyMatchingDelegateServerProcess(original, current) {
1337
+ if (!isDelegateServerCommand(current.command)) {
1338
+ return 'replaced';
1339
+ }
1340
+ if (current.command !== original.command) {
1341
+ return 'replaced';
1342
+ }
1343
+ if (original.elapsedSeconds !== null && current.elapsedSeconds !== null && current.elapsedSeconds < original.elapsedSeconds) {
1344
+ return 'replaced';
1345
+ }
1346
+ return 'same';
1347
+ }
1348
+ function tryKillProcess(pid, signal) {
1349
+ try {
1350
+ process.kill(pid, signal);
1351
+ return { status: 'signaled' };
1352
+ }
1353
+ catch (error) {
1354
+ const code = error?.code ?? null;
1355
+ if (code === 'ESRCH') {
1356
+ return { status: 'missing' };
1357
+ }
1358
+ return {
1359
+ status: 'blocked',
1360
+ code,
1361
+ detail: error instanceof Error ? error.message : `process.kill(${pid}, ${signal}) failed`
1362
+ };
1363
+ }
1364
+ }
1365
+ function isProcessAlive(pid) {
1366
+ try {
1367
+ process.kill(pid, 0);
1368
+ return true;
1369
+ }
1370
+ catch (error) {
1371
+ const code = error?.code;
1372
+ if (code === 'EPERM') {
1373
+ return true;
1374
+ }
1375
+ return false;
1376
+ }
1377
+ }
1378
+ async function waitForMs(durationMs) {
1379
+ await new Promise((resolve) => {
1380
+ setTimeout(resolve, durationMs);
1381
+ });
1382
+ }