@danmoisan/drm-copilot-mcp 1.1.17 → 1.1.19

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 (225) hide show
  1. package/out/mcp-server.js +1405 -684
  2. package/package.json +6 -4
  3. package/resources/claude-customizations/.claude/agents/atomic-executor.md +11 -0
  4. package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -0
  5. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +12 -4
  6. package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
  7. package/resources/claude-customizations/.claude/agents/feature-review.md +16 -5
  8. package/resources/claude-customizations/.claude/agents/orchestrator.md +21 -7
  9. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +37 -13
  10. package/resources/claude-customizations/.claude/agents/parallel-planner.md +9 -6
  11. package/resources/claude-customizations/.claude/agents/pr-author.md +15 -2
  12. package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -1
  13. package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
  14. package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
  15. package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  16. package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
  17. package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
  18. package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
  19. package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
  20. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
  21. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +55 -23
  22. package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
  23. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
  24. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
  25. package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
  26. package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
  27. package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
  28. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
  29. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
  30. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  31. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  32. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  33. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
  34. package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
  35. package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
  36. package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
  37. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
  38. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  39. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
  40. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
  41. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
  42. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
  43. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
  44. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
  45. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
  46. package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
  47. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
  48. package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
  49. package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  50. package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
  51. package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
  52. package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
  53. package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
  54. package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
  55. package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
  56. package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
  57. package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +493 -0
  58. package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
  59. package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
  60. package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
  61. package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +66 -38
  62. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
  63. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
  64. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
  65. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
  66. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
  67. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
  68. package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +64 -32
  69. package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
  70. package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
  71. package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
  72. package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +31 -34
  73. package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
  74. package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
  75. package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
  76. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
  77. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
  78. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
  79. package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
  80. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
  81. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
  82. package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
  83. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
  84. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
  85. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +396 -0
  86. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
  87. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
  88. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
  89. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
  90. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
  91. package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
  92. package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
  93. package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
  94. package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
  95. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +153 -4
  96. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
  97. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +47 -8
  98. package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
  99. package/resources/claude-customizations/.claude/rules/shell.md +10 -8
  100. package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
  101. package/resources/claude-customizations/.claude/settings.json +3 -4
  102. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +9 -1
  103. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +7 -1
  104. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
  105. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
  106. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
  107. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +171 -5
  108. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
  109. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
  110. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +6 -15
  111. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +45 -11
  112. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
  113. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  114. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
  115. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +7 -4
  116. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +42 -16
  117. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
  118. package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
  119. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +97 -19
  120. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
  121. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
  122. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
  123. package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +1 -1
  124. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
  125. package/resources/claude-customizations/pack-manifests/core.json +25 -0
  126. package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +9 -1
  127. package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
  128. package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +11 -0
  129. package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +4 -0
  130. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +10 -0
  131. package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
  132. package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
  133. package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +13 -3
  134. package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
  135. package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
  136. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  137. package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
  138. package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +30 -6
  139. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +16 -6
  140. package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
  141. package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
  142. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +43 -11
  143. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
  144. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +19 -4
  145. package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
  146. package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
  147. package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
  148. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
  149. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
  150. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -0
  151. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -0
  152. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -0
  153. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -0
  154. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -0
  155. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -0
  156. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +10 -0
  157. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +10 -0
  158. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +10 -0
  159. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +10 -0
  160. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +10 -0
  161. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +10 -0
  162. package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +2 -1
  163. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
  164. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -0
  165. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
  166. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
  167. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
  168. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
  169. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
  170. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +3 -3
  171. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +3 -3
  172. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +3 -3
  173. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +3 -3
  174. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +3 -3
  175. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +3 -3
  176. package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
  177. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  178. package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
  179. package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
  180. package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
  181. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  182. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
  183. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
  184. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
  185. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
  186. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +37 -5
  187. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
  188. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
  189. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
  190. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
  191. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
  192. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
  193. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  194. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  195. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  196. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
  197. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  198. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
  199. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
  200. package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
  201. package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  202. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
  203. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
  204. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
  205. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
  206. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
  207. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
  208. package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
  209. package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +493 -0
  210. package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
  211. package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
  212. package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
  213. package/resources/codex-and-agents-customizations/pack-manifests/core.json +9 -0
  214. package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +2 -2
  215. package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
  216. package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
  217. package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +9 -1
  218. package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
  219. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  220. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
  221. package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
  222. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +25 -28
  223. package/resources/powershell/PoshQC/PoshQC.psm1 +1 -0
  224. package/resources/powershell/PoshQC/README.md +8 -2
  225. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -315
package/out/mcp-server.js CHANGED
@@ -4150,13 +4150,14 @@ var require_fast_uri = __commonJS({
4150
4150
  if (!malformedIPLiteral) {
4151
4151
  malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4152
4152
  }
4153
- if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4154
- if (uri.indexOf("%") !== -1) {
4155
- if (parsed.host !== void 0 && !malformedIPLiteral) {
4156
- const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4157
- parsed.host = reescapeHostDelimiters(host, isIP);
4158
- }
4153
+ if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
4154
+ let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4155
+ if (!isIP) {
4156
+ host = normalizePercentEncoding(host.toLowerCase());
4159
4157
  }
4158
+ parsed.host = reescapeHostDelimiters(host, isIP);
4159
+ }
4160
+ if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4160
4161
  if (parsed.path) {
4161
4162
  parsed.path = normalizePathEncoding(parsed.path);
4162
4163
  }
@@ -9273,13 +9274,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
9273
9274
  }
9274
9275
  return propValues;
9275
9276
  });
9276
- const isObject15 = isObject;
9277
+ const isObject16 = isObject;
9277
9278
  const catchall = def.catchall;
9278
9279
  let value;
9279
9280
  inst._zod.parse = (payload, ctx) => {
9280
9281
  value ?? (value = _normalized.value);
9281
9282
  const input = payload.value;
9282
- if (!isObject15(input)) {
9283
+ if (!isObject16(input)) {
9283
9284
  payload.issues.push({
9284
9285
  expected: "object",
9285
9286
  code: "invalid_type",
@@ -9406,7 +9407,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
9406
9407
  return (payload, ctx) => fn(shape, payload, ctx);
9407
9408
  };
9408
9409
  let fastpass;
9409
- const isObject15 = isObject;
9410
+ const isObject16 = isObject;
9410
9411
  const jit = !globalConfig.jitless;
9411
9412
  const allowsEval2 = allowsEval;
9412
9413
  const fastEnabled = jit && allowsEval2.value;
@@ -9415,7 +9416,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
9415
9416
  inst._zod.parse = (payload, ctx) => {
9416
9417
  value ?? (value = _normalized.value);
9417
9418
  const input = payload.value;
9418
- if (!isObject15(input)) {
9419
+ if (!isObject16(input)) {
9419
9420
  payload.issues.push({
9420
9421
  expected: "object",
9421
9422
  code: "invalid_type",
@@ -14077,6 +14078,9 @@ var Protocol = class {
14077
14078
  this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
14078
14079
  const handleTaskResult = async () => {
14079
14080
  const taskId = request.params.taskId;
14081
+ if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
14082
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
14083
+ }
14080
14084
  if (this._taskMessageQueue) {
14081
14085
  let queuedMessage;
14082
14086
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -14107,12 +14111,12 @@ var Protocol = class {
14107
14111
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
14108
14112
  }
14109
14113
  if (!isTerminal(task.status)) {
14110
- await this._waitForTaskUpdate(taskId, extra.signal);
14114
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
14111
14115
  return await handleTaskResult();
14112
14116
  }
14113
14117
  if (isTerminal(task.status)) {
14114
14118
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
14115
- this._clearTaskQueue(taskId);
14119
+ this._clearTaskQueue(taskId, extra.sessionId);
14116
14120
  return {
14117
14121
  ...result,
14118
14122
  _meta: {
@@ -14149,7 +14153,7 @@ var Protocol = class {
14149
14153
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
14150
14154
  }
14151
14155
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
14152
- this._clearTaskQueue(request.params.taskId);
14156
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
14153
14157
  const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
14154
14158
  if (!cancelledTask) {
14155
14159
  throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -14277,6 +14281,19 @@ var Protocol = class {
14277
14281
  const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
14278
14282
  const capturedTransport = this._transport;
14279
14283
  const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
14284
+ const sessionId = capturedTransport?.sessionId;
14285
+ const store = this._taskStore;
14286
+ let relatedTaskFound = true;
14287
+ let relatedTaskLookup;
14288
+ if (relatedTaskId && store && this._taskMessageQueue && sessionId !== void 0) {
14289
+ relatedTaskFound = false;
14290
+ relatedTaskLookup = (async () => {
14291
+ if (!await store.getTask(relatedTaskId, sessionId)) {
14292
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
14293
+ }
14294
+ relatedTaskFound = true;
14295
+ })();
14296
+ }
14280
14297
  if (handler === void 0) {
14281
14298
  const errorResponse = {
14282
14299
  jsonrpc: "2.0",
@@ -14286,7 +14303,10 @@ var Protocol = class {
14286
14303
  message: "Method not found"
14287
14304
  }
14288
14305
  };
14289
- if (relatedTaskId && this._taskMessageQueue) {
14306
+ if (relatedTaskId && relatedTaskLookup) {
14307
+ const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
14308
+ relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error2) => this._onerror(new Error(`Failed to send an error response: ${error2}`)));
14309
+ } else if (relatedTaskId && this._taskMessageQueue) {
14290
14310
  this._enqueueTaskMessage(relatedTaskId, {
14291
14311
  type: "error",
14292
14312
  message: errorResponse,
@@ -14337,7 +14357,10 @@ var Protocol = class {
14337
14357
  closeSSEStream: extra?.closeSSEStream,
14338
14358
  closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
14339
14359
  };
14340
- Promise.resolve().then(() => {
14360
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
14361
+ if (relatedTaskLookup && abortController.signal.aborted) {
14362
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
14363
+ }
14341
14364
  if (taskCreationParams) {
14342
14365
  this.assertTaskHandlerCapability(request.method);
14343
14366
  }
@@ -14372,7 +14395,7 @@ var Protocol = class {
14372
14395
  ...error2["data"] !== void 0 && { data: error2["data"] }
14373
14396
  }
14374
14397
  };
14375
- if (relatedTaskId && this._taskMessageQueue) {
14398
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
14376
14399
  await this._enqueueTaskMessage(relatedTaskId, {
14377
14400
  type: "error",
14378
14401
  message: errorResponse,
@@ -14852,7 +14875,7 @@ var Protocol = class {
14852
14875
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
14853
14876
  }
14854
14877
  const maxQueueSize = this._options?.maxTaskQueueSize;
14855
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
14878
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
14856
14879
  }
14857
14880
  /**
14858
14881
  * Clears the message queue for a task and rejects any pending request resolvers.
@@ -14881,12 +14904,13 @@ var Protocol = class {
14881
14904
  * Uses polling to check for updates at the task's configured poll interval.
14882
14905
  * @param taskId The task ID to wait for
14883
14906
  * @param signal Abort signal to cancel the wait
14907
+ * @param sessionId Session of the request that waits, passed to the task store
14884
14908
  * @returns Promise that resolves when an update occurs or rejects if aborted
14885
14909
  */
14886
- async _waitForTaskUpdate(taskId, signal) {
14910
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
14887
14911
  let interval = this._options?.defaultTaskPollInterval ?? 1e3;
14888
14912
  try {
14889
- const task = await this._taskStore?.getTask(taskId);
14913
+ const task = await this._taskStore?.getTask(taskId, sessionId);
14890
14914
  if (task?.pollInterval) {
14891
14915
  interval = task.pollInterval;
14892
14916
  }
@@ -17830,7 +17854,8 @@ function toAuthorityMcpResult(tool, workspaceRoot, result) {
17830
17854
  primary_failure_code: result.primaryFailureCode,
17831
17855
  affected_paths: result.affectedPaths,
17832
17856
  unsupported_capabilities: result.unsupportedCapabilities,
17833
- resolution: result.resolution
17857
+ resolution: result.resolution,
17858
+ ...result.failureCause === void 0 ? {} : { failure_cause: result.failureCause }
17834
17859
  };
17835
17860
  }
17836
17861
  function toTransitionMcpResult(workspaceRoot, result) {
@@ -17849,7 +17874,8 @@ function toTransitionMcpResult(workspaceRoot, result) {
17849
17874
  destination_checkpoint_sha256: result.destinationCheckpointSha256,
17850
17875
  primary_failure_code: result.primaryFailureCode,
17851
17876
  affected_paths: result.affectedPaths,
17852
- unsupported_capabilities: result.unsupportedCapabilities
17877
+ unsupported_capabilities: result.unsupportedCapabilities,
17878
+ ...result.failureCause === void 0 ? {} : { failure_cause: result.failureCause }
17853
17879
  };
17854
17880
  }
17855
17881
  async function handlePortableHandoffTool(tool, rawInput, service) {
@@ -18294,6 +18320,33 @@ function buildPoshQcWorkflowArguments(tool, input) {
18294
18320
  // ../../extensions/drm-copilot/src/lib/push-down/filesystem-adapter.ts
18295
18321
  var fs2 = __toESM(require("node:fs"));
18296
18322
  var nodePath2 = __toESM(require("node:path"));
18323
+
18324
+ // ../../extensions/drm-copilot/src/lib/string-ordering.ts
18325
+ function rankCodeUnit(unit) {
18326
+ if (unit >= 55296 && unit <= 57343) {
18327
+ return unit + 8192;
18328
+ }
18329
+ if (unit >= 57344) {
18330
+ return unit - 2048;
18331
+ }
18332
+ return unit;
18333
+ }
18334
+ function compareCodePoint(left, right) {
18335
+ const sharedLength = Math.min(left.length, right.length);
18336
+ for (let index = 0; index < sharedLength; index += 1) {
18337
+ const leftUnit = left.charCodeAt(index);
18338
+ const rightUnit = right.charCodeAt(index);
18339
+ if (leftUnit !== rightUnit) {
18340
+ return rankCodeUnit(leftUnit) < rankCodeUnit(rightUnit) ? -1 : 1;
18341
+ }
18342
+ }
18343
+ if (left.length === right.length) {
18344
+ return 0;
18345
+ }
18346
+ return left.length < right.length ? -1 : 1;
18347
+ }
18348
+
18349
+ // ../../extensions/drm-copilot/src/lib/push-down/filesystem-adapter.ts
18297
18350
  function toPosixPath(value) {
18298
18351
  return value.replace(/\\/g, "/");
18299
18352
  }
@@ -18342,9 +18395,7 @@ var RealPushDownFileSystem = class {
18342
18395
  }
18343
18396
  };
18344
18397
  walk(normalizedRoot);
18345
- return files.sort(
18346
- (left, right) => left < right ? -1 : left > right ? 1 : 0
18347
- );
18398
+ return files.sort(compareCodePoint);
18348
18399
  }
18349
18400
  /**
18350
18401
  * @param path Path to inspect.
@@ -18554,7 +18605,7 @@ function enumerateSourceFiles(fs12, sourceRoot, rootFolders) {
18554
18605
  const sorted = [...rootFiles].sort((left, right) => {
18555
18606
  const leftRel = relativeToPosix(left, rootPath) ?? left;
18556
18607
  const rightRel = relativeToPosix(right, rootPath) ?? right;
18557
- return leftRel < rightRel ? -1 : leftRel > rightRel ? 1 : 0;
18608
+ return compareCodePoint(leftRel, rightRel);
18558
18609
  });
18559
18610
  orderedFiles.push(...sorted);
18560
18611
  }
@@ -18612,7 +18663,7 @@ function stringifySorted(value, indent) {
18612
18663
  }
18613
18664
  if (input !== null && typeof input === "object") {
18614
18665
  const entries = Object.entries(input).sort(
18615
- ([leftKey], [rightKey]) => leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0
18666
+ ([leftKey], [rightKey]) => compareCodePoint(leftKey, rightKey)
18616
18667
  );
18617
18668
  const result = {};
18618
18669
  for (const [key, val] of entries) {
@@ -18666,11 +18717,11 @@ function pushDownCustomizations(options) {
18666
18717
  effectiveSource,
18667
18718
  effectiveRoots
18668
18719
  )) {
18669
- const relativePath2 = relativeToPosix(sourcePath, effectiveSource);
18670
- if (relativePath2 === null) {
18720
+ const relativePath = relativeToPosix(sourcePath, effectiveSource);
18721
+ if (relativePath === null) {
18671
18722
  continue;
18672
18723
  }
18673
- const destinationPath = joinPosix2(destinationRoot, relativePath2);
18724
+ const destinationPath = joinPosix2(destinationRoot, relativePath);
18674
18725
  const destinationStatus = fs12.isFile(
18675
18726
  destinationPath
18676
18727
  ) ? "overwritten" : "created";
@@ -18695,7 +18746,7 @@ function pushDownCustomizations(options) {
18695
18746
  fs12.ensureDir(destParent);
18696
18747
  fs12.writeTextFile(destinationPath, rewrittenText);
18697
18748
  fileResults.push({
18698
- relativePath: relativePath2,
18749
+ relativePath,
18699
18750
  destinationStatus,
18700
18751
  rewrittenReferenceCount: rewrittenDelta,
18701
18752
  placeholderRewriteCount: placeholderDelta,
@@ -18786,12 +18837,14 @@ function loadPackManifests(manifestDir, selectedPackNames, fs12) {
18786
18837
  (name) => !MANIFEST_PACK_NAMES.has(name)
18787
18838
  );
18788
18839
  if (unknown2.length > 0) {
18789
- throw new ManifestError(`Unknown Codex pack name(s): ${unknown2.sort()}`);
18840
+ throw new ManifestError(
18841
+ `Unknown Codex pack name(s): ${unknown2.sort(compareCodePoint)}`
18842
+ );
18790
18843
  }
18791
18844
  const namesToLoad = new Set(selectedPackNames);
18792
18845
  namesToLoad.add(CORE_PACK_NAME);
18793
18846
  const manifests = /* @__PURE__ */ new Map();
18794
- for (const name of [...namesToLoad].sort()) {
18847
+ for (const name of [...namesToLoad].sort(compareCodePoint)) {
18795
18848
  const manifestPath = joinPosix3(manifestDir, `${name}.json`);
18796
18849
  if (!fs12.isFile(manifestPath)) {
18797
18850
  throw new ManifestError(
@@ -18814,14 +18867,16 @@ function resolveManifestPackNames(selectedPackNames, csharpVariant) {
18814
18867
  );
18815
18868
  if (variantSpecific.length > 0) {
18816
18869
  throw new ManifestError(
18817
- `Use public Codex pack 'csharp' with csharpVariant instead of variant-specific pack name(s): ${variantSpecific.sort().join(", ")}.`
18870
+ `Use public Codex pack 'csharp' with csharpVariant instead of variant-specific pack name(s): ${variantSpecific.sort(compareCodePoint).join(", ")}.`
18818
18871
  );
18819
18872
  }
18820
18873
  const unknown2 = [...selectedPackNames].filter(
18821
18874
  (name) => !SUPPORTED_PACK_NAMES.has(name)
18822
18875
  );
18823
18876
  if (unknown2.length > 0) {
18824
- throw new ManifestError(`Unknown Codex pack name(s): ${unknown2.sort()}`);
18877
+ throw new ManifestError(
18878
+ `Unknown Codex pack name(s): ${unknown2.sort(compareCodePoint)}`
18879
+ );
18825
18880
  }
18826
18881
  const manifestNames = new Set(selectedPackNames);
18827
18882
  if (manifestNames.has(PUBLIC_CSHARP_PACK_NAME)) {
@@ -18917,7 +18972,7 @@ function resolveVariantSourcePath(destinationRelativePath, csharpVariant) {
18917
18972
  return destinationRelativePath;
18918
18973
  }
18919
18974
  function assertSingleCsharpToolchain(publishedPaths, selectedPackNames) {
18920
- const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES.has(name)).sort();
18975
+ const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES.has(name)).sort(compareCodePoint);
18921
18976
  if (selectedCsharp.length > 1) {
18922
18977
  throw new ManifestError(
18923
18978
  `C# mutual exclusion violated: both modern and legacy Codex C# packs were selected (${selectedCsharp.join(", ")}); select exactly one C# variant.`
@@ -19207,7 +19262,7 @@ function loadPackManifests2(manifestDir, selectedPackNames, fs12) {
19207
19262
  const namesToLoad = new Set(selectedPackNames);
19208
19263
  namesToLoad.add(CORE_PACK_NAME2);
19209
19264
  const manifests = /* @__PURE__ */ new Map();
19210
- for (const name of [...namesToLoad].sort()) {
19265
+ for (const name of [...namesToLoad].sort(compareCodePoint)) {
19211
19266
  const manifestPath = joinPosix5(manifestDir, `${name}.json`);
19212
19267
  if (!fs12.isFile(manifestPath)) {
19213
19268
  throw new ManifestError2(
@@ -19302,7 +19357,7 @@ function resolveVariantSourcePath2(destinationRelativePath, csharpVariant) {
19302
19357
  return destinationRelativePath;
19303
19358
  }
19304
19359
  function assertSingleCsharpToolchain2(publishedPaths, selectedPackNames) {
19305
- const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES2.has(name)).sort();
19360
+ const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES2.has(name)).sort(compareCodePoint);
19306
19361
  if (selectedCsharp.length > 1) {
19307
19362
  throw new ManifestError2(
19308
19363
  `C# mutual exclusion violated: both modern and legacy C# packs were selected ([${selectedCsharp.map((n) => `'${n}'`).join(", ")}]); select exactly one C# variant.`
@@ -19312,6 +19367,10 @@ function assertSingleCsharpToolchain2(publishedPaths, selectedPackNames) {
19312
19367
  }
19313
19368
 
19314
19369
  // ../../extensions/drm-copilot/src/lib/push-down/claude-filesystem-adapter.ts
19370
+ var LOCAL_RUNTIME_RELATIVE_DIRECTORIES = [
19371
+ ".claude/state",
19372
+ ".claude/worktrees"
19373
+ ];
19315
19374
  function normalizePosix3(value) {
19316
19375
  return value.replace(/\\/g, "/").replace(/\/+$/, "");
19317
19376
  }
@@ -19377,6 +19436,21 @@ var ExcludingFileSystem = class {
19377
19436
  sourceRelativePosix(path16) {
19378
19437
  return relativeToPosix3(path16, this.sourceRoot);
19379
19438
  }
19439
+ /**
19440
+ * Return whether a path is a local runtime directory or lies below one.
19441
+ *
19442
+ * @param path An absolute candidate POSIX path from the inner adapter.
19443
+ * @returns True when the source-relative path is in a runtime directory.
19444
+ */
19445
+ isLocalRuntimePath(path16) {
19446
+ const relative2 = this.sourceRelativePosix(path16);
19447
+ if (relative2 === null) {
19448
+ return false;
19449
+ }
19450
+ return LOCAL_RUNTIME_RELATIVE_DIRECTORIES.some(
19451
+ (directory) => relative2 === directory || relative2.startsWith(`${directory}/`)
19452
+ );
19453
+ }
19380
19454
  /**
19381
19455
  * Return whether a candidate path is in the active published set.
19382
19456
  *
@@ -19402,15 +19476,15 @@ var ExcludingFileSystem = class {
19402
19476
  * @returns True when the file is outside the memory subtree or general-scoped.
19403
19477
  */
19404
19478
  isScopeIncluded(path16) {
19405
- const relativePath2 = relativeToPosix3(path16, this.repoRoot);
19406
- if (relativePath2 === null) {
19479
+ const relativePath = relativeToPosix3(path16, this.repoRoot);
19480
+ if (relativePath === null) {
19407
19481
  return true;
19408
19482
  }
19409
- if (!isUnderAgentMemory(relativePath2)) {
19483
+ if (!isUnderAgentMemory(relativePath)) {
19410
19484
  return true;
19411
19485
  }
19412
19486
  const content = this.readText(path16);
19413
- return isGeneralMemoryFile(relativePath2, content);
19487
+ return isGeneralMemoryFile(relativePath, content);
19414
19488
  }
19415
19489
  /**
19416
19490
  * Return whether a candidate file passes the memory-mode filter.
@@ -19460,7 +19534,7 @@ var ExcludingFileSystem = class {
19460
19534
  }
19461
19535
  listFiles(root) {
19462
19536
  return this.inner.listFiles(root).filter(
19463
- (p) => !this.excluded.has(normalizePosix3(p)) && this.isPackIncluded(p) && this.isScopeIncluded(p) && this.isMemoryModeIncluded(p)
19537
+ (p) => !this.isLocalRuntimePath(p) && !this.excluded.has(normalizePosix3(p)) && this.isPackIncluded(p) && this.isScopeIncluded(p) && this.isMemoryModeIncluded(p)
19464
19538
  );
19465
19539
  }
19466
19540
  isDir(path16) {
@@ -19677,9 +19751,6 @@ var EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([
19677
19751
  "tests",
19678
19752
  "venv"
19679
19753
  ]);
19680
- function compareOrdinal(left, right) {
19681
- return left < right ? -1 : left > right ? 1 : 0;
19682
- }
19683
19754
  function isExcludedDirectoryName(name) {
19684
19755
  return name.startsWith(".") || EXCLUDED_DIR_NAMES.has(name);
19685
19756
  }
@@ -19708,7 +19779,7 @@ function classifyProjectDirectories(observations) {
19708
19779
  structureObserved = true;
19709
19780
  }
19710
19781
  }
19711
- return { modulePaths: modulePaths.sort(compareOrdinal), structureObserved };
19782
+ return { modulePaths: modulePaths.sort(compareCodePoint), structureObserved };
19712
19783
  }
19713
19784
 
19714
19785
  // ../../extensions/drm-copilot/src/lib/push-down/claude-blast-radius-derive-core.ts
@@ -19776,12 +19847,12 @@ function pruneAncestors(paths) {
19776
19847
  function topLevelDirectories(observations) {
19777
19848
  const names = [];
19778
19849
  for (const observation of observations) {
19779
- const relativePath2 = observation.relativePath;
19780
- if (relativePath2 !== "" && !relativePath2.includes("/")) {
19781
- names.push(relativePath2);
19850
+ const relativePath = observation.relativePath;
19851
+ if (relativePath !== "" && !relativePath.includes("/")) {
19852
+ names.push(relativePath);
19782
19853
  }
19783
19854
  }
19784
- return names.sort(compareOrdinal);
19855
+ return names.sort(compareCodePoint);
19785
19856
  }
19786
19857
  function assembleModules(derivedPaths) {
19787
19858
  const combined = /* @__PURE__ */ new Map();
@@ -19792,7 +19863,7 @@ function assembleModules(derivedPaths) {
19792
19863
  combined.set(name, [...globs]);
19793
19864
  }
19794
19865
  const modules = {};
19795
- for (const name of [...combined.keys()].sort(compareOrdinal)) {
19866
+ for (const name of [...combined.keys()].sort(compareCodePoint)) {
19796
19867
  const globs = combined.get(name);
19797
19868
  if (globs !== void 0) {
19798
19869
  modules[name] = globs;
@@ -19868,9 +19939,7 @@ var realDirectoryLister = (root) => {
19868
19939
  } catch {
19869
19940
  return [];
19870
19941
  }
19871
- return entries.map((entry) => ({ name: entry.name, isDir: entry.isDirectory() })).sort(
19872
- (left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0
19873
- );
19942
+ return entries.map((entry) => ({ name: entry.name, isDir: entry.isDirectory() })).sort((left, right) => compareCodePoint(left.name, right.name));
19874
19943
  };
19875
19944
  function listTolerantly(lister, path16) {
19876
19945
  try {
@@ -20064,7 +20133,7 @@ function composeModules(base, overlay, overlayPath) {
20064
20133
  merged[name] = globs;
20065
20134
  }
20066
20135
  const composed = {};
20067
- for (const name of Object.keys(merged).sort(compareOrdinal)) {
20136
+ for (const name of Object.keys(merged).sort(compareCodePoint)) {
20068
20137
  const globs = merged[name] ?? [];
20069
20138
  composed[name] = globs;
20070
20139
  for (const glob of Array.isArray(globs) ? globs : []) {
@@ -20392,19 +20461,19 @@ function matchesExclusionEntry(entry, candidate) {
20392
20461
  function planExclusions(payloadRelativePaths, manifest, destinationExists) {
20393
20462
  const kept = [];
20394
20463
  const skipped = [];
20395
- for (const relativePath2 of payloadRelativePaths) {
20464
+ for (const relativePath of payloadRelativePaths) {
20396
20465
  const entry = manifest.entries.find(
20397
- (candidate) => matchesExclusionEntry(candidate, relativePath2)
20466
+ (candidate) => matchesExclusionEntry(candidate, relativePath)
20398
20467
  );
20399
20468
  if (entry === void 0) {
20400
- kept.push(relativePath2);
20469
+ kept.push(relativePath);
20401
20470
  continue;
20402
20471
  }
20403
20472
  skipped.push({
20404
- relativePath: relativePath2,
20473
+ relativePath,
20405
20474
  entry: entry.normalized,
20406
20475
  line: entry.line,
20407
- destinationStatus: destinationExists(relativePath2) ? "present" : "absent"
20476
+ destinationStatus: destinationExists(relativePath) ? "present" : "absent"
20408
20477
  });
20409
20478
  }
20410
20479
  const claimed = new Set(
@@ -20415,16 +20484,16 @@ function planExclusions(payloadRelativePaths, manifest, destinationExists) {
20415
20484
  );
20416
20485
  return { kept, skipped, unmatchedEntries };
20417
20486
  }
20418
- function assertManifestPathIsRootLevel(relativePath2, rootFolders) {
20419
- if (relativePath2.includes("/")) {
20487
+ function assertManifestPathIsRootLevel(relativePath, rootFolders) {
20488
+ if (relativePath.includes("/")) {
20420
20489
  throw new Error(
20421
- `Exclusion manifest path must be root-level: ${relativePath2}`
20490
+ `Exclusion manifest path must be root-level: ${relativePath}`
20422
20491
  );
20423
20492
  }
20424
- const root = rootFolders.find((name) => relativePath2.startsWith(name));
20493
+ const root = rootFolders.find((name) => relativePath.startsWith(name));
20425
20494
  if (root !== void 0) {
20426
20495
  throw new Error(
20427
- `Exclusion manifest path must not begin with published root ${root}: ${relativePath2}`
20496
+ `Exclusion manifest path must not begin with published root ${root}: ${relativePath}`
20428
20497
  );
20429
20498
  }
20430
20499
  }
@@ -21019,12 +21088,12 @@ var RealFileSystem = class {
21019
21088
  return;
21020
21089
  }
21021
21090
  for (const entry of entries) {
21022
- const relativePath2 = relativePrefix === "" ? entry.name : `${relativePrefix}/${entry.name}`;
21023
- if (matcher.test(relativePath2)) {
21024
- matches.push(joinPosix8(normalizedRoot, relativePath2));
21091
+ const relativePath = relativePrefix === "" ? entry.name : `${relativePrefix}/${entry.name}`;
21092
+ if (matcher.test(relativePath)) {
21093
+ matches.push(joinPosix8(normalizedRoot, relativePath));
21025
21094
  }
21026
21095
  if (entry.isDirectory()) {
21027
- walk(nodePath3.join(currentDir, entry.name), relativePath2);
21096
+ walk(nodePath3.join(currentDir, entry.name), relativePath);
21028
21097
  }
21029
21098
  }
21030
21099
  };
@@ -21422,12 +21491,12 @@ function extractTemplateVariables(template) {
21422
21491
  }
21423
21492
  function replaceAllVariables(template, variables) {
21424
21493
  const referenced = extractTemplateVariables(template);
21425
- const missing = [...referenced].filter((name) => !(name in variables)).sort();
21494
+ const missing = [...referenced].filter((name) => !(name in variables)).sort(compareCodePoint);
21426
21495
  if (missing.length > 0) {
21427
21496
  throw new Error(`Unresolved template variables: ${missing.join(", ")}`);
21428
21497
  }
21429
21498
  let resolved = template;
21430
- for (const key of [...referenced].sort()) {
21499
+ for (const key of [...referenced].sort(compareCodePoint)) {
21431
21500
  resolved = resolved.split(`\${${key}}`).join(variables[key] ?? "");
21432
21501
  }
21433
21502
  if (extractTemplateVariables(resolved).size > 0) {
@@ -21876,9 +21945,7 @@ function validationFindingToJson(finding) {
21876
21945
  }
21877
21946
  function sourceArtifactToJson(artifact) {
21878
21947
  const sortedFrontmatter = {};
21879
- for (const key of Object.keys(artifact.frontmatter).sort(
21880
- (left, right) => left < right ? -1 : left > right ? 1 : 0
21881
- )) {
21948
+ for (const key of Object.keys(artifact.frontmatter).sort(compareCodePoint)) {
21882
21949
  sortedFrontmatter[key] = artifact.frontmatter[key];
21883
21950
  }
21884
21951
  return {
@@ -22376,9 +22443,7 @@ function normalizeSelectedPaths(sourceRoot, selectedPaths) {
22376
22443
  for (const candidatePath of selectedPaths) {
22377
22444
  normalized.add(normalizeRelativePath(sourceRoot, candidatePath));
22378
22445
  }
22379
- return [...normalized].sort(
22380
- (left, right) => left < right ? -1 : left > right ? 1 : 0
22381
- );
22446
+ return [...normalized].sort(compareCodePoint);
22382
22447
  }
22383
22448
  function collectFilesRecursive(fileSystem, absoluteDir, out) {
22384
22449
  for (const childName of fileSystem.listDirectory(absoluteDir)) {
@@ -22411,9 +22476,7 @@ function iterSupportedArtifacts(fileSystem, sourceRoot, sourceEcosystem) {
22411
22476
  discovered.add(filePath.slice(rootPrefix.length));
22412
22477
  }
22413
22478
  }
22414
- return [...discovered].sort(
22415
- (left, right) => left < right ? -1 : left > right ? 1 : 0
22416
- );
22479
+ return [...discovered].sort(compareCodePoint);
22417
22480
  }
22418
22481
  function discoverSourceArtifacts(fileSystem, sourceRoot, sourceEcosystem, selectedPaths) {
22419
22482
  const allArtifacts = iterSupportedArtifacts(
@@ -22439,9 +22502,7 @@ function discoverSourceArtifacts(fileSystem, sourceRoot, sourceEcosystem, select
22439
22502
  matched.push(artifactPath);
22440
22503
  }
22441
22504
  }
22442
- return matched.sort(
22443
- (left, right) => left < right ? -1 : left > right ? 1 : 0
22444
- );
22505
+ return matched.sort(compareCodePoint);
22445
22506
  }
22446
22507
  function isUnderSelectedDirectory(artifactPath, selectedSet) {
22447
22508
  const segments = artifactPath.split("/");
@@ -23282,23 +23343,19 @@ function buildPromptTranslationTraces(fileSystem, runOptions, mappingRecord) {
23282
23343
  });
23283
23344
  }
23284
23345
  return [...translationTraces].sort((left, right) => {
23285
- if (left.sourcePath !== right.sourcePath) {
23286
- return left.sourcePath < right.sourcePath ? -1 : 1;
23287
- }
23288
- if (left.sectionId !== right.sectionId) {
23289
- return left.sectionId < right.sectionId ? -1 : 1;
23346
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23347
+ if (bySource !== 0) {
23348
+ return bySource;
23290
23349
  }
23291
- if (left.targetRole !== right.targetRole) {
23292
- return left.targetRole < right.targetRole ? -1 : 1;
23350
+ const bySection = compareCodePoint(left.sectionId, right.sectionId);
23351
+ if (bySection !== 0) {
23352
+ return bySection;
23293
23353
  }
23294
- return 0;
23354
+ return compareCodePoint(left.targetRole, right.targetRole);
23295
23355
  });
23296
23356
  }
23297
23357
 
23298
23358
  // ../../extensions/drm-copilot/src/lib/codex-native-converter/engine-pipeline.ts
23299
- function compareStrings(left, right) {
23300
- return left < right ? -1 : left > right ? 1 : 0;
23301
- }
23302
23359
  function planMappings(fileSystem, runOptions) {
23303
23360
  const discoveredPaths = discoverSourceArtifacts(
23304
23361
  fileSystem,
@@ -23320,7 +23377,7 @@ function planMappings(fileSystem, runOptions) {
23320
23377
  mappingRecords.push(mappedRecord);
23321
23378
  }
23322
23379
  return [...mappingRecords].sort(
23323
- (left, right) => compareStrings(left.sourcePath, right.sourcePath)
23380
+ (left, right) => compareCodePoint(left.sourcePath, right.sourcePath)
23324
23381
  );
23325
23382
  }
23326
23383
  function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEmissions) {
@@ -23347,7 +23404,7 @@ function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEm
23347
23404
  sectionEmissionsByTarget.set(plannedEmission.targetPath, bucket);
23348
23405
  }
23349
23406
  for (const targetPath of [...mappingRecordsByTarget.keys()].sort(
23350
- compareStrings
23407
+ compareCodePoint
23351
23408
  )) {
23352
23409
  const recordsForTarget = mappingRecordsByTarget.get(targetPath) ?? [];
23353
23410
  if (recordsForTarget.length === 0) {
@@ -23375,7 +23432,7 @@ function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEm
23375
23432
  ...new Set(
23376
23433
  plannedEmissions.filter((emission) => emission.targetPath !== null).map((emission) => emission.sourcePath)
23377
23434
  )
23378
- ].sort(compareStrings);
23435
+ ].sort(compareCodePoint);
23379
23436
  for (const sourcePath of parsedSourcePaths) {
23380
23437
  const sourceArtifact = parseSourceArtifact(
23381
23438
  fileSystem,
@@ -23389,7 +23446,7 @@ function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEm
23389
23446
  }
23390
23447
  }
23391
23448
  for (const targetPath of [...sectionEmissionsByTarget.keys()].sort(
23392
- compareStrings
23449
+ compareCodePoint
23393
23450
  )) {
23394
23451
  if (targetPath in generatedOutput) {
23395
23452
  continue;
@@ -23412,15 +23469,15 @@ function buildTranslationTraces(fileSystem, runOptions, mappingRecords) {
23412
23469
  );
23413
23470
  }
23414
23471
  return [...translationTraces].sort((left, right) => {
23415
- const bySource = compareStrings(left.sourcePath, right.sourcePath);
23472
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23416
23473
  if (bySource !== 0) {
23417
23474
  return bySource;
23418
23475
  }
23419
- const bySection = compareStrings(left.sectionId, right.sectionId);
23476
+ const bySection = compareCodePoint(left.sectionId, right.sectionId);
23420
23477
  if (bySection !== 0) {
23421
23478
  return bySection;
23422
23479
  }
23423
- return compareStrings(left.targetRole, right.targetRole);
23480
+ return compareCodePoint(left.targetRole, right.targetRole);
23424
23481
  });
23425
23482
  }
23426
23483
  function buildPlannedEmissions(translationTraces) {
@@ -23438,7 +23495,9 @@ function buildPlannedEmissions(translationTraces) {
23438
23495
  }
23439
23496
  function writeDestinationOutputs(fileSystem, destinationRoot, generatedOutput) {
23440
23497
  const normalizedRoot = destinationRoot.replace(/\/+$/, "");
23441
- for (const targetPath of Object.keys(generatedOutput).sort(compareStrings)) {
23498
+ for (const targetPath of Object.keys(generatedOutput).sort(
23499
+ compareCodePoint
23500
+ )) {
23442
23501
  const fullPath = normalizedRoot === "" ? targetPath : `${normalizedRoot}/${targetPath}`;
23443
23502
  fileSystem.writeTextFile(fullPath, generatedOutput[targetPath] ?? "");
23444
23503
  }
@@ -23452,7 +23511,7 @@ function sortKeysDeep(value) {
23452
23511
  if (value !== null && typeof value === "object") {
23453
23512
  const sorted = {};
23454
23513
  for (const key of Object.keys(value).sort(
23455
- (left, right) => left < right ? -1 : left > right ? 1 : 0
23514
+ compareCodePoint
23456
23515
  )) {
23457
23516
  sorted[key] = sortKeysDeep(value[key]);
23458
23517
  }
@@ -23528,7 +23587,7 @@ function extractTopologyDestinations(renderedText, knownDestinationPaths) {
23528
23587
  if (left[0] !== right[0]) {
23529
23588
  return left[0] - right[0];
23530
23589
  }
23531
- return left[1] < right[1] ? -1 : left[1] > right[1] ? 1 : 0;
23590
+ return compareCodePoint(left[1], right[1]);
23532
23591
  });
23533
23592
  return destinationsByPosition.map(([, destinationPath]) => destinationPath);
23534
23593
  }
@@ -23540,7 +23599,7 @@ function buildTopologyEdges(fileSystem, runOptions, mappingRecords, translationT
23540
23599
  ...new Set(
23541
23600
  mappingRecords.filter((record3) => record3.targetPath !== null).map((record3) => record3.targetPath)
23542
23601
  )
23543
- ].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
23602
+ ].sort(compareCodePoint);
23544
23603
  const topologyEdges = [];
23545
23604
  const translationTraceSourcePaths = new Set(
23546
23605
  translationTraces.map((trace) => trace.sourcePath)
@@ -23586,13 +23645,11 @@ function buildTopologyEdges(fileSystem, runOptions, mappingRecords, translationT
23586
23645
  }
23587
23646
  }
23588
23647
  return [...topologyEdges].sort((left, right) => {
23589
- if (left.sourcePath !== right.sourcePath) {
23590
- return left.sourcePath < right.sourcePath ? -1 : 1;
23591
- }
23592
- if (left.destinationPath !== right.destinationPath) {
23593
- return left.destinationPath < right.destinationPath ? -1 : 1;
23648
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23649
+ if (bySource !== 0) {
23650
+ return bySource;
23594
23651
  }
23595
- return 0;
23652
+ return compareCodePoint(left.destinationPath, right.destinationPath);
23596
23653
  });
23597
23654
  }
23598
23655
 
@@ -23665,38 +23722,35 @@ function renderDestinationToRepeatedSourceChart(topologyEdges) {
23665
23722
  }
23666
23723
 
23667
23724
  // ../../extensions/drm-copilot/src/lib/codex-native-converter/reporting-render.ts
23668
- function compareStrings2(left, right) {
23669
- return left < right ? -1 : left > right ? 1 : 0;
23670
- }
23671
23725
  function renderConversionReport(runOptions, mappingRecords, topologyEdges, translationTraces, validationFindings) {
23672
23726
  const blockingCount = validationFindings.filter(
23673
23727
  (finding) => finding.blocking
23674
23728
  ).length;
23675
23729
  const destinationRootText = runOptions.destinationRoot !== null ? toPosixPath2(runOptions.destinationRoot) : "review-only";
23676
23730
  const sortedMappingRecords = [...mappingRecords].sort(
23677
- (left, right) => compareStrings2(left.sourcePath, right.sourcePath)
23731
+ (left, right) => compareCodePoint(left.sourcePath, right.sourcePath)
23678
23732
  );
23679
23733
  const sortedTopologyEdges = [...topologyEdges].sort((left, right) => {
23680
- const bySource = compareStrings2(left.sourcePath, right.sourcePath);
23734
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23681
23735
  if (bySource !== 0) {
23682
23736
  return bySource;
23683
23737
  }
23684
- return compareStrings2(left.destinationPath, right.destinationPath);
23738
+ return compareCodePoint(left.destinationPath, right.destinationPath);
23685
23739
  });
23686
23740
  const sortedTranslationTraces = [...translationTraces].sort((left, right) => {
23687
- const bySource = compareStrings2(left.sourcePath, right.sourcePath);
23741
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23688
23742
  if (bySource !== 0) {
23689
23743
  return bySource;
23690
23744
  }
23691
- const bySection = compareStrings2(left.sectionId, right.sectionId);
23745
+ const bySection = compareCodePoint(left.sectionId, right.sectionId);
23692
23746
  if (bySection !== 0) {
23693
23747
  return bySection;
23694
23748
  }
23695
- const byRole = compareStrings2(left.targetRole, right.targetRole);
23749
+ const byRole = compareCodePoint(left.targetRole, right.targetRole);
23696
23750
  if (byRole !== 0) {
23697
23751
  return byRole;
23698
23752
  }
23699
- return compareStrings2(left.targetPath ?? "", right.targetPath ?? "");
23753
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
23700
23754
  });
23701
23755
  const lines = [
23702
23756
  "# Conversion Report",
@@ -23764,18 +23818,18 @@ function renderConversionReport(runOptions, mappingRecords, topologyEdges, trans
23764
23818
  lines.push("- None");
23765
23819
  } else {
23766
23820
  const sortedFindings = [...validationFindings].sort((left, right) => {
23767
- const byCode = compareStrings2(left.code, right.code);
23821
+ const byCode = compareCodePoint(left.code, right.code);
23768
23822
  if (byCode !== 0) {
23769
23823
  return byCode;
23770
23824
  }
23771
- const bySource = compareStrings2(
23825
+ const bySource = compareCodePoint(
23772
23826
  left.sourcePath ?? "",
23773
23827
  right.sourcePath ?? ""
23774
23828
  );
23775
23829
  if (bySource !== 0) {
23776
23830
  return bySource;
23777
23831
  }
23778
- return compareStrings2(left.targetPath ?? "", right.targetPath ?? "");
23832
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
23779
23833
  });
23780
23834
  for (const validationFinding of sortedFindings) {
23781
23835
  lines.push(
@@ -23794,7 +23848,7 @@ function sortKeysDeep2(value) {
23794
23848
  if (value !== null && typeof value === "object") {
23795
23849
  const sorted = {};
23796
23850
  for (const key of Object.keys(value).sort(
23797
- (left, right) => left < right ? -1 : left > right ? 1 : 0
23851
+ compareCodePoint
23798
23852
  )) {
23799
23853
  sorted[key] = sortKeysDeep2(value[key]);
23800
23854
  }
@@ -23836,21 +23890,23 @@ function joinPosix12(root, child) {
23836
23890
  }
23837
23891
  function sortBySourcePath(mappingRecords) {
23838
23892
  return [...mappingRecords].sort(
23839
- (left, right) => left.sourcePath < right.sourcePath ? -1 : left.sourcePath > right.sourcePath ? 1 : 0
23893
+ (left, right) => compareCodePoint(left.sourcePath, right.sourcePath)
23840
23894
  );
23841
23895
  }
23842
23896
  function sortFindings(validationFindings) {
23843
- const compare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
23844
23897
  return [...validationFindings].sort((left, right) => {
23845
- const byCode = compare(left.code, right.code);
23898
+ const byCode = compareCodePoint(left.code, right.code);
23846
23899
  if (byCode !== 0) {
23847
23900
  return byCode;
23848
23901
  }
23849
- const bySource = compare(left.sourcePath ?? "", right.sourcePath ?? "");
23902
+ const bySource = compareCodePoint(
23903
+ left.sourcePath ?? "",
23904
+ right.sourcePath ?? ""
23905
+ );
23850
23906
  if (bySource !== 0) {
23851
23907
  return bySource;
23852
23908
  }
23853
- return compare(left.targetPath ?? "", right.targetPath ?? "");
23909
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
23854
23910
  });
23855
23911
  }
23856
23912
  function writeConversionReportSet(fileSystem, runOptions, mappingRecords, topologyEdges, translationTraces, validationFindings, generatedOutput) {
@@ -23889,7 +23945,7 @@ function writeConversionReportSet(fileSystem, runOptions, mappingRecords, topolo
23889
23945
  dumpsSortedWithNewline(validationResultsPayload)
23890
23946
  );
23891
23947
  for (const targetPath of Object.keys(generatedOutput).sort(
23892
- (left, right) => left < right ? -1 : left > right ? 1 : 0
23948
+ compareCodePoint
23893
23949
  )) {
23894
23950
  fileSystem.writeTextFile(
23895
23951
  joinPosix12(proposedTreeRoot, targetPath),
@@ -24055,9 +24111,7 @@ function validateDuplicateTargets(mappingRecords, plannedEmissions) {
24055
24111
  conflictingTargets.add(targetPath);
24056
24112
  }
24057
24113
  }
24058
- for (const targetPath of [...conflictingTargets].sort(
24059
- (left, right) => left < right ? -1 : left > right ? 1 : 0
24060
- )) {
24114
+ for (const targetPath of [...conflictingTargets].sort(compareCodePoint)) {
24061
24115
  for (const plannedEmission of sectionEmissionsByTarget.get(targetPath) ?? []) {
24062
24116
  findings.push(
24063
24117
  buildFinding({
@@ -24100,17 +24154,19 @@ function validateConversionPlan(runOptions, mappingRecords, plannedEmissions, ge
24100
24154
  ...validateDuplicateTargets(mappingRecords, plannedEmissions),
24101
24155
  ...validateGeneratedOutput(generatedOutput)
24102
24156
  ];
24103
- const compare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
24104
24157
  return [...findings].sort((left, right) => {
24105
- const byCode = compare(left.code, right.code);
24158
+ const byCode = compareCodePoint(left.code, right.code);
24106
24159
  if (byCode !== 0) {
24107
24160
  return byCode;
24108
24161
  }
24109
- const bySource = compare(left.sourcePath ?? "", right.sourcePath ?? "");
24162
+ const bySource = compareCodePoint(
24163
+ left.sourcePath ?? "",
24164
+ right.sourcePath ?? ""
24165
+ );
24110
24166
  if (bySource !== 0) {
24111
24167
  return bySource;
24112
24168
  }
24113
- return compare(left.targetPath ?? "", right.targetPath ?? "");
24169
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
24114
24170
  });
24115
24171
  }
24116
24172
 
@@ -24887,13 +24943,13 @@ function validateLaunchBindings(features, context) {
24887
24943
  });
24888
24944
  return errors;
24889
24945
  }
24890
- function validateEpicPlannerChildLaunchBindings(features) {
24946
+ function validateEpicPlannerChildLaunchBindings(features, options = {}) {
24891
24947
  return validateLaunchBindings(features, {
24892
24948
  expectedExecutionContext: "epic_preparation_child",
24893
24949
  planner: true,
24894
24950
  requireGeneratedOrchestrator: true,
24895
24951
  skipNotStarted: false,
24896
- requireLaunchPaths: false
24952
+ requireLaunchPaths: options.requireLaunchPaths === true
24897
24953
  });
24898
24954
  }
24899
24955
  function validateEpicChildLaunchBindings(state, options = {}) {
@@ -25260,7 +25316,7 @@ function validateCodexModelRoutingGate(state) {
25260
25316
  deploymentAgents.add(deployment);
25261
25317
  }
25262
25318
  }
25263
- for (const agent of [...delegated].sort()) {
25319
+ for (const agent of [...delegated].sort(compareCodePoint)) {
25264
25320
  if (!logicalAgents.has(agent) && !deploymentAgents.has(agent)) {
25265
25321
  errors.push(
25266
25322
  `Checkpoint ${CODEX_MODEL_ROUTING_RECEIPTS_KEY} is missing a receipt for delegated agent: ${agent}.`
@@ -25354,7 +25410,7 @@ function normalizeLanguages(value) {
25354
25410
  const normalized = new Set(
25355
25411
  value.map((language) => language.trim().toLowerCase())
25356
25412
  );
25357
- return [...normalized].sort();
25413
+ return [...normalized].sort(compareCodePoint);
25358
25414
  }
25359
25415
  function requireInteger(value, fieldName) {
25360
25416
  if (typeof value !== "number" || !Number.isInteger(value)) {
@@ -25690,7 +25746,7 @@ function validateCodexTopologyGate(state, options = {}) {
25690
25746
  allowedNames.add(receipt.logical_agent);
25691
25747
  if ([...delegated].every((agent) => !allowedNames.has(agent))) {
25692
25748
  errors.push(
25693
- `Checkpoint delegation_receipts is missing the exact resolved topology agent for ${receipt.logical_agent}: ${[...allowedNames].sort().join(", ")}.`
25749
+ `Checkpoint delegation_receipts is missing the exact resolved topology agent for ${receipt.logical_agent}: ${[...allowedNames].sort(compareCodePoint).join(", ")}.`
25694
25750
  );
25695
25751
  }
25696
25752
  }
@@ -25739,6 +25795,7 @@ var MERGED_STATUSES = /* @__PURE__ */ new Set([
25739
25795
  "merged",
25740
25796
  "worktree_removed"
25741
25797
  ]);
25798
+ var NOT_STARTED_MERGE_STATUS = "not_started";
25742
25799
  function isObject6(value) {
25743
25800
  return typeof value === "object" && value !== null && !Array.isArray(value);
25744
25801
  }
@@ -25799,7 +25856,7 @@ function validateFeatureFolderUniquenessAndDependencies(features) {
25799
25856
  }
25800
25857
  }
25801
25858
  }
25802
- for (const folder of [...duplicates].sort()) {
25859
+ for (const folder of [...duplicates].sort(compareCodePoint)) {
25803
25860
  errors.push(
25804
25861
  `Epic checkpoint has duplicate features[].feature_folder: ${folder}`
25805
25862
  );
@@ -25819,6 +25876,9 @@ function validateMergeStatusEnum(features) {
25819
25876
  }
25820
25877
  return errors;
25821
25878
  }
25879
+ function hasStarted(feature) {
25880
+ return typeof feature["worktree_created_at"] === "string" || feature["merge_status"] !== NOT_STARTED_MERGE_STATUS;
25881
+ }
25822
25882
  function validateWaveBarrierOrdering(features) {
25823
25883
  const errors = [];
25824
25884
  const byFolder = /* @__PURE__ */ new Map();
@@ -25835,6 +25895,9 @@ function validateWaveBarrierOrdering(features) {
25835
25895
  if (typeof folder !== "string" || !Array.isArray(dependsOn)) {
25836
25896
  continue;
25837
25897
  }
25898
+ if (!hasStarted(feature)) {
25899
+ continue;
25900
+ }
25838
25901
  const worktreeCreatedAt = feature["worktree_created_at"];
25839
25902
  for (const dependency of dependsOn) {
25840
25903
  const resolved = resolveFeatureReference(dependency, index);
@@ -25846,9 +25909,13 @@ function validateWaveBarrierOrdering(features) {
25846
25909
  const depConfirmedAt = dependencyFeature["merge_confirmed_at"];
25847
25910
  const statusViolation = typeof depMergeStatus !== "string" || !MERGED_STATUSES.has(depMergeStatus);
25848
25911
  const timingViolation = typeof depConfirmedAt === "string" && typeof worktreeCreatedAt === "string" && depConfirmedAt > worktreeCreatedAt;
25849
- if (statusViolation || timingViolation) {
25912
+ if (statusViolation) {
25850
25913
  errors.push(
25851
- `EPIC_WAVE_BARRIER_VIOLATION: ${folder} started before dependency ${String(dependency)} merged`
25914
+ `EPIC_WAVE_BARRIER_VIOLATION: ${folder} is treated as started while dependency ${String(dependency)} is not merged`
25915
+ );
25916
+ } else if (timingViolation) {
25917
+ errors.push(
25918
+ `EPIC_WAVE_BARRIER_VIOLATION: ${folder} worktree_created_at precedes dependency ${String(dependency)} merge_confirmed_at`
25852
25919
  );
25853
25920
  }
25854
25921
  }
@@ -26127,6 +26194,53 @@ function validateCommittedFile(git, ref, path16, label) {
26127
26194
  }
26128
26195
  return [];
26129
26196
  }
26197
+ function repositoryRelativePath(value, field) {
26198
+ if (typeof value !== "string" || value.trim().length === 0) {
26199
+ return {
26200
+ errors: [`${field} must be a non-empty repository-relative path.`]
26201
+ };
26202
+ }
26203
+ if (value.includes("\\")) {
26204
+ return { errors: [`${field} must use forward slashes.`] };
26205
+ }
26206
+ const parts = value.split("/").filter((part) => part.length > 0 && part !== ".");
26207
+ if (value.startsWith("/") || /^[A-Za-z]:/.test(value) || parts.includes("..")) {
26208
+ return { errors: [`${field} must stay within the workspace root.`] };
26209
+ }
26210
+ return { path: parts.length === 0 ? "." : parts.join("/"), errors: [] };
26211
+ }
26212
+ function derivedPlanPath(feature) {
26213
+ return repositoryRelativePath(feature["plan_path"], "plan_path").path;
26214
+ }
26215
+ function pairPlansWithFeatures(features, plans) {
26216
+ const entries = [];
26217
+ if (Array.isArray(features)) {
26218
+ features.forEach((item, index) => {
26219
+ if (isRecord(item)) {
26220
+ entries.push([index, item]);
26221
+ }
26222
+ });
26223
+ }
26224
+ const paired = [];
26225
+ let position = 0;
26226
+ for (const plan of plans) {
26227
+ let entry = entries[position];
26228
+ while (entry !== void 0 && derivedPlanPath(entry[1]) !== plan) {
26229
+ position += 1;
26230
+ entry = entries[position];
26231
+ }
26232
+ if (entry === void 0) {
26233
+ return plans.map((fallbackPlan, slot) => [
26234
+ slot,
26235
+ entries[slot]?.[1] ?? {},
26236
+ fallbackPlan
26237
+ ]);
26238
+ }
26239
+ paired.push([entry[0], entry[1], plan]);
26240
+ position += 1;
26241
+ }
26242
+ return paired;
26243
+ }
26130
26244
  function validatePlanningGitIntegrity(state, parsed, plans, git) {
26131
26245
  const branch = state["integration_branch"];
26132
26246
  if (typeof branch !== "string" || !git.refExists(branch)) {
@@ -26148,8 +26262,8 @@ function validatePlanningGitIntegrity(state, parsed, plans, git) {
26148
26262
  );
26149
26263
  }
26150
26264
  }
26151
- const features = Array.isArray(state["features"]) ? state["features"].filter(isRecord) : [];
26152
- plans.forEach((plan, index) => {
26265
+ const pairs = pairPlansWithFeatures(state["features"], plans);
26266
+ pairs.forEach(([index, feature, plan]) => {
26153
26267
  const derived = git.lastCommit(plan);
26154
26268
  if (derived === void 0) {
26155
26269
  errors.push(
@@ -26164,7 +26278,6 @@ function validatePlanningGitIntegrity(state, parsed, plans, git) {
26164
26278
  return;
26165
26279
  }
26166
26280
  const candidates = [derived];
26167
- const feature = features[index] ?? {};
26168
26281
  const featureCommit = feature["planning_commit"];
26169
26282
  if (featureCommit !== void 0) {
26170
26283
  if (typeof featureCommit !== "string" || !COMMIT_RE.test(featureCommit)) {
@@ -26222,7 +26335,7 @@ function validatePlanningGitIntegrity(state, parsed, plans, git) {
26222
26335
  }
26223
26336
  }
26224
26337
  });
26225
- for (const extra of Object.keys(integrity.planHashes).filter((path16) => !plans.includes(path16)).sort()) {
26338
+ for (const extra of Object.keys(integrity.planHashes).filter((path16) => !plans.includes(path16)).sort(compareCodePoint)) {
26226
26339
  errors.push(
26227
26340
  `Optional plan_hashes contains unknown planner path: '${extra}'.`
26228
26341
  );
@@ -26508,7 +26621,7 @@ function validateStatus(feature, index, receipt, receiptPath, status, statusPath
26508
26621
  }
26509
26622
  return errors;
26510
26623
  }
26511
- function validateEpicPlannerLaunchEvidence(state, context) {
26624
+ function validateEpicPlannerLaunchEvidence(state, context, options = {}) {
26512
26625
  const features = state["features"];
26513
26626
  if (!Array.isArray(features)) {
26514
26627
  return [];
@@ -26520,6 +26633,9 @@ function validateEpicPlannerLaunchEvidence(state, context) {
26520
26633
  if (!isRecord2(item)) {
26521
26634
  return;
26522
26635
  }
26636
+ if (options.requireLaunchPaths === true && !featureCarriesLaunchPath(item)) {
26637
+ return;
26638
+ }
26523
26639
  const receipt = validateReceipt3(item, index, context);
26524
26640
  errors.push(...receipt.errors);
26525
26641
  const featureStatus = launchPath(
@@ -26566,21 +26682,6 @@ var SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
26566
26682
  function join9(root, relative2) {
26567
26683
  return `${toPosixPath2(root).replace(/\/+$/, "")}/${relative2.replace(/^\/+/, "")}`;
26568
26684
  }
26569
- function relativePath(value, field) {
26570
- if (typeof value !== "string" || value.trim().length === 0) {
26571
- return {
26572
- errors: [`${field} must be a non-empty repository-relative path.`]
26573
- };
26574
- }
26575
- if (value.includes("\\")) {
26576
- return { errors: [`${field} must use forward slashes.`] };
26577
- }
26578
- const parts = value.split("/");
26579
- if (value.startsWith("/") || /^[A-Za-z]:/.test(value) || parts.includes("..") || parts.includes(".")) {
26580
- return { errors: [`${field} must stay within the workspace root.`] };
26581
- }
26582
- return { path: parts.join("/"), errors: [] };
26583
- }
26584
26685
  function readRequired(context, relative2, label) {
26585
26686
  const path16 = join9(context.workspaceRoot, relative2);
26586
26687
  if (!context.fileSystem.isFile(path16)) {
@@ -26621,12 +26722,15 @@ function validateArtifactSource(stateText, context) {
26621
26722
  }
26622
26723
  function validateFeatureFiles(feature, index, context) {
26623
26724
  const prefix = `Epic planner checkpoint features[${index}]`;
26624
- const folderResult = relativePath(
26725
+ const folderResult = repositoryRelativePath(
26625
26726
  feature["feature_folder"],
26626
26727
  `${prefix}.feature_folder`
26627
26728
  );
26628
- const planResult = relativePath(feature["plan_path"], `${prefix}.plan_path`);
26629
- const researchResult = relativePath(
26729
+ const planResult = repositoryRelativePath(
26730
+ feature["plan_path"],
26731
+ `${prefix}.plan_path`
26732
+ );
26733
+ const researchResult = repositoryRelativePath(
26630
26734
  feature["research_path"],
26631
26735
  `${prefix}.research_path`
26632
26736
  );
@@ -26671,7 +26775,7 @@ function validateFeatureFiles(feature, index, context) {
26671
26775
  const evidenceValue = feature["preflight_evidence_path"];
26672
26776
  const evidencePaths = [];
26673
26777
  if (evidenceValue !== void 0) {
26674
- const evidence = relativePath(
26778
+ const evidence = repositoryRelativePath(
26675
26779
  evidenceValue,
26676
26780
  `${prefix}.preflight_evidence_path`
26677
26781
  );
@@ -26752,7 +26856,7 @@ function validateKickoffAgainstState(parsed, state, label) {
26752
26856
  }
26753
26857
  return errors;
26754
26858
  }
26755
- function validateEpicReadinessIntegrity(state, stateText, context) {
26859
+ function validateEpicReadinessIntegrity(state, stateText, context, options = {}) {
26756
26860
  const errors = validateArtifactSource(stateText, context);
26757
26861
  const slug = state["epic_feature_folder"];
26758
26862
  if (typeof slug !== "string" || !SLUG_RE.test(slug)) {
@@ -26773,7 +26877,7 @@ function validateEpicReadinessIntegrity(state, stateText, context) {
26773
26877
  }
26774
26878
  const manifest = readRequired(context, manifestPath, "the epic manifest");
26775
26879
  errors.push(...manifest.errors);
26776
- const ignoredResult = relativePath(
26880
+ const ignoredResult = repositoryRelativePath(
26777
26881
  state["kickoff_prompt_path"],
26778
26882
  "Epic planner checkpoint kickoff_prompt_path"
26779
26883
  );
@@ -26821,7 +26925,7 @@ function validateEpicReadinessIntegrity(state, stateText, context) {
26821
26925
  }
26822
26926
  });
26823
26927
  }
26824
- errors.push(...validateEpicPlannerLaunchEvidence(state, context));
26928
+ errors.push(...validateEpicPlannerLaunchEvidence(state, context, options));
26825
26929
  if (parsed !== void 0) {
26826
26930
  errors.push(
26827
26931
  ...validatePlanningGitIntegrity(state, parsed, plans, context.git),
@@ -26957,18 +27061,19 @@ function extractFeatures2(value) {
26957
27061
  if (!Array.isArray(value)) {
26958
27062
  return {
26959
27063
  errors: ["Epic planner checkpoint features must be a list."],
26960
- features: []
27064
+ indexedFeatures: [],
27065
+ entries: []
26961
27066
  };
26962
27067
  }
26963
27068
  const errors = [];
26964
- const features = [];
27069
+ const indexedFeatures = [];
26965
27070
  value.forEach((item, index) => {
26966
27071
  const prefix = `Epic planner checkpoint features[${index}]`;
26967
27072
  if (!isObject7(item)) {
26968
27073
  errors.push(`${prefix} must be an object.`);
26969
27074
  return;
26970
27075
  }
26971
- features.push(item);
27076
+ indexedFeatures.push([index, item]);
26972
27077
  const missing = REQUIRED_FEATURE_KEYS.filter((key) => !(key in item));
26973
27078
  if (missing.length > 0) {
26974
27079
  errors.push(`${prefix} missing required keys: ${missing.join(", ")}.`);
@@ -26988,13 +27093,14 @@ function extractFeatures2(value) {
26988
27093
  );
26989
27094
  }
26990
27095
  });
26991
- return { errors, features };
27096
+ return { errors, indexedFeatures, entries: value };
26992
27097
  }
26993
- function validateDependencyWaves(features) {
27098
+ function validateDependencyWaves(indexedFeatures) {
27099
+ const features = indexedFeatures.map(([, feature]) => feature);
26994
27100
  const errors = [];
26995
27101
  const seenFolders = /* @__PURE__ */ new Set();
26996
27102
  const seenIssues = /* @__PURE__ */ new Set();
26997
- features.forEach((feature, index2) => {
27103
+ indexedFeatures.forEach(([index2, feature]) => {
26998
27104
  const prefix = `Epic planner checkpoint features[${index2}]`;
26999
27105
  const folder = feature["feature_folder"];
27000
27106
  if (typeof folder === "string" && folder.length > 0) {
@@ -27017,7 +27123,7 @@ function validateDependencyWaves(features) {
27017
27123
  });
27018
27124
  const index = buildFeatureReferenceIndex(features);
27019
27125
  const manifest = /* @__PURE__ */ new Map();
27020
- features.forEach((feature, featureIndex) => {
27126
+ indexedFeatures.forEach(([featureIndex, feature]) => {
27021
27127
  const folder = feature["feature_folder"];
27022
27128
  const dependencies = feature["depends_on"];
27023
27129
  if (typeof folder !== "string" || folder.length === 0 || !Array.isArray(dependencies)) {
@@ -27046,7 +27152,7 @@ function validateDependencyWaves(features) {
27046
27152
  }
27047
27153
  throw error2;
27048
27154
  }
27049
- features.forEach((feature, index2) => {
27155
+ indexedFeatures.forEach(([index2, feature]) => {
27050
27156
  const folder = feature["feature_folder"];
27051
27157
  if (typeof folder !== "string" || !expectedWaves.has(folder)) {
27052
27158
  return;
@@ -27060,14 +27166,14 @@ function validateDependencyWaves(features) {
27060
27166
  });
27061
27167
  return errors;
27062
27168
  }
27063
- function validateReadyFeatures(features) {
27169
+ function validateReadyFeatures(indexedFeatures, keyGated) {
27064
27170
  const errors = [];
27065
- if (features.length < 2) {
27171
+ if (indexedFeatures.length < 2) {
27066
27172
  errors.push(
27067
27173
  "Execution-ready epic planning requires at least two features."
27068
27174
  );
27069
27175
  }
27070
- features.forEach((feature, index) => {
27176
+ indexedFeatures.forEach(([index, feature]) => {
27071
27177
  const prefix = `Epic planner checkpoint features[${index}]`;
27072
27178
  const issueNum = feature["issue_num"];
27073
27179
  if (typeof issueNum !== "number" || !Number.isInteger(issueNum) || issueNum <= 0) {
@@ -27089,36 +27195,40 @@ function validateReadyFeatures(features) {
27089
27195
  if (feature["preflight_status"] !== "PREFLIGHT: ALL CLEAR") {
27090
27196
  errors.push(`${prefix}.preflight_status must be 'PREFLIGHT: ALL CLEAR'.`);
27091
27197
  }
27092
- const receipt = feature["model_routing_receipt"];
27093
- errors.push(
27094
- ...validateCodexModelRoutingReceipt(
27095
- receipt,
27096
- `${prefix}.model_routing_receipt`
27097
- )
27098
- );
27099
- if (isObject7(receipt) && receipt["logical_agent"] !== "orchestrator") {
27198
+ if (!keyGated || "model_routing_receipt" in feature) {
27199
+ const receipt = feature["model_routing_receipt"];
27100
27200
  errors.push(
27101
- `${prefix}.model_routing_receipt.logical_agent must be 'orchestrator'.`
27201
+ ...validateCodexModelRoutingReceipt(
27202
+ receipt,
27203
+ `${prefix}.model_routing_receipt`
27204
+ )
27102
27205
  );
27103
- }
27104
- if (isObject7(receipt)) {
27105
- if (receipt["complexity_band"] !== feature["complexity_band"]) {
27206
+ if (isObject7(receipt) && receipt["logical_agent"] !== "orchestrator") {
27106
27207
  errors.push(
27107
- `${prefix}.model_routing_receipt.complexity_band must match feature complexity_band ${pythonRepr6(feature["complexity_band"])}.`
27208
+ `${prefix}.model_routing_receipt.logical_agent must be 'orchestrator'.`
27108
27209
  );
27109
27210
  }
27110
- if (receipt["execution_context"] !== "epic_preparation_child") {
27111
- errors.push(
27112
- `${prefix}.model_routing_receipt.execution_context must be 'epic_preparation_child'.`
27113
- );
27211
+ if (isObject7(receipt)) {
27212
+ if (receipt["complexity_band"] !== feature["complexity_band"]) {
27213
+ errors.push(
27214
+ `${prefix}.model_routing_receipt.complexity_band must match feature complexity_band ${pythonRepr6(feature["complexity_band"])}.`
27215
+ );
27216
+ }
27217
+ if (receipt["execution_context"] !== "epic_preparation_child") {
27218
+ errors.push(
27219
+ `${prefix}.model_routing_receipt.execution_context must be 'epic_preparation_child'.`
27220
+ );
27221
+ }
27114
27222
  }
27115
27223
  }
27116
- errors.push(
27117
- ...validateChildTopologyReceipt(
27118
- feature["topology_receipt"],
27119
- `${prefix}.topology_receipt`
27120
- )
27121
- );
27224
+ if (!keyGated || "topology_receipt" in feature) {
27225
+ errors.push(
27226
+ ...validateChildTopologyReceipt(
27227
+ feature["topology_receipt"],
27228
+ `${prefix}.topology_receipt`
27229
+ )
27230
+ );
27231
+ }
27122
27232
  });
27123
27233
  return errors;
27124
27234
  }
@@ -27141,7 +27251,7 @@ function validateEpicPlannerStateText(text2, options = {}) {
27141
27251
  errors.push(...worthiness.errors);
27142
27252
  const featureResult = extractFeatures2(value["features"]);
27143
27253
  errors.push(...featureResult.errors);
27144
- errors.push(...validateDependencyWaves(featureResult.features));
27254
+ errors.push(...validateDependencyWaves(featureResult.indexedFeatures));
27145
27255
  const maxParallel = value["max_parallel_features"];
27146
27256
  if (typeof maxParallel !== "number" || !Number.isInteger(maxParallel) || maxParallel < 1 || maxParallel > 8) {
27147
27257
  errors.push(
@@ -27154,6 +27264,7 @@ function validateEpicPlannerStateText(text2, options = {}) {
27154
27264
  );
27155
27265
  }
27156
27266
  if (options.requireReadyForExecution === true) {
27267
+ const requireLaunchPaths = options.requireCodexModelRouting !== true && options.requireCodexTopology !== true;
27157
27268
  if (worthiness.verdict !== "epic") {
27158
27269
  errors.push(
27159
27270
  "Execution readiness requires epic_worthiness.verdict 'epic'."
@@ -27164,11 +27275,20 @@ function validateEpicPlannerStateText(text2, options = {}) {
27164
27275
  `Execution-ready planner checkpoint next_step must be '${READY_NEXT_STEP}'.`
27165
27276
  );
27166
27277
  }
27167
- errors.push(...validateReadyFeatures(featureResult.features));
27168
27278
  errors.push(
27169
- ...validateEpicPlannerChildLaunchBindings(featureResult.features)
27279
+ ...validateReadyFeatures(
27280
+ featureResult.indexedFeatures,
27281
+ requireLaunchPaths
27282
+ )
27283
+ );
27284
+ errors.push(
27285
+ ...validateEpicPlannerChildLaunchBindings(featureResult.entries, {
27286
+ requireLaunchPaths
27287
+ })
27170
27288
  );
27171
- errors.push(...validatePlannerTopologyReceipt(value["topology_receipt"]));
27289
+ if (!requireLaunchPaths || "topology_receipt" in value) {
27290
+ errors.push(...validatePlannerTopologyReceipt(value["topology_receipt"]));
27291
+ }
27172
27292
  const expectedKickoff = `artifacts/orchestration/epic-kickoff-${String(
27173
27293
  value["epic_feature_folder"]
27174
27294
  )}.md`;
@@ -27186,7 +27306,8 @@ function validateEpicPlannerStateText(text2, options = {}) {
27186
27306
  ...validateEpicReadinessIntegrity(
27187
27307
  value,
27188
27308
  text2,
27189
- options.readinessContext
27309
+ options.readinessContext,
27310
+ { requireLaunchPaths }
27190
27311
  )
27191
27312
  );
27192
27313
  }
@@ -27194,6 +27315,215 @@ function validateEpicPlannerStateText(text2, options = {}) {
27194
27315
  return errors;
27195
27316
  }
27196
27317
 
27318
+ // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-blocked-reason.ts
27319
+ var MECHANICAL_BLOCKED_REASONS = /* @__PURE__ */ new Set([
27320
+ "spawn_agent_unavailable",
27321
+ "delegation_launch_failed",
27322
+ "delegate_no_receipt",
27323
+ "delegate_contract_incomplete",
27324
+ "validator_failed",
27325
+ "user_requested_stop"
27326
+ ]);
27327
+ var NON_MECHANICAL_BLOCKED_REASONS = /* @__PURE__ */ new Set([
27328
+ "premise_falsified",
27329
+ "external_dependency",
27330
+ "policy_hold",
27331
+ "awaiting_ci",
27332
+ "human_decision_required"
27333
+ ]);
27334
+ var VALID_BLOCKED_REASONS = /* @__PURE__ */ new Set([
27335
+ "none",
27336
+ ...MECHANICAL_BLOCKED_REASONS,
27337
+ ...NON_MECHANICAL_BLOCKED_REASONS
27338
+ ]);
27339
+
27340
+ // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-promotion-tools.ts
27341
+ var FEATURE_PROMOTION_ENTRY_TOOL = "new_potential_entry";
27342
+ var BUG_PROMOTION_ENTRY_TOOL = "new_potential_bug_entry";
27343
+ var BUG_PROMOTION_TYPE = "bug";
27344
+ var PROMOTION_TYPE_KEY = "promotion-type";
27345
+ function resolvePromotionEntryTools(requiredMcpTools, state) {
27346
+ if (state[PROMOTION_TYPE_KEY] !== BUG_PROMOTION_TYPE) {
27347
+ return [...requiredMcpTools];
27348
+ }
27349
+ return requiredMcpTools.map(
27350
+ (tool) => tool === FEATURE_PROMOTION_ENTRY_TOOL ? BUG_PROMOTION_ENTRY_TOOL : tool
27351
+ );
27352
+ }
27353
+
27354
+ // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-issue-adoption.ts
27355
+ var ISSUE_ADOPTION_KEY = "issue_adoption";
27356
+ var POTENTIAL_TO_ISSUE_TOOL = "potential_to_issue";
27357
+ var ORIGIN_VALUES = /* @__PURE__ */ new Set([
27358
+ "transferred",
27359
+ "filed_before_orchestration",
27360
+ "epic_decomposition"
27361
+ ]);
27362
+ var VERIFIED_VIA_VALUES = /* @__PURE__ */ new Set([
27363
+ "gh_issue_view",
27364
+ "gh_api_get",
27365
+ "github_mcp_issue_read"
27366
+ ]);
27367
+ var WAIVABLE_TOOLS = /* @__PURE__ */ new Set([
27368
+ POTENTIAL_TO_ISSUE_TOOL,
27369
+ FEATURE_PROMOTION_ENTRY_TOOL,
27370
+ BUG_PROMOTION_ENTRY_TOOL
27371
+ ]);
27372
+ var PROMOTION_ENTRY_TOOLS = /* @__PURE__ */ new Set([
27373
+ FEATURE_PROMOTION_ENTRY_TOOL,
27374
+ BUG_PROMOTION_ENTRY_TOOL
27375
+ ]);
27376
+ var POTENTIAL_RECORD_PREFIX = "docs/features/potential/";
27377
+ var POTENTIAL_RECORD_SUFFIX = ".md";
27378
+ var RECORD_OPTIONAL_ORIGINS = /* @__PURE__ */ new Set([
27379
+ "transferred",
27380
+ "filed_before_orchestration"
27381
+ ]);
27382
+ var ISSUE_NUM_PATTERN = /^[1-9][0-9]*$/;
27383
+ var ERROR_NOT_OBJECT = "Checkpoint issue_adoption must be an object when present.";
27384
+ var ERROR_ISSUE_NUM_FORMAT = "Checkpoint issue_adoption.issue_num must be a string of decimal digits without a leading zero.";
27385
+ var ERROR_ISSUE_NUM_MISMATCH = "Checkpoint issue_adoption.issue_num must equal the checkpoint issue-num.";
27386
+ var ERROR_ISSUE_URL = "Checkpoint issue_adoption.issue_url must end with /issues/ followed by issue_num.";
27387
+ var ERROR_ORIGIN = "Checkpoint issue_adoption.origin must be one of transferred, filed_before_orchestration, epic_decomposition.";
27388
+ var ERROR_VERIFIED_VIA = "Checkpoint issue_adoption.verified_via must be one of gh_issue_view, gh_api_get, github_mcp_issue_read.";
27389
+ var ERROR_VERIFIED_AT = "Checkpoint issue_adoption.verified_at must be present.";
27390
+ var ERROR_EVIDENCE = "Checkpoint issue_adoption.evidence must be a non-empty string.";
27391
+ var ERROR_WAIVED_TOOLS_SHAPE = "Checkpoint issue_adoption.waived_tools must be a non-empty list of tool names.";
27392
+ var ERROR_WAIVED_TOOLS_INCLUDE = "Checkpoint issue_adoption.waived_tools must include potential_to_issue.";
27393
+ function isPlainObject3(value) {
27394
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27395
+ }
27396
+ function isNonBlankString(value) {
27397
+ return typeof value === "string" && value.trim().length > 0;
27398
+ }
27399
+ function validIssueNum(value) {
27400
+ return typeof value === "string" && ISSUE_NUM_PATTERN.test(value) ? value : null;
27401
+ }
27402
+ function issueIdentityErrors(adoption, state) {
27403
+ const errors = [];
27404
+ const issueNum = validIssueNum(adoption["issue_num"]);
27405
+ if (issueNum === null) {
27406
+ errors.push(ERROR_ISSUE_NUM_FORMAT);
27407
+ } else {
27408
+ const checkpointIssueNum = state["issue-num"];
27409
+ if (typeof checkpointIssueNum === "string" && checkpointIssueNum !== issueNum) {
27410
+ errors.push(ERROR_ISSUE_NUM_MISMATCH);
27411
+ }
27412
+ }
27413
+ const issueUrl = adoption["issue_url"];
27414
+ if (issueNum === null || typeof issueUrl !== "string" || !issueUrl.endsWith(`/issues/${issueNum}`)) {
27415
+ errors.push(ERROR_ISSUE_URL);
27416
+ }
27417
+ return errors;
27418
+ }
27419
+ function provenanceErrors(adoption) {
27420
+ const errors = [];
27421
+ const origin = adoption["origin"];
27422
+ if (typeof origin !== "string" || !ORIGIN_VALUES.has(origin)) {
27423
+ errors.push(ERROR_ORIGIN);
27424
+ }
27425
+ const verifiedVia = adoption["verified_via"];
27426
+ if (typeof verifiedVia !== "string" || !VERIFIED_VIA_VALUES.has(verifiedVia)) {
27427
+ errors.push(ERROR_VERIFIED_VIA);
27428
+ }
27429
+ const verifiedAt = adoption["verified_at"];
27430
+ if (verifiedAt === void 0 || verifiedAt === null || typeof verifiedAt === "string" && verifiedAt.trim().length === 0) {
27431
+ errors.push(ERROR_VERIFIED_AT);
27432
+ }
27433
+ if (!isNonBlankString(adoption["evidence"])) {
27434
+ errors.push(ERROR_EVIDENCE);
27435
+ }
27436
+ return errors;
27437
+ }
27438
+ function waivedToolList(value) {
27439
+ if (!Array.isArray(value)) {
27440
+ return null;
27441
+ }
27442
+ const items = value;
27443
+ if (items.length === 0 || !items.every((item) => isNonBlankString(item))) {
27444
+ return null;
27445
+ }
27446
+ return items;
27447
+ }
27448
+ function waivedToolErrors(waived, options) {
27449
+ const errors = [];
27450
+ const seen = /* @__PURE__ */ new Set();
27451
+ for (const tool of waived) {
27452
+ if (seen.has(tool)) {
27453
+ errors.push(
27454
+ `Checkpoint issue_adoption.waived_tools lists a tool more than once: ${tool}.`
27455
+ );
27456
+ } else if (!WAIVABLE_TOOLS.has(tool)) {
27457
+ errors.push(
27458
+ `Checkpoint issue_adoption.waived_tools names a tool that cannot be waived: ${tool}.`
27459
+ );
27460
+ } else if (!options.requiredMcpTools.includes(tool)) {
27461
+ errors.push(
27462
+ `Checkpoint issue_adoption.waived_tools names a tool that is not required by route ${options.routeId}: ${tool}.`
27463
+ );
27464
+ } else if (options.successfulTools.has(tool)) {
27465
+ errors.push(
27466
+ `Checkpoint issue_adoption.waived_tools names a tool that has a successful MCP receipt: ${tool}.`
27467
+ );
27468
+ }
27469
+ seen.add(tool);
27470
+ }
27471
+ if (!seen.has(POTENTIAL_TO_ISSUE_TOOL)) {
27472
+ errors.push(ERROR_WAIVED_TOOLS_INCLUDE);
27473
+ }
27474
+ return errors;
27475
+ }
27476
+ function potentialRecordErrors(waived, potentialRecord, origin, recordPresent) {
27477
+ if (!recordPresent && typeof origin === "string" && RECORD_OPTIONAL_ORIGINS.has(origin)) {
27478
+ return [];
27479
+ }
27480
+ if (typeof potentialRecord === "string" && potentialRecord.startsWith(POTENTIAL_RECORD_PREFIX) && potentialRecord.endsWith(POTENTIAL_RECORD_SUFFIX)) {
27481
+ return [];
27482
+ }
27483
+ const errors = [];
27484
+ const reported = /* @__PURE__ */ new Set();
27485
+ for (const tool of waived) {
27486
+ if (PROMOTION_ENTRY_TOOLS.has(tool) && !reported.has(tool)) {
27487
+ errors.push(
27488
+ `Checkpoint issue_adoption.potential_record must name a markdown file under docs/features/potential/ when waiving ${tool}.`
27489
+ );
27490
+ reported.add(tool);
27491
+ }
27492
+ }
27493
+ return errors;
27494
+ }
27495
+ function resolveIssueAdoption(state, options) {
27496
+ if (!Object.prototype.hasOwnProperty.call(state, ISSUE_ADOPTION_KEY)) {
27497
+ return { errors: [], waivedTools: /* @__PURE__ */ new Set() };
27498
+ }
27499
+ const adoption = state[ISSUE_ADOPTION_KEY];
27500
+ if (!isPlainObject3(adoption)) {
27501
+ return { errors: [ERROR_NOT_OBJECT], waivedTools: /* @__PURE__ */ new Set() };
27502
+ }
27503
+ const errors = [
27504
+ ...issueIdentityErrors(adoption, state),
27505
+ ...provenanceErrors(adoption)
27506
+ ];
27507
+ const waived = waivedToolList(adoption["waived_tools"]);
27508
+ if (waived === null) {
27509
+ errors.push(ERROR_WAIVED_TOOLS_SHAPE);
27510
+ return { errors, waivedTools: /* @__PURE__ */ new Set() };
27511
+ }
27512
+ errors.push(...waivedToolErrors(waived, options));
27513
+ errors.push(
27514
+ ...potentialRecordErrors(
27515
+ waived,
27516
+ adoption["potential_record"],
27517
+ adoption["origin"],
27518
+ Object.prototype.hasOwnProperty.call(adoption, "potential_record")
27519
+ )
27520
+ );
27521
+ if (errors.length > 0) {
27522
+ return { errors, waivedTools: /* @__PURE__ */ new Set() };
27523
+ }
27524
+ return { errors: [], waivedTools: new Set(waived) };
27525
+ }
27526
+
27197
27527
  // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-routing.ts
27198
27528
  var ROUTING_MATRIX_RELATIVE_PATH = "config/orchestration-routing.json";
27199
27529
  var MANDATORY_ROUTE_PHASES = {
@@ -27382,7 +27712,10 @@ function validateRoutingContract(state, options = {}) {
27382
27712
  const errors = [];
27383
27713
  const requiredAgents = routeList(rawRoute, "required_agents");
27384
27714
  const requiredSkills = routeList(rawRoute, "required_skills");
27385
- const requiredMcpTools = routeList(rawRoute, "required_mcp_tools");
27715
+ const requiredMcpTools = resolvePromotionEntryTools(
27716
+ routeList(rawRoute, "required_mcp_tools"),
27717
+ state
27718
+ );
27386
27719
  if (stateList(state, "required_agents", requiredAgents) === null) {
27387
27720
  errors.push(
27388
27721
  `Checkpoint required_agents must match routing matrix for route ${routeId}.`
@@ -27411,11 +27744,20 @@ function validateRoutingContract(state, options = {}) {
27411
27744
  }
27412
27745
  }
27413
27746
  const actualTools = mcpTools(state);
27747
+ const adoption = resolveIssueAdoption(state, {
27748
+ routeId,
27749
+ requiredMcpTools,
27750
+ successfulTools: actualTools
27751
+ });
27414
27752
  for (const tool of requiredMcpTools) {
27753
+ if (adoption.waivedTools.has(tool)) {
27754
+ continue;
27755
+ }
27415
27756
  if (!actualTools.has(tool)) {
27416
27757
  errors.push(`Checkpoint missing successful MCP receipt: ${tool}.`);
27417
27758
  }
27418
27759
  }
27760
+ errors.push(...adoption.errors);
27419
27761
  errors.push(...validateEmptyListField(state, "local_execution_overrides"));
27420
27762
  errors.push(...validateEmptyListField(state, "delegation_bypasses"));
27421
27763
  errors.push(...validateLifecycleOperations(state));
@@ -27561,14 +27903,137 @@ function validateHumanInteraction(humanInteraction) {
27561
27903
  return errors;
27562
27904
  }
27563
27905
 
27906
+ // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-remediation-accounting.ts
27907
+ var REVIEW_OUTCOMES_KEY = "review_outcomes";
27908
+ var REVIEW_VERDICTS = [
27909
+ "PASS",
27910
+ "REMEDIATION_REQUIRED",
27911
+ "HALT_NON_REMEDIABLE",
27912
+ "AWAITING_CI"
27913
+ ];
27914
+ var REMEDIABILITY_CLASSES = [
27915
+ "autonomous",
27916
+ "external_dependency",
27917
+ "policy_hold",
27918
+ "awaiting_ci",
27919
+ "human_decision_required"
27920
+ ];
27921
+ var HALT_CLASSES = /* @__PURE__ */ new Set([
27922
+ "external_dependency",
27923
+ "policy_hold",
27924
+ "human_decision_required"
27925
+ ]);
27926
+ var REMEDIABLE_CLASS = "autonomous";
27927
+ function isObject11(value) {
27928
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27929
+ }
27930
+ function pythonRepr8(value) {
27931
+ if (value === null || value === void 0) {
27932
+ return "None";
27933
+ }
27934
+ if (value === true) {
27935
+ return "True";
27936
+ }
27937
+ if (value === false) {
27938
+ return "False";
27939
+ }
27940
+ return String(value);
27941
+ }
27942
+ function deriveReviewVerdict(remediabilities) {
27943
+ for (const value of remediabilities) {
27944
+ if (!REMEDIABILITY_CLASSES.includes(value)) {
27945
+ throw new RangeError(`invalid remediability: ${value}`);
27946
+ }
27947
+ }
27948
+ if (remediabilities.length === 0) {
27949
+ return "PASS";
27950
+ }
27951
+ if (remediabilities.includes(REMEDIABLE_CLASS)) {
27952
+ return "REMEDIATION_REQUIRED";
27953
+ }
27954
+ if (remediabilities.some((value) => HALT_CLASSES.has(value))) {
27955
+ return "HALT_NON_REMEDIABLE";
27956
+ }
27957
+ return "AWAITING_CI";
27958
+ }
27959
+ function validateReviewOutcome(index, outcome) {
27960
+ const errors = [];
27961
+ const prefix = `Checkpoint remediation review outcome #${index}`;
27962
+ const verdict = outcome["verdict"];
27963
+ if (typeof verdict !== "string" || !REVIEW_VERDICTS.includes(verdict)) {
27964
+ errors.push(
27965
+ `${prefix} verdict must be one of PASS, REMEDIATION_REQUIRED, HALT_NON_REMEDIABLE, AWAITING_CI; got: ${pythonRepr8(verdict)}`
27966
+ );
27967
+ }
27968
+ const classes = [];
27969
+ const findings = outcome["findings"];
27970
+ if (!Array.isArray(findings)) {
27971
+ errors.push(`${prefix} findings must be a list.`);
27972
+ } else {
27973
+ findings.forEach((finding, findingIndex) => {
27974
+ if (!isObject11(finding)) {
27975
+ errors.push(`${prefix} finding #${findingIndex} must be an object.`);
27976
+ return;
27977
+ }
27978
+ const remediability = finding["remediability"];
27979
+ if (typeof remediability !== "string" || !REMEDIABILITY_CLASSES.includes(remediability)) {
27980
+ errors.push(
27981
+ `${prefix} finding #${findingIndex} remediability must be one of autonomous, external_dependency, policy_hold, awaiting_ci, human_decision_required; got: ${pythonRepr8(remediability)}`
27982
+ );
27983
+ return;
27984
+ }
27985
+ classes.push(remediability);
27986
+ });
27987
+ }
27988
+ if (errors.length === 0) {
27989
+ const expected = deriveReviewVerdict(classes);
27990
+ if (verdict !== expected) {
27991
+ errors.push(
27992
+ `${prefix} verdict ${pythonRepr8(verdict)} does not match its findings (expected ${expected}).`
27993
+ );
27994
+ }
27995
+ }
27996
+ return errors;
27997
+ }
27998
+ function validateReviewOutcomes(loop) {
27999
+ if (!Object.prototype.hasOwnProperty.call(loop, REVIEW_OUTCOMES_KEY)) {
28000
+ return [];
28001
+ }
28002
+ const outcomes = loop[REVIEW_OUTCOMES_KEY];
28003
+ if (!Array.isArray(outcomes)) {
28004
+ return ["Checkpoint remediation_loop review_outcomes must be a list."];
28005
+ }
28006
+ const errors = [];
28007
+ outcomes.forEach((outcome, index) => {
28008
+ if (!isObject11(outcome)) {
28009
+ errors.push(
28010
+ `Checkpoint remediation review outcome #${index} must be an object.`
28011
+ );
28012
+ return;
28013
+ }
28014
+ errors.push(...validateReviewOutcome(index, outcome));
28015
+ });
28016
+ return errors;
28017
+ }
28018
+
27564
28019
  // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-remediation.ts
27565
28020
  var REMEDIATION_LOOP_KEY = "remediation_loop";
27566
28021
  var REMEDIATION_CYCLES_KEY = "cycles";
27567
28022
  var EXECUTION_STATUSES_REQUIRING_CLEAR_PREFLIGHT = /* @__PURE__ */ new Set(["in_progress", "complete", "failed"]);
27568
28023
  var PREFLIGHT_CLEARED_STATUS = "clear";
27569
- function isObject11(value) {
28024
+ var COMPLETED_ATTEMPTS_KEY = "completed_attempts";
28025
+ var CANDIDATE_APPLIED_KEY = "candidate_applied";
28026
+ var OPENED_BY_REVIEW_KEY = "opened_by_review";
28027
+ var COMPLETED_EXECUTION_STATUS = "complete";
28028
+ function isObject12(value) {
27570
28029
  return typeof value === "object" && value !== null && !Array.isArray(value);
27571
28030
  }
28031
+ function isStrictInteger(value) {
28032
+ return typeof value === "number" && Number.isInteger(value);
28033
+ }
28034
+ function hasKey(value, key) {
28035
+ return Object.prototype.hasOwnProperty.call(value, key);
28036
+ }
27572
28037
  function validateRemediationCycle(index, cycle) {
27573
28038
  const errors = [];
27574
28039
  const planPath = cycle["plan_path"];
@@ -27580,7 +28045,7 @@ function validateRemediationCycle(index, cycle) {
27580
28045
  const executionStatus = cycle["execution_status"];
27581
28046
  if (typeof executionStatus === "string" && EXECUTION_STATUSES_REQUIRING_CLEAR_PREFLIGHT.has(executionStatus)) {
27582
28047
  const preflight = cycle["preflight"];
27583
- const preflightStatus = isObject11(preflight) ? preflight["final_status"] : void 0;
28048
+ const preflightStatus = isObject12(preflight) ? preflight["final_status"] : void 0;
27584
28049
  if (preflightStatus !== PREFLIGHT_CLEARED_STATUS) {
27585
28050
  errors.push(
27586
28051
  `Checkpoint remediation cycle #${index} execution_status is ${executionStatus} but preflight.final_status is not 'clear'.`
@@ -27594,22 +28059,79 @@ function validateRemediationCycle(index, cycle) {
27594
28059
  }
27595
28060
  return errors;
27596
28061
  }
28062
+ function opensRemediationReview(openedByReview, outcomes) {
28063
+ if (!isStrictInteger(openedByReview) || !Array.isArray(outcomes)) {
28064
+ return false;
28065
+ }
28066
+ if (openedByReview < 0 || openedByReview >= outcomes.length) {
28067
+ return false;
28068
+ }
28069
+ const target = outcomes[openedByReview];
28070
+ return isObject12(target) && target["verdict"] === "REMEDIATION_REQUIRED";
28071
+ }
28072
+ function validateRemediationAccounting(loop, cycleList) {
28073
+ const errors = [];
28074
+ const outcomes = loop[REVIEW_OUTCOMES_KEY];
28075
+ let appliedCount = 0;
28076
+ (cycleList ?? []).forEach((cycle, index) => {
28077
+ if (!isObject12(cycle)) {
28078
+ return;
28079
+ }
28080
+ const prefix = `Checkpoint remediation cycle #${index}`;
28081
+ if (hasKey(cycle, CANDIDATE_APPLIED_KEY)) {
28082
+ const candidateApplied = cycle[CANDIDATE_APPLIED_KEY];
28083
+ if (typeof candidateApplied !== "boolean") {
28084
+ errors.push(`${prefix} candidate_applied must be a boolean.`);
28085
+ } else if (candidateApplied) {
28086
+ appliedCount += 1;
28087
+ if (cycle["execution_status"] !== COMPLETED_EXECUTION_STATUS) {
28088
+ errors.push(
28089
+ `${prefix} candidate_applied is true but execution_status is not 'complete'.`
28090
+ );
28091
+ }
28092
+ }
28093
+ }
28094
+ if (hasKey(cycle, OPENED_BY_REVIEW_KEY) && !opensRemediationReview(cycle[OPENED_BY_REVIEW_KEY], outcomes)) {
28095
+ errors.push(
28096
+ `${prefix} opened_by_review must reference a review outcome whose verdict is REMEDIATION_REQUIRED.`
28097
+ );
28098
+ }
28099
+ });
28100
+ if (hasKey(loop, COMPLETED_ATTEMPTS_KEY)) {
28101
+ const completedAttempts = loop[COMPLETED_ATTEMPTS_KEY];
28102
+ if (!isStrictInteger(completedAttempts) || completedAttempts < 0) {
28103
+ errors.push(
28104
+ "Checkpoint remediation_loop completed_attempts must be a non-negative integer."
28105
+ );
28106
+ } else if (completedAttempts !== appliedCount) {
28107
+ errors.push(
28108
+ `Checkpoint remediation_loop completed_attempts is ${completedAttempts} but ${appliedCount} cycles have candidate_applied true.`
28109
+ );
28110
+ }
28111
+ }
28112
+ return errors;
28113
+ }
27597
28114
  function validateRemediationLoop(remediationLoop) {
27598
28115
  const errors = [];
27599
- if (!isObject11(remediationLoop)) {
28116
+ if (!isObject12(remediationLoop)) {
27600
28117
  return errors;
27601
28118
  }
27602
28119
  const cycles = remediationLoop[REMEDIATION_CYCLES_KEY];
27603
- if (!Array.isArray(cycles)) {
27604
- return errors;
28120
+ let cycleList = null;
28121
+ if (Array.isArray(cycles)) {
28122
+ cycleList = cycles;
28123
+ cycles.forEach((cycle, index) => {
28124
+ if (!isObject12(cycle)) {
28125
+ errors.push(
28126
+ `Checkpoint remediation cycle #${index} must be an object.`
28127
+ );
28128
+ return;
28129
+ }
28130
+ errors.push(...validateRemediationCycle(index, cycle));
28131
+ });
27605
28132
  }
27606
- cycles.forEach((cycle, index) => {
27607
- if (!isObject11(cycle)) {
27608
- errors.push(`Checkpoint remediation cycle #${index} must be an object.`);
27609
- return;
27610
- }
27611
- errors.push(...validateRemediationCycle(index, cycle));
27612
- });
28133
+ errors.push(...validateReviewOutcomes(remediationLoop));
28134
+ errors.push(...validateRemediationAccounting(remediationLoop, cycleList));
27613
28135
  return errors;
27614
28136
  }
27615
28137
 
@@ -27623,7 +28145,7 @@ var OUT_OF_SCOPE_STEP_KEYS = [
27623
28145
  "step9_status",
27624
28146
  "step10_status"
27625
28147
  ];
27626
- function pythonRepr8(value) {
28148
+ function pythonRepr9(value) {
27627
28149
  if (value === void 0 || value === null) {
27628
28150
  return "None";
27629
28151
  }
@@ -27638,11 +28160,11 @@ function pythonRepr8(value) {
27638
28160
  return String(value);
27639
28161
  }
27640
28162
  if (Array.isArray(value)) {
27641
- return `[${value.map(pythonRepr8).join(", ")}]`;
28163
+ return `[${value.map(pythonRepr9).join(", ")}]`;
27642
28164
  }
27643
28165
  if (typeof value === "object") {
27644
28166
  const entries = Object.entries(value).map(
27645
- ([key, item]) => `${pythonRepr8(key)}: ${pythonRepr8(item)}`
28167
+ ([key, item]) => `${pythonRepr9(key)}: ${pythonRepr9(item)}`
27646
28168
  );
27647
28169
  return `{${entries.join(", ")}}`;
27648
28170
  }
@@ -27656,13 +28178,13 @@ function validatePreparationTerminalContract(state) {
27656
28178
  const errors = [];
27657
28179
  if (state["next_step"] !== EXPECTED_NEXT_STEP) {
27658
28180
  errors.push(
27659
- `Preparation checkpoint next_step must be ${pythonRepr8(EXPECTED_NEXT_STEP)}, found ${pythonRepr8(state["next_step"])}.`
28181
+ `Preparation checkpoint next_step must be ${pythonRepr9(EXPECTED_NEXT_STEP)}, found ${pythonRepr9(state["next_step"])}.`
27660
28182
  );
27661
28183
  }
27662
28184
  for (const key of OUT_OF_SCOPE_STEP_KEYS) {
27663
28185
  if (state[key] !== "not-applicable") {
27664
28186
  errors.push(
27665
- `Preparation checkpoint ${key} must be 'not-applicable', found ${pythonRepr8(state[key])}.`
28187
+ `Preparation checkpoint ${key} must be 'not-applicable', found ${pythonRepr9(state[key])}.`
27666
28188
  );
27667
28189
  }
27668
28190
  }
@@ -27678,18 +28200,18 @@ var DELEGATING_AGENTS = /* @__PURE__ */ new Set([
27678
28200
  "prd-feature",
27679
28201
  "pr-author"
27680
28202
  ]);
27681
- function isObject12(value) {
28203
+ function isObject13(value) {
27682
28204
  return typeof value === "object" && value !== null && !Array.isArray(value);
27683
28205
  }
27684
28206
  function delegatedAgents(state) {
27685
28207
  const agents = /* @__PURE__ */ new Set();
27686
28208
  let receipts = state["delegation_receipts"];
27687
- if (isObject12(receipts)) {
28209
+ if (isObject13(receipts)) {
27688
28210
  receipts = receipts["agents"];
27689
28211
  }
27690
28212
  if (Array.isArray(receipts)) {
27691
28213
  for (const receipt of receipts) {
27692
- if (!isObject12(receipt)) {
28214
+ if (!isObject13(receipt)) {
27693
28215
  continue;
27694
28216
  }
27695
28217
  const agentName = receipt["agent_name"];
@@ -27713,7 +28235,7 @@ function validateModelRoutingExistence(state) {
27713
28235
  const receipts = state["model_routing_receipts"];
27714
28236
  if (Array.isArray(receipts)) {
27715
28237
  for (const receipt of receipts) {
27716
- if (!isObject12(receipt)) {
28238
+ if (!isObject13(receipt)) {
27717
28239
  continue;
27718
28240
  }
27719
28241
  const agent = receipt["agent"];
@@ -27722,7 +28244,7 @@ function validateModelRoutingExistence(state) {
27722
28244
  }
27723
28245
  }
27724
28246
  }
27725
- return [...delegated].filter((agent) => !receiptAgents2.has(agent)).sort().map(
28247
+ return [...delegated].filter((agent) => !receiptAgents2.has(agent)).sort(compareCodePoint).map(
27726
28248
  (agent) => `Checkpoint model_routing_receipts is missing a receipt for delegated agent: ${agent}.`
27727
28249
  );
27728
28250
  }
@@ -27762,15 +28284,6 @@ var VALID_STEP_STATUS = /* @__PURE__ */ new Set([
27762
28284
  "in_progress",
27763
28285
  "completed"
27764
28286
  ]);
27765
- var VALID_BLOCKED_REASONS = /* @__PURE__ */ new Set([
27766
- "none",
27767
- "spawn_agent_unavailable",
27768
- "delegation_launch_failed",
27769
- "delegate_no_receipt",
27770
- "delegate_contract_incomplete",
27771
- "validator_failed",
27772
- "user_requested_stop"
27773
- ]);
27774
28287
  var REQUIRED_RECEIPT_KEYS = [
27775
28288
  "step",
27776
28289
  "agent_name",
@@ -27810,13 +28323,13 @@ function isValidStepStatus(key, value) {
27810
28323
  }
27811
28324
  return STEP_SPECIFIC_EXTRA_STATUS.get(key)?.has(value) === true;
27812
28325
  }
27813
- function isObject13(value) {
28326
+ function isObject14(value) {
27814
28327
  return typeof value === "object" && value !== null && !Array.isArray(value);
27815
28328
  }
27816
28329
  function validateListDelegationReceipts(receipts) {
27817
28330
  const errors = [];
27818
28331
  receipts.forEach((receipt, index) => {
27819
- if (!isObject13(receipt)) {
28332
+ if (!isObject14(receipt)) {
27820
28333
  errors.push(`Checkpoint delegation receipt #${index} must be an object.`);
27821
28334
  return;
27822
28335
  }
@@ -27840,7 +28353,7 @@ function validateNamespacedDelegationReceipts(receipts) {
27840
28353
  const errors = [];
27841
28354
  const unsupportedKeys = Object.keys(receipts).filter(
27842
28355
  (key) => key !== AGENT_RECEIPT_NAMESPACE_KEY && key !== PROMOTION_RECEIPT_NAMESPACE_KEY
27843
- ).sort();
28356
+ ).sort(compareCodePoint);
27844
28357
  for (const key of unsupportedKeys) {
27845
28358
  errors.push(
27846
28359
  `Checkpoint delegation_receipts object contains unsupported key: ${key}`
@@ -27858,7 +28371,7 @@ function validateNamespacedDelegationReceipts(receipts) {
27858
28371
  if (promotionReceipts === void 0 || promotionReceipts === null) {
27859
28372
  return errors;
27860
28373
  }
27861
- if (!isObject13(promotionReceipts)) {
28374
+ if (!isObject14(promotionReceipts)) {
27862
28375
  errors.push(
27863
28376
  "Checkpoint delegation_receipts.promotion must be an object namespace."
27864
28377
  );
@@ -27866,7 +28379,7 @@ function validateNamespacedDelegationReceipts(receipts) {
27866
28379
  }
27867
28380
  const unsupportedPromotionKeys = Object.keys(promotionReceipts).filter(
27868
28381
  (key) => !PROMOTION_RECEIPT_KEYS.includes(key)
27869
- ).sort();
28382
+ ).sort(compareCodePoint);
27870
28383
  for (const key of unsupportedPromotionKeys) {
27871
28384
  errors.push(
27872
28385
  "Checkpoint delegation_receipts.promotion contains unsupported key: " + key
@@ -27893,7 +28406,7 @@ function validateOrchestratorStateText(text2, options = {}) {
27893
28406
  `Checkpoint is not valid JSON: ${exc instanceof Error ? exc.message : String(exc)}`
27894
28407
  ];
27895
28408
  }
27896
- if (!isObject13(state)) {
28409
+ if (!isObject14(state)) {
27897
28410
  return ["Checkpoint root must be a JSON object."];
27898
28411
  }
27899
28412
  const stateMap = state;
@@ -27918,7 +28431,7 @@ function validateOrchestratorStateText(text2, options = {}) {
27918
28431
  if (receipts !== void 0 && receipts !== null) {
27919
28432
  if (Array.isArray(receipts)) {
27920
28433
  errors.push(...validateListDelegationReceipts(receipts));
27921
- } else if (isObject13(receipts)) {
28434
+ } else if (isObject14(receipts)) {
27922
28435
  errors.push(...validateNamespacedDelegationReceipts(receipts));
27923
28436
  } else {
27924
28437
  errors.push(
@@ -28336,7 +28849,7 @@ function classifyKind(argv) {
28336
28849
  }
28337
28850
  return "other";
28338
28851
  }
28339
- function splitLines2(text2) {
28852
+ function splitPlanLines(text2) {
28340
28853
  if (text2 === "") {
28341
28854
  return [];
28342
28855
  }
@@ -28346,6 +28859,11 @@ function splitLines2(text2) {
28346
28859
  }
28347
28860
  return lines;
28348
28861
  }
28862
+ var PLAN_WHITESPACE_CLASS = String.raw`[\t\n\v\f\r \u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]`;
28863
+ var PLAN_WHITESPACE_RUN_RE = new RegExp(`${PLAN_WHITESPACE_CLASS}+`);
28864
+ function normalizePlanWhitespace(value) {
28865
+ return value.split(PLAN_WHITESPACE_RUN_RE).filter((word) => word !== "").join(" ");
28866
+ }
28349
28867
  function inlineSpans(line) {
28350
28868
  const spans = [];
28351
28869
  for (const match of line.matchAll(INLINE_SPAN_RE)) {
@@ -28389,7 +28907,7 @@ function extractPlanCommands(text2) {
28389
28907
  let inFence = false;
28390
28908
  let windowLines = [];
28391
28909
  let windowStart = 0;
28392
- const lines = splitLines2(text2);
28910
+ const lines = splitPlanLines(text2);
28393
28911
  for (let index = 0; index < lines.length; index += 1) {
28394
28912
  const line = lines[index] ?? "";
28395
28913
  const lineNumber = index + 1;
@@ -28559,7 +29077,7 @@ function planQuotesLiteral(text2, literal2, excludeSpan) {
28559
29077
  return normalizeWhitespace(remainder).includes(needle);
28560
29078
  }
28561
29079
  function windowJoin(lines, size = WINDOW_SIZE) {
28562
- const dense = lines.filter((line) => line.trim() !== "").map((line) => normalizeWhitespace(line));
29080
+ const dense = lines.map((line) => normalizePlanWhitespace(line)).filter((line) => line !== "");
28563
29081
  const windows = [];
28564
29082
  for (let index = 0; index < dense.length; index += 1) {
28565
29083
  windows.push(dense.slice(index, index + size).join(" "));
@@ -28567,15 +29085,15 @@ function windowJoin(lines, size = WINDOW_SIZE) {
28567
29085
  return windows;
28568
29086
  }
28569
29087
  function hasCrossLinePresence(context, literal2) {
28570
- const words2 = literal2.split(/\s+/).filter((word) => word !== "");
29088
+ const needle = normalizePlanWhitespace(literal2);
29089
+ const words2 = needle.split(" ");
28571
29090
  if (words2.length < 2) {
28572
29091
  return false;
28573
29092
  }
28574
- const needle = words2.join(" ");
28575
29093
  const firstWord = words2[0] ?? "";
28576
29094
  for (const path16 of context.git.filesContaining(firstWord)) {
28577
29095
  const lines = context.git.readTrackedText(path16).split(/\r\n|\n|\r/);
28578
- if (lines.some((line) => normalizeWhitespace(line).includes(needle))) {
29096
+ if (lines.some((line) => normalizePlanWhitespace(line).includes(needle))) {
28579
29097
  continue;
28580
29098
  }
28581
29099
  if (windowJoin(lines).some((window2) => window2.includes(needle))) {
@@ -28821,6 +29339,71 @@ function evaluateObservabilityGates(report, commands, context) {
28821
29339
  }
28822
29340
  }
28823
29341
 
29342
+ // ../../extensions/drm-copilot/src/lib/validate/plan-gate-scratch.ts
29343
+ var G10_SEVERITY = "blocking";
29344
+ var BACKTICK = "`";
29345
+ var SCRATCH_DEFINITION_PATTERN = String.raw`(?:^|[^A-Za-z0-9_<>$/.-])${BACKTICK}?SCRATCH${BACKTICK}?(?:\*\*)?[ \t]*(?:means\b|:=|=|:|is (?:the|a|an)\b|resolves to\b|abbreviates\b|denotes\b|refers to\b|stands for\b)`;
29346
+ var SCRATCH_NAMESPACE_PATTERN = String.raw`issue-(?:<issue-num>|[0-9]+)`;
29347
+ var FENCE_RE2 = /^\s*```/;
29348
+ var DEFINITION_RE = new RegExp(SCRATCH_DEFINITION_PATTERN);
29349
+ var NAMESPACE_RE = new RegExp(SCRATCH_NAMESPACE_PATTERN);
29350
+ var LEADING_WHITESPACE_RE = new RegExp(`^${PLAN_WHITESPACE_CLASS}`);
29351
+ function continuesLogicalLine(line) {
29352
+ if (normalizePlanWhitespace(line) === "" || !LEADING_WHITESPACE_RE.test(line)) {
29353
+ return false;
29354
+ }
29355
+ return !FENCE_RE2.test(line);
29356
+ }
29357
+ function isBareDefinition(logical) {
29358
+ const match = DEFINITION_RE.exec(logical);
29359
+ if (match === null) {
29360
+ return false;
29361
+ }
29362
+ return !NAMESPACE_RE.test(logical.slice(match.index + match[0].length));
29363
+ }
29364
+ function recordIfBare(findings, pending) {
29365
+ const logical = normalizePlanWhitespace(pending.parts.join(" "));
29366
+ if (isBareDefinition(logical)) {
29367
+ findings.push([pending.start + 1, logical]);
29368
+ }
29369
+ }
29370
+ function bareScratchDefinitions(text2) {
29371
+ const findings = [];
29372
+ let inFence = false;
29373
+ let pending = null;
29374
+ for (const [index, line] of splitPlanLines(text2).entries()) {
29375
+ if (pending !== null && continuesLogicalLine(line)) {
29376
+ pending.parts.push(line);
29377
+ continue;
29378
+ }
29379
+ if (pending !== null) {
29380
+ recordIfBare(findings, pending);
29381
+ pending = null;
29382
+ }
29383
+ if (FENCE_RE2.test(line)) {
29384
+ inFence = !inFence;
29385
+ continue;
29386
+ }
29387
+ if (inFence || normalizePlanWhitespace(line) === "") {
29388
+ continue;
29389
+ }
29390
+ pending = { start: index, parts: [line] };
29391
+ }
29392
+ if (pending !== null) {
29393
+ recordIfBare(findings, pending);
29394
+ }
29395
+ return findings;
29396
+ }
29397
+ function scratchFindingMessage(lineNumber, logicalLine) {
29398
+ return `Line ${String(lineNumber)}: SCRATCH definition \`${logicalLine}\` is not namespaced by issue number; define SCRATCH as \`<session scratchpad>/issue-<issue-num>/\`.`;
29399
+ }
29400
+ function evaluateScratchGate(report, text2, severity = G10_SEVERITY) {
29401
+ const channel = severity === "blocking" ? report.blocking : report.warnings;
29402
+ for (const [lineNumber, logicalLine] of bareScratchDefinitions(text2)) {
29403
+ channel.push(scratchFindingMessage(lineNumber, logicalLine));
29404
+ }
29405
+ }
29406
+
28824
29407
  // ../../extensions/drm-copilot/src/lib/validate/plan-gate-discrimination.ts
28825
29408
  var G5_SEVERITY = "warning";
28826
29409
  var CommandRunnerPlanGateRepository = class {
@@ -28920,6 +29503,7 @@ function evaluatePlanGates(text2, context) {
28920
29503
  if (context !== void 0) {
28921
29504
  evaluateLiteralRules(report, text2, commands, context);
28922
29505
  }
29506
+ evaluateScratchGate(report, text2);
28923
29507
  return report;
28924
29508
  }
28925
29509
 
@@ -28955,10 +29539,10 @@ var PROHIBITED_ANY_LEVEL_KEYS = words(
28955
29539
  "depends_on integration_branch epic_merge_pr"
28956
29540
  );
28957
29541
  var ROOT_PATH = "<root>";
28958
- function isObject14(value) {
29542
+ function isObject15(value) {
28959
29543
  return typeof value === "object" && value !== null && !Array.isArray(value);
28960
29544
  }
28961
- function pythonRepr9(value) {
29545
+ function pythonRepr10(value) {
28962
29546
  if (value === null || value === void 0) {
28963
29547
  return "None";
28964
29548
  }
@@ -28969,18 +29553,18 @@ function pythonRepr9(value) {
28969
29553
  return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
28970
29554
  }
28971
29555
  if (Array.isArray(value)) {
28972
- return `[${value.map(pythonRepr9).join(", ")}]`;
29556
+ return `[${value.map(pythonRepr10).join(", ")}]`;
28973
29557
  }
28974
- if (isObject14(value)) {
29558
+ if (isObject15(value)) {
28975
29559
  const pairs = Object.entries(value).map(
28976
- ([key, item]) => `${pythonRepr9(key)}: ${pythonRepr9(item)}`
29560
+ ([key, item]) => `${pythonRepr10(key)}: ${pythonRepr10(item)}`
28977
29561
  );
28978
29562
  return `{${pairs.join(", ")}}`;
28979
29563
  }
28980
29564
  return String(value);
28981
29565
  }
28982
29566
  function pythonStr2(value) {
28983
- return typeof value === "string" ? value : pythonRepr9(value);
29567
+ return typeof value === "string" ? value : pythonRepr10(value);
28984
29568
  }
28985
29569
  function isEnumMember(members, value) {
28986
29570
  return typeof value === "string" && members.includes(value);
@@ -29004,13 +29588,13 @@ function inBoundedRange(value, minimum, maximum) {
29004
29588
  return isIntegral(value) && value >= minimum && value <= maximum;
29005
29589
  }
29006
29590
  function enumError(context, field, members, value) {
29007
- return `${context} ${field} must be one of ${members.join(", ")}; found: ${pythonRepr9(value)}.`;
29591
+ return `${context} ${field} must be one of ${members.join(", ")}; found: ${pythonRepr10(value)}.`;
29008
29592
  }
29009
29593
  function itemContext(context, index) {
29010
29594
  return `${context} items[${index}]`;
29011
29595
  }
29012
29596
  function validateBlastRadiusBlock(radius, context) {
29013
- if (!isObject14(radius)) {
29597
+ if (!isObject15(radius)) {
29014
29598
  return [`${context} blast_radius must be an object.`];
29015
29599
  }
29016
29600
  const errors = [];
@@ -29046,25 +29630,25 @@ function validateMergeStatus(record3, context, state) {
29046
29630
  }
29047
29631
  if (isEnumMember(MERGED_MERGE_STATUSES, mergeStatus) && state !== "merged") {
29048
29632
  return [
29049
- `${context} merge_status ${pythonRepr9(mergeStatus)} requires state 'merged'; found: ${pythonRepr9(state)}.`
29633
+ `${context} merge_status ${pythonRepr10(mergeStatus)} requires state 'merged'; found: ${pythonRepr10(state)}.`
29050
29634
  ];
29051
29635
  }
29052
29636
  if (isEnumMember(BLOCKED_MERGE_STATUSES, mergeStatus) && state !== "blocked") {
29053
29637
  return [
29054
- `${context} merge_status ${pythonRepr9(mergeStatus)} requires state 'blocked'; found: ${pythonRepr9(state)}.`
29638
+ `${context} merge_status ${pythonRepr10(mergeStatus)} requires state 'blocked'; found: ${pythonRepr10(state)}.`
29055
29639
  ];
29056
29640
  }
29057
29641
  return [];
29058
29642
  }
29059
29643
  function validateItemRecord(item, context, requireKind = false) {
29060
- if (!isObject14(item)) {
29644
+ if (!isObject15(item)) {
29061
29645
  return [`${context} must be an object.`];
29062
29646
  }
29063
29647
  const errors = [];
29064
29648
  const issueNum = item["issue_num"];
29065
29649
  if (!isPositiveInteger(issueNum)) {
29066
29650
  errors.push(
29067
- `${context} issue_num must be a positive integer; found: ${pythonRepr9(issueNum)}.`
29651
+ `${context} issue_num must be a positive integer; found: ${pythonRepr10(issueNum)}.`
29068
29652
  );
29069
29653
  }
29070
29654
  if (!isNonEmptyString2(item["feature_folder"])) {
@@ -29095,7 +29679,7 @@ function validateItems(items, context, requireKind = false) {
29095
29679
  errors.push(
29096
29680
  ...validateItemRecord(entry, itemContext(context, index), requireKind)
29097
29681
  );
29098
- if (!isObject14(entry)) {
29682
+ if (!isObject15(entry)) {
29099
29683
  return;
29100
29684
  }
29101
29685
  const issueNum = entry["issue_num"];
@@ -29114,7 +29698,7 @@ function validateItems(items, context, requireKind = false) {
29114
29698
  }
29115
29699
  function prohibitedKeyErrors(value, path16, context, keys) {
29116
29700
  const errors = [];
29117
- if (isObject14(value)) {
29701
+ if (isObject15(value)) {
29118
29702
  for (const [key, child] of Object.entries(value)) {
29119
29703
  if (keys.includes(key)) {
29120
29704
  errors.push(`${context} carries prohibited key '${key}' at ${path16}.`);
@@ -29133,7 +29717,7 @@ function prohibitedKeyErrors(value, path16, context, keys) {
29133
29717
  }
29134
29718
  function scanProhibitedKeys(root, context, deepKeys = PROHIBITED_ANY_LEVEL_KEYS, topLevelKeys = []) {
29135
29719
  const errors = prohibitedKeyErrors(root, ROOT_PATH, context, deepKeys);
29136
- if (isObject14(root) && topLevelKeys.length > 0) {
29720
+ if (isObject15(root) && topLevelKeys.length > 0) {
29137
29721
  for (const key of topLevelKeys) {
29138
29722
  if (key in root) {
29139
29723
  errors.push(
@@ -29149,7 +29733,7 @@ function scanProhibitedKeys(root, context, deepKeys = PROHIBITED_ANY_LEVEL_KEYS,
29149
29733
  var VIOLATION_PREFIX = "PARALLEL_COHORT_BARRIER_VIOLATION";
29150
29734
  var ITEM_START_TIMESTAMP_FIELD = "worktree_created_at";
29151
29735
  var MERGE_CONFIRMATION_TIMESTAMP_FIELD = "merged_at";
29152
- var NOT_STARTED_MERGE_STATUS = "not_started";
29736
+ var NOT_STARTED_MERGE_STATUS2 = "not_started";
29153
29737
  var GATING_KEYS = ["conflict_edges", "cohorts"];
29154
29738
  var FOLDER_HINT_PREFIXES = [
29155
29739
  "docs/features/active/",
@@ -29172,7 +29756,7 @@ function buildReferenceIndex(items) {
29172
29756
  return { records, byFolderHint };
29173
29757
  }
29174
29758
  for (const entry of items) {
29175
- if (!isObject14(entry)) {
29759
+ if (!isObject15(entry)) {
29176
29760
  continue;
29177
29761
  }
29178
29762
  const issueNum = entry["issue_num"];
@@ -29207,7 +29791,7 @@ function cohortIndexByItem(cohorts, recolorGeneration, references) {
29207
29791
  return assignments;
29208
29792
  }
29209
29793
  for (const entry of cohorts) {
29210
- if (!isObject14(entry) || entry["generation"] !== recolorGeneration) {
29794
+ if (!isObject15(entry) || entry["generation"] !== recolorGeneration) {
29211
29795
  continue;
29212
29796
  }
29213
29797
  const cohortIndex = entry["index"];
@@ -29224,13 +29808,13 @@ function cohortIndexByItem(cohorts, recolorGeneration, references) {
29224
29808
  }
29225
29809
  return assignments;
29226
29810
  }
29227
- function hasStarted(record3) {
29811
+ function hasStarted2(record3) {
29228
29812
  const start = record3[ITEM_START_TIMESTAMP_FIELD];
29229
29813
  if (typeof start === "string" && start.trim().length > 0) {
29230
29814
  return true;
29231
29815
  }
29232
29816
  const mergeStatus = record3["merge_status"];
29233
- return typeof mergeStatus === "string" && mergeStatus !== NOT_STARTED_MERGE_STATUS;
29817
+ return typeof mergeStatus === "string" && mergeStatus !== NOT_STARTED_MERGE_STATUS2;
29234
29818
  }
29235
29819
  function satisfiesBarrier(record3) {
29236
29820
  return isEnumMember(MERGED_MERGE_STATUSES, record3["merge_status"]);
@@ -29258,7 +29842,7 @@ function violationEndpoints(first, second, assignments, records) {
29258
29842
  if (earlier === void 0 || later === void 0) {
29259
29843
  return null;
29260
29844
  }
29261
- const statusViolation = hasStarted(later) && !satisfiesBarrier(earlier);
29845
+ const statusViolation = hasStarted2(later) && !satisfiesBarrier(earlier);
29262
29846
  if (statusViolation || mergeConfirmedAfterStart(earlier, later)) {
29263
29847
  return [earlierKey, laterKey];
29264
29848
  }
@@ -29280,7 +29864,7 @@ function validateCohortBarrierOrdering(state) {
29280
29864
  );
29281
29865
  const errors = [];
29282
29866
  for (const entry of edges) {
29283
- if (!isObject14(entry)) {
29867
+ if (!isObject15(entry)) {
29284
29868
  continue;
29285
29869
  }
29286
29870
  const first = resolveReference(entry["a"], references);
@@ -29318,14 +29902,14 @@ function validateMutationItemKey(entry, entryContext, op, issueNums) {
29318
29902
  if (op === "close") {
29319
29903
  if (!isNone(itemKey)) {
29320
29904
  return [
29321
- `${entryContext} item_key must be null for op 'close'; found: ${pythonRepr9(itemKey)}.`
29905
+ `${entryContext} item_key must be null for op 'close'; found: ${pythonRepr10(itemKey)}.`
29322
29906
  ];
29323
29907
  }
29324
29908
  return [];
29325
29909
  }
29326
29910
  if (isEnumMember(OPS_REQUIRING_ITEM_KEY, op) && !resolves(itemKey, issueNums)) {
29327
29911
  return [
29328
- `${entryContext} item_key ${pythonRepr9(itemKey)} does not resolve to an items[].issue_num.`
29912
+ `${entryContext} item_key ${pythonRepr10(itemKey)} does not resolve to an items[].issue_num.`
29329
29913
  ];
29330
29914
  }
29331
29915
  return [];
@@ -29337,12 +29921,12 @@ function validateMutationStateField(entry, entryContext, field, op, nullOps) {
29337
29921
  }
29338
29922
  if (isEnumMember(nullOps, op)) {
29339
29923
  return [
29340
- `${entryContext} ${field} must be null for op ${pythonRepr9(op)}; found: ${pythonRepr9(value)}.`
29924
+ `${entryContext} ${field} must be null for op ${pythonRepr10(op)}; found: ${pythonRepr10(value)}.`
29341
29925
  ];
29342
29926
  }
29343
29927
  if (!isEnumMember(VALID_ITEM_STATES, value)) {
29344
29928
  return [
29345
- `${entryContext} ${field} must be null or one of ${VALID_ITEM_STATES.join(", ")}; found: ${pythonRepr9(value)}.`
29929
+ `${entryContext} ${field} must be null or one of ${VALID_ITEM_STATES.join(", ")}; found: ${pythonRepr10(value)}.`
29346
29930
  ];
29347
29931
  }
29348
29932
  return [];
@@ -29352,14 +29936,14 @@ function validateMutationDisposition(entry, entryContext, op) {
29352
29936
  if (op === "remove" && entry["prior_state"] === "in_flight") {
29353
29937
  if (!isEnumMember(VALID_DISPOSITIONS, disposition)) {
29354
29938
  return [
29355
- `${entryContext} disposition must be one of ${VALID_DISPOSITIONS.join(", ")} for an in-flight removal; found: ${pythonRepr9(disposition)}.`
29939
+ `${entryContext} disposition must be one of ${VALID_DISPOSITIONS.join(", ")} for an in-flight removal; found: ${pythonRepr10(disposition)}.`
29356
29940
  ];
29357
29941
  }
29358
29942
  return [];
29359
29943
  }
29360
29944
  if (!isNone(disposition)) {
29361
29945
  return [
29362
- `${entryContext} disposition must be null unless op is 'remove' with prior_state 'in_flight'; found: ${pythonRepr9(disposition)}.`
29946
+ `${entryContext} disposition must be null unless op is 'remove' with prior_state 'in_flight'; found: ${pythonRepr10(disposition)}.`
29363
29947
  ];
29364
29948
  }
29365
29949
  return [];
@@ -29368,7 +29952,7 @@ function validateMutationGeneration(entry, entryContext, recolorGeneration) {
29368
29952
  const generation = entry["recolor_generation"];
29369
29953
  if (!isNonNegativeInteger(generation)) {
29370
29954
  return [
29371
- `${entryContext} recolor_generation must be a non-negative integer; found: ${pythonRepr9(generation)}.`
29955
+ `${entryContext} recolor_generation must be a non-negative integer; found: ${pythonRepr10(generation)}.`
29372
29956
  ];
29373
29957
  }
29374
29958
  if (isNonNegativeInteger(recolorGeneration) && typeof generation === "number" && typeof recolorGeneration === "number" && generation > recolorGeneration) {
@@ -29385,7 +29969,7 @@ function validateMutations(mutations, issueNums, recolorGeneration, context) {
29385
29969
  const errors = [];
29386
29970
  mutations.forEach((entry, position) => {
29387
29971
  const entryContext = `${context} mutations[${position}]`;
29388
- if (!isObject14(entry)) {
29972
+ if (!isObject15(entry)) {
29389
29973
  errors.push(`${entryContext} must be an object.`);
29390
29974
  return;
29391
29975
  }
@@ -29429,14 +30013,14 @@ function validateDriftEvents(events, issueNums, context) {
29429
30013
  const errors = [];
29430
30014
  events.forEach((entry, position) => {
29431
30015
  const entryContext = `${context} drift_events[${position}]`;
29432
- if (!isObject14(entry)) {
30016
+ if (!isObject15(entry)) {
29433
30017
  errors.push(`${entryContext} must be an object.`);
29434
30018
  return;
29435
30019
  }
29436
30020
  const itemKey = entry["item_key"];
29437
30021
  if (!resolves(itemKey, issueNums)) {
29438
30022
  errors.push(
29439
- `${entryContext} item_key ${pythonRepr9(itemKey)} does not resolve to an items[].issue_num.`
30023
+ `${entryContext} item_key ${pythonRepr10(itemKey)} does not resolve to an items[].issue_num.`
29440
30024
  );
29441
30025
  }
29442
30026
  for (const field of ["declared", "observed"]) {
@@ -29474,7 +30058,7 @@ function collectItemKeysAndStates(items) {
29474
30058
  return pairs;
29475
30059
  }
29476
30060
  for (const entry of items) {
29477
- if (!isObject14(entry)) {
30061
+ if (!isObject15(entry)) {
29478
30062
  continue;
29479
30063
  }
29480
30064
  const issueNum = entry["issue_num"];
@@ -29492,13 +30076,13 @@ function validateCohortEntry(entry, entryContext, issueNums, recolorGeneration)
29492
30076
  const index = entry["index"];
29493
30077
  if (!isNonNegativeInteger(index)) {
29494
30078
  errors.push(
29495
- `${entryContext} index must be a non-negative integer; found: ${pythonRepr9(index)}.`
30079
+ `${entryContext} index must be a non-negative integer; found: ${pythonRepr10(index)}.`
29496
30080
  );
29497
30081
  }
29498
30082
  const generation = entry["generation"];
29499
30083
  if (!isNonNegativeInteger(generation)) {
29500
30084
  errors.push(
29501
- `${entryContext} generation must be a non-negative integer; found: ${pythonRepr9(generation)}.`
30085
+ `${entryContext} generation must be a non-negative integer; found: ${pythonRepr10(generation)}.`
29502
30086
  );
29503
30087
  } else if (recolorGeneration !== null && typeof generation === "number" && generation > recolorGeneration) {
29504
30088
  errors.push(
@@ -29513,7 +30097,7 @@ function validateCohortEntry(entry, entryContext, issueNums, recolorGeneration)
29513
30097
  for (const key of itemKeys) {
29514
30098
  if (typeof key !== "number" || !Number.isInteger(key) || !issueNums.has(key)) {
29515
30099
  errors.push(
29516
- `${entryContext} item_keys entry ${pythonRepr9(key)} does not resolve to an items[].issue_num.`
30100
+ `${entryContext} item_keys entry ${pythonRepr10(key)} does not resolve to an items[].issue_num.`
29517
30101
  );
29518
30102
  }
29519
30103
  }
@@ -29524,7 +30108,7 @@ function validateCohortShapes(cohorts, issueNums, recolorGeneration, context) {
29524
30108
  const generationOk = isNonNegativeInteger(recolorGeneration);
29525
30109
  if (!generationOk) {
29526
30110
  errors.push(
29527
- `${context} recolor_generation must be a non-negative integer; found: ${pythonRepr9(recolorGeneration)}.`
30111
+ `${context} recolor_generation must be a non-negative integer; found: ${pythonRepr10(recolorGeneration)}.`
29528
30112
  );
29529
30113
  }
29530
30114
  if (!Array.isArray(cohorts)) {
@@ -29534,7 +30118,7 @@ function validateCohortShapes(cohorts, issueNums, recolorGeneration, context) {
29534
30118
  const bound = generationOk && typeof recolorGeneration === "number" ? recolorGeneration : null;
29535
30119
  cohorts.forEach((entry, position) => {
29536
30120
  const entryContext = `${context} cohorts[${position}]`;
29537
- if (!isObject14(entry)) {
30121
+ if (!isObject15(entry)) {
29538
30122
  errors.push(`${entryContext} must be an object.`);
29539
30123
  return;
29540
30124
  }
@@ -29546,7 +30130,7 @@ function currentGenerationCohorts(cohorts, recolorGeneration) {
29546
30130
  if (!isNonNegativeInteger(recolorGeneration) || !Array.isArray(cohorts)) {
29547
30131
  return [];
29548
30132
  }
29549
- return cohorts.filter(isObject14).filter((entry) => entry["generation"] === recolorGeneration);
30133
+ return cohorts.filter(isObject15).filter((entry) => entry["generation"] === recolorGeneration);
29550
30134
  }
29551
30135
  function validateCurrentGenerationCohorts(cohorts, items, recolorGeneration, context) {
29552
30136
  const current = currentGenerationCohorts(cohorts, recolorGeneration);
@@ -29591,7 +30175,7 @@ function validateCurrentGenerationCohorts(cohorts, items, recolorGeneration, con
29591
30175
  continue;
29592
30176
  }
29593
30177
  errors.push(
29594
- `${context} item ${issueNum} in state ${pythonRepr9(state)} must appear in exactly one current-generation cohort; found ${count}.`
30178
+ `${context} item ${issueNum} in state ${pythonRepr10(state)} must appear in exactly one current-generation cohort; found ${count}.`
29595
30179
  );
29596
30180
  }
29597
30181
  return errors;
@@ -29599,7 +30183,7 @@ function validateCurrentGenerationCohorts(cohorts, items, recolorGeneration, con
29599
30183
  function validateCurrentCohortBound(currentCohort, cohorts, recolorGeneration, context) {
29600
30184
  if (!isNonNegativeInteger(currentCohort) || typeof currentCohort !== "number") {
29601
30185
  return [
29602
- `${context} current_cohort must be a non-negative integer; found: ${pythonRepr9(currentCohort)}.`
30186
+ `${context} current_cohort must be a non-negative integer; found: ${pythonRepr10(currentCohort)}.`
29603
30187
  ];
29604
30188
  }
29605
30189
  const indices = [];
@@ -29629,7 +30213,7 @@ function validateEdgeEndpoints(entry, entryContext, issueNums) {
29629
30213
  endpoints.set(field, value);
29630
30214
  } else {
29631
30215
  errors.push(
29632
- `${entryContext} ${field} ${pythonRepr9(value)} does not resolve to an items[].issue_num.`
30216
+ `${entryContext} ${field} ${pythonRepr10(value)} does not resolve to an items[].issue_num.`
29633
30217
  );
29634
30218
  }
29635
30219
  }
@@ -29659,7 +30243,7 @@ function validateConflictEdges(edges, issueNums, context) {
29659
30243
  const duplicates = /* @__PURE__ */ new Map();
29660
30244
  edges.forEach((entry, position) => {
29661
30245
  const entryContext = `${context} conflict_edges[${position}]`;
29662
- if (!isObject14(entry)) {
30246
+ if (!isObject15(entry)) {
29663
30247
  errors.push(`${entryContext} must be an object.`);
29664
30248
  return;
29665
30249
  }
@@ -29738,7 +30322,7 @@ function validateIdentity(state) {
29738
30322
  const routeId = state["route_id"];
29739
30323
  if ("route_id" in state && routeId !== EXPECTED_ROUTE_ID2) {
29740
30324
  errors.push(
29741
- `${CONTEXT} route_id must be '${EXPECTED_ROUTE_ID2}'; found: ${pythonRepr9(routeId)}.`
30325
+ `${CONTEXT} route_id must be '${EXPECTED_ROUTE_ID2}'; found: ${pythonRepr10(routeId)}.`
29742
30326
  );
29743
30327
  }
29744
30328
  const mode = state["mode"];
@@ -29748,7 +30332,7 @@ function validateIdentity(state) {
29748
30332
  const concurrency = state["max_concurrency"];
29749
30333
  if ("max_concurrency" in state && !inBoundedRange(concurrency, MIN_CONCURRENCY, MAX_CONCURRENCY)) {
29750
30334
  errors.push(
29751
- `${CONTEXT} max_concurrency must be an integer from ${MIN_CONCURRENCY} through ${MAX_CONCURRENCY}; found: ${pythonRepr9(concurrency)}.`
30335
+ `${CONTEXT} max_concurrency must be an integer from ${MIN_CONCURRENCY} through ${MAX_CONCURRENCY}; found: ${pythonRepr10(concurrency)}.`
29752
30336
  );
29753
30337
  }
29754
30338
  return errors;
@@ -29804,7 +30388,7 @@ function recordsCloseMutation(state) {
29804
30388
  return false;
29805
30389
  }
29806
30390
  return mutations.some(
29807
- (entry) => isObject14(entry) && entry["op"] === "close"
30391
+ (entry) => isObject15(entry) && entry["op"] === "close"
29808
30392
  );
29809
30393
  }
29810
30394
  function validateCompletion2(state) {
@@ -29812,7 +30396,7 @@ function validateCompletion2(state) {
29812
30396
  const items = state["items"];
29813
30397
  const entries = Array.isArray(items) ? items : [];
29814
30398
  entries.forEach((entry, index) => {
29815
- if (!isObject14(entry)) {
30399
+ if (!isObject15(entry)) {
29816
30400
  return;
29817
30401
  }
29818
30402
  if (entry["state"] === "withdrawn") {
@@ -29821,7 +30405,7 @@ function validateCompletion2(state) {
29821
30405
  const mergeStatus = entry["merge_status"];
29822
30406
  if (!isEnumMember(MERGED_MERGE_STATUSES, mergeStatus)) {
29823
30407
  errors.push(
29824
- `${itemContext(CONTEXT, index)} completion validation failed: merge_status is not merged or worktree_removed; found: ${pythonRepr9(mergeStatus)}.`
30408
+ `${itemContext(CONTEXT, index)} completion validation failed: merge_status is not merged or worktree_removed; found: ${pythonRepr10(mergeStatus)}.`
29825
30409
  );
29826
30410
  }
29827
30411
  });
@@ -29840,7 +30424,7 @@ function validateParallelOrchestratorStateText(text2, options = {}) {
29840
30424
  const detail = error2 instanceof Error ? error2.message : String(error2);
29841
30425
  return [`${CONTEXT} is not valid JSON: ${detail}.`];
29842
30426
  }
29843
- if (!isObject14(state)) {
30427
+ if (!isObject15(state)) {
29844
30428
  return [`${CONTEXT} root must be a JSON object.`];
29845
30429
  }
29846
30430
  const errors = [];
@@ -29855,6 +30439,110 @@ function validateParallelOrchestratorStateText(text2, options = {}) {
29855
30439
  return errors;
29856
30440
  }
29857
30441
 
30442
+ // ../../extensions/drm-copilot/src/lib/validate/parallel-planner-state-routing.ts
30443
+ var BAND_ORDER2 = ["C1", "C2", "C3", "C4"];
30444
+ var VALID_FABLE_POLICIES = [
30445
+ "disabled",
30446
+ "available",
30447
+ "preferred"
30448
+ ];
30449
+ var ROUTING_AGENT = "orchestrator";
30450
+ function sameValue(left, right) {
30451
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
30452
+ }
30453
+ function isListOfStrings(value) {
30454
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
30455
+ }
30456
+ function validateAssessmentEntry(assessment, context) {
30457
+ const errors = [];
30458
+ const band = assessment["band"];
30459
+ const floor = assessment["floor"];
30460
+ if (!isEnumMember(BAND_ORDER2, band)) {
30461
+ errors.push(
30462
+ `${context} band must be one of C1, C2, C3, C4; got: ${pythonStr2(band)}.`
30463
+ );
30464
+ }
30465
+ if (!isListOfStrings(assessment["signals_present"])) {
30466
+ errors.push(`${context} signals_present must be a list of strings.`);
30467
+ }
30468
+ if (isEnumMember(BAND_ORDER2, band) && isEnumMember(BAND_ORDER2, floor) && BAND_ORDER2.indexOf(String(band)) < BAND_ORDER2.indexOf(String(floor))) {
30469
+ errors.push(
30470
+ `${context} band ${pythonStr2(band)} is below its floor ${pythonStr2(floor)}.`
30471
+ );
30472
+ }
30473
+ if (!isNonEmptyString2(assessment["rationale"])) {
30474
+ errors.push(`${context} rationale must be a non-empty string.`);
30475
+ }
30476
+ return errors;
30477
+ }
30478
+ function validateAssessment(assessment, band, entryContext) {
30479
+ const context = `${entryContext} complexity_assessment`;
30480
+ const errors = validateAssessmentEntry(assessment, context);
30481
+ if (!isNonEmptyString2(assessment["assessed_at"])) {
30482
+ errors.push(`${context}.assessed_at must be a non-empty string.`);
30483
+ }
30484
+ const assessedBand = assessment["band"];
30485
+ if (!sameValue(assessedBand, band)) {
30486
+ errors.push(
30487
+ `${context}.band ${pythonRepr10(assessedBand)} does not equal complexity_band ${pythonRepr10(band)}.`
30488
+ );
30489
+ }
30490
+ return errors;
30491
+ }
30492
+ function validateReceipt4(receipt, band, entryContext) {
30493
+ const context = `${entryContext} model_routing_receipt`;
30494
+ const errors = [];
30495
+ const receiptBand = receipt["complexity_band"];
30496
+ if (!isEnumMember(BAND_ORDER2, receiptBand)) {
30497
+ errors.push(
30498
+ `${context} complexity_band must be one of C1, C2, C3, C4; got: ${pythonStr2(receiptBand)}.`
30499
+ );
30500
+ }
30501
+ const agent = receipt["agent"];
30502
+ if (agent !== ROUTING_AGENT) {
30503
+ errors.push(
30504
+ `${context}.agent must be ${pythonRepr10(ROUTING_AGENT)}; found: ${pythonRepr10(agent)}.`
30505
+ );
30506
+ }
30507
+ if (!sameValue(receiptBand, band)) {
30508
+ errors.push(
30509
+ `${context}.complexity_band ${pythonRepr10(receiptBand)} does not equal complexity_band ${pythonRepr10(band)}.`
30510
+ );
30511
+ }
30512
+ const fablePolicy = receipt["fable_policy"];
30513
+ if (!isEnumMember(VALID_FABLE_POLICIES, fablePolicy)) {
30514
+ errors.push(
30515
+ enumError(
30516
+ entryContext,
30517
+ "model_routing_receipt.fable_policy",
30518
+ VALID_FABLE_POLICIES,
30519
+ fablePolicy
30520
+ )
30521
+ );
30522
+ }
30523
+ return errors;
30524
+ }
30525
+ function validateReadyItemRouting(record3, entryContext) {
30526
+ const errors = [];
30527
+ const band = record3["complexity_band"];
30528
+ if (!isEnumMember(BAND_ORDER2, band)) {
30529
+ errors.push(enumError(entryContext, "complexity_band", BAND_ORDER2, band));
30530
+ }
30531
+ const assessment = record3["complexity_assessment"];
30532
+ if (isObject15(assessment)) {
30533
+ errors.push(...validateAssessment(assessment, band, entryContext));
30534
+ } else {
30535
+ errors.push(`${entryContext} complexity_assessment must be an object.`);
30536
+ }
30537
+ const receipt = record3["model_routing_receipt"];
30538
+ if (isObject15(receipt)) {
30539
+ errors.push(...validateReceipt4(receipt, band, entryContext));
30540
+ } else {
30541
+ errors.push(`${entryContext} model_routing_receipt must be an object.`);
30542
+ }
30543
+ return errors;
30544
+ }
30545
+
29858
30546
  // ../../extensions/drm-copilot/src/lib/validate/parallel-planner-state-core.ts
29859
30547
  var CONTEXT2 = "Parallel planner checkpoint";
29860
30548
  var MIN_CONCURRENCY2 = 1;
@@ -29918,7 +30606,7 @@ function validateIdentity2(state) {
29918
30606
  const concurrency = state["max_concurrency"];
29919
30607
  if ("max_concurrency" in state && !inBoundedRange(concurrency, MIN_CONCURRENCY2, MAX_CONCURRENCY2)) {
29920
30608
  errors.push(
29921
- `${CONTEXT2} max_concurrency must be an integer from ${MIN_CONCURRENCY2} through ${MAX_CONCURRENCY2}; found: ${pythonRepr9(concurrency)}.`
30609
+ `${CONTEXT2} max_concurrency must be an integer from ${MIN_CONCURRENCY2} through ${MAX_CONCURRENCY2}; found: ${pythonRepr10(concurrency)}.`
29922
30610
  );
29923
30611
  }
29924
30612
  return errors;
@@ -29929,7 +30617,7 @@ function itemRecords(items) {
29929
30617
  }
29930
30618
  const records = [];
29931
30619
  items.forEach((entry, index) => {
29932
- if (isObject14(entry)) {
30620
+ if (isObject15(entry)) {
29933
30621
  records.push({ index, record: entry });
29934
30622
  }
29935
30623
  });
@@ -29998,13 +30686,13 @@ function validateReadyItem(record3, entryContext) {
29998
30686
  const preparationStatus = record3["preparation_status"];
29999
30687
  if (preparationStatus !== READY_PREPARATION_STATUS) {
30000
30688
  errors.push(
30001
- `${entryContext} preparation_status must be ${pythonRepr9(READY_PREPARATION_STATUS)}; found: ${pythonRepr9(preparationStatus)}.`
30689
+ `${entryContext} preparation_status must be ${pythonRepr10(READY_PREPARATION_STATUS)}; found: ${pythonRepr10(preparationStatus)}.`
30002
30690
  );
30003
30691
  }
30004
30692
  const preflightStatus = record3["preflight_status"];
30005
30693
  if (preflightStatus !== READY_PREFLIGHT_STATUS) {
30006
30694
  errors.push(
30007
- `${entryContext} preflight_status must be ${pythonRepr9(READY_PREFLIGHT_STATUS)}; found: ${pythonRepr9(preflightStatus)}.`
30695
+ `${entryContext} preflight_status must be ${pythonRepr10(READY_PREFLIGHT_STATUS)}; found: ${pythonRepr10(preflightStatus)}.`
30008
30696
  );
30009
30697
  }
30010
30698
  for (const key of READY_ITEM_PATH_KEYS) {
@@ -30013,10 +30701,10 @@ function validateReadyItem(record3, entryContext) {
30013
30701
  }
30014
30702
  }
30015
30703
  const radius = record3["blast_radius"];
30016
- const source = isObject14(radius) ? radius["source"] : null;
30704
+ const source = isObject15(radius) ? radius["source"] : null;
30017
30705
  if (source !== READY_RADIUS_SOURCE) {
30018
30706
  errors.push(
30019
- `${entryContext} blast_radius.source must be ${pythonRepr9(READY_RADIUS_SOURCE)} for execution readiness; found: ${pythonRepr9(source)}.`
30707
+ `${entryContext} blast_radius.source must be ${pythonRepr10(READY_RADIUS_SOURCE)} for execution readiness; found: ${pythonRepr10(source)}.`
30020
30708
  );
30021
30709
  }
30022
30710
  return errors;
@@ -30032,20 +30720,22 @@ function validateReadyGate(state) {
30032
30720
  );
30033
30721
  }
30034
30722
  for (const { index, record: record3 } of itemRecords(items)) {
30035
- errors.push(...validateReadyItem(record3, itemContext(CONTEXT2, index)));
30723
+ const entryContext = itemContext(CONTEXT2, index);
30724
+ errors.push(...validateReadyItem(record3, entryContext));
30725
+ errors.push(...validateReadyItemRouting(record3, entryContext));
30036
30726
  }
30037
30727
  }
30038
30728
  const nextStep = state["next_step"];
30039
30729
  if (nextStep !== READY_NEXT_STEP2) {
30040
30730
  errors.push(
30041
- `${CONTEXT2} next_step must be ${pythonRepr9(READY_NEXT_STEP2)}; found: ${pythonRepr9(nextStep)}.`
30731
+ `${CONTEXT2} next_step must be ${pythonRepr10(READY_NEXT_STEP2)}; found: ${pythonRepr10(nextStep)}.`
30042
30732
  );
30043
30733
  }
30044
30734
  const expectedKickoff = kickoffPathFor(state["parallel_slug"]);
30045
30735
  const kickoffPromptPath = state["kickoff_prompt_path"];
30046
30736
  if (kickoffPromptPath !== expectedKickoff) {
30047
30737
  errors.push(
30048
- `${CONTEXT2} kickoff_prompt_path must be ${pythonRepr9(expectedKickoff)}; found: ${pythonRepr9(kickoffPromptPath)}.`
30738
+ `${CONTEXT2} kickoff_prompt_path must be ${pythonRepr10(expectedKickoff)}; found: ${pythonRepr10(kickoffPromptPath)}.`
30049
30739
  );
30050
30740
  }
30051
30741
  return errors;
@@ -30058,7 +30748,7 @@ function validateParallelPlannerStateText(text2, options = {}) {
30058
30748
  const detail = error2 instanceof Error ? error2.message : String(error2);
30059
30749
  return [`${CONTEXT2} is not valid JSON: ${detail}.`];
30060
30750
  }
30061
- if (!isObject14(state)) {
30751
+ if (!isObject15(state)) {
30062
30752
  return [`${CONTEXT2} root must be a JSON object.`];
30063
30753
  }
30064
30754
  const errors = [];
@@ -31198,6 +31888,8 @@ function dispatchValidatorErrors(input) {
31198
31888
  case "epic-planner-state": {
31199
31889
  const options = {
31200
31890
  ...input.requireReadyForExecution === void 0 ? {} : { requireReadyForExecution: input.requireReadyForExecution },
31891
+ ...input.requireCodexModelRouting === void 0 ? {} : { requireCodexModelRouting: input.requireCodexModelRouting },
31892
+ ...input.requireCodexTopology === void 0 ? {} : { requireCodexTopology: input.requireCodexTopology },
31201
31893
  ...input.fs === void 0 || input.root === void 0 || input.artifactPath === void 0 || input.runner === void 0 ? {} : {
31202
31894
  readinessContext: {
31203
31895
  workspaceRoot: input.root,
@@ -31395,6 +32087,76 @@ function createGitCheckoutContext(runner) {
31395
32087
  return { observe, isHeadRelationshipSatisfied };
31396
32088
  }
31397
32089
 
32090
+ // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-materializer-request.ts
32091
+ var HANDOFF_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]*$/;
32092
+ var HANDOFF_ERROR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
32093
+ function describeHandoffFailureCause(stage, error2) {
32094
+ if (typeof error2 === "object" && error2 !== null && "code" in error2) {
32095
+ const code = error2.code;
32096
+ if (typeof code === "string" && HANDOFF_ERROR_CODE_PATTERN.test(code)) {
32097
+ return `${stage}: ${code}`;
32098
+ }
32099
+ }
32100
+ if (error2 instanceof Error) {
32101
+ return HANDOFF_ERROR_NAME_PATTERN.test(error2.name) ? `${stage}: ${error2.name}` : `${stage}: Error`;
32102
+ }
32103
+ return `${stage}: non-error value`;
32104
+ }
32105
+ function describeEnvelopeParseFailure(error2) {
32106
+ return {
32107
+ code: error2 instanceof HandoffContractError ? error2.code : "HANDOFF_UNSUPPORTED_VERSION",
32108
+ failureCause: describeHandoffFailureCause("envelope-parse", error2)
32109
+ };
32110
+ }
32111
+ function toReferenceRequest(request) {
32112
+ return {
32113
+ workspaceRoot: request.workspaceRoot,
32114
+ handoffEnvelopePath: request.handoffEnvelopePath,
32115
+ expectedHandoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
32116
+ destinationProvider: request.destinationProvider,
32117
+ expectedRepositoryId: request.expectedRepositoryId,
32118
+ expectedWorkspaceRoot: request.expectedWorkspaceRoot,
32119
+ expectedBranch: request.expectedBranch,
32120
+ expectedSourceHeadSha: request.expectedSourceHeadSha,
32121
+ allowedHeadRelationship: request.allowedHeadRelationship,
32122
+ expectedIssueNumber: request.expectedIssueNumber,
32123
+ expectedFeatureFolder: request.expectedFeatureFolder,
32124
+ expectedWorkMode: request.expectedWorkMode,
32125
+ expectedPlanPath: request.expectedPlanPath,
32126
+ expectedPlanSha256: request.expectedPlanSha256
32127
+ };
32128
+ }
32129
+ function blockedResult(request, primaryFailureCode, options = {}) {
32130
+ return {
32131
+ status: "blocked",
32132
+ handoffId: options.handoffId ?? null,
32133
+ sourceCheckpointSha256: request.expectedSourceCheckpointSha256,
32134
+ handoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
32135
+ handoffHistorySha256: options.handoffHistorySha256 ?? null,
32136
+ requestedTransition: "prepared_to_atomic_execution",
32137
+ destinationCheckpointPath: null,
32138
+ destinationCheckpointSha256: null,
32139
+ primaryFailureCode,
32140
+ affectedPaths: options.affectedPaths ?? [],
32141
+ unsupportedCapabilities: options.unsupportedCapabilities ?? [],
32142
+ ...options.failureCause === void 0 ? {} : { failureCause: options.failureCause }
32143
+ };
32144
+ }
32145
+ function authorityFailure(request, authority, handoffHistorySha256) {
32146
+ if (authority.status === "validated") return null;
32147
+ return blockedResult(
32148
+ request,
32149
+ authority.primaryFailureCode ?? "HANDOFF_VALIDATOR_UNAVAILABLE",
32150
+ {
32151
+ handoffId: authority.handoffId,
32152
+ handoffHistorySha256,
32153
+ affectedPaths: authority.affectedPaths,
32154
+ unsupportedCapabilities: authority.unsupportedCapabilities,
32155
+ ...authority.failureCause === void 0 ? {} : { failureCause: authority.failureCause }
32156
+ }
32157
+ );
32158
+ }
32159
+
31398
32160
  // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-path-boundary.ts
31399
32161
  var fs6 = __toESM(require("node:fs"));
31400
32162
  var path11 = __toESM(require("node:path"));
@@ -31423,6 +32185,13 @@ function normalizedRepositorySegments(repositoryPath2) {
31423
32185
  function missingPath(error2) {
31424
32186
  return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
31425
32187
  }
32188
+ function guardedResolution(stage, operation) {
32189
+ try {
32190
+ return { ok: true, value: operation() };
32191
+ } catch (error2) {
32192
+ return { ok: false, cause: describeHandoffFailureCause(stage, error2) };
32193
+ }
32194
+ }
31426
32195
  function lexicalCandidate(canonicalWorkspaceRoot, repositoryPath2, caseSensitive) {
31427
32196
  if (!path11.isAbsolute(canonicalWorkspaceRoot)) return null;
31428
32197
  const segments = normalizedRepositorySegments(repositoryPath2);
@@ -31433,14 +32202,13 @@ function lexicalCandidate(canonicalWorkspaceRoot, repositoryPath2, caseSensitive
31433
32202
  function createHandoffPathBoundary(fileSystem, caseSensitive = process.platform !== "win32") {
31434
32203
  const resolveWorkspaceRoot = (workspaceRoot) => {
31435
32204
  if (!path11.isAbsolute(workspaceRoot)) return null;
31436
- try {
32205
+ const resolution = guardedResolution("workspace-root", () => {
31437
32206
  const canonicalRoot = normalizedAbsolutePath(
31438
32207
  fileSystem.realpath(path11.resolve(workspaceRoot))
31439
32208
  );
31440
32209
  return fileSystem.stat(canonicalRoot).isDirectory() ? canonicalRoot : null;
31441
- } catch {
31442
- return null;
31443
- }
32210
+ });
32211
+ return resolution.ok ? resolution.value : null;
31444
32212
  };
31445
32213
  const resolveExistingTarget = (canonicalWorkspaceRoot, repositoryPath2) => {
31446
32214
  const candidate = lexicalCandidate(
@@ -31449,14 +32217,12 @@ function createHandoffPathBoundary(fileSystem, caseSensitive = process.platform
31449
32217
  caseSensitive
31450
32218
  );
31451
32219
  if (candidate === null) return null;
31452
- try {
31453
- const canonicalTarget = normalizedAbsolutePath(
31454
- fileSystem.realpath(candidate)
31455
- );
31456
- return isContained(canonicalWorkspaceRoot, canonicalTarget, caseSensitive) ? canonicalTarget : null;
31457
- } catch {
31458
- return null;
31459
- }
32220
+ const resolution = guardedResolution(
32221
+ "target-path",
32222
+ () => normalizedAbsolutePath(fileSystem.realpath(candidate))
32223
+ );
32224
+ if (!resolution.ok) return null;
32225
+ return isContained(canonicalWorkspaceRoot, resolution.value, caseSensitive) ? resolution.value : null;
31460
32226
  };
31461
32227
  const resolveCreatableTarget = (canonicalWorkspaceRoot, repositoryPath2) => {
31462
32228
  const candidate = lexicalCandidate(
@@ -31559,7 +32325,8 @@ function blocked(request, code, options = {}) {
31559
32325
  primaryFailureCode: code,
31560
32326
  affectedPaths: options.affectedPaths ?? [],
31561
32327
  unsupportedCapabilities: options.unsupportedCapabilities ?? [],
31562
- resolution: null
32328
+ resolution: null,
32329
+ ...options.failureCause === void 0 ? {} : { failureCause: options.failureCause }
31563
32330
  };
31564
32331
  }
31565
32332
  function readEnvelope(fileSystem, request, pathBoundary, canonicalWorkspaceRoot) {
@@ -31568,13 +32335,17 @@ function readEnvelope(fileSystem, request, pathBoundary, canonicalWorkspaceRoot)
31568
32335
  request.handoffEnvelopePath
31569
32336
  );
31570
32337
  if (envelopePath === null) {
31571
- return blocked(request, "HANDOFF_PLAN_PATH_INVALID");
32338
+ return blocked(request, "HANDOFF_PLAN_PATH_INVALID", {
32339
+ failureCause: "target-path: unresolved"
32340
+ });
31572
32341
  }
31573
32342
  let envelopeText;
31574
32343
  try {
31575
32344
  envelopeText = fileSystem.readTextFile(envelopePath);
31576
- } catch {
31577
- return blocked(request, "HANDOFF_VALIDATOR_UNAVAILABLE");
32345
+ } catch (error2) {
32346
+ return blocked(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32347
+ failureCause: describeHandoffFailureCause("envelope-read", error2)
32348
+ });
31578
32349
  }
31579
32350
  if (sha256(envelopeText) !== request.expectedHandoffEnvelopeSha256) {
31580
32351
  return blocked(request, "HANDOFF_SOURCE_HASH_MISMATCH");
@@ -31582,10 +32353,10 @@ function readEnvelope(fileSystem, request, pathBoundary, canonicalWorkspaceRoot)
31582
32353
  try {
31583
32354
  return parseHandoffEnvelopeText(envelopeText);
31584
32355
  } catch (error2) {
31585
- return blocked(
31586
- request,
31587
- error2 instanceof HandoffContractError ? error2.code : "HANDOFF_UNSUPPORTED_VERSION"
31588
- );
32356
+ const failure = describeEnvelopeParseFailure(error2);
32357
+ return blocked(request, failure.code, {
32358
+ failureCause: failure.failureCause
32359
+ });
31589
32360
  }
31590
32361
  }
31591
32362
  function observedPlanSha256(fileSystem, expectedPlanPath, pathBoundary, canonicalWorkspaceRoot) {
@@ -31593,11 +32364,11 @@ function observedPlanSha256(fileSystem, expectedPlanPath, pathBoundary, canonica
31593
32364
  canonicalWorkspaceRoot,
31594
32365
  expectedPlanPath
31595
32366
  );
31596
- if (planPath === null) return null;
32367
+ if (planPath === null) return { failureCause: "target-path: unresolved" };
31597
32368
  try {
31598
- return sha256(fileSystem.readTextFile(planPath));
31599
- } catch {
31600
- return null;
32369
+ return { sha256: sha256(fileSystem.readTextFile(planPath)) };
32370
+ } catch (error2) {
32371
+ return { failureCause: describeHandoffFailureCause("plan-read", error2) };
31601
32372
  }
31602
32373
  }
31603
32374
  function canonicalizeObservedPath(value) {
@@ -31657,7 +32428,9 @@ function resolvePortableHandoffAuthority(fileSystem, request, kind, pathBoundary
31657
32428
  request.workspaceRoot
31658
32429
  );
31659
32430
  if (canonicalWorkspaceRoot === null) {
31660
- return blocked(request, "HANDOFF_PLAN_PATH_INVALID");
32431
+ return blocked(request, "HANDOFF_PLAN_PATH_INVALID", {
32432
+ failureCause: "workspace-root: unresolved"
32433
+ });
31661
32434
  }
31662
32435
  const effectiveCheckoutContext = checkoutContext ?? createGitCheckoutContext(new SubprocessRunner());
31663
32436
  const observation = effectiveCheckoutContext.observe(
@@ -31695,17 +32468,19 @@ function resolvePortableHandoffAuthority(fileSystem, request, kind, pathBoundary
31695
32468
  handoffId: envelope.handoffId
31696
32469
  });
31697
32470
  }
31698
- const planSha256 = observedPlanSha256(
32471
+ const planObservation = observedPlanSha256(
31699
32472
  fileSystem,
31700
32473
  request.expectedPlanPath,
31701
32474
  effectivePathBoundary,
31702
32475
  canonicalWorkspaceRoot
31703
32476
  );
31704
- if (planSha256 === null) {
32477
+ if ("failureCause" in planObservation) {
31705
32478
  return blocked(request, "HANDOFF_PLAN_PATH_INVALID", {
31706
- handoffId: envelope.handoffId
32479
+ handoffId: envelope.handoffId,
32480
+ failureCause: planObservation.failureCause
31707
32481
  });
31708
32482
  }
32483
+ const planSha256 = planObservation.sha256;
31709
32484
  const validation = collectHandoffValidationFailures(envelope, {
31710
32485
  repositoryId: request.expectedRepositoryId,
31711
32486
  workspaceRoot: request.expectedWorkspaceRoot,
@@ -31809,54 +32584,6 @@ function porcelainAffectedPaths(output) {
31809
32584
  return [...paths].sort((left, right) => left.localeCompare(right));
31810
32585
  }
31811
32586
 
31812
- // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-materializer-request.ts
31813
- function toReferenceRequest(request) {
31814
- return {
31815
- workspaceRoot: request.workspaceRoot,
31816
- handoffEnvelopePath: request.handoffEnvelopePath,
31817
- expectedHandoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
31818
- destinationProvider: request.destinationProvider,
31819
- expectedRepositoryId: request.expectedRepositoryId,
31820
- expectedWorkspaceRoot: request.expectedWorkspaceRoot,
31821
- expectedBranch: request.expectedBranch,
31822
- expectedSourceHeadSha: request.expectedSourceHeadSha,
31823
- allowedHeadRelationship: request.allowedHeadRelationship,
31824
- expectedIssueNumber: request.expectedIssueNumber,
31825
- expectedFeatureFolder: request.expectedFeatureFolder,
31826
- expectedWorkMode: request.expectedWorkMode,
31827
- expectedPlanPath: request.expectedPlanPath,
31828
- expectedPlanSha256: request.expectedPlanSha256
31829
- };
31830
- }
31831
- function blockedResult(request, primaryFailureCode, options = {}) {
31832
- return {
31833
- status: "blocked",
31834
- handoffId: options.handoffId ?? null,
31835
- sourceCheckpointSha256: request.expectedSourceCheckpointSha256,
31836
- handoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
31837
- handoffHistorySha256: options.handoffHistorySha256 ?? null,
31838
- requestedTransition: "prepared_to_atomic_execution",
31839
- destinationCheckpointPath: null,
31840
- destinationCheckpointSha256: null,
31841
- primaryFailureCode,
31842
- affectedPaths: options.affectedPaths ?? [],
31843
- unsupportedCapabilities: options.unsupportedCapabilities ?? []
31844
- };
31845
- }
31846
- function authorityFailure(request, authority, handoffHistorySha256) {
31847
- if (authority.status === "validated") return null;
31848
- return blockedResult(
31849
- request,
31850
- authority.primaryFailureCode ?? "HANDOFF_VALIDATOR_UNAVAILABLE",
31851
- {
31852
- handoffId: authority.handoffId,
31853
- handoffHistorySha256,
31854
- affectedPaths: authority.affectedPaths,
31855
- unsupportedCapabilities: authority.unsupportedCapabilities
31856
- }
31857
- );
31858
- }
31859
-
31860
32587
  // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-provider-adapters.ts
31861
32588
  var PROVIDER_ADAPTERS = {
31862
32589
  claude: {
@@ -32022,7 +32749,9 @@ var OrchestrationHandoffMaterializer = class {
32022
32749
  request.workspaceRoot
32023
32750
  );
32024
32751
  if (canonicalWorkspaceRoot === null) {
32025
- return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID");
32752
+ return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID", {
32753
+ failureCause: "workspace-root: unresolved"
32754
+ });
32026
32755
  }
32027
32756
  const sourcePath = pathBoundary.resolveExistingTarget(
32028
32757
  canonicalWorkspaceRoot,
@@ -32033,15 +32762,19 @@ var OrchestrationHandoffMaterializer = class {
32033
32762
  request.handoffEnvelopePath
32034
32763
  );
32035
32764
  if (sourcePath === null || envelopePath === null) {
32036
- return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID");
32765
+ return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID", {
32766
+ failureCause: "target-path: unresolved"
32767
+ });
32037
32768
  }
32038
32769
  let sourceBytes;
32039
32770
  let envelopeBytes;
32040
32771
  try {
32041
32772
  sourceBytes = this.dependencies.fileSystem.readFile(sourcePath);
32042
32773
  envelopeBytes = this.dependencies.fileSystem.readFile(envelopePath);
32043
- } catch {
32044
- return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE");
32774
+ } catch (error2) {
32775
+ return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32776
+ failureCause: describeHandoffFailureCause("checkpoint-read", error2)
32777
+ });
32045
32778
  }
32046
32779
  if (sha2562(sourceBytes) !== request.expectedSourceCheckpointSha256 || sha2562(envelopeBytes) !== request.expectedHandoffEnvelopeSha256) {
32047
32780
  return blockedResult(request, "HANDOFF_SOURCE_HASH_MISMATCH");
@@ -32049,8 +32782,10 @@ var OrchestrationHandoffMaterializer = class {
32049
32782
  let envelopeText;
32050
32783
  try {
32051
32784
  envelopeText = textDecoder.decode(envelopeBytes);
32052
- } catch {
32053
- return blockedResult(request, "HANDOFF_UNSUPPORTED_VERSION");
32785
+ } catch (error2) {
32786
+ return blockedResult(request, "HANDOFF_UNSUPPORTED_VERSION", {
32787
+ failureCause: describeHandoffFailureCause("envelope-decode", error2)
32788
+ });
32054
32789
  }
32055
32790
  const validation = this.dependencies.validator.validateEnvelope(envelopeText);
32056
32791
  if (validation.primaryFailureCode !== null || validation.envelope === null) {
@@ -32059,7 +32794,8 @@ var OrchestrationHandoffMaterializer = class {
32059
32794
  validation.primaryFailureCode ?? "HANDOFF_VALIDATOR_UNAVAILABLE",
32060
32795
  {
32061
32796
  affectedPaths: validation.affectedPaths,
32062
- unsupportedCapabilities: validation.unsupportedCapabilities
32797
+ unsupportedCapabilities: validation.unsupportedCapabilities,
32798
+ failureCause: validation.failureCause
32063
32799
  }
32064
32800
  );
32065
32801
  }
@@ -32106,7 +32842,8 @@ var OrchestrationHandoffMaterializer = class {
32106
32842
  if (archivePath === null || destinationPath === null || candidatePath === null) {
32107
32843
  return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID", {
32108
32844
  handoffId: envelope.handoffId,
32109
- handoffHistorySha256: lastHistoryEntry.entrySha256
32845
+ handoffHistorySha256: lastHistoryEntry.entrySha256,
32846
+ failureCause: "target-path: unresolved"
32110
32847
  });
32111
32848
  }
32112
32849
  const referenceRequest = toReferenceRequest(request);
@@ -32139,7 +32876,11 @@ var OrchestrationHandoffMaterializer = class {
32139
32876
  error2 instanceof Error && "code" in error2 ? error2.code : "HANDOFF_VALIDATOR_UNAVAILABLE",
32140
32877
  {
32141
32878
  handoffId: envelope.handoffId,
32142
- handoffHistorySha256: lastHistoryEntry.entrySha256
32879
+ handoffHistorySha256: lastHistoryEntry.entrySha256,
32880
+ failureCause: describeHandoffFailureCause(
32881
+ "destination-projection",
32882
+ error2
32883
+ )
32143
32884
  }
32144
32885
  );
32145
32886
  }
@@ -32148,7 +32889,8 @@ var OrchestrationHandoffMaterializer = class {
32148
32889
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32149
32890
  handoffId: envelope.handoffId,
32150
32891
  handoffHistorySha256: lastHistoryEntry.entrySha256,
32151
- affectedPaths: [envelope.destinationCheckpointPath]
32892
+ affectedPaths: [envelope.destinationCheckpointPath],
32893
+ failureCause: "destination-projection: invalid"
32152
32894
  });
32153
32895
  }
32154
32896
  let porcelainStatus;
@@ -32156,10 +32898,11 @@ var OrchestrationHandoffMaterializer = class {
32156
32898
  porcelainStatus = await this.dependencies.git.readPorcelainStatus(
32157
32899
  canonicalWorkspaceRoot
32158
32900
  );
32159
- } catch {
32901
+ } catch (error2) {
32160
32902
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32161
32903
  handoffId: envelope.handoffId,
32162
- handoffHistorySha256: lastHistoryEntry.entrySha256
32904
+ handoffHistorySha256: lastHistoryEntry.entrySha256,
32905
+ failureCause: describeHandoffFailureCause("git-status", error2)
32163
32906
  });
32164
32907
  }
32165
32908
  const affectedPaths = porcelainAffectedPaths(porcelainStatus);
@@ -32205,24 +32948,30 @@ var OrchestrationHandoffMaterializer = class {
32205
32948
  preparation.sourceBytes,
32206
32949
  { exclusive: true }
32207
32950
  );
32208
- } catch {
32951
+ } catch (writeError) {
32952
+ const writeCause = describeHandoffFailureCause(
32953
+ "archive-write",
32954
+ writeError
32955
+ );
32209
32956
  let archivedBytes;
32210
32957
  try {
32211
32958
  archivedBytes = this.dependencies.fileSystem.readFile(
32212
32959
  preparation.archivePath
32213
32960
  );
32214
- } catch {
32961
+ } catch (readError) {
32215
32962
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32216
32963
  handoffId: preparation.result.handoffId,
32217
32964
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32218
- affectedPaths: [preparation.archivePath]
32965
+ affectedPaths: [preparation.archivePath],
32966
+ failureCause: `${writeCause}; ${describeHandoffFailureCause("archive-readback", readError)}`
32219
32967
  });
32220
32968
  }
32221
32969
  if (sha2562(archivedBytes) !== expectedSourceSha256) {
32222
32970
  return blockedResult(request, "HANDOFF_SOURCE_HASH_MISMATCH", {
32223
32971
  handoffId: preparation.result.handoffId,
32224
32972
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32225
- affectedPaths: [preparation.archivePath]
32973
+ affectedPaths: [preparation.archivePath],
32974
+ failureCause: writeCause
32226
32975
  });
32227
32976
  }
32228
32977
  }
@@ -32232,24 +32981,30 @@ var OrchestrationHandoffMaterializer = class {
32232
32981
  preparation.projectionBytes,
32233
32982
  { exclusive: true }
32234
32983
  );
32235
- } catch {
32984
+ } catch (writeError) {
32985
+ const writeCause = describeHandoffFailureCause(
32986
+ "candidate-write",
32987
+ writeError
32988
+ );
32236
32989
  let existingCandidate;
32237
32990
  try {
32238
32991
  existingCandidate = this.dependencies.fileSystem.readFile(
32239
32992
  preparation.candidatePath
32240
32993
  );
32241
- } catch {
32994
+ } catch (readError) {
32242
32995
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32243
32996
  handoffId: preparation.result.handoffId,
32244
32997
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32245
- affectedPaths: [preparation.candidatePath]
32998
+ affectedPaths: [preparation.candidatePath],
32999
+ failureCause: `${writeCause}; ${describeHandoffFailureCause("candidate-readback", readError)}`
32246
33000
  });
32247
33001
  }
32248
33002
  if (sha2562(existingCandidate) !== sha2562(preparation.projectionBytes)) {
32249
33003
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32250
33004
  handoffId: preparation.result.handoffId,
32251
33005
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32252
- affectedPaths: [preparation.candidatePath]
33006
+ affectedPaths: [preparation.candidatePath],
33007
+ failureCause: writeCause
32253
33008
  });
32254
33009
  }
32255
33010
  }
@@ -32259,35 +33014,51 @@ var OrchestrationHandoffMaterializer = class {
32259
33014
  );
32260
33015
  const writtenText = textDecoder.decode(writtenCandidate);
32261
33016
  if (sha2562(writtenCandidate) !== sha2562(preparation.projectionBytes) || this.dependencies.validator.validateDestinationProjection(writtenText).length > 0) {
32262
- throw new Error("Candidate validation failed.");
33017
+ throw Object.assign(new Error("Candidate validation failed."), {
33018
+ code: "HANDOFF_CANDIDATE_MISMATCH"
33019
+ });
32263
33020
  }
32264
- } catch {
32265
- this.discardCandidate(preparation.candidatePath);
32266
- return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32267
- handoffId: preparation.result.handoffId,
32268
- handoffHistorySha256: preparation.result.handoffHistorySha256,
32269
- affectedPaths: [preparation.candidatePath]
32270
- });
33021
+ } catch (error2) {
33022
+ return this.discardedCandidateResult(
33023
+ request,
33024
+ preparation,
33025
+ describeHandoffFailureCause("candidate-validate", error2)
33026
+ );
32271
33027
  }
32272
33028
  try {
32273
33029
  this.dependencies.fileSystem.replaceFile(
32274
33030
  preparation.candidatePath,
32275
33031
  preparation.destinationPath
32276
33032
  );
32277
- } catch {
32278
- this.discardCandidate(preparation.candidatePath);
32279
- return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32280
- handoffId: preparation.result.handoffId,
32281
- handoffHistorySha256: preparation.result.handoffHistorySha256,
32282
- affectedPaths: [preparation.candidatePath]
32283
- });
33033
+ } catch (error2) {
33034
+ return this.discardedCandidateResult(
33035
+ request,
33036
+ preparation,
33037
+ describeHandoffFailureCause("candidate-replace", error2)
33038
+ );
32284
33039
  }
32285
33040
  return { ...preparation.result, status: "materialized" };
32286
33041
  }
33042
+ /** Discard the candidate and block, appending any cleanup failure cause. */
33043
+ discardedCandidateResult(request, preparation, cause) {
33044
+ const cleanupCause = this.discardCandidate(preparation.candidatePath);
33045
+ return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
33046
+ handoffId: preparation.result.handoffId,
33047
+ handoffHistorySha256: preparation.result.handoffHistorySha256,
33048
+ affectedPaths: [preparation.candidatePath],
33049
+ failureCause: cleanupCause === null ? cause : `${cause}; ${cleanupCause}`
33050
+ });
33051
+ }
33052
+ /**
33053
+ * Remove the candidate. Returns `null` on success, otherwise the cleanup
33054
+ * cause; the blocked result names the retained candidate for explicit cleanup.
33055
+ */
32287
33056
  discardCandidate(candidatePath) {
32288
33057
  try {
32289
33058
  this.dependencies.fileSystem.removeFile(candidatePath);
32290
- } catch {
33059
+ return null;
33060
+ } catch (error2) {
33061
+ return describeHandoffFailureCause("candidate-cleanup", error2);
32291
33062
  }
32292
33063
  }
32293
33064
  };
@@ -32305,11 +33076,13 @@ function validateEnvelope(text2) {
32305
33076
  unsupportedCapabilities: []
32306
33077
  };
32307
33078
  } catch (error2) {
33079
+ const failure = describeEnvelopeParseFailure(error2);
32308
33080
  return {
32309
33081
  envelope: null,
32310
- primaryFailureCode: error2 instanceof HandoffContractError ? error2.code : "HANDOFF_UNSUPPORTED_VERSION",
33082
+ primaryFailureCode: failure.code,
32311
33083
  affectedPaths: [],
32312
- unsupportedCapabilities: []
33084
+ unsupportedCapabilities: [],
33085
+ failureCause: failure.failureCause
32313
33086
  };
32314
33087
  }
32315
33088
  }
@@ -32317,8 +33090,10 @@ function validateDestinationProjection(text2) {
32317
33090
  let value;
32318
33091
  try {
32319
33092
  value = JSON.parse(text2);
32320
- } catch {
32321
- return ["destination checkpoint must be valid JSON"];
33093
+ } catch (error2) {
33094
+ return [
33095
+ `destination checkpoint must be valid JSON (${describeHandoffFailureCause("destination-projection", error2)})`
33096
+ ];
32322
33097
  }
32323
33098
  if (!isRecord4(value)) return ["destination checkpoint must be an object"];
32324
33099
  const provider = value["provider"];
@@ -32634,7 +33409,7 @@ function truncate(text2, limit = 800) {
32634
33409
  }
32635
33410
  return rstrip3(text2.slice(0, limit - 3)) + "...";
32636
33411
  }
32637
- function splitLines3(value) {
33412
+ function splitLines2(value) {
32638
33413
  if (value === "") {
32639
33414
  return [];
32640
33415
  }
@@ -32645,7 +33420,7 @@ function splitLines3(value) {
32645
33420
  return lines;
32646
33421
  }
32647
33422
  function truncateLines(text2, limit) {
32648
- const lines = splitLines3(text2);
33423
+ const lines = splitLines2(text2);
32649
33424
  if (lines.length <= limit) {
32650
33425
  return text2;
32651
33426
  }
@@ -32685,14 +33460,11 @@ function formatList(values, emptyText) {
32685
33460
  }
32686
33461
  return valuesList.map((item) => `- ${item}`).join("\n");
32687
33462
  }
32688
- function compareCodePoint(left, right) {
32689
- if (left < right) {
32690
- return -1;
32691
- }
32692
- if (left > right) {
32693
- return 1;
32694
- }
32695
- return 0;
33463
+ function sortedSet(values) {
33464
+ return [...new Set(values)].sort(compareCodePoint);
33465
+ }
33466
+ function escapeRegExp4(value) {
33467
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
32696
33468
  }
32697
33469
 
32698
33470
  // ../../extensions/drm-copilot/src/lib/pr-context/git-client.ts
@@ -32885,9 +33657,6 @@ function extractClosingNumbers(raw) {
32885
33657
  }
32886
33658
  return numbers;
32887
33659
  }
32888
- function sortedSet(values) {
32889
- return [...new Set(values)].sort(compareCodePoint);
32890
- }
32891
33660
  function authorLogin(record3, key) {
32892
33661
  const raw = record3[key];
32893
33662
  if (isRecord5(raw)) {
@@ -33543,7 +34312,7 @@ function convertNumstat(numstatText) {
33543
34312
  let adds = 0;
33544
34313
  let dels = 0;
33545
34314
  const files = [];
33546
- for (const rawLine of splitLines4(numstatText)) {
34315
+ for (const rawLine of splitLines2(numstatText)) {
33547
34316
  if (!rawLine.trim()) {
33548
34317
  continue;
33549
34318
  }
@@ -33606,7 +34375,7 @@ function summarizeConventionalCommits(subjects) {
33606
34375
  }
33607
34376
  counts.set("other", 0);
33608
34377
  const typePattern = /^(feat|fix|refactor|perf|docs|test|chore|build|ci|style)(\(|!|:)/u;
33609
- for (const rawLine of splitLines4(subjects)) {
34378
+ for (const rawLine of splitLines2(subjects)) {
33610
34379
  const line = rawLine.trim();
33611
34380
  if (!line) {
33612
34381
  continue;
@@ -33624,7 +34393,7 @@ function summarizeConventionalCommits(subjects) {
33624
34393
  function extractChangedPaths(contextText) {
33625
34394
  const paths = [];
33626
34395
  let capture = false;
33627
- for (const line of splitLines4(contextText)) {
34396
+ for (const line of splitLines2(contextText)) {
33628
34397
  if (line.startsWith("===== Changed files")) {
33629
34398
  capture = true;
33630
34399
  continue;
@@ -33661,15 +34430,144 @@ function padName(name) {
33661
34430
  function isDigits(value) {
33662
34431
  return value.length > 0 && /^\d+$/u.test(value);
33663
34432
  }
33664
- function splitLines4(value) {
33665
- if (value === "") {
34433
+
34434
+ // ../../extensions/drm-copilot/src/lib/pr-context/feature-docs-parsers.ts
34435
+ function parseSection(markdown, heading) {
34436
+ const escaped = escapeRegExp4(heading);
34437
+ const pattern = new RegExp(
34438
+ `^##\\s+${escaped}\\s*\\r?\\n([\\s\\S]*?)(?=^##\\s+|$(?![\\s\\S]))`,
34439
+ "m"
34440
+ );
34441
+ const match = pattern.exec(markdown);
34442
+ if (!match) {
34443
+ return "";
34444
+ }
34445
+ return match[1].trim();
34446
+ }
34447
+ function completedPlanTasks(markdown, limit = 10) {
34448
+ const tasks = [];
34449
+ for (const line of splitLines2(markdown)) {
34450
+ if (/\[x\]/iu.test(line)) {
34451
+ const cleaned = line.replace(/^[-*]\s*\[[xX]\]\s*/u, "").trim();
34452
+ tasks.push(cleaned);
34453
+ }
34454
+ if (tasks.length >= limit) {
34455
+ break;
34456
+ }
34457
+ }
34458
+ return tasks;
34459
+ }
34460
+ function extractIssueReferences2(text2) {
34461
+ if (!text2) {
33666
34462
  return [];
33667
34463
  }
33668
- const lines = value.split(/\r\n|\r|\n/u);
33669
- if (lines.length > 0 && lines[lines.length - 1] === "" && /(\r\n|\r|\n)$/u.test(value)) {
33670
- lines.pop();
34464
+ const matches = text2.match(new RegExp(ISSUE_REFERENCE_PATTERN, "gu")) ?? [];
34465
+ const seen = /* @__PURE__ */ new Set();
34466
+ const ordered = [];
34467
+ for (const item of matches) {
34468
+ if (!seen.has(item)) {
34469
+ seen.add(item);
34470
+ ordered.push(item);
34471
+ }
33671
34472
  }
33672
- return lines;
34473
+ return ordered;
34474
+ }
34475
+ function resolveFeatureDir(fs12, baseDir, feature) {
34476
+ const direct = `${baseDir}/${feature}`;
34477
+ if (fs12.exists(direct)) {
34478
+ return direct;
34479
+ }
34480
+ const pattern = new RegExp(
34481
+ `(?:^|[-_])${escapeRegExp4(feature)}(?:[-_]|$)`,
34482
+ "u"
34483
+ );
34484
+ const strongMatches = [];
34485
+ const weakMatches = [];
34486
+ for (const name of fs12.listDirectory(baseDir)) {
34487
+ const candidate = `${baseDir}/${name}`;
34488
+ if (!fs12.isDirectory(candidate)) {
34489
+ continue;
34490
+ }
34491
+ if (pattern.test(name)) {
34492
+ strongMatches.push(candidate);
34493
+ } else if (name.includes(feature)) {
34494
+ weakMatches.push(candidate);
34495
+ }
34496
+ }
34497
+ if (strongMatches.length > 0) {
34498
+ return strongMatches[0];
34499
+ }
34500
+ if (weakMatches.length > 0) {
34501
+ return weakMatches[0];
34502
+ }
34503
+ return null;
34504
+ }
34505
+ function readText(fs12, path16) {
34506
+ return fs12.exists(path16) ? fs12.readTextFile(path16) : "";
34507
+ }
34508
+ function latestGlobPath(fs12, directory, pattern) {
34509
+ const matches = [...fs12.glob(directory, pattern)].sort(compareCodePoint);
34510
+ return matches.length > 0 ? matches[matches.length - 1] : null;
34511
+ }
34512
+ function verificationText(planText) {
34513
+ for (const heading of ["Verification", "Test Plan"]) {
34514
+ const sectionText = parseSection(planText, heading);
34515
+ if (sectionText) {
34516
+ return sectionText;
34517
+ }
34518
+ }
34519
+ return "";
34520
+ }
34521
+ function parsePrimaryIssueFromMetadata(params) {
34522
+ const pattern = /^\s*[-*]?\s*Issue:\s*(#\d+)\s*$/iu;
34523
+ for (const sourceText of [
34524
+ params.specText,
34525
+ params.storyText,
34526
+ params.issueText
34527
+ ]) {
34528
+ for (const line of splitLines2(sourceText)) {
34529
+ const match = pattern.exec(line);
34530
+ if (match) {
34531
+ return match[1];
34532
+ }
34533
+ }
34534
+ }
34535
+ return null;
34536
+ }
34537
+ function parseReadinessValue(text2) {
34538
+ const normalized = text2.replaceAll("**", "");
34539
+ const match = /^\s*(?:Readiness|Overall feature readiness):\s*(.+?)\s*$/im.exec(
34540
+ normalized
34541
+ );
34542
+ if (!match) {
34543
+ return null;
34544
+ }
34545
+ const value = match[1].trim().toUpperCase();
34546
+ if (value === "PASS" || value === "NEEDS REVISION" || value === "BLOCKED") {
34547
+ return value;
34548
+ }
34549
+ return null;
34550
+ }
34551
+ function resolveReadinessSignal(fs12, featureDir) {
34552
+ const auditFiles = [...fs12.glob(featureDir, "feature-audit.*.md")].sort(
34553
+ compareCodePoint
34554
+ );
34555
+ for (let index = auditFiles.length - 1; index >= 0; index -= 1) {
34556
+ const auditPath = auditFiles[index];
34557
+ const readiness = parseReadinessValue(readText(fs12, auditPath));
34558
+ if (readiness) {
34559
+ return [readiness, auditPath];
34560
+ }
34561
+ }
34562
+ return [null, null];
34563
+ }
34564
+ function relativeToPosix8(root, path16) {
34565
+ const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
34566
+ const normalized = toPosixPath2(path16);
34567
+ if (normalized.startsWith(`${normalizedRoot}/`)) {
34568
+ return normalized.slice(normalizedRoot.length + 1);
34569
+ }
34570
+ return normalized.replace(/^\/+/u, "");
33673
34571
  }
33674
34572
 
33675
34573
  // ../../extensions/drm-copilot/src/lib/pr-context/render.ts
@@ -33730,8 +34628,8 @@ function buildPrContext(options) {
33730
34628
  const oneline = git.log("--pretty=format:%h %ad %an %s", revRange);
33731
34629
  const subjects = git.log("--pretty=%s", revRange);
33732
34630
  const authors = git.log("--format=%an <%ae>", revRange);
33733
- const authorsList = sortedSet2(
33734
- splitLines5(authors).map((line) => line.trim()).filter((line) => line)
34631
+ const authorsList = sortedSet(
34632
+ splitLines2(authors).map((line) => line.trim()).filter((line) => line)
33735
34633
  );
33736
34634
  const nameStatus = git.diffRange(["--name-status", mergeBase, headSha]);
33737
34635
  const numstat = git.diffRange(["--numstat", mergeBase, headSha]);
@@ -33739,7 +34637,7 @@ function buildPrContext(options) {
33739
34637
  const stat = git.diffRange(["--stat", mergeBase, headSha]);
33740
34638
  const [additions, deletions, files] = convertNumstat(numstat);
33741
34639
  const extSummary = extensionSummary(files);
33742
- const mergePrs = extractMergePrNumbers(splitLines5(oneline));
34640
+ const mergePrs = extractMergePrNumbers(splitLines2(oneline));
33743
34641
  const issueCandidates = extractIssueReferences(
33744
34642
  oneline + "\n" + subjects
33745
34643
  ).filter((ref) => !mergePrs.includes(ref));
@@ -33759,9 +34657,9 @@ function buildPrContext(options) {
33759
34657
  issues.push(formattedRef);
33760
34658
  }
33761
34659
  }
33762
- referencedIssues = sortedSet2(issues);
33763
- referencedPrs = sortedSet2([...prs, ...mergePrs]);
33764
- let issuesDisplay = sortedSet2([
34660
+ referencedIssues = sortedSet(issues);
34661
+ referencedPrs = sortedSet([...prs, ...mergePrs]);
34662
+ let issuesDisplay = sortedSet([
33765
34663
  ...referencedIssues,
33766
34664
  ...featureIssueList
33767
34665
  ]).join(", ");
@@ -33871,8 +34769,8 @@ Deletions: ${deletions}
33871
34769
  text: combinedText,
33872
34770
  referencedIssues,
33873
34771
  referencedPrs,
33874
- verifiedClosing: sortedSet2(verifiedClosing),
33875
- invalidReferences: sortedSet2(invalidReferences),
34772
+ verifiedClosing: sortedSet(verifiedClosing),
34773
+ invalidReferences: sortedSet(invalidReferences),
33876
34774
  baseRef,
33877
34775
  resolvedBase,
33878
34776
  baseSha,
@@ -33886,161 +34784,6 @@ Deletions: ${deletions}
33886
34784
  function errorMessage(exc) {
33887
34785
  return exc instanceof Error ? exc.message : String(exc);
33888
34786
  }
33889
- function sortedSet2(values) {
33890
- return [...new Set(values)].sort(compareCodePoint);
33891
- }
33892
- function splitLines5(value) {
33893
- if (value === "") {
33894
- return [];
33895
- }
33896
- const lines = value.split(/\r\n|\r|\n/u);
33897
- if (lines.length > 0 && lines[lines.length - 1] === "" && /(\r\n|\r|\n)$/u.test(value)) {
33898
- lines.pop();
33899
- }
33900
- return lines;
33901
- }
33902
-
33903
- // ../../extensions/drm-copilot/src/lib/pr-context/feature-docs-parsers.ts
33904
- function parseSection2(markdown, heading) {
33905
- const escaped = escapeRegExp4(heading);
33906
- const pattern = new RegExp(
33907
- `^##\\s+${escaped}\\s*\\r?\\n([\\s\\S]*?)(?=^##\\s+|$(?![\\s\\S]))`,
33908
- "m"
33909
- );
33910
- const match = pattern.exec(markdown);
33911
- if (!match) {
33912
- return "";
33913
- }
33914
- return match[1].trim();
33915
- }
33916
- function completedPlanTasks2(markdown, limit = 10) {
33917
- const tasks = [];
33918
- for (const line of splitLines3(markdown)) {
33919
- if (/\[x\]/iu.test(line)) {
33920
- const cleaned = line.replace(/^[-*]\s*\[[xX]\]\s*/u, "").trim();
33921
- tasks.push(cleaned);
33922
- }
33923
- if (tasks.length >= limit) {
33924
- break;
33925
- }
33926
- }
33927
- return tasks;
33928
- }
33929
- function extractIssueReferences2(text2) {
33930
- if (!text2) {
33931
- return [];
33932
- }
33933
- const matches = text2.match(new RegExp(ISSUE_REFERENCE_PATTERN, "gu")) ?? [];
33934
- const seen = /* @__PURE__ */ new Set();
33935
- const ordered = [];
33936
- for (const item of matches) {
33937
- if (!seen.has(item)) {
33938
- seen.add(item);
33939
- ordered.push(item);
33940
- }
33941
- }
33942
- return ordered;
33943
- }
33944
- function resolveFeatureDir2(fs12, baseDir, feature) {
33945
- const direct = `${baseDir}/${feature}`;
33946
- if (fs12.exists(direct)) {
33947
- return direct;
33948
- }
33949
- const pattern = new RegExp(
33950
- `(?:^|[-_])${escapeRegExp4(feature)}(?:[-_]|$)`,
33951
- "u"
33952
- );
33953
- const strongMatches = [];
33954
- const weakMatches = [];
33955
- for (const name of fs12.listDirectory(baseDir)) {
33956
- const candidate = `${baseDir}/${name}`;
33957
- if (!fs12.isDirectory(candidate)) {
33958
- continue;
33959
- }
33960
- if (pattern.test(name)) {
33961
- strongMatches.push(candidate);
33962
- } else if (name.includes(feature)) {
33963
- weakMatches.push(candidate);
33964
- }
33965
- }
33966
- if (strongMatches.length > 0) {
33967
- return strongMatches[0];
33968
- }
33969
- if (weakMatches.length > 0) {
33970
- return weakMatches[0];
33971
- }
33972
- return null;
33973
- }
33974
- function readText(fs12, path16) {
33975
- return fs12.exists(path16) ? fs12.readTextFile(path16) : "";
33976
- }
33977
- function latestGlobPath(fs12, directory, pattern) {
33978
- const matches = [...fs12.glob(directory, pattern)].sort(compareCodePoint);
33979
- return matches.length > 0 ? matches[matches.length - 1] : null;
33980
- }
33981
- function verificationText(planText) {
33982
- for (const heading of ["Verification", "Test Plan"]) {
33983
- const sectionText = parseSection2(planText, heading);
33984
- if (sectionText) {
33985
- return sectionText;
33986
- }
33987
- }
33988
- return "";
33989
- }
33990
- function parsePrimaryIssueFromMetadata(params) {
33991
- const pattern = /^\s*[-*]?\s*Issue:\s*(#\d+)\s*$/iu;
33992
- for (const sourceText of [
33993
- params.specText,
33994
- params.storyText,
33995
- params.issueText
33996
- ]) {
33997
- for (const line of splitLines3(sourceText)) {
33998
- const match = pattern.exec(line);
33999
- if (match) {
34000
- return match[1];
34001
- }
34002
- }
34003
- }
34004
- return null;
34005
- }
34006
- function parseReadinessValue(text2) {
34007
- const normalized = text2.replaceAll("**", "");
34008
- const match = /^\s*(?:Readiness|Overall feature readiness):\s*(.+?)\s*$/im.exec(
34009
- normalized
34010
- );
34011
- if (!match) {
34012
- return null;
34013
- }
34014
- const value = match[1].trim().toUpperCase();
34015
- if (value === "PASS" || value === "NEEDS REVISION" || value === "BLOCKED") {
34016
- return value;
34017
- }
34018
- return null;
34019
- }
34020
- function resolveReadinessSignal(fs12, featureDir) {
34021
- const auditFiles = [...fs12.glob(featureDir, "feature-audit.*.md")].sort(
34022
- compareCodePoint
34023
- );
34024
- for (let index = auditFiles.length - 1; index >= 0; index -= 1) {
34025
- const auditPath = auditFiles[index];
34026
- const readiness = parseReadinessValue(readText(fs12, auditPath));
34027
- if (readiness) {
34028
- return [readiness, auditPath];
34029
- }
34030
- }
34031
- return [null, null];
34032
- }
34033
- function relativeToPosix8(root, path16) {
34034
- const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
34035
- const normalized = toPosixPath2(path16);
34036
- if (normalized.startsWith(`${normalizedRoot}/`)) {
34037
- return normalized.slice(normalizedRoot.length + 1);
34038
- }
34039
- return normalized.replace(/^\/+/u, "");
34040
- }
34041
- function escapeRegExp4(value) {
34042
- return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
34043
- }
34044
34787
 
34045
34788
  // ../../extensions/drm-copilot/src/lib/pr-context/verification-evidence.ts
34046
34789
  var REQUIRED_FIELDS = ["Timestamp", "Command", "EXIT_CODE"];
@@ -34063,7 +34806,7 @@ function discoverCanonicalEvidenceFiles(fs12, root, feature) {
34063
34806
  for (const pattern of CANONICAL_GLOBS) {
34064
34807
  for (const candidate of fs12.glob(featureRoot, pattern)) {
34065
34808
  if (fs12.isFile(candidate)) {
34066
- discovered.add(relativeToPosix9(normalizedRoot, candidate));
34809
+ discovered.add(relativeToPosix8(normalizedRoot, candidate));
34067
34810
  }
34068
34811
  }
34069
34812
  }
@@ -34072,7 +34815,7 @@ function discoverCanonicalEvidenceFiles(fs12, root, feature) {
34072
34815
  function parseVerificationEvidenceMarkdown(params) {
34073
34816
  const { feature, sourceFile, markdown } = params;
34074
34817
  const parsed = /* @__PURE__ */ new Map();
34075
- for (const rawLine of splitLines6(markdown)) {
34818
+ for (const rawLine of splitLines2(markdown)) {
34076
34819
  const colonIndex = rawLine.indexOf(":");
34077
34820
  if (colonIndex === -1) {
34078
34821
  continue;
@@ -34140,9 +34883,9 @@ function parseVerificationEvidenceMarkdown(params) {
34140
34883
  };
34141
34884
  }
34142
34885
  function parseVerificationEvidenceFile(params) {
34143
- const { fs: fs12, root, feature, relativePath: relativePath2 } = params;
34886
+ const { fs: fs12, root, feature, relativePath } = params;
34144
34887
  const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
34145
- const relPosix = toPosixPath2(relativePath2).replace(/^\/+/u, "");
34888
+ const relPosix = toPosixPath2(relativePath).replace(/^\/+/u, "");
34146
34889
  const markdown = fs12.readTextFile(`${normalizedRoot}/${relPosix}`);
34147
34890
  return parseVerificationEvidenceMarkdown({
34148
34891
  feature,
@@ -34156,23 +34899,6 @@ function parseIntegerStrict(value) {
34156
34899
  }
34157
34900
  return Number.parseInt(value, 10);
34158
34901
  }
34159
- function relativeToPosix9(root, absolute) {
34160
- const normalized = toPosixPath2(absolute);
34161
- if (normalized.startsWith(`${root}/`)) {
34162
- return normalized.slice(root.length + 1);
34163
- }
34164
- return normalized.replace(/^\/+/u, "");
34165
- }
34166
- function splitLines6(value) {
34167
- if (value === "") {
34168
- return [];
34169
- }
34170
- const lines = value.split(/\r\n|\r|\n/u);
34171
- if (lines.length > 0 && lines[lines.length - 1] === "" && /(\r\n|\r|\n)$/u.test(value)) {
34172
- lines.pop();
34173
- }
34174
- return lines;
34175
- }
34176
34902
 
34177
34903
  // ../../extensions/drm-copilot/src/lib/pr-context/feature-docs.ts
34178
34904
  var SPEC_HEADINGS = [
@@ -34203,8 +34929,8 @@ function gatherFeatureExcerpts2(fs12, root, changedFiles) {
34203
34929
  const baseDir = `${normalizedRoot}/docs/features/active`;
34204
34930
  const promotedDir = `${normalizedRoot}/docs/features/potential/promoted`;
34205
34931
  for (const feature of [...features].sort(compareCodePoint)) {
34206
- const featureDir = resolveFeatureDir2(fs12, baseDir, feature);
34207
- const promotedFeatureDir = resolveFeatureDir2(fs12, promotedDir, feature);
34932
+ const featureDir = resolveFeatureDir(fs12, baseDir, feature);
34933
+ const promotedFeatureDir = resolveFeatureDir(fs12, promotedDir, feature);
34208
34934
  if (featureDir === null && promotedFeatureDir === null) {
34209
34935
  continue;
34210
34936
  }
@@ -34279,7 +35005,7 @@ function gatherFeatureExcerpts2(fs12, root, changedFiles) {
34279
35005
  function buildSpecParts(specText) {
34280
35006
  const specParts = [];
34281
35007
  for (const heading of SPEC_HEADINGS) {
34282
- const sectionText = parseSection2(specText, heading);
35008
+ const sectionText = parseSection(specText, heading);
34283
35009
  if (sectionText) {
34284
35010
  specParts.push(`${heading}: ${truncate(sectionText)}`);
34285
35011
  }
@@ -34287,7 +35013,7 @@ function buildSpecParts(specText) {
34287
35013
  return specParts;
34288
35014
  }
34289
35015
  function buildPlanSection(planText) {
34290
- const planTasks = completedPlanTasks2(planText);
35016
+ const planTasks = completedPlanTasks(planText);
34291
35017
  return planTasks.length > 0 ? planTasks.map((task) => `- ${task}`).join("\n") : "";
34292
35018
  }
34293
35019
  function buildVerificationBlock(planText) {
@@ -34296,7 +35022,7 @@ function buildVerificationBlock(planText) {
34296
35022
  }
34297
35023
  function buildStoryParts(userStoryText, promotedStoryText) {
34298
35024
  const storyParts = [];
34299
- const storyStatements = parseSection2(userStoryText, "Story Statement");
35025
+ const storyStatements = parseSection(userStoryText, "Story Statement");
34300
35026
  if (storyStatements) {
34301
35027
  const storyLines = storyStatements.split(/\r\n|\r|\n/u).filter((line) => line.trim()).map((line) => line.replace(/^[- ]+|[- ]+$/gu, ""));
34302
35028
  if (storyLines.length > 0) {
@@ -34305,14 +35031,14 @@ function buildStoryParts(userStoryText, promotedStoryText) {
34305
35031
  );
34306
35032
  }
34307
35033
  }
34308
- const problemSection = parseSection2(userStoryText, "Problem / Why");
35034
+ const problemSection = parseSection(userStoryText, "Problem / Why");
34309
35035
  if (problemSection) {
34310
35036
  storyParts.push("Problem / Why:\n" + truncate(problemSection));
34311
35037
  }
34312
35038
  if (storyParts.length === 0 && promotedStoryText) {
34313
- let promotedProblem = parseSection2(promotedStoryText, "Problem / Why");
35039
+ let promotedProblem = parseSection(promotedStoryText, "Problem / Why");
34314
35040
  if (!promotedProblem) {
34315
- promotedProblem = parseSection2(promotedStoryText, "Summary");
35041
+ promotedProblem = parseSection(promotedStoryText, "Summary");
34316
35042
  }
34317
35043
  if (promotedProblem) {
34318
35044
  storyParts.push("Problem / Why:\n" + truncate(promotedProblem));
@@ -34385,7 +35111,7 @@ function extractDigestBullets(body, headings, limit) {
34385
35111
  if (!sectionText) {
34386
35112
  continue;
34387
35113
  }
34388
- for (const line of splitLines3(sectionText)) {
35114
+ for (const line of splitLines2(sectionText)) {
34389
35115
  if (!line.trim()) {
34390
35116
  continue;
34391
35117
  }
@@ -34526,7 +35252,7 @@ function parseNumstatDetailed(numstatText) {
34526
35252
  let addsTotal = 0;
34527
35253
  let delsTotal = 0;
34528
35254
  const perFile = /* @__PURE__ */ new Map();
34529
- for (const rawLine of splitLines3(numstatText)) {
35255
+ for (const rawLine of splitLines2(numstatText)) {
34530
35256
  if (!rawLine.trim()) {
34531
35257
  continue;
34532
35258
  }
@@ -34545,7 +35271,7 @@ function parseNumstatDetailed(numstatText) {
34545
35271
  }
34546
35272
  function parseNameStatusMap(nameStatusText) {
34547
35273
  const mapping = /* @__PURE__ */ new Map();
34548
- for (const rawLine of splitLines3(nameStatusText)) {
35274
+ for (const rawLine of splitLines2(nameStatusText)) {
34549
35275
  if (!rawLine.trim()) {
34550
35276
  continue;
34551
35277
  }
@@ -34593,7 +35319,7 @@ function scopingDocChanges(options) {
34593
35319
  path16
34594
35320
  ]);
34595
35321
  let headingTouched = false;
34596
- for (const line of splitLines3(diffText)) {
35322
+ for (const line of splitLines2(diffText)) {
34597
35323
  if (!line.startsWith("+") || line.startsWith("+++")) {
34598
35324
  continue;
34599
35325
  }
@@ -34609,7 +35335,7 @@ function scopingDocChanges(options) {
34609
35335
  material = true;
34610
35336
  reasons.push("key section touched");
34611
35337
  }
34612
- const addedLines = splitLines3(diffText).filter((line) => line.startsWith("+") && !line.startsWith("+++")).map((line) => line.replace(/^\++/u, "").trim());
35338
+ const addedLines = splitLines2(diffText).filter((line) => line.startsWith("+") && !line.startsWith("+++")).map((line) => line.replace(/^\++/u, "").trim());
34613
35339
  if (addedLines.length > 0 && addedLines.every(
34614
35340
  (line) => !line || line.startsWith("[") || line.startsWith("http")
34615
35341
  )) {
@@ -34759,10 +35485,10 @@ function collectPrContext(options) {
34759
35485
  });
34760
35486
  const changedPaths = extractChangedPaths(contextResult.text);
34761
35487
  const featureDocs = gatherFeatureExcerpts2(fs12, resolvedRoot, changedPaths);
34762
- const additionalContextFiles = sortedSet3(
35488
+ const additionalContextFiles = sortedSet(
34763
35489
  featureDocs.flatMap((doc) => doc.contextFiles).filter((path16) => path16)
34764
35490
  );
34765
- const featureIssueRefs = sortedSet3(
35491
+ const featureIssueRefs = sortedSet(
34766
35492
  featureDocs.flatMap((doc) => doc.issueRefs).filter((ref) => ref.trim())
34767
35493
  );
34768
35494
  if (featureIssueRefs.length > 0) {
@@ -34820,7 +35546,7 @@ function collectPrContext(options) {
34820
35546
  pendingPrimary.push(featureDoc.primaryIssueRef);
34821
35547
  }
34822
35548
  }
34823
- const readinessSignals = sortedSet3(
35549
+ const readinessSignals = sortedSet(
34824
35550
  featureDocs.map((doc) => doc.readinessSignal).filter((signal) => Boolean(signal))
34825
35551
  );
34826
35552
  const selection = selectPendingPrimary({ gh, ghAvailable, pendingPrimary });
@@ -34831,7 +35557,7 @@ function collectPrContext(options) {
34831
35557
  ghAvailable,
34832
35558
  pendingPrimaryExcluded: selection.excluded
34833
35559
  });
34834
- const issuesToFetch = sortedSet3([
35560
+ const issuesToFetch = sortedSet([
34835
35561
  ...verified,
34836
35562
  ...referencedIssues,
34837
35563
  ...selection.kept
@@ -34919,7 +35645,7 @@ function collectPrContext(options) {
34919
35645
  verified,
34920
35646
  verifiedReason,
34921
35647
  authorReason,
34922
- authorAsserted: sortedSet3(authorAsserted),
35648
+ authorAsserted: sortedSet(authorAsserted),
34923
35649
  issuesToAutocloseSection,
34924
35650
  issueDetails,
34925
35651
  prDetailsList,
@@ -34940,9 +35666,6 @@ function collectPrContext(options) {
34940
35666
  function errorMessage2(exc) {
34941
35667
  return exc instanceof Error ? exc.message : String(exc);
34942
35668
  }
34943
- function sortedSet3(values) {
34944
- return [...new Set(values)].sort(compareCodePoint);
34945
- }
34946
35669
 
34947
35670
  // ../../extensions/drm-copilot/src/lib/pr-context/collector-output.ts
34948
35671
  function renderVerificationEvidenceSection(fs12, resolvedRoot, featureDocs) {
@@ -34975,7 +35698,7 @@ function renderVerificationEvidenceSection(fs12, resolvedRoot, featureDocs) {
34975
35698
  }
34976
35699
  const lines = [];
34977
35700
  const sorted = [...parseableRecords].sort(
34978
- (left, right) => left.sourceFile < right.sourceFile ? -1 : left.sourceFile > right.sourceFile ? 1 : 0
35701
+ (left, right) => compareCodePoint(left.sourceFile, right.sourceFile)
34979
35702
  );
34980
35703
  for (const record3 of sorted) {
34981
35704
  const expected = record3.expectedExitCode;
@@ -35508,7 +36231,7 @@ function getSection(content, heading) {
35508
36231
  }
35509
36232
  return match[1].trim();
35510
36233
  }
35511
- function buildBody(workMode, problem, behavior, criteria, constraints, tests, relativePath2) {
36234
+ function buildBody(workMode, problem, behavior, criteria, constraints, tests, relativePath) {
35512
36235
  return `- Work Mode: ${workMode}
35513
36236
  ## Problem / Why
35514
36237
  ${problem}
@@ -35526,20 +36249,20 @@ ${constraints}
35526
36249
  ${tests}
35527
36250
 
35528
36251
  ## Source
35529
- From: ${relativePath2}
36252
+ From: ${relativePath}
35530
36253
  `;
35531
36254
  }
35532
- function buildBugBody(workMode, sections, relativePath2) {
36255
+ function buildBugBody(workMode, sections, relativePath) {
35533
36256
  const parts = [`- Work Mode: ${workMode}`];
35534
36257
  for (const heading of BUG_SECTION_HEADINGS) {
35535
36258
  parts.push(`## ${heading}
35536
36259
  ${sections[heading] ?? ""}`);
35537
36260
  }
35538
36261
  parts.push(`## Source
35539
- From: ${relativePath2}`);
36262
+ From: ${relativePath}`);
35540
36263
  return parts.join("\n\n") + "\n";
35541
36264
  }
35542
- function buildMinorAuditBody(workMode, problem, implementationIntent, acceptanceCriteria, dependenciesRisks, verificationSteps, evidenceChecklist, relativePath2) {
36265
+ function buildMinorAuditBody(workMode, problem, implementationIntent, acceptanceCriteria, dependenciesRisks, verificationSteps, evidenceChecklist, relativePath) {
35543
36266
  return `- Work Mode: ${workMode}
35544
36267
  ## Problem / Why
35545
36268
  ${problem}
@@ -35560,7 +36283,7 @@ ${verificationSteps}
35560
36283
  ${evidenceChecklist}
35561
36284
 
35562
36285
  ## Source
35563
- From: ${relativePath2}
36286
+ From: ${relativePath}
35564
36287
  `;
35565
36288
  }
35566
36289
  function parseIssueReference(output) {
@@ -35725,13 +36448,13 @@ function posixBasename(pathStr) {
35725
36448
  const lastSlash = normalized.lastIndexOf("/");
35726
36449
  return lastSlash === -1 ? normalized : normalized.slice(lastSlash + 1);
35727
36450
  }
35728
- function buildIssueBody(content, selectedMode, promotionType, relativePath2) {
36451
+ function buildIssueBody(content, selectedMode, promotionType, relativePath) {
35729
36452
  if (promotionType === "bug") {
35730
36453
  const bugSections = {};
35731
36454
  for (const heading of BUG_SECTION_HEADINGS) {
35732
36455
  bugSections[heading] = getSection(content, heading) || PLACEHOLDER;
35733
36456
  }
35734
- return buildBugBody(selectedMode, bugSections, relativePath2);
36457
+ return buildBugBody(selectedMode, bugSections, relativePath);
35735
36458
  }
35736
36459
  if (selectedMode === "minor-audit") {
35737
36460
  const problem2 = getSection(content, "Problem / Why") || PLACEHOLDER;
@@ -35751,7 +36474,7 @@ function buildIssueBody(content, selectedMode, promotionType, relativePath2) {
35751
36474
  dependenciesRisks,
35752
36475
  verificationSteps,
35753
36476
  evidenceChecklist,
35754
- relativePath2
36477
+ relativePath
35755
36478
  );
35756
36479
  }
35757
36480
  const problem = getSection(content, "Problem / Why") || PLACEHOLDER;
@@ -35766,7 +36489,7 @@ function buildIssueBody(content, selectedMode, promotionType, relativePath2) {
35766
36489
  criteria,
35767
36490
  constraints,
35768
36491
  tests,
35769
- relativePath2
36492
+ relativePath
35770
36493
  );
35771
36494
  }
35772
36495
  function promotePotential(options) {
@@ -35801,7 +36524,7 @@ function promotePotential(options) {
35801
36524
  const featurePath = getFeaturePath(featureName);
35802
36525
  const prefix = TITLE_PREFIXES[promotionType] ?? "Feature";
35803
36526
  const issueTitle = normalizeSmartPunctuation(`${prefix}: ${featureName}`);
35804
- const relativePath2 = computeRelativePath(resolved, workspacePath);
36527
+ const relativePath = computeRelativePath(resolved, workspacePath);
35805
36528
  let selectedMode;
35806
36529
  try {
35807
36530
  selectedMode = normalizeRequestedWorkMode(workMode, promotionType);
@@ -35810,7 +36533,7 @@ function promotePotential(options) {
35810
36533
  throw new PromotionError(message);
35811
36534
  }
35812
36535
  const fallbackReason = "";
35813
- let body = buildIssueBody(content, selectedMode, promotionType, relativePath2);
36536
+ let body = buildIssueBody(content, selectedMode, promotionType, relativePath);
35814
36537
  body = normalizeSmartPunctuation(body);
35815
36538
  const messages = [];
35816
36539
  const emitLine = (message) => {
@@ -35873,6 +36596,10 @@ function promotePotential(options) {
35873
36596
  filesystem.ensureDir(promotedDir);
35874
36597
  const destPath = posixJoin(promotedDir, posixBasename(resolved));
35875
36598
  filesystem.move(resolved, destPath);
36599
+ if (!filesystem.exists(destPath)) {
36600
+ emitLine(`Promoted file missing after move: ${destPath}`);
36601
+ return { exitCode: 1, messages };
36602
+ }
35876
36603
  emitLine(`Moved potential file to promoted folder: ${destPath}`);
35877
36604
  return { exitCode: 0, messages, destination: destPath };
35878
36605
  }
@@ -36188,12 +36915,12 @@ function validateFeatureName2(featureName) {
36188
36915
  function escapeRegExp6(value) {
36189
36916
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
36190
36917
  }
36191
- function splitLines7(text2) {
36918
+ function splitLines3(text2) {
36192
36919
  return text2.split(/\r\n|\r|\n/);
36193
36920
  }
36194
36921
  function formatChecklist(text2) {
36195
36922
  const lines = [];
36196
- for (const rawLine of splitLines7(text2)) {
36923
+ for (const rawLine of splitLines3(text2)) {
36197
36924
  const trimmed = rawLine.trim();
36198
36925
  if (!trimmed) {
36199
36926
  continue;
@@ -36222,7 +36949,7 @@ function getSection2(content, name) {
36222
36949
  function upsertWorkModeMarker(content, mode) {
36223
36950
  const markerLine = `- Work Mode: ${mode}`;
36224
36951
  const markerPattern = /^- Work Mode:\s*(minor-audit|full-feature|full-bug|full)\s*$/;
36225
- const lines = splitLines7(content).filter((line) => !markerPattern.test(line));
36952
+ const lines = splitLines3(content).filter((line) => !markerPattern.test(line));
36226
36953
  for (let idx = 0; idx < lines.length; idx += 1) {
36227
36954
  const line = lines[idx] ?? "";
36228
36955
  if (line.replace(/^\s+/, "").startsWith("## ")) {
@@ -37215,13 +37942,7 @@ function findParentKey(toolUseId, transcriptsByKey) {
37215
37942
  return void 0;
37216
37943
  }
37217
37944
  function compareByAgentId(a, b) {
37218
- if (a.meta.agentId < b.meta.agentId) {
37219
- return -1;
37220
- }
37221
- if (a.meta.agentId > b.meta.agentId) {
37222
- return 1;
37223
- }
37224
- return 0;
37945
+ return compareCodePoint(a.meta.agentId, b.meta.agentId);
37225
37946
  }
37226
37947
  function sortBySpawnIndex(children, parentTranscript) {
37227
37948
  return [...children].sort((a, b) => {
@@ -37265,7 +37986,7 @@ function buildNode(input) {
37265
37986
  agentType,
37266
37987
  description,
37267
37988
  depth,
37268
- models: [...models].sort(),
37989
+ models: [...models].sort(compareCodePoint),
37269
37990
  children
37270
37991
  };
37271
37992
  }
@@ -37395,7 +38116,7 @@ function formatTree(node) {
37395
38116
  }
37396
38117
  function renderLines(node) {
37397
38118
  const indent = " ".repeat(node.depth);
37398
- const sortedModels = [...node.models].sort();
38119
+ const sortedModels = [...node.models].sort(compareCodePoint);
37399
38120
  const line = `${indent}${node.agentType} \xB7 [${sortedModels.join(",")}] \xB7 ${node.depth} \xB7 ${node.description}`;
37400
38121
  const childLines = node.children.flatMap((child) => renderLines(child));
37401
38122
  return [line, ...childLines];