@danmoisan/drm-copilot-mcp 1.1.18 → 1.1.20

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 (264) hide show
  1. package/out/mcp-server.js +1149 -661
  2. package/package.json +3 -2
  3. package/resources/claude-customizations/.claude/agents/atomic-executor.md +28 -6
  4. package/resources/claude-customizations/.claude/agents/atomic-planner.md +20 -2
  5. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +17 -4
  6. package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
  7. package/resources/claude-customizations/.claude/agents/feature-review.md +6 -4
  8. package/resources/claude-customizations/.claude/agents/orchestrator.md +9 -5
  9. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +35 -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/agents/task-researcher.md +8 -0
  14. package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
  15. package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
  16. package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  17. package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
  18. package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
  19. package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
  20. package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
  21. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-command.ps1 +190 -0
  22. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
  23. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +78 -77
  24. package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
  25. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
  26. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
  27. package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
  28. package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
  29. package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
  30. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
  31. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
  32. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  33. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  34. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  35. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
  36. package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
  37. package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
  38. package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
  39. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
  40. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  41. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
  42. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
  43. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
  44. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
  45. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
  46. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
  47. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
  48. package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
  49. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
  50. package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
  51. package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  52. package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
  53. package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
  54. package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
  55. package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
  56. package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
  57. package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
  58. package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
  59. package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +497 -0
  60. package/resources/claude-customizations/.claude/hooks/premortem-section.ps1 +149 -0
  61. package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
  62. package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
  63. package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
  64. package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +267 -113
  65. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
  66. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
  67. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
  68. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
  69. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
  70. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
  71. package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +77 -33
  72. package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
  73. package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
  74. package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
  75. package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +52 -36
  76. package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
  77. package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
  78. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
  79. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
  80. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
  81. package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
  82. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
  83. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
  84. package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
  85. package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-MergeConfirmationParser.ps1 +203 -0
  86. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
  87. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +24 -3
  88. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
  89. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
  90. package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
  91. package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
  92. package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
  93. package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
  94. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +37 -4
  95. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
  96. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +85 -10
  97. package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
  98. package/resources/claude-customizations/.claude/rules/shell.md +10 -8
  99. package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
  100. package/resources/claude-customizations/.claude/settings.json +3 -4
  101. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +1 -1
  102. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +52 -16
  103. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +7 -3
  104. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
  105. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +2 -0
  106. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +2 -0
  107. package/resources/claude-customizations/.claude/skills/csharp-change-budget-router/SKILL.md +2 -2
  108. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +45 -9
  109. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +5 -3
  110. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
  111. package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +134 -0
  112. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +1 -1
  113. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +4 -3
  114. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +36 -15
  115. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
  116. package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
  117. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +108 -21
  118. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
  119. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
  120. package/resources/claude-customizations/.claude/skills/powershell-change-budget-router/SKILL.md +1 -1
  121. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
  122. package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +1 -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 +16 -8
  125. package/resources/claude-customizations/.claude/skills/research-issue/SKILL.md +6 -0
  126. package/resources/claude-customizations/pack-manifests/core.json +27 -0
  127. package/resources/codex-and-agents-customizations/.agents/skills/README.md +1 -0
  128. package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +1 -1
  129. package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
  130. package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +19 -7
  131. package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +43 -4
  132. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +18 -6
  133. package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
  134. package/resources/codex-and-agents-customizations/.agents/skills/csharp-change-budget-router/SKILL.md +2 -2
  135. package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
  136. package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +16 -1
  137. package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
  138. package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
  139. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
  140. package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +134 -0
  141. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +13 -5
  142. package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
  143. package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
  144. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +27 -8
  145. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +1 -1
  146. package/resources/codex-and-agents-customizations/.agents/skills/powershell-change-budget-router/SKILL.md +1 -1
  147. package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +1 -1
  148. package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
  149. package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
  150. package/resources/codex-and-agents-customizations/.agents/skills/research-issue/SKILL.md +6 -0
  151. package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
  152. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
  153. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
  154. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +21 -6
  155. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +21 -6
  156. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +21 -6
  157. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +21 -6
  158. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +21 -6
  159. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +21 -6
  160. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +15 -2
  161. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +15 -2
  162. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +15 -2
  163. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +15 -2
  164. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +15 -2
  165. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +15 -2
  166. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planning.toml +1 -1
  167. package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +1 -1
  168. package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +4 -1
  169. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
  170. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +7 -4
  171. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +7 -4
  172. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +7 -4
  173. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +7 -4
  174. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +7 -4
  175. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +7 -4
  176. package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +1 -1
  177. package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.toml +1 -1
  178. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c1.toml +6 -0
  179. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c2.toml +6 -0
  180. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c3-elevated.toml +6 -0
  181. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c3.toml +6 -0
  182. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c4.toml +6 -0
  183. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher.toml +6 -0
  184. package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
  185. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  186. package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
  187. package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
  188. package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
  189. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  190. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
  191. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
  192. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
  193. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
  194. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate-command.ps1 +190 -0
  195. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +54 -43
  196. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
  197. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
  198. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
  199. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
  200. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
  201. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
  202. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  203. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  204. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  205. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
  206. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  207. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
  208. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
  209. package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
  210. package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  211. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
  212. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
  213. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
  214. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
  215. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
  216. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
  217. package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
  218. package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +497 -0
  219. package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
  220. package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
  221. package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
  222. package/resources/codex-and-agents-customizations/.codex/prompts/feature-review-remediate.md +6 -4
  223. package/resources/codex-and-agents-customizations/pack-manifests/core.json +11 -0
  224. package/resources/customizations/.github/agents/atomic_executor.agent.md +21 -11
  225. package/resources/customizations/.github/agents/atomic_planning.agent.md +8 -3
  226. package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +13 -9
  227. package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +2 -2
  228. package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +2 -2
  229. package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +5 -5
  230. package/resources/customizations/.github/agents/orchestrator.agent.md +8 -5
  231. package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +13 -9
  232. package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +2 -2
  233. package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +2 -2
  234. package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +3 -3
  235. package/resources/customizations/.github/agents/python-atomic-executor.agent.md +13 -9
  236. package/resources/customizations/.github/agents/python-atomic-planning.agent.md +2 -2
  237. package/resources/customizations/.github/agents/python-orchestrator.agent.md +2 -2
  238. package/resources/customizations/.github/agents/task-researcher.agent.md +6 -0
  239. package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
  240. package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
  241. package/resources/customizations/.github/prompts/generate-atomic-plan.prompt.md +16 -10
  242. package/resources/customizations/.github/prompts/orchestrate-csharp-work.prompt.md +2 -2
  243. package/resources/customizations/.github/prompts/orchestrate-powershell-work.prompt.md +1 -1
  244. package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +1 -1
  245. package/resources/customizations/.github/prompts/orchestrate-work.prompt.md +2 -2
  246. package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +1 -1
  247. package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +43 -4
  248. package/resources/customizations/.github/skills/csharp-change-budget-router/SKILL.md +1 -1
  249. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
  250. package/resources/customizations/.github/skills/execution-environment/SKILL.md +134 -0
  251. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
  252. package/resources/customizations/.github/skills/powershell-change-budget-router/SKILL.md +1 -1
  253. package/resources/customizations/.github/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
  254. package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +10 -0
  255. package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +11 -0
  256. package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +11 -0
  257. package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
  258. package/resources/powershell/PoshQC/PoshQC.CoverageMerge.psm1 +163 -0
  259. package/resources/powershell/PoshQC/PoshQC.Shard.psm1 +296 -0
  260. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +48 -32
  261. package/resources/powershell/PoshQC/PoshQC.psd1 +7 -1
  262. package/resources/powershell/PoshQC/PoshQC.psm1 +18 -5
  263. package/resources/powershell/PoshQC/README.md +21 -3
  264. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +5 -319
package/out/mcp-server.js CHANGED
@@ -14078,6 +14078,9 @@ var Protocol = class {
14078
14078
  this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
14079
14079
  const handleTaskResult = async () => {
14080
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
+ }
14081
14084
  if (this._taskMessageQueue) {
14082
14085
  let queuedMessage;
14083
14086
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -14108,12 +14111,12 @@ var Protocol = class {
14108
14111
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
14109
14112
  }
14110
14113
  if (!isTerminal(task.status)) {
14111
- await this._waitForTaskUpdate(taskId, extra.signal);
14114
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
14112
14115
  return await handleTaskResult();
14113
14116
  }
14114
14117
  if (isTerminal(task.status)) {
14115
14118
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
14116
- this._clearTaskQueue(taskId);
14119
+ this._clearTaskQueue(taskId, extra.sessionId);
14117
14120
  return {
14118
14121
  ...result,
14119
14122
  _meta: {
@@ -14150,7 +14153,7 @@ var Protocol = class {
14150
14153
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
14151
14154
  }
14152
14155
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
14153
- this._clearTaskQueue(request.params.taskId);
14156
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
14154
14157
  const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
14155
14158
  if (!cancelledTask) {
14156
14159
  throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -14278,6 +14281,19 @@ var Protocol = class {
14278
14281
  const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
14279
14282
  const capturedTransport = this._transport;
14280
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
+ }
14281
14297
  if (handler === void 0) {
14282
14298
  const errorResponse = {
14283
14299
  jsonrpc: "2.0",
@@ -14287,7 +14303,10 @@ var Protocol = class {
14287
14303
  message: "Method not found"
14288
14304
  }
14289
14305
  };
14290
- 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) {
14291
14310
  this._enqueueTaskMessage(relatedTaskId, {
14292
14311
  type: "error",
14293
14312
  message: errorResponse,
@@ -14338,7 +14357,10 @@ var Protocol = class {
14338
14357
  closeSSEStream: extra?.closeSSEStream,
14339
14358
  closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
14340
14359
  };
14341
- Promise.resolve().then(() => {
14360
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
14361
+ if (relatedTaskLookup && abortController.signal.aborted) {
14362
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
14363
+ }
14342
14364
  if (taskCreationParams) {
14343
14365
  this.assertTaskHandlerCapability(request.method);
14344
14366
  }
@@ -14373,7 +14395,7 @@ var Protocol = class {
14373
14395
  ...error2["data"] !== void 0 && { data: error2["data"] }
14374
14396
  }
14375
14397
  };
14376
- if (relatedTaskId && this._taskMessageQueue) {
14398
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
14377
14399
  await this._enqueueTaskMessage(relatedTaskId, {
14378
14400
  type: "error",
14379
14401
  message: errorResponse,
@@ -14853,7 +14875,7 @@ var Protocol = class {
14853
14875
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
14854
14876
  }
14855
14877
  const maxQueueSize = this._options?.maxTaskQueueSize;
14856
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
14878
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
14857
14879
  }
14858
14880
  /**
14859
14881
  * Clears the message queue for a task and rejects any pending request resolvers.
@@ -14882,12 +14904,13 @@ var Protocol = class {
14882
14904
  * Uses polling to check for updates at the task's configured poll interval.
14883
14905
  * @param taskId The task ID to wait for
14884
14906
  * @param signal Abort signal to cancel the wait
14907
+ * @param sessionId Session of the request that waits, passed to the task store
14885
14908
  * @returns Promise that resolves when an update occurs or rejects if aborted
14886
14909
  */
14887
- async _waitForTaskUpdate(taskId, signal) {
14910
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
14888
14911
  let interval = this._options?.defaultTaskPollInterval ?? 1e3;
14889
14912
  try {
14890
- const task = await this._taskStore?.getTask(taskId);
14913
+ const task = await this._taskStore?.getTask(taskId, sessionId);
14891
14914
  if (task?.pollInterval) {
14892
14915
  interval = task.pollInterval;
14893
14916
  }
@@ -17831,7 +17854,8 @@ function toAuthorityMcpResult(tool, workspaceRoot, result) {
17831
17854
  primary_failure_code: result.primaryFailureCode,
17832
17855
  affected_paths: result.affectedPaths,
17833
17856
  unsupported_capabilities: result.unsupportedCapabilities,
17834
- resolution: result.resolution
17857
+ resolution: result.resolution,
17858
+ ...result.failureCause === void 0 ? {} : { failure_cause: result.failureCause }
17835
17859
  };
17836
17860
  }
17837
17861
  function toTransitionMcpResult(workspaceRoot, result) {
@@ -17850,7 +17874,8 @@ function toTransitionMcpResult(workspaceRoot, result) {
17850
17874
  destination_checkpoint_sha256: result.destinationCheckpointSha256,
17851
17875
  primary_failure_code: result.primaryFailureCode,
17852
17876
  affected_paths: result.affectedPaths,
17853
- unsupported_capabilities: result.unsupportedCapabilities
17877
+ unsupported_capabilities: result.unsupportedCapabilities,
17878
+ ...result.failureCause === void 0 ? {} : { failure_cause: result.failureCause }
17854
17879
  };
17855
17880
  }
17856
17881
  async function handlePortableHandoffTool(tool, rawInput, service) {
@@ -18295,6 +18320,33 @@ function buildPoshQcWorkflowArguments(tool, input) {
18295
18320
  // ../../extensions/drm-copilot/src/lib/push-down/filesystem-adapter.ts
18296
18321
  var fs2 = __toESM(require("node:fs"));
18297
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
18298
18350
  function toPosixPath(value) {
18299
18351
  return value.replace(/\\/g, "/");
18300
18352
  }
@@ -18343,9 +18395,7 @@ var RealPushDownFileSystem = class {
18343
18395
  }
18344
18396
  };
18345
18397
  walk(normalizedRoot);
18346
- return files.sort(
18347
- (left, right) => left < right ? -1 : left > right ? 1 : 0
18348
- );
18398
+ return files.sort(compareCodePoint);
18349
18399
  }
18350
18400
  /**
18351
18401
  * @param path Path to inspect.
@@ -18555,7 +18605,7 @@ function enumerateSourceFiles(fs12, sourceRoot, rootFolders) {
18555
18605
  const sorted = [...rootFiles].sort((left, right) => {
18556
18606
  const leftRel = relativeToPosix(left, rootPath) ?? left;
18557
18607
  const rightRel = relativeToPosix(right, rootPath) ?? right;
18558
- return leftRel < rightRel ? -1 : leftRel > rightRel ? 1 : 0;
18608
+ return compareCodePoint(leftRel, rightRel);
18559
18609
  });
18560
18610
  orderedFiles.push(...sorted);
18561
18611
  }
@@ -18613,7 +18663,7 @@ function stringifySorted(value, indent) {
18613
18663
  }
18614
18664
  if (input !== null && typeof input === "object") {
18615
18665
  const entries = Object.entries(input).sort(
18616
- ([leftKey], [rightKey]) => leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0
18666
+ ([leftKey], [rightKey]) => compareCodePoint(leftKey, rightKey)
18617
18667
  );
18618
18668
  const result = {};
18619
18669
  for (const [key, val] of entries) {
@@ -18667,11 +18717,11 @@ function pushDownCustomizations(options) {
18667
18717
  effectiveSource,
18668
18718
  effectiveRoots
18669
18719
  )) {
18670
- const relativePath2 = relativeToPosix(sourcePath, effectiveSource);
18671
- if (relativePath2 === null) {
18720
+ const relativePath = relativeToPosix(sourcePath, effectiveSource);
18721
+ if (relativePath === null) {
18672
18722
  continue;
18673
18723
  }
18674
- const destinationPath = joinPosix2(destinationRoot, relativePath2);
18724
+ const destinationPath = joinPosix2(destinationRoot, relativePath);
18675
18725
  const destinationStatus = fs12.isFile(
18676
18726
  destinationPath
18677
18727
  ) ? "overwritten" : "created";
@@ -18696,7 +18746,7 @@ function pushDownCustomizations(options) {
18696
18746
  fs12.ensureDir(destParent);
18697
18747
  fs12.writeTextFile(destinationPath, rewrittenText);
18698
18748
  fileResults.push({
18699
- relativePath: relativePath2,
18749
+ relativePath,
18700
18750
  destinationStatus,
18701
18751
  rewrittenReferenceCount: rewrittenDelta,
18702
18752
  placeholderRewriteCount: placeholderDelta,
@@ -18787,12 +18837,14 @@ function loadPackManifests(manifestDir, selectedPackNames, fs12) {
18787
18837
  (name) => !MANIFEST_PACK_NAMES.has(name)
18788
18838
  );
18789
18839
  if (unknown2.length > 0) {
18790
- throw new ManifestError(`Unknown Codex pack name(s): ${unknown2.sort()}`);
18840
+ throw new ManifestError(
18841
+ `Unknown Codex pack name(s): ${unknown2.sort(compareCodePoint)}`
18842
+ );
18791
18843
  }
18792
18844
  const namesToLoad = new Set(selectedPackNames);
18793
18845
  namesToLoad.add(CORE_PACK_NAME);
18794
18846
  const manifests = /* @__PURE__ */ new Map();
18795
- for (const name of [...namesToLoad].sort()) {
18847
+ for (const name of [...namesToLoad].sort(compareCodePoint)) {
18796
18848
  const manifestPath = joinPosix3(manifestDir, `${name}.json`);
18797
18849
  if (!fs12.isFile(manifestPath)) {
18798
18850
  throw new ManifestError(
@@ -18815,14 +18867,16 @@ function resolveManifestPackNames(selectedPackNames, csharpVariant) {
18815
18867
  );
18816
18868
  if (variantSpecific.length > 0) {
18817
18869
  throw new ManifestError(
18818
- `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(", ")}.`
18819
18871
  );
18820
18872
  }
18821
18873
  const unknown2 = [...selectedPackNames].filter(
18822
18874
  (name) => !SUPPORTED_PACK_NAMES.has(name)
18823
18875
  );
18824
18876
  if (unknown2.length > 0) {
18825
- throw new ManifestError(`Unknown Codex pack name(s): ${unknown2.sort()}`);
18877
+ throw new ManifestError(
18878
+ `Unknown Codex pack name(s): ${unknown2.sort(compareCodePoint)}`
18879
+ );
18826
18880
  }
18827
18881
  const manifestNames = new Set(selectedPackNames);
18828
18882
  if (manifestNames.has(PUBLIC_CSHARP_PACK_NAME)) {
@@ -18918,7 +18972,7 @@ function resolveVariantSourcePath(destinationRelativePath, csharpVariant) {
18918
18972
  return destinationRelativePath;
18919
18973
  }
18920
18974
  function assertSingleCsharpToolchain(publishedPaths, selectedPackNames) {
18921
- const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES.has(name)).sort();
18975
+ const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES.has(name)).sort(compareCodePoint);
18922
18976
  if (selectedCsharp.length > 1) {
18923
18977
  throw new ManifestError(
18924
18978
  `C# mutual exclusion violated: both modern and legacy Codex C# packs were selected (${selectedCsharp.join(", ")}); select exactly one C# variant.`
@@ -19208,7 +19262,7 @@ function loadPackManifests2(manifestDir, selectedPackNames, fs12) {
19208
19262
  const namesToLoad = new Set(selectedPackNames);
19209
19263
  namesToLoad.add(CORE_PACK_NAME2);
19210
19264
  const manifests = /* @__PURE__ */ new Map();
19211
- for (const name of [...namesToLoad].sort()) {
19265
+ for (const name of [...namesToLoad].sort(compareCodePoint)) {
19212
19266
  const manifestPath = joinPosix5(manifestDir, `${name}.json`);
19213
19267
  if (!fs12.isFile(manifestPath)) {
19214
19268
  throw new ManifestError2(
@@ -19303,7 +19357,7 @@ function resolveVariantSourcePath2(destinationRelativePath, csharpVariant) {
19303
19357
  return destinationRelativePath;
19304
19358
  }
19305
19359
  function assertSingleCsharpToolchain2(publishedPaths, selectedPackNames) {
19306
- const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES2.has(name)).sort();
19360
+ const selectedCsharp = [...selectedPackNames].filter((name) => CSHARP_PACK_NAMES2.has(name)).sort(compareCodePoint);
19307
19361
  if (selectedCsharp.length > 1) {
19308
19362
  throw new ManifestError2(
19309
19363
  `C# mutual exclusion violated: both modern and legacy C# packs were selected ([${selectedCsharp.map((n) => `'${n}'`).join(", ")}]); select exactly one C# variant.`
@@ -19313,6 +19367,10 @@ function assertSingleCsharpToolchain2(publishedPaths, selectedPackNames) {
19313
19367
  }
19314
19368
 
19315
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
+ ];
19316
19374
  function normalizePosix3(value) {
19317
19375
  return value.replace(/\\/g, "/").replace(/\/+$/, "");
19318
19376
  }
@@ -19378,6 +19436,21 @@ var ExcludingFileSystem = class {
19378
19436
  sourceRelativePosix(path16) {
19379
19437
  return relativeToPosix3(path16, this.sourceRoot);
19380
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
+ }
19381
19454
  /**
19382
19455
  * Return whether a candidate path is in the active published set.
19383
19456
  *
@@ -19403,15 +19476,15 @@ var ExcludingFileSystem = class {
19403
19476
  * @returns True when the file is outside the memory subtree or general-scoped.
19404
19477
  */
19405
19478
  isScopeIncluded(path16) {
19406
- const relativePath2 = relativeToPosix3(path16, this.repoRoot);
19407
- if (relativePath2 === null) {
19479
+ const relativePath = relativeToPosix3(path16, this.repoRoot);
19480
+ if (relativePath === null) {
19408
19481
  return true;
19409
19482
  }
19410
- if (!isUnderAgentMemory(relativePath2)) {
19483
+ if (!isUnderAgentMemory(relativePath)) {
19411
19484
  return true;
19412
19485
  }
19413
19486
  const content = this.readText(path16);
19414
- return isGeneralMemoryFile(relativePath2, content);
19487
+ return isGeneralMemoryFile(relativePath, content);
19415
19488
  }
19416
19489
  /**
19417
19490
  * Return whether a candidate file passes the memory-mode filter.
@@ -19461,7 +19534,7 @@ var ExcludingFileSystem = class {
19461
19534
  }
19462
19535
  listFiles(root) {
19463
19536
  return this.inner.listFiles(root).filter(
19464
- (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)
19465
19538
  );
19466
19539
  }
19467
19540
  isDir(path16) {
@@ -19678,9 +19751,6 @@ var EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([
19678
19751
  "tests",
19679
19752
  "venv"
19680
19753
  ]);
19681
- function compareOrdinal(left, right) {
19682
- return left < right ? -1 : left > right ? 1 : 0;
19683
- }
19684
19754
  function isExcludedDirectoryName(name) {
19685
19755
  return name.startsWith(".") || EXCLUDED_DIR_NAMES.has(name);
19686
19756
  }
@@ -19709,7 +19779,7 @@ function classifyProjectDirectories(observations) {
19709
19779
  structureObserved = true;
19710
19780
  }
19711
19781
  }
19712
- return { modulePaths: modulePaths.sort(compareOrdinal), structureObserved };
19782
+ return { modulePaths: modulePaths.sort(compareCodePoint), structureObserved };
19713
19783
  }
19714
19784
 
19715
19785
  // ../../extensions/drm-copilot/src/lib/push-down/claude-blast-radius-derive-core.ts
@@ -19777,12 +19847,12 @@ function pruneAncestors(paths) {
19777
19847
  function topLevelDirectories(observations) {
19778
19848
  const names = [];
19779
19849
  for (const observation of observations) {
19780
- const relativePath2 = observation.relativePath;
19781
- if (relativePath2 !== "" && !relativePath2.includes("/")) {
19782
- names.push(relativePath2);
19850
+ const relativePath = observation.relativePath;
19851
+ if (relativePath !== "" && !relativePath.includes("/")) {
19852
+ names.push(relativePath);
19783
19853
  }
19784
19854
  }
19785
- return names.sort(compareOrdinal);
19855
+ return names.sort(compareCodePoint);
19786
19856
  }
19787
19857
  function assembleModules(derivedPaths) {
19788
19858
  const combined = /* @__PURE__ */ new Map();
@@ -19793,7 +19863,7 @@ function assembleModules(derivedPaths) {
19793
19863
  combined.set(name, [...globs]);
19794
19864
  }
19795
19865
  const modules = {};
19796
- for (const name of [...combined.keys()].sort(compareOrdinal)) {
19866
+ for (const name of [...combined.keys()].sort(compareCodePoint)) {
19797
19867
  const globs = combined.get(name);
19798
19868
  if (globs !== void 0) {
19799
19869
  modules[name] = globs;
@@ -19869,9 +19939,7 @@ var realDirectoryLister = (root) => {
19869
19939
  } catch {
19870
19940
  return [];
19871
19941
  }
19872
- return entries.map((entry) => ({ name: entry.name, isDir: entry.isDirectory() })).sort(
19873
- (left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0
19874
- );
19942
+ return entries.map((entry) => ({ name: entry.name, isDir: entry.isDirectory() })).sort((left, right) => compareCodePoint(left.name, right.name));
19875
19943
  };
19876
19944
  function listTolerantly(lister, path16) {
19877
19945
  try {
@@ -20065,7 +20133,7 @@ function composeModules(base, overlay, overlayPath) {
20065
20133
  merged[name] = globs;
20066
20134
  }
20067
20135
  const composed = {};
20068
- for (const name of Object.keys(merged).sort(compareOrdinal)) {
20136
+ for (const name of Object.keys(merged).sort(compareCodePoint)) {
20069
20137
  const globs = merged[name] ?? [];
20070
20138
  composed[name] = globs;
20071
20139
  for (const glob of Array.isArray(globs) ? globs : []) {
@@ -20393,19 +20461,19 @@ function matchesExclusionEntry(entry, candidate) {
20393
20461
  function planExclusions(payloadRelativePaths, manifest, destinationExists) {
20394
20462
  const kept = [];
20395
20463
  const skipped = [];
20396
- for (const relativePath2 of payloadRelativePaths) {
20464
+ for (const relativePath of payloadRelativePaths) {
20397
20465
  const entry = manifest.entries.find(
20398
- (candidate) => matchesExclusionEntry(candidate, relativePath2)
20466
+ (candidate) => matchesExclusionEntry(candidate, relativePath)
20399
20467
  );
20400
20468
  if (entry === void 0) {
20401
- kept.push(relativePath2);
20469
+ kept.push(relativePath);
20402
20470
  continue;
20403
20471
  }
20404
20472
  skipped.push({
20405
- relativePath: relativePath2,
20473
+ relativePath,
20406
20474
  entry: entry.normalized,
20407
20475
  line: entry.line,
20408
- destinationStatus: destinationExists(relativePath2) ? "present" : "absent"
20476
+ destinationStatus: destinationExists(relativePath) ? "present" : "absent"
20409
20477
  });
20410
20478
  }
20411
20479
  const claimed = new Set(
@@ -20416,16 +20484,16 @@ function planExclusions(payloadRelativePaths, manifest, destinationExists) {
20416
20484
  );
20417
20485
  return { kept, skipped, unmatchedEntries };
20418
20486
  }
20419
- function assertManifestPathIsRootLevel(relativePath2, rootFolders) {
20420
- if (relativePath2.includes("/")) {
20487
+ function assertManifestPathIsRootLevel(relativePath, rootFolders) {
20488
+ if (relativePath.includes("/")) {
20421
20489
  throw new Error(
20422
- `Exclusion manifest path must be root-level: ${relativePath2}`
20490
+ `Exclusion manifest path must be root-level: ${relativePath}`
20423
20491
  );
20424
20492
  }
20425
- const root = rootFolders.find((name) => relativePath2.startsWith(name));
20493
+ const root = rootFolders.find((name) => relativePath.startsWith(name));
20426
20494
  if (root !== void 0) {
20427
20495
  throw new Error(
20428
- `Exclusion manifest path must not begin with published root ${root}: ${relativePath2}`
20496
+ `Exclusion manifest path must not begin with published root ${root}: ${relativePath}`
20429
20497
  );
20430
20498
  }
20431
20499
  }
@@ -21020,12 +21088,12 @@ var RealFileSystem = class {
21020
21088
  return;
21021
21089
  }
21022
21090
  for (const entry of entries) {
21023
- const relativePath2 = relativePrefix === "" ? entry.name : `${relativePrefix}/${entry.name}`;
21024
- if (matcher.test(relativePath2)) {
21025
- 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));
21026
21094
  }
21027
21095
  if (entry.isDirectory()) {
21028
- walk(nodePath3.join(currentDir, entry.name), relativePath2);
21096
+ walk(nodePath3.join(currentDir, entry.name), relativePath);
21029
21097
  }
21030
21098
  }
21031
21099
  };
@@ -21423,12 +21491,12 @@ function extractTemplateVariables(template) {
21423
21491
  }
21424
21492
  function replaceAllVariables(template, variables) {
21425
21493
  const referenced = extractTemplateVariables(template);
21426
- const missing = [...referenced].filter((name) => !(name in variables)).sort();
21494
+ const missing = [...referenced].filter((name) => !(name in variables)).sort(compareCodePoint);
21427
21495
  if (missing.length > 0) {
21428
21496
  throw new Error(`Unresolved template variables: ${missing.join(", ")}`);
21429
21497
  }
21430
21498
  let resolved = template;
21431
- for (const key of [...referenced].sort()) {
21499
+ for (const key of [...referenced].sort(compareCodePoint)) {
21432
21500
  resolved = resolved.split(`\${${key}}`).join(variables[key] ?? "");
21433
21501
  }
21434
21502
  if (extractTemplateVariables(resolved).size > 0) {
@@ -21877,9 +21945,7 @@ function validationFindingToJson(finding) {
21877
21945
  }
21878
21946
  function sourceArtifactToJson(artifact) {
21879
21947
  const sortedFrontmatter = {};
21880
- for (const key of Object.keys(artifact.frontmatter).sort(
21881
- (left, right) => left < right ? -1 : left > right ? 1 : 0
21882
- )) {
21948
+ for (const key of Object.keys(artifact.frontmatter).sort(compareCodePoint)) {
21883
21949
  sortedFrontmatter[key] = artifact.frontmatter[key];
21884
21950
  }
21885
21951
  return {
@@ -22377,9 +22443,7 @@ function normalizeSelectedPaths(sourceRoot, selectedPaths) {
22377
22443
  for (const candidatePath of selectedPaths) {
22378
22444
  normalized.add(normalizeRelativePath(sourceRoot, candidatePath));
22379
22445
  }
22380
- return [...normalized].sort(
22381
- (left, right) => left < right ? -1 : left > right ? 1 : 0
22382
- );
22446
+ return [...normalized].sort(compareCodePoint);
22383
22447
  }
22384
22448
  function collectFilesRecursive(fileSystem, absoluteDir, out) {
22385
22449
  for (const childName of fileSystem.listDirectory(absoluteDir)) {
@@ -22412,9 +22476,7 @@ function iterSupportedArtifacts(fileSystem, sourceRoot, sourceEcosystem) {
22412
22476
  discovered.add(filePath.slice(rootPrefix.length));
22413
22477
  }
22414
22478
  }
22415
- return [...discovered].sort(
22416
- (left, right) => left < right ? -1 : left > right ? 1 : 0
22417
- );
22479
+ return [...discovered].sort(compareCodePoint);
22418
22480
  }
22419
22481
  function discoverSourceArtifacts(fileSystem, sourceRoot, sourceEcosystem, selectedPaths) {
22420
22482
  const allArtifacts = iterSupportedArtifacts(
@@ -22440,9 +22502,7 @@ function discoverSourceArtifacts(fileSystem, sourceRoot, sourceEcosystem, select
22440
22502
  matched.push(artifactPath);
22441
22503
  }
22442
22504
  }
22443
- return matched.sort(
22444
- (left, right) => left < right ? -1 : left > right ? 1 : 0
22445
- );
22505
+ return matched.sort(compareCodePoint);
22446
22506
  }
22447
22507
  function isUnderSelectedDirectory(artifactPath, selectedSet) {
22448
22508
  const segments = artifactPath.split("/");
@@ -22853,7 +22913,7 @@ var BASE_REWRITE_RULES = [
22853
22913
  },
22854
22914
  {
22855
22915
  pattern: /Return the finalized plan for validation-only preflight through `atomic-executor` and preserve the same target file path across revision loops\. Do not claim nested worker delegation from within planner execution\./g,
22856
- replacement: 'Before reporting completion, explicitly spawn the `atomic-executor` subagent for validation-only preflight. The delegated prompt MUST include the exact directive `DIRECTIVE: PREFLIGHT VALIDATION ONLY`.\n\n- `atomic-executor` MUST return exactly one of:\n - `PREFLIGHT: ALL CLEAR`\n - `PREFLIGHT: REVISIONS REQUIRED`\n- Treat executor preflight findings as binding plan defects.\n- If preflight returns `PREFLIGHT: REVISIONS REQUIRED`, revise the same target plan file using the executor\'s precise plan delta and re-run preflight.\n- Reuse the same target plan file for every preflight revision iteration in the same planning cycle.\n- If the required `atomic-executor` handoff cannot be started or completed, stop and report blocked state; do not self-approve the plan.\n- Before reporting completion, the target plan MUST pass the `validate_orchestration_artifacts` MCP tool with `artifact_type: "plan"` and `artifact_path: <plan-path>`.\n\nDo not claim nested worker delegation from within planner execution.',
22916
+ replacement: 'Before reporting completion, explicitly spawn the `atomic-executor` subagent for validation-only preflight. The delegated prompt MUST include the exact directive `DIRECTIVE: PREFLIGHT VALIDATION ONLY`.\n\n- `atomic-executor` MUST return exactly one of:\n - `PREFLIGHT: ALL CLEAR`\n - `PREFLIGHT: REVISIONS REQUIRED`\n- Treat executor preflight findings as binding plan defects.\n- If preflight returns `PREFLIGHT: REVISIONS REQUIRED`, revise the same target plan file once using the executor\'s precise plan delta and its full `PREFLIGHT-DEFECT:` list, and run one confirming preflight. Preflight is single-pass: trivial defects are fixed in place by the executor, and a plan returns to the planner at most once; a second substantive result halts with `blocked_reason: "validator_failed"`.\n- Reuse the same target plan file for the single permitted preflight revision in the same planning cycle.\n- If the required `atomic-executor` handoff cannot be started or completed, stop and report blocked state; do not self-approve the plan.\n- Before reporting completion, the target plan MUST pass the `validate_orchestration_artifacts` MCP tool with `artifact_type: "plan"` and `artifact_path: <plan-path>`.\n\nDo not claim nested worker delegation from within planner execution.',
22857
22917
  description: "Expand the Claude atomic-planner preflight shorthand into the strict Codex atomic-executor handoff contract."
22858
22918
  },
22859
22919
  {
@@ -23283,23 +23343,19 @@ function buildPromptTranslationTraces(fileSystem, runOptions, mappingRecord) {
23283
23343
  });
23284
23344
  }
23285
23345
  return [...translationTraces].sort((left, right) => {
23286
- if (left.sourcePath !== right.sourcePath) {
23287
- return left.sourcePath < right.sourcePath ? -1 : 1;
23288
- }
23289
- if (left.sectionId !== right.sectionId) {
23290
- return left.sectionId < right.sectionId ? -1 : 1;
23346
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23347
+ if (bySource !== 0) {
23348
+ return bySource;
23291
23349
  }
23292
- if (left.targetRole !== right.targetRole) {
23293
- return left.targetRole < right.targetRole ? -1 : 1;
23350
+ const bySection = compareCodePoint(left.sectionId, right.sectionId);
23351
+ if (bySection !== 0) {
23352
+ return bySection;
23294
23353
  }
23295
- return 0;
23354
+ return compareCodePoint(left.targetRole, right.targetRole);
23296
23355
  });
23297
23356
  }
23298
23357
 
23299
23358
  // ../../extensions/drm-copilot/src/lib/codex-native-converter/engine-pipeline.ts
23300
- function compareStrings(left, right) {
23301
- return left < right ? -1 : left > right ? 1 : 0;
23302
- }
23303
23359
  function planMappings(fileSystem, runOptions) {
23304
23360
  const discoveredPaths = discoverSourceArtifacts(
23305
23361
  fileSystem,
@@ -23321,7 +23377,7 @@ function planMappings(fileSystem, runOptions) {
23321
23377
  mappingRecords.push(mappedRecord);
23322
23378
  }
23323
23379
  return [...mappingRecords].sort(
23324
- (left, right) => compareStrings(left.sourcePath, right.sourcePath)
23380
+ (left, right) => compareCodePoint(left.sourcePath, right.sourcePath)
23325
23381
  );
23326
23382
  }
23327
23383
  function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEmissions) {
@@ -23348,7 +23404,7 @@ function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEm
23348
23404
  sectionEmissionsByTarget.set(plannedEmission.targetPath, bucket);
23349
23405
  }
23350
23406
  for (const targetPath of [...mappingRecordsByTarget.keys()].sort(
23351
- compareStrings
23407
+ compareCodePoint
23352
23408
  )) {
23353
23409
  const recordsForTarget = mappingRecordsByTarget.get(targetPath) ?? [];
23354
23410
  if (recordsForTarget.length === 0) {
@@ -23376,7 +23432,7 @@ function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEm
23376
23432
  ...new Set(
23377
23433
  plannedEmissions.filter((emission) => emission.targetPath !== null).map((emission) => emission.sourcePath)
23378
23434
  )
23379
- ].sort(compareStrings);
23435
+ ].sort(compareCodePoint);
23380
23436
  for (const sourcePath of parsedSourcePaths) {
23381
23437
  const sourceArtifact = parseSourceArtifact(
23382
23438
  fileSystem,
@@ -23390,7 +23446,7 @@ function renderGeneratedOutput(fileSystem, runOptions, mappingRecords, plannedEm
23390
23446
  }
23391
23447
  }
23392
23448
  for (const targetPath of [...sectionEmissionsByTarget.keys()].sort(
23393
- compareStrings
23449
+ compareCodePoint
23394
23450
  )) {
23395
23451
  if (targetPath in generatedOutput) {
23396
23452
  continue;
@@ -23413,15 +23469,15 @@ function buildTranslationTraces(fileSystem, runOptions, mappingRecords) {
23413
23469
  );
23414
23470
  }
23415
23471
  return [...translationTraces].sort((left, right) => {
23416
- const bySource = compareStrings(left.sourcePath, right.sourcePath);
23472
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23417
23473
  if (bySource !== 0) {
23418
23474
  return bySource;
23419
23475
  }
23420
- const bySection = compareStrings(left.sectionId, right.sectionId);
23476
+ const bySection = compareCodePoint(left.sectionId, right.sectionId);
23421
23477
  if (bySection !== 0) {
23422
23478
  return bySection;
23423
23479
  }
23424
- return compareStrings(left.targetRole, right.targetRole);
23480
+ return compareCodePoint(left.targetRole, right.targetRole);
23425
23481
  });
23426
23482
  }
23427
23483
  function buildPlannedEmissions(translationTraces) {
@@ -23439,7 +23495,9 @@ function buildPlannedEmissions(translationTraces) {
23439
23495
  }
23440
23496
  function writeDestinationOutputs(fileSystem, destinationRoot, generatedOutput) {
23441
23497
  const normalizedRoot = destinationRoot.replace(/\/+$/, "");
23442
- for (const targetPath of Object.keys(generatedOutput).sort(compareStrings)) {
23498
+ for (const targetPath of Object.keys(generatedOutput).sort(
23499
+ compareCodePoint
23500
+ )) {
23443
23501
  const fullPath = normalizedRoot === "" ? targetPath : `${normalizedRoot}/${targetPath}`;
23444
23502
  fileSystem.writeTextFile(fullPath, generatedOutput[targetPath] ?? "");
23445
23503
  }
@@ -23453,7 +23511,7 @@ function sortKeysDeep(value) {
23453
23511
  if (value !== null && typeof value === "object") {
23454
23512
  const sorted = {};
23455
23513
  for (const key of Object.keys(value).sort(
23456
- (left, right) => left < right ? -1 : left > right ? 1 : 0
23514
+ compareCodePoint
23457
23515
  )) {
23458
23516
  sorted[key] = sortKeysDeep(value[key]);
23459
23517
  }
@@ -23529,7 +23587,7 @@ function extractTopologyDestinations(renderedText, knownDestinationPaths) {
23529
23587
  if (left[0] !== right[0]) {
23530
23588
  return left[0] - right[0];
23531
23589
  }
23532
- return left[1] < right[1] ? -1 : left[1] > right[1] ? 1 : 0;
23590
+ return compareCodePoint(left[1], right[1]);
23533
23591
  });
23534
23592
  return destinationsByPosition.map(([, destinationPath]) => destinationPath);
23535
23593
  }
@@ -23541,7 +23599,7 @@ function buildTopologyEdges(fileSystem, runOptions, mappingRecords, translationT
23541
23599
  ...new Set(
23542
23600
  mappingRecords.filter((record3) => record3.targetPath !== null).map((record3) => record3.targetPath)
23543
23601
  )
23544
- ].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
23602
+ ].sort(compareCodePoint);
23545
23603
  const topologyEdges = [];
23546
23604
  const translationTraceSourcePaths = new Set(
23547
23605
  translationTraces.map((trace) => trace.sourcePath)
@@ -23587,13 +23645,11 @@ function buildTopologyEdges(fileSystem, runOptions, mappingRecords, translationT
23587
23645
  }
23588
23646
  }
23589
23647
  return [...topologyEdges].sort((left, right) => {
23590
- if (left.sourcePath !== right.sourcePath) {
23591
- return left.sourcePath < right.sourcePath ? -1 : 1;
23592
- }
23593
- if (left.destinationPath !== right.destinationPath) {
23594
- return left.destinationPath < right.destinationPath ? -1 : 1;
23648
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23649
+ if (bySource !== 0) {
23650
+ return bySource;
23595
23651
  }
23596
- return 0;
23652
+ return compareCodePoint(left.destinationPath, right.destinationPath);
23597
23653
  });
23598
23654
  }
23599
23655
 
@@ -23666,38 +23722,35 @@ function renderDestinationToRepeatedSourceChart(topologyEdges) {
23666
23722
  }
23667
23723
 
23668
23724
  // ../../extensions/drm-copilot/src/lib/codex-native-converter/reporting-render.ts
23669
- function compareStrings2(left, right) {
23670
- return left < right ? -1 : left > right ? 1 : 0;
23671
- }
23672
23725
  function renderConversionReport(runOptions, mappingRecords, topologyEdges, translationTraces, validationFindings) {
23673
23726
  const blockingCount = validationFindings.filter(
23674
23727
  (finding) => finding.blocking
23675
23728
  ).length;
23676
23729
  const destinationRootText = runOptions.destinationRoot !== null ? toPosixPath2(runOptions.destinationRoot) : "review-only";
23677
23730
  const sortedMappingRecords = [...mappingRecords].sort(
23678
- (left, right) => compareStrings2(left.sourcePath, right.sourcePath)
23731
+ (left, right) => compareCodePoint(left.sourcePath, right.sourcePath)
23679
23732
  );
23680
23733
  const sortedTopologyEdges = [...topologyEdges].sort((left, right) => {
23681
- const bySource = compareStrings2(left.sourcePath, right.sourcePath);
23734
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23682
23735
  if (bySource !== 0) {
23683
23736
  return bySource;
23684
23737
  }
23685
- return compareStrings2(left.destinationPath, right.destinationPath);
23738
+ return compareCodePoint(left.destinationPath, right.destinationPath);
23686
23739
  });
23687
23740
  const sortedTranslationTraces = [...translationTraces].sort((left, right) => {
23688
- const bySource = compareStrings2(left.sourcePath, right.sourcePath);
23741
+ const bySource = compareCodePoint(left.sourcePath, right.sourcePath);
23689
23742
  if (bySource !== 0) {
23690
23743
  return bySource;
23691
23744
  }
23692
- const bySection = compareStrings2(left.sectionId, right.sectionId);
23745
+ const bySection = compareCodePoint(left.sectionId, right.sectionId);
23693
23746
  if (bySection !== 0) {
23694
23747
  return bySection;
23695
23748
  }
23696
- const byRole = compareStrings2(left.targetRole, right.targetRole);
23749
+ const byRole = compareCodePoint(left.targetRole, right.targetRole);
23697
23750
  if (byRole !== 0) {
23698
23751
  return byRole;
23699
23752
  }
23700
- return compareStrings2(left.targetPath ?? "", right.targetPath ?? "");
23753
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
23701
23754
  });
23702
23755
  const lines = [
23703
23756
  "# Conversion Report",
@@ -23765,18 +23818,18 @@ function renderConversionReport(runOptions, mappingRecords, topologyEdges, trans
23765
23818
  lines.push("- None");
23766
23819
  } else {
23767
23820
  const sortedFindings = [...validationFindings].sort((left, right) => {
23768
- const byCode = compareStrings2(left.code, right.code);
23821
+ const byCode = compareCodePoint(left.code, right.code);
23769
23822
  if (byCode !== 0) {
23770
23823
  return byCode;
23771
23824
  }
23772
- const bySource = compareStrings2(
23825
+ const bySource = compareCodePoint(
23773
23826
  left.sourcePath ?? "",
23774
23827
  right.sourcePath ?? ""
23775
23828
  );
23776
23829
  if (bySource !== 0) {
23777
23830
  return bySource;
23778
23831
  }
23779
- return compareStrings2(left.targetPath ?? "", right.targetPath ?? "");
23832
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
23780
23833
  });
23781
23834
  for (const validationFinding of sortedFindings) {
23782
23835
  lines.push(
@@ -23795,7 +23848,7 @@ function sortKeysDeep2(value) {
23795
23848
  if (value !== null && typeof value === "object") {
23796
23849
  const sorted = {};
23797
23850
  for (const key of Object.keys(value).sort(
23798
- (left, right) => left < right ? -1 : left > right ? 1 : 0
23851
+ compareCodePoint
23799
23852
  )) {
23800
23853
  sorted[key] = sortKeysDeep2(value[key]);
23801
23854
  }
@@ -23837,21 +23890,23 @@ function joinPosix12(root, child) {
23837
23890
  }
23838
23891
  function sortBySourcePath(mappingRecords) {
23839
23892
  return [...mappingRecords].sort(
23840
- (left, right) => left.sourcePath < right.sourcePath ? -1 : left.sourcePath > right.sourcePath ? 1 : 0
23893
+ (left, right) => compareCodePoint(left.sourcePath, right.sourcePath)
23841
23894
  );
23842
23895
  }
23843
23896
  function sortFindings(validationFindings) {
23844
- const compare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
23845
23897
  return [...validationFindings].sort((left, right) => {
23846
- const byCode = compare(left.code, right.code);
23898
+ const byCode = compareCodePoint(left.code, right.code);
23847
23899
  if (byCode !== 0) {
23848
23900
  return byCode;
23849
23901
  }
23850
- const bySource = compare(left.sourcePath ?? "", right.sourcePath ?? "");
23902
+ const bySource = compareCodePoint(
23903
+ left.sourcePath ?? "",
23904
+ right.sourcePath ?? ""
23905
+ );
23851
23906
  if (bySource !== 0) {
23852
23907
  return bySource;
23853
23908
  }
23854
- return compare(left.targetPath ?? "", right.targetPath ?? "");
23909
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
23855
23910
  });
23856
23911
  }
23857
23912
  function writeConversionReportSet(fileSystem, runOptions, mappingRecords, topologyEdges, translationTraces, validationFindings, generatedOutput) {
@@ -23890,7 +23945,7 @@ function writeConversionReportSet(fileSystem, runOptions, mappingRecords, topolo
23890
23945
  dumpsSortedWithNewline(validationResultsPayload)
23891
23946
  );
23892
23947
  for (const targetPath of Object.keys(generatedOutput).sort(
23893
- (left, right) => left < right ? -1 : left > right ? 1 : 0
23948
+ compareCodePoint
23894
23949
  )) {
23895
23950
  fileSystem.writeTextFile(
23896
23951
  joinPosix12(proposedTreeRoot, targetPath),
@@ -24056,9 +24111,7 @@ function validateDuplicateTargets(mappingRecords, plannedEmissions) {
24056
24111
  conflictingTargets.add(targetPath);
24057
24112
  }
24058
24113
  }
24059
- for (const targetPath of [...conflictingTargets].sort(
24060
- (left, right) => left < right ? -1 : left > right ? 1 : 0
24061
- )) {
24114
+ for (const targetPath of [...conflictingTargets].sort(compareCodePoint)) {
24062
24115
  for (const plannedEmission of sectionEmissionsByTarget.get(targetPath) ?? []) {
24063
24116
  findings.push(
24064
24117
  buildFinding({
@@ -24101,17 +24154,19 @@ function validateConversionPlan(runOptions, mappingRecords, plannedEmissions, ge
24101
24154
  ...validateDuplicateTargets(mappingRecords, plannedEmissions),
24102
24155
  ...validateGeneratedOutput(generatedOutput)
24103
24156
  ];
24104
- const compare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
24105
24157
  return [...findings].sort((left, right) => {
24106
- const byCode = compare(left.code, right.code);
24158
+ const byCode = compareCodePoint(left.code, right.code);
24107
24159
  if (byCode !== 0) {
24108
24160
  return byCode;
24109
24161
  }
24110
- const bySource = compare(left.sourcePath ?? "", right.sourcePath ?? "");
24162
+ const bySource = compareCodePoint(
24163
+ left.sourcePath ?? "",
24164
+ right.sourcePath ?? ""
24165
+ );
24111
24166
  if (bySource !== 0) {
24112
24167
  return bySource;
24113
24168
  }
24114
- return compare(left.targetPath ?? "", right.targetPath ?? "");
24169
+ return compareCodePoint(left.targetPath ?? "", right.targetPath ?? "");
24115
24170
  });
24116
24171
  }
24117
24172
 
@@ -24888,13 +24943,13 @@ function validateLaunchBindings(features, context) {
24888
24943
  });
24889
24944
  return errors;
24890
24945
  }
24891
- function validateEpicPlannerChildLaunchBindings(features) {
24946
+ function validateEpicPlannerChildLaunchBindings(features, options = {}) {
24892
24947
  return validateLaunchBindings(features, {
24893
24948
  expectedExecutionContext: "epic_preparation_child",
24894
24949
  planner: true,
24895
24950
  requireGeneratedOrchestrator: true,
24896
24951
  skipNotStarted: false,
24897
- requireLaunchPaths: false
24952
+ requireLaunchPaths: options.requireLaunchPaths === true
24898
24953
  });
24899
24954
  }
24900
24955
  function validateEpicChildLaunchBindings(state, options = {}) {
@@ -25261,7 +25316,7 @@ function validateCodexModelRoutingGate(state) {
25261
25316
  deploymentAgents.add(deployment);
25262
25317
  }
25263
25318
  }
25264
- for (const agent of [...delegated].sort()) {
25319
+ for (const agent of [...delegated].sort(compareCodePoint)) {
25265
25320
  if (!logicalAgents.has(agent) && !deploymentAgents.has(agent)) {
25266
25321
  errors.push(
25267
25322
  `Checkpoint ${CODEX_MODEL_ROUTING_RECEIPTS_KEY} is missing a receipt for delegated agent: ${agent}.`
@@ -25355,7 +25410,7 @@ function normalizeLanguages(value) {
25355
25410
  const normalized = new Set(
25356
25411
  value.map((language) => language.trim().toLowerCase())
25357
25412
  );
25358
- return [...normalized].sort();
25413
+ return [...normalized].sort(compareCodePoint);
25359
25414
  }
25360
25415
  function requireInteger(value, fieldName) {
25361
25416
  if (typeof value !== "number" || !Number.isInteger(value)) {
@@ -25691,7 +25746,7 @@ function validateCodexTopologyGate(state, options = {}) {
25691
25746
  allowedNames.add(receipt.logical_agent);
25692
25747
  if ([...delegated].every((agent) => !allowedNames.has(agent))) {
25693
25748
  errors.push(
25694
- `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(", ")}.`
25695
25750
  );
25696
25751
  }
25697
25752
  }
@@ -25801,7 +25856,7 @@ function validateFeatureFolderUniquenessAndDependencies(features) {
25801
25856
  }
25802
25857
  }
25803
25858
  }
25804
- for (const folder of [...duplicates].sort()) {
25859
+ for (const folder of [...duplicates].sort(compareCodePoint)) {
25805
25860
  errors.push(
25806
25861
  `Epic checkpoint has duplicate features[].feature_folder: ${folder}`
25807
25862
  );
@@ -26139,6 +26194,53 @@ function validateCommittedFile(git, ref, path16, label) {
26139
26194
  }
26140
26195
  return [];
26141
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
+ }
26142
26244
  function validatePlanningGitIntegrity(state, parsed, plans, git) {
26143
26245
  const branch = state["integration_branch"];
26144
26246
  if (typeof branch !== "string" || !git.refExists(branch)) {
@@ -26160,8 +26262,8 @@ function validatePlanningGitIntegrity(state, parsed, plans, git) {
26160
26262
  );
26161
26263
  }
26162
26264
  }
26163
- const features = Array.isArray(state["features"]) ? state["features"].filter(isRecord) : [];
26164
- plans.forEach((plan, index) => {
26265
+ const pairs = pairPlansWithFeatures(state["features"], plans);
26266
+ pairs.forEach(([index, feature, plan]) => {
26165
26267
  const derived = git.lastCommit(plan);
26166
26268
  if (derived === void 0) {
26167
26269
  errors.push(
@@ -26176,7 +26278,6 @@ function validatePlanningGitIntegrity(state, parsed, plans, git) {
26176
26278
  return;
26177
26279
  }
26178
26280
  const candidates = [derived];
26179
- const feature = features[index] ?? {};
26180
26281
  const featureCommit = feature["planning_commit"];
26181
26282
  if (featureCommit !== void 0) {
26182
26283
  if (typeof featureCommit !== "string" || !COMMIT_RE.test(featureCommit)) {
@@ -26234,7 +26335,7 @@ function validatePlanningGitIntegrity(state, parsed, plans, git) {
26234
26335
  }
26235
26336
  }
26236
26337
  });
26237
- 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)) {
26238
26339
  errors.push(
26239
26340
  `Optional plan_hashes contains unknown planner path: '${extra}'.`
26240
26341
  );
@@ -26520,7 +26621,7 @@ function validateStatus(feature, index, receipt, receiptPath, status, statusPath
26520
26621
  }
26521
26622
  return errors;
26522
26623
  }
26523
- function validateEpicPlannerLaunchEvidence(state, context) {
26624
+ function validateEpicPlannerLaunchEvidence(state, context, options = {}) {
26524
26625
  const features = state["features"];
26525
26626
  if (!Array.isArray(features)) {
26526
26627
  return [];
@@ -26532,6 +26633,9 @@ function validateEpicPlannerLaunchEvidence(state, context) {
26532
26633
  if (!isRecord2(item)) {
26533
26634
  return;
26534
26635
  }
26636
+ if (options.requireLaunchPaths === true && !featureCarriesLaunchPath(item)) {
26637
+ return;
26638
+ }
26535
26639
  const receipt = validateReceipt3(item, index, context);
26536
26640
  errors.push(...receipt.errors);
26537
26641
  const featureStatus = launchPath(
@@ -26578,21 +26682,6 @@ var SLUG_RE = /^[a-z0-9][a-z0-9-]*$/;
26578
26682
  function join9(root, relative2) {
26579
26683
  return `${toPosixPath2(root).replace(/\/+$/, "")}/${relative2.replace(/^\/+/, "")}`;
26580
26684
  }
26581
- function relativePath(value, field) {
26582
- if (typeof value !== "string" || value.trim().length === 0) {
26583
- return {
26584
- errors: [`${field} must be a non-empty repository-relative path.`]
26585
- };
26586
- }
26587
- if (value.includes("\\")) {
26588
- return { errors: [`${field} must use forward slashes.`] };
26589
- }
26590
- const parts = value.split("/");
26591
- if (value.startsWith("/") || /^[A-Za-z]:/.test(value) || parts.includes("..") || parts.includes(".")) {
26592
- return { errors: [`${field} must stay within the workspace root.`] };
26593
- }
26594
- return { path: parts.join("/"), errors: [] };
26595
- }
26596
26685
  function readRequired(context, relative2, label) {
26597
26686
  const path16 = join9(context.workspaceRoot, relative2);
26598
26687
  if (!context.fileSystem.isFile(path16)) {
@@ -26633,12 +26722,15 @@ function validateArtifactSource(stateText, context) {
26633
26722
  }
26634
26723
  function validateFeatureFiles(feature, index, context) {
26635
26724
  const prefix = `Epic planner checkpoint features[${index}]`;
26636
- const folderResult = relativePath(
26725
+ const folderResult = repositoryRelativePath(
26637
26726
  feature["feature_folder"],
26638
26727
  `${prefix}.feature_folder`
26639
26728
  );
26640
- const planResult = relativePath(feature["plan_path"], `${prefix}.plan_path`);
26641
- const researchResult = relativePath(
26729
+ const planResult = repositoryRelativePath(
26730
+ feature["plan_path"],
26731
+ `${prefix}.plan_path`
26732
+ );
26733
+ const researchResult = repositoryRelativePath(
26642
26734
  feature["research_path"],
26643
26735
  `${prefix}.research_path`
26644
26736
  );
@@ -26683,7 +26775,7 @@ function validateFeatureFiles(feature, index, context) {
26683
26775
  const evidenceValue = feature["preflight_evidence_path"];
26684
26776
  const evidencePaths = [];
26685
26777
  if (evidenceValue !== void 0) {
26686
- const evidence = relativePath(
26778
+ const evidence = repositoryRelativePath(
26687
26779
  evidenceValue,
26688
26780
  `${prefix}.preflight_evidence_path`
26689
26781
  );
@@ -26764,7 +26856,7 @@ function validateKickoffAgainstState(parsed, state, label) {
26764
26856
  }
26765
26857
  return errors;
26766
26858
  }
26767
- function validateEpicReadinessIntegrity(state, stateText, context) {
26859
+ function validateEpicReadinessIntegrity(state, stateText, context, options = {}) {
26768
26860
  const errors = validateArtifactSource(stateText, context);
26769
26861
  const slug = state["epic_feature_folder"];
26770
26862
  if (typeof slug !== "string" || !SLUG_RE.test(slug)) {
@@ -26785,7 +26877,7 @@ function validateEpicReadinessIntegrity(state, stateText, context) {
26785
26877
  }
26786
26878
  const manifest = readRequired(context, manifestPath, "the epic manifest");
26787
26879
  errors.push(...manifest.errors);
26788
- const ignoredResult = relativePath(
26880
+ const ignoredResult = repositoryRelativePath(
26789
26881
  state["kickoff_prompt_path"],
26790
26882
  "Epic planner checkpoint kickoff_prompt_path"
26791
26883
  );
@@ -26833,7 +26925,7 @@ function validateEpicReadinessIntegrity(state, stateText, context) {
26833
26925
  }
26834
26926
  });
26835
26927
  }
26836
- errors.push(...validateEpicPlannerLaunchEvidence(state, context));
26928
+ errors.push(...validateEpicPlannerLaunchEvidence(state, context, options));
26837
26929
  if (parsed !== void 0) {
26838
26930
  errors.push(
26839
26931
  ...validatePlanningGitIntegrity(state, parsed, plans, context.git),
@@ -26969,18 +27061,19 @@ function extractFeatures2(value) {
26969
27061
  if (!Array.isArray(value)) {
26970
27062
  return {
26971
27063
  errors: ["Epic planner checkpoint features must be a list."],
26972
- features: []
27064
+ indexedFeatures: [],
27065
+ entries: []
26973
27066
  };
26974
27067
  }
26975
27068
  const errors = [];
26976
- const features = [];
27069
+ const indexedFeatures = [];
26977
27070
  value.forEach((item, index) => {
26978
27071
  const prefix = `Epic planner checkpoint features[${index}]`;
26979
27072
  if (!isObject7(item)) {
26980
27073
  errors.push(`${prefix} must be an object.`);
26981
27074
  return;
26982
27075
  }
26983
- features.push(item);
27076
+ indexedFeatures.push([index, item]);
26984
27077
  const missing = REQUIRED_FEATURE_KEYS.filter((key) => !(key in item));
26985
27078
  if (missing.length > 0) {
26986
27079
  errors.push(`${prefix} missing required keys: ${missing.join(", ")}.`);
@@ -27000,13 +27093,14 @@ function extractFeatures2(value) {
27000
27093
  );
27001
27094
  }
27002
27095
  });
27003
- return { errors, features };
27096
+ return { errors, indexedFeatures, entries: value };
27004
27097
  }
27005
- function validateDependencyWaves(features) {
27098
+ function validateDependencyWaves(indexedFeatures) {
27099
+ const features = indexedFeatures.map(([, feature]) => feature);
27006
27100
  const errors = [];
27007
27101
  const seenFolders = /* @__PURE__ */ new Set();
27008
27102
  const seenIssues = /* @__PURE__ */ new Set();
27009
- features.forEach((feature, index2) => {
27103
+ indexedFeatures.forEach(([index2, feature]) => {
27010
27104
  const prefix = `Epic planner checkpoint features[${index2}]`;
27011
27105
  const folder = feature["feature_folder"];
27012
27106
  if (typeof folder === "string" && folder.length > 0) {
@@ -27029,7 +27123,7 @@ function validateDependencyWaves(features) {
27029
27123
  });
27030
27124
  const index = buildFeatureReferenceIndex(features);
27031
27125
  const manifest = /* @__PURE__ */ new Map();
27032
- features.forEach((feature, featureIndex) => {
27126
+ indexedFeatures.forEach(([featureIndex, feature]) => {
27033
27127
  const folder = feature["feature_folder"];
27034
27128
  const dependencies = feature["depends_on"];
27035
27129
  if (typeof folder !== "string" || folder.length === 0 || !Array.isArray(dependencies)) {
@@ -27058,7 +27152,7 @@ function validateDependencyWaves(features) {
27058
27152
  }
27059
27153
  throw error2;
27060
27154
  }
27061
- features.forEach((feature, index2) => {
27155
+ indexedFeatures.forEach(([index2, feature]) => {
27062
27156
  const folder = feature["feature_folder"];
27063
27157
  if (typeof folder !== "string" || !expectedWaves.has(folder)) {
27064
27158
  return;
@@ -27072,14 +27166,14 @@ function validateDependencyWaves(features) {
27072
27166
  });
27073
27167
  return errors;
27074
27168
  }
27075
- function validateReadyFeatures(features) {
27169
+ function validateReadyFeatures(indexedFeatures, keyGated) {
27076
27170
  const errors = [];
27077
- if (features.length < 2) {
27171
+ if (indexedFeatures.length < 2) {
27078
27172
  errors.push(
27079
27173
  "Execution-ready epic planning requires at least two features."
27080
27174
  );
27081
27175
  }
27082
- features.forEach((feature, index) => {
27176
+ indexedFeatures.forEach(([index, feature]) => {
27083
27177
  const prefix = `Epic planner checkpoint features[${index}]`;
27084
27178
  const issueNum = feature["issue_num"];
27085
27179
  if (typeof issueNum !== "number" || !Number.isInteger(issueNum) || issueNum <= 0) {
@@ -27101,36 +27195,40 @@ function validateReadyFeatures(features) {
27101
27195
  if (feature["preflight_status"] !== "PREFLIGHT: ALL CLEAR") {
27102
27196
  errors.push(`${prefix}.preflight_status must be 'PREFLIGHT: ALL CLEAR'.`);
27103
27197
  }
27104
- const receipt = feature["model_routing_receipt"];
27105
- errors.push(
27106
- ...validateCodexModelRoutingReceipt(
27107
- receipt,
27108
- `${prefix}.model_routing_receipt`
27109
- )
27110
- );
27111
- if (isObject7(receipt) && receipt["logical_agent"] !== "orchestrator") {
27198
+ if (!keyGated || "model_routing_receipt" in feature) {
27199
+ const receipt = feature["model_routing_receipt"];
27112
27200
  errors.push(
27113
- `${prefix}.model_routing_receipt.logical_agent must be 'orchestrator'.`
27201
+ ...validateCodexModelRoutingReceipt(
27202
+ receipt,
27203
+ `${prefix}.model_routing_receipt`
27204
+ )
27114
27205
  );
27115
- }
27116
- if (isObject7(receipt)) {
27117
- if (receipt["complexity_band"] !== feature["complexity_band"]) {
27206
+ if (isObject7(receipt) && receipt["logical_agent"] !== "orchestrator") {
27118
27207
  errors.push(
27119
- `${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'.`
27120
27209
  );
27121
27210
  }
27122
- if (receipt["execution_context"] !== "epic_preparation_child") {
27123
- errors.push(
27124
- `${prefix}.model_routing_receipt.execution_context must be 'epic_preparation_child'.`
27125
- );
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
+ }
27126
27222
  }
27127
27223
  }
27128
- errors.push(
27129
- ...validateChildTopologyReceipt(
27130
- feature["topology_receipt"],
27131
- `${prefix}.topology_receipt`
27132
- )
27133
- );
27224
+ if (!keyGated || "topology_receipt" in feature) {
27225
+ errors.push(
27226
+ ...validateChildTopologyReceipt(
27227
+ feature["topology_receipt"],
27228
+ `${prefix}.topology_receipt`
27229
+ )
27230
+ );
27231
+ }
27134
27232
  });
27135
27233
  return errors;
27136
27234
  }
@@ -27153,7 +27251,7 @@ function validateEpicPlannerStateText(text2, options = {}) {
27153
27251
  errors.push(...worthiness.errors);
27154
27252
  const featureResult = extractFeatures2(value["features"]);
27155
27253
  errors.push(...featureResult.errors);
27156
- errors.push(...validateDependencyWaves(featureResult.features));
27254
+ errors.push(...validateDependencyWaves(featureResult.indexedFeatures));
27157
27255
  const maxParallel = value["max_parallel_features"];
27158
27256
  if (typeof maxParallel !== "number" || !Number.isInteger(maxParallel) || maxParallel < 1 || maxParallel > 8) {
27159
27257
  errors.push(
@@ -27166,6 +27264,7 @@ function validateEpicPlannerStateText(text2, options = {}) {
27166
27264
  );
27167
27265
  }
27168
27266
  if (options.requireReadyForExecution === true) {
27267
+ const requireLaunchPaths = options.requireCodexModelRouting !== true && options.requireCodexTopology !== true;
27169
27268
  if (worthiness.verdict !== "epic") {
27170
27269
  errors.push(
27171
27270
  "Execution readiness requires epic_worthiness.verdict 'epic'."
@@ -27176,11 +27275,20 @@ function validateEpicPlannerStateText(text2, options = {}) {
27176
27275
  `Execution-ready planner checkpoint next_step must be '${READY_NEXT_STEP}'.`
27177
27276
  );
27178
27277
  }
27179
- errors.push(...validateReadyFeatures(featureResult.features));
27180
27278
  errors.push(
27181
- ...validateEpicPlannerChildLaunchBindings(featureResult.features)
27279
+ ...validateReadyFeatures(
27280
+ featureResult.indexedFeatures,
27281
+ requireLaunchPaths
27282
+ )
27283
+ );
27284
+ errors.push(
27285
+ ...validateEpicPlannerChildLaunchBindings(featureResult.entries, {
27286
+ requireLaunchPaths
27287
+ })
27182
27288
  );
27183
- errors.push(...validatePlannerTopologyReceipt(value["topology_receipt"]));
27289
+ if (!requireLaunchPaths || "topology_receipt" in value) {
27290
+ errors.push(...validatePlannerTopologyReceipt(value["topology_receipt"]));
27291
+ }
27184
27292
  const expectedKickoff = `artifacts/orchestration/epic-kickoff-${String(
27185
27293
  value["epic_feature_folder"]
27186
27294
  )}.md`;
@@ -27198,7 +27306,8 @@ function validateEpicPlannerStateText(text2, options = {}) {
27198
27306
  ...validateEpicReadinessIntegrity(
27199
27307
  value,
27200
27308
  text2,
27201
- options.readinessContext
27309
+ options.readinessContext,
27310
+ { requireLaunchPaths }
27202
27311
  )
27203
27312
  );
27204
27313
  }
@@ -27266,6 +27375,10 @@ var PROMOTION_ENTRY_TOOLS = /* @__PURE__ */ new Set([
27266
27375
  ]);
27267
27376
  var POTENTIAL_RECORD_PREFIX = "docs/features/potential/";
27268
27377
  var POTENTIAL_RECORD_SUFFIX = ".md";
27378
+ var RECORD_OPTIONAL_ORIGINS = /* @__PURE__ */ new Set([
27379
+ "transferred",
27380
+ "filed_before_orchestration"
27381
+ ]);
27269
27382
  var ISSUE_NUM_PATTERN = /^[1-9][0-9]*$/;
27270
27383
  var ERROR_NOT_OBJECT = "Checkpoint issue_adoption must be an object when present.";
27271
27384
  var ERROR_ISSUE_NUM_FORMAT = "Checkpoint issue_adoption.issue_num must be a string of decimal digits without a leading zero.";
@@ -27360,7 +27473,10 @@ function waivedToolErrors(waived, options) {
27360
27473
  }
27361
27474
  return errors;
27362
27475
  }
27363
- function potentialRecordErrors(waived, potentialRecord) {
27476
+ function potentialRecordErrors(waived, potentialRecord, origin, recordPresent) {
27477
+ if (!recordPresent && typeof origin === "string" && RECORD_OPTIONAL_ORIGINS.has(origin)) {
27478
+ return [];
27479
+ }
27364
27480
  if (typeof potentialRecord === "string" && potentialRecord.startsWith(POTENTIAL_RECORD_PREFIX) && potentialRecord.endsWith(POTENTIAL_RECORD_SUFFIX)) {
27365
27481
  return [];
27366
27482
  }
@@ -27394,7 +27510,14 @@ function resolveIssueAdoption(state, options) {
27394
27510
  return { errors, waivedTools: /* @__PURE__ */ new Set() };
27395
27511
  }
27396
27512
  errors.push(...waivedToolErrors(waived, options));
27397
- errors.push(...potentialRecordErrors(waived, adoption["potential_record"]));
27513
+ errors.push(
27514
+ ...potentialRecordErrors(
27515
+ waived,
27516
+ adoption["potential_record"],
27517
+ adoption["origin"],
27518
+ Object.prototype.hasOwnProperty.call(adoption, "potential_record")
27519
+ )
27520
+ );
27398
27521
  if (errors.length > 0) {
27399
27522
  return { errors, waivedTools: /* @__PURE__ */ new Set() };
27400
27523
  }
@@ -28121,7 +28244,7 @@ function validateModelRoutingExistence(state) {
28121
28244
  }
28122
28245
  }
28123
28246
  }
28124
- return [...delegated].filter((agent) => !receiptAgents2.has(agent)).sort().map(
28247
+ return [...delegated].filter((agent) => !receiptAgents2.has(agent)).sort(compareCodePoint).map(
28125
28248
  (agent) => `Checkpoint model_routing_receipts is missing a receipt for delegated agent: ${agent}.`
28126
28249
  );
28127
28250
  }
@@ -28230,7 +28353,7 @@ function validateNamespacedDelegationReceipts(receipts) {
28230
28353
  const errors = [];
28231
28354
  const unsupportedKeys = Object.keys(receipts).filter(
28232
28355
  (key) => key !== AGENT_RECEIPT_NAMESPACE_KEY && key !== PROMOTION_RECEIPT_NAMESPACE_KEY
28233
- ).sort();
28356
+ ).sort(compareCodePoint);
28234
28357
  for (const key of unsupportedKeys) {
28235
28358
  errors.push(
28236
28359
  `Checkpoint delegation_receipts object contains unsupported key: ${key}`
@@ -28256,7 +28379,7 @@ function validateNamespacedDelegationReceipts(receipts) {
28256
28379
  }
28257
28380
  const unsupportedPromotionKeys = Object.keys(promotionReceipts).filter(
28258
28381
  (key) => !PROMOTION_RECEIPT_KEYS.includes(key)
28259
- ).sort();
28382
+ ).sort(compareCodePoint);
28260
28383
  for (const key of unsupportedPromotionKeys) {
28261
28384
  errors.push(
28262
28385
  "Checkpoint delegation_receipts.promotion contains unsupported key: " + key
@@ -28726,7 +28849,7 @@ function classifyKind(argv) {
28726
28849
  }
28727
28850
  return "other";
28728
28851
  }
28729
- function splitLines2(text2) {
28852
+ function splitPlanLines(text2) {
28730
28853
  if (text2 === "") {
28731
28854
  return [];
28732
28855
  }
@@ -28736,6 +28859,11 @@ function splitLines2(text2) {
28736
28859
  }
28737
28860
  return lines;
28738
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
+ }
28739
28867
  function inlineSpans(line) {
28740
28868
  const spans = [];
28741
28869
  for (const match of line.matchAll(INLINE_SPAN_RE)) {
@@ -28779,7 +28907,7 @@ function extractPlanCommands(text2) {
28779
28907
  let inFence = false;
28780
28908
  let windowLines = [];
28781
28909
  let windowStart = 0;
28782
- const lines = splitLines2(text2);
28910
+ const lines = splitPlanLines(text2);
28783
28911
  for (let index = 0; index < lines.length; index += 1) {
28784
28912
  const line = lines[index] ?? "";
28785
28913
  const lineNumber = index + 1;
@@ -28829,6 +28957,166 @@ function extractPlanCommands(text2) {
28829
28957
  return commands;
28830
28958
  }
28831
28959
 
28960
+ // ../../extensions/drm-copilot/src/lib/validate/plan-gate-document.ts
28961
+ var G11_SEVERITY = "blocking";
28962
+ var G12_SEVERITY = "blocking";
28963
+ var G13_SEVERITY = "blocking";
28964
+ var PLAN_TASK_GUIDELINE = 40;
28965
+ var PLAN_LINE_GUIDELINE = 400;
28966
+ var G11_PROSE_PATTERN = String.raw`\b[Ll]ines?[ \t]+[0-9]+`;
28967
+ var G11_PATH_PATTERN = String.raw`[A-Za-z0-9_./-]+\.[A-Za-z][A-Za-z0-9]{0,5}:[0-9]+`;
28968
+ var G11_ANCHOR_PATTERN = String.raw`#L[0-9]+`;
28969
+ var G12_SHA_PATTERN = String.raw`\b[0-9a-f]{7,40}\b`;
28970
+ var G13_TASK_PATTERN = String.raw`^- \[[ xX]\] \[P[0-9]+-T[0-9]+\] `;
28971
+ var INLINE_CODE_PATTERN = "`[^`]*`";
28972
+ var FENCE_RE2 = /^\s*```/;
28973
+ var PROSE_RE = new RegExp(G11_PROSE_PATTERN, "g");
28974
+ var PATH_RE = new RegExp(G11_PATH_PATTERN, "g");
28975
+ var ANCHOR_RE = new RegExp(G11_ANCHOR_PATTERN, "g");
28976
+ var SHA_RE = new RegExp(G12_SHA_PATTERN, "g");
28977
+ var TASK_RE = new RegExp(G13_TASK_PATTERN);
28978
+ var INLINE_CODE_RE = new RegExp(INLINE_CODE_PATTERN, "g");
28979
+ var WHITESPACE_RE = new RegExp(`^${PLAN_WHITESPACE_CLASS}$`);
28980
+ var JUSTIFICATION_HEADING_RE = /^##[ \t]+Size Justification[ \t]*$/;
28981
+ var SECTION_END_RE = /^#{1,2}(?:[ \t]|$)/;
28982
+ var HEADING_RE = /^#{1,6}(?:[ \t]|$)/;
28983
+ var DIGITS = "0123456789";
28984
+ var HEX_LETTERS = "abcdef";
28985
+ var SHA_BEFORE_REJECT = "-_.";
28986
+ var SHA_AFTER_REJECT = "-_";
28987
+ function unfencedLines(text2) {
28988
+ const result = [];
28989
+ let inFence = false;
28990
+ for (const [index, line] of splitPlanLines(text2).entries()) {
28991
+ if (FENCE_RE2.test(line)) {
28992
+ inFence = !inFence;
28993
+ continue;
28994
+ }
28995
+ if (!inFence) {
28996
+ result.push([index + 1, line]);
28997
+ }
28998
+ }
28999
+ return result;
29000
+ }
29001
+ function maskInlineCode(line) {
29002
+ return line.replace(INLINE_CODE_RE, (span) => " ".repeat(span.length));
29003
+ }
29004
+ function isWhitespace(character) {
29005
+ return character !== void 0 && WHITESPACE_RE.test(character);
29006
+ }
29007
+ function enclosingToken(line, start, end) {
29008
+ let left = start;
29009
+ while (left > 0 && !isWhitespace(line[left - 1])) {
29010
+ left -= 1;
29011
+ }
29012
+ let right = end;
29013
+ while (right < line.length && !isWhitespace(line[right])) {
29014
+ right += 1;
29015
+ }
29016
+ return line.slice(left, right);
29017
+ }
29018
+ function lineCitations(text2) {
29019
+ const findings = [];
29020
+ for (const [lineNumber, line] of unfencedLines(text2)) {
29021
+ for (const match of maskInlineCode(line).matchAll(PROSE_RE)) {
29022
+ findings.push([lineNumber, match[0]]);
29023
+ }
29024
+ for (const match of line.matchAll(PATH_RE)) {
29025
+ const token = enclosingToken(
29026
+ line,
29027
+ match.index,
29028
+ match.index + match[0].length
29029
+ );
29030
+ if (!token.includes("://")) {
29031
+ findings.push([lineNumber, match[0]]);
29032
+ }
29033
+ }
29034
+ for (const match of line.matchAll(ANCHOR_RE)) {
29035
+ findings.push([lineNumber, match[0]]);
29036
+ }
29037
+ }
29038
+ return findings;
29039
+ }
29040
+ function isShaCandidate(line, start, end) {
29041
+ const token = line.slice(start, end);
29042
+ if (![...token].some((character) => DIGITS.includes(character))) {
29043
+ return false;
29044
+ }
29045
+ if (![...token].some((character) => HEX_LETTERS.includes(character))) {
29046
+ return false;
29047
+ }
29048
+ const before = start > 0 ? line.charAt(start - 1) : "";
29049
+ if (before !== "" && SHA_BEFORE_REJECT.includes(before)) {
29050
+ return false;
29051
+ }
29052
+ const after = end < line.length ? line.charAt(end) : "";
29053
+ return !(after !== "" && SHA_AFTER_REJECT.includes(after));
29054
+ }
29055
+ function shaCitations(text2) {
29056
+ const findings = [];
29057
+ for (const [lineNumber, line] of unfencedLines(text2)) {
29058
+ for (const match of line.matchAll(SHA_RE)) {
29059
+ if (isShaCandidate(line, match.index, match.index + match[0].length)) {
29060
+ findings.push([lineNumber, match[0]]);
29061
+ }
29062
+ }
29063
+ }
29064
+ return findings;
29065
+ }
29066
+ function hasSizeJustification(text2) {
29067
+ let inSection = false;
29068
+ for (const [, line] of unfencedLines(text2)) {
29069
+ if (JUSTIFICATION_HEADING_RE.test(line)) {
29070
+ inSection = true;
29071
+ continue;
29072
+ }
29073
+ if (!inSection) {
29074
+ continue;
29075
+ }
29076
+ if (SECTION_END_RE.test(line)) {
29077
+ inSection = false;
29078
+ continue;
29079
+ }
29080
+ if (normalizePlanWhitespace(line) !== "" && !HEADING_RE.test(line)) {
29081
+ return true;
29082
+ }
29083
+ }
29084
+ return false;
29085
+ }
29086
+ function planSize(text2) {
29087
+ const tasks = unfencedLines(text2).filter(
29088
+ ([, line]) => TASK_RE.test(line)
29089
+ ).length;
29090
+ return [tasks, splitPlanLines(text2).length];
29091
+ }
29092
+ function lineCitationMessage(lineNumber, value) {
29093
+ return `Line ${String(lineNumber)}: line-number citation \`${value}\` anchors on a position that moves when main moves; cite the symbol, heading, or test name instead.`;
29094
+ }
29095
+ function shaCitationMessage(lineNumber, value) {
29096
+ return `Line ${String(lineNumber)}: commit-SHA citation \`${value}\` names a commit that goes stale when main moves; cite the branch, ref name, or merge base derivation instead.`;
29097
+ }
29098
+ function planSizeMessage(tasks, lines) {
29099
+ return `Line 1: plan size \`${String(tasks)} tasks, ${String(lines)} lines\` exceeds the guideline of ${String(PLAN_TASK_GUIDELINE)} tasks or ${String(PLAN_LINE_GUIDELINE)} lines and carries no \`## Size Justification\` section; split the item or state why the size is necessary.`;
29100
+ }
29101
+ function channelFor(report, severity) {
29102
+ return severity === "blocking" ? report.blocking : report.warnings;
29103
+ }
29104
+ function evaluateDocumentGates(report, text2) {
29105
+ const g11 = channelFor(report, G11_SEVERITY);
29106
+ for (const [lineNumber, value] of lineCitations(text2)) {
29107
+ g11.push(lineCitationMessage(lineNumber, value));
29108
+ }
29109
+ const g12 = channelFor(report, G12_SEVERITY);
29110
+ for (const [lineNumber, value] of shaCitations(text2)) {
29111
+ g12.push(shaCitationMessage(lineNumber, value));
29112
+ }
29113
+ const [tasks, lines] = planSize(text2);
29114
+ const overGuideline = tasks > PLAN_TASK_GUIDELINE || lines > PLAN_LINE_GUIDELINE;
29115
+ if (overGuideline && !hasSizeJustification(text2)) {
29116
+ channelFor(report, G13_SEVERITY).push(planSizeMessage(tasks, lines));
29117
+ }
29118
+ }
29119
+
28832
29120
  // ../../extensions/drm-copilot/src/lib/validate/plan-gate-rules.ts
28833
29121
  function emptyPlanGateReport() {
28834
29122
  return { blocking: [], warnings: [] };
@@ -28949,7 +29237,7 @@ function planQuotesLiteral(text2, literal2, excludeSpan) {
28949
29237
  return normalizeWhitespace(remainder).includes(needle);
28950
29238
  }
28951
29239
  function windowJoin(lines, size = WINDOW_SIZE) {
28952
- const dense = lines.filter((line) => line.trim() !== "").map((line) => normalizeWhitespace(line));
29240
+ const dense = lines.map((line) => normalizePlanWhitespace(line)).filter((line) => line !== "");
28953
29241
  const windows = [];
28954
29242
  for (let index = 0; index < dense.length; index += 1) {
28955
29243
  windows.push(dense.slice(index, index + size).join(" "));
@@ -28957,15 +29245,15 @@ function windowJoin(lines, size = WINDOW_SIZE) {
28957
29245
  return windows;
28958
29246
  }
28959
29247
  function hasCrossLinePresence(context, literal2) {
28960
- const words2 = literal2.split(/\s+/).filter((word) => word !== "");
29248
+ const needle = normalizePlanWhitespace(literal2);
29249
+ const words2 = needle.split(" ");
28961
29250
  if (words2.length < 2) {
28962
29251
  return false;
28963
29252
  }
28964
- const needle = words2.join(" ");
28965
29253
  const firstWord = words2[0] ?? "";
28966
29254
  for (const path16 of context.git.filesContaining(firstWord)) {
28967
29255
  const lines = context.git.readTrackedText(path16).split(/\r\n|\n|\r/);
28968
- if (lines.some((line) => normalizeWhitespace(line).includes(needle))) {
29256
+ if (lines.some((line) => normalizePlanWhitespace(line).includes(needle))) {
28969
29257
  continue;
28970
29258
  }
28971
29259
  if (windowJoin(lines).some((window2) => window2.includes(needle))) {
@@ -29211,6 +29499,71 @@ function evaluateObservabilityGates(report, commands, context) {
29211
29499
  }
29212
29500
  }
29213
29501
 
29502
+ // ../../extensions/drm-copilot/src/lib/validate/plan-gate-scratch.ts
29503
+ var G10_SEVERITY = "blocking";
29504
+ var BACKTICK = "`";
29505
+ 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)`;
29506
+ var SCRATCH_NAMESPACE_PATTERN = String.raw`issue-(?:<issue-num>|[0-9]+)`;
29507
+ var FENCE_RE3 = /^\s*```/;
29508
+ var DEFINITION_RE = new RegExp(SCRATCH_DEFINITION_PATTERN);
29509
+ var NAMESPACE_RE = new RegExp(SCRATCH_NAMESPACE_PATTERN);
29510
+ var LEADING_WHITESPACE_RE = new RegExp(`^${PLAN_WHITESPACE_CLASS}`);
29511
+ function continuesLogicalLine(line) {
29512
+ if (normalizePlanWhitespace(line) === "" || !LEADING_WHITESPACE_RE.test(line)) {
29513
+ return false;
29514
+ }
29515
+ return !FENCE_RE3.test(line);
29516
+ }
29517
+ function isBareDefinition(logical) {
29518
+ const match = DEFINITION_RE.exec(logical);
29519
+ if (match === null) {
29520
+ return false;
29521
+ }
29522
+ return !NAMESPACE_RE.test(logical.slice(match.index + match[0].length));
29523
+ }
29524
+ function recordIfBare(findings, pending) {
29525
+ const logical = normalizePlanWhitespace(pending.parts.join(" "));
29526
+ if (isBareDefinition(logical)) {
29527
+ findings.push([pending.start + 1, logical]);
29528
+ }
29529
+ }
29530
+ function bareScratchDefinitions(text2) {
29531
+ const findings = [];
29532
+ let inFence = false;
29533
+ let pending = null;
29534
+ for (const [index, line] of splitPlanLines(text2).entries()) {
29535
+ if (pending !== null && continuesLogicalLine(line)) {
29536
+ pending.parts.push(line);
29537
+ continue;
29538
+ }
29539
+ if (pending !== null) {
29540
+ recordIfBare(findings, pending);
29541
+ pending = null;
29542
+ }
29543
+ if (FENCE_RE3.test(line)) {
29544
+ inFence = !inFence;
29545
+ continue;
29546
+ }
29547
+ if (inFence || normalizePlanWhitespace(line) === "") {
29548
+ continue;
29549
+ }
29550
+ pending = { start: index, parts: [line] };
29551
+ }
29552
+ if (pending !== null) {
29553
+ recordIfBare(findings, pending);
29554
+ }
29555
+ return findings;
29556
+ }
29557
+ function scratchFindingMessage(lineNumber, logicalLine) {
29558
+ return `Line ${String(lineNumber)}: SCRATCH definition \`${logicalLine}\` is not namespaced by issue number; define SCRATCH as \`<session scratchpad>/issue-<issue-num>/\`.`;
29559
+ }
29560
+ function evaluateScratchGate(report, text2, severity = G10_SEVERITY) {
29561
+ const channel = severity === "blocking" ? report.blocking : report.warnings;
29562
+ for (const [lineNumber, logicalLine] of bareScratchDefinitions(text2)) {
29563
+ channel.push(scratchFindingMessage(lineNumber, logicalLine));
29564
+ }
29565
+ }
29566
+
29214
29567
  // ../../extensions/drm-copilot/src/lib/validate/plan-gate-discrimination.ts
29215
29568
  var G5_SEVERITY = "warning";
29216
29569
  var CommandRunnerPlanGateRepository = class {
@@ -29310,6 +29663,8 @@ function evaluatePlanGates(text2, context) {
29310
29663
  if (context !== void 0) {
29311
29664
  evaluateLiteralRules(report, text2, commands, context);
29312
29665
  }
29666
+ evaluateScratchGate(report, text2);
29667
+ evaluateDocumentGates(report, text2);
29313
29668
  return report;
29314
29669
  }
29315
29670
 
@@ -30245,45 +30600,149 @@ function validateParallelOrchestratorStateText(text2, options = {}) {
30245
30600
  return errors;
30246
30601
  }
30247
30602
 
30248
- // ../../extensions/drm-copilot/src/lib/validate/parallel-planner-state-core.ts
30249
- var CONTEXT2 = "Parallel planner checkpoint";
30250
- var MIN_CONCURRENCY2 = 1;
30251
- var MAX_CONCURRENCY2 = 32;
30252
- var REQUIRED_KEYS5 = [
30253
- "objective",
30254
- "parallel_slug",
30255
- "parallel_manifest_path",
30256
- "mode",
30257
- "max_concurrency",
30258
- "items",
30259
- "cohorts",
30260
- "conflict_edges",
30261
- "recolor_generation",
30262
- "completed_steps",
30263
- "next_step",
30264
- "last_updated"
30265
- ];
30266
- var REQUIRED_ITEM_KEYS = [
30267
- "issue_num",
30268
- "feature_folder",
30269
- "kind",
30270
- "state",
30271
- "blast_radius",
30272
- "preparation_status",
30273
- "research_path",
30274
- "plan_path",
30275
- "preflight_status"
30276
- ];
30277
- var VALID_COMPLEXITY_BANDS = [
30278
- "C1",
30279
- "C2",
30280
- "C3",
30281
- "C4"
30603
+ // ../../extensions/drm-copilot/src/lib/validate/parallel-planner-state-routing.ts
30604
+ var BAND_ORDER2 = ["C1", "C2", "C3", "C4"];
30605
+ var VALID_FABLE_POLICIES = [
30606
+ "disabled",
30607
+ "available",
30608
+ "preferred"
30282
30609
  ];
30283
- var READY_NEXT_STEP2 = "PARALLEL_EXECUTION_READY";
30284
- var READY_PREPARATION_STATUS = "prepared";
30285
- var READY_PREFLIGHT_STATUS = "PREFLIGHT: ALL CLEAR";
30286
- var READY_RADIUS_SOURCE = "declared";
30610
+ var ROUTING_AGENT = "orchestrator";
30611
+ function sameValue(left, right) {
30612
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
30613
+ }
30614
+ function isListOfStrings(value) {
30615
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
30616
+ }
30617
+ function validateAssessmentEntry(assessment, context) {
30618
+ const errors = [];
30619
+ const band = assessment["band"];
30620
+ const floor = assessment["floor"];
30621
+ if (!isEnumMember(BAND_ORDER2, band)) {
30622
+ errors.push(
30623
+ `${context} band must be one of C1, C2, C3, C4; got: ${pythonStr2(band)}.`
30624
+ );
30625
+ }
30626
+ if (!isListOfStrings(assessment["signals_present"])) {
30627
+ errors.push(`${context} signals_present must be a list of strings.`);
30628
+ }
30629
+ if (isEnumMember(BAND_ORDER2, band) && isEnumMember(BAND_ORDER2, floor) && BAND_ORDER2.indexOf(String(band)) < BAND_ORDER2.indexOf(String(floor))) {
30630
+ errors.push(
30631
+ `${context} band ${pythonStr2(band)} is below its floor ${pythonStr2(floor)}.`
30632
+ );
30633
+ }
30634
+ if (!isNonEmptyString2(assessment["rationale"])) {
30635
+ errors.push(`${context} rationale must be a non-empty string.`);
30636
+ }
30637
+ return errors;
30638
+ }
30639
+ function validateAssessment(assessment, band, entryContext) {
30640
+ const context = `${entryContext} complexity_assessment`;
30641
+ const errors = validateAssessmentEntry(assessment, context);
30642
+ if (!isNonEmptyString2(assessment["assessed_at"])) {
30643
+ errors.push(`${context}.assessed_at must be a non-empty string.`);
30644
+ }
30645
+ const assessedBand = assessment["band"];
30646
+ if (!sameValue(assessedBand, band)) {
30647
+ errors.push(
30648
+ `${context}.band ${pythonRepr10(assessedBand)} does not equal complexity_band ${pythonRepr10(band)}.`
30649
+ );
30650
+ }
30651
+ return errors;
30652
+ }
30653
+ function validateReceipt4(receipt, band, entryContext) {
30654
+ const context = `${entryContext} model_routing_receipt`;
30655
+ const errors = [];
30656
+ const receiptBand = receipt["complexity_band"];
30657
+ if (!isEnumMember(BAND_ORDER2, receiptBand)) {
30658
+ errors.push(
30659
+ `${context} complexity_band must be one of C1, C2, C3, C4; got: ${pythonStr2(receiptBand)}.`
30660
+ );
30661
+ }
30662
+ const agent = receipt["agent"];
30663
+ if (agent !== ROUTING_AGENT) {
30664
+ errors.push(
30665
+ `${context}.agent must be ${pythonRepr10(ROUTING_AGENT)}; found: ${pythonRepr10(agent)}.`
30666
+ );
30667
+ }
30668
+ if (!sameValue(receiptBand, band)) {
30669
+ errors.push(
30670
+ `${context}.complexity_band ${pythonRepr10(receiptBand)} does not equal complexity_band ${pythonRepr10(band)}.`
30671
+ );
30672
+ }
30673
+ const fablePolicy = receipt["fable_policy"];
30674
+ if (!isEnumMember(VALID_FABLE_POLICIES, fablePolicy)) {
30675
+ errors.push(
30676
+ enumError(
30677
+ entryContext,
30678
+ "model_routing_receipt.fable_policy",
30679
+ VALID_FABLE_POLICIES,
30680
+ fablePolicy
30681
+ )
30682
+ );
30683
+ }
30684
+ return errors;
30685
+ }
30686
+ function validateReadyItemRouting(record3, entryContext) {
30687
+ const errors = [];
30688
+ const band = record3["complexity_band"];
30689
+ if (!isEnumMember(BAND_ORDER2, band)) {
30690
+ errors.push(enumError(entryContext, "complexity_band", BAND_ORDER2, band));
30691
+ }
30692
+ const assessment = record3["complexity_assessment"];
30693
+ if (isObject15(assessment)) {
30694
+ errors.push(...validateAssessment(assessment, band, entryContext));
30695
+ } else {
30696
+ errors.push(`${entryContext} complexity_assessment must be an object.`);
30697
+ }
30698
+ const receipt = record3["model_routing_receipt"];
30699
+ if (isObject15(receipt)) {
30700
+ errors.push(...validateReceipt4(receipt, band, entryContext));
30701
+ } else {
30702
+ errors.push(`${entryContext} model_routing_receipt must be an object.`);
30703
+ }
30704
+ return errors;
30705
+ }
30706
+
30707
+ // ../../extensions/drm-copilot/src/lib/validate/parallel-planner-state-core.ts
30708
+ var CONTEXT2 = "Parallel planner checkpoint";
30709
+ var MIN_CONCURRENCY2 = 1;
30710
+ var MAX_CONCURRENCY2 = 32;
30711
+ var REQUIRED_KEYS5 = [
30712
+ "objective",
30713
+ "parallel_slug",
30714
+ "parallel_manifest_path",
30715
+ "mode",
30716
+ "max_concurrency",
30717
+ "items",
30718
+ "cohorts",
30719
+ "conflict_edges",
30720
+ "recolor_generation",
30721
+ "completed_steps",
30722
+ "next_step",
30723
+ "last_updated"
30724
+ ];
30725
+ var REQUIRED_ITEM_KEYS = [
30726
+ "issue_num",
30727
+ "feature_folder",
30728
+ "kind",
30729
+ "state",
30730
+ "blast_radius",
30731
+ "preparation_status",
30732
+ "research_path",
30733
+ "plan_path",
30734
+ "preflight_status"
30735
+ ];
30736
+ var VALID_COMPLEXITY_BANDS = [
30737
+ "C1",
30738
+ "C2",
30739
+ "C3",
30740
+ "C4"
30741
+ ];
30742
+ var READY_NEXT_STEP2 = "PARALLEL_EXECUTION_READY";
30743
+ var READY_PREPARATION_STATUS = "prepared";
30744
+ var READY_PREFLIGHT_STATUS = "PREFLIGHT: ALL CLEAR";
30745
+ var READY_RADIUS_SOURCE = "declared";
30287
30746
  var MINIMUM_READY_ITEMS = 2;
30288
30747
  var READY_ITEM_PATH_KEYS = ["research_path", "plan_path"];
30289
30748
  function kickoffPathFor(slug) {
@@ -30422,7 +30881,9 @@ function validateReadyGate(state) {
30422
30881
  );
30423
30882
  }
30424
30883
  for (const { index, record: record3 } of itemRecords(items)) {
30425
- errors.push(...validateReadyItem(record3, itemContext(CONTEXT2, index)));
30884
+ const entryContext = itemContext(CONTEXT2, index);
30885
+ errors.push(...validateReadyItem(record3, entryContext));
30886
+ errors.push(...validateReadyItemRouting(record3, entryContext));
30426
30887
  }
30427
30888
  }
30428
30889
  const nextStep = state["next_step"];
@@ -31588,6 +32049,8 @@ function dispatchValidatorErrors(input) {
31588
32049
  case "epic-planner-state": {
31589
32050
  const options = {
31590
32051
  ...input.requireReadyForExecution === void 0 ? {} : { requireReadyForExecution: input.requireReadyForExecution },
32052
+ ...input.requireCodexModelRouting === void 0 ? {} : { requireCodexModelRouting: input.requireCodexModelRouting },
32053
+ ...input.requireCodexTopology === void 0 ? {} : { requireCodexTopology: input.requireCodexTopology },
31591
32054
  ...input.fs === void 0 || input.root === void 0 || input.artifactPath === void 0 || input.runner === void 0 ? {} : {
31592
32055
  readinessContext: {
31593
32056
  workspaceRoot: input.root,
@@ -31785,6 +32248,76 @@ function createGitCheckoutContext(runner) {
31785
32248
  return { observe, isHeadRelationshipSatisfied };
31786
32249
  }
31787
32250
 
32251
+ // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-materializer-request.ts
32252
+ var HANDOFF_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]*$/;
32253
+ var HANDOFF_ERROR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
32254
+ function describeHandoffFailureCause(stage, error2) {
32255
+ if (typeof error2 === "object" && error2 !== null && "code" in error2) {
32256
+ const code = error2.code;
32257
+ if (typeof code === "string" && HANDOFF_ERROR_CODE_PATTERN.test(code)) {
32258
+ return `${stage}: ${code}`;
32259
+ }
32260
+ }
32261
+ if (error2 instanceof Error) {
32262
+ return HANDOFF_ERROR_NAME_PATTERN.test(error2.name) ? `${stage}: ${error2.name}` : `${stage}: Error`;
32263
+ }
32264
+ return `${stage}: non-error value`;
32265
+ }
32266
+ function describeEnvelopeParseFailure(error2) {
32267
+ return {
32268
+ code: error2 instanceof HandoffContractError ? error2.code : "HANDOFF_UNSUPPORTED_VERSION",
32269
+ failureCause: describeHandoffFailureCause("envelope-parse", error2)
32270
+ };
32271
+ }
32272
+ function toReferenceRequest(request) {
32273
+ return {
32274
+ workspaceRoot: request.workspaceRoot,
32275
+ handoffEnvelopePath: request.handoffEnvelopePath,
32276
+ expectedHandoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
32277
+ destinationProvider: request.destinationProvider,
32278
+ expectedRepositoryId: request.expectedRepositoryId,
32279
+ expectedWorkspaceRoot: request.expectedWorkspaceRoot,
32280
+ expectedBranch: request.expectedBranch,
32281
+ expectedSourceHeadSha: request.expectedSourceHeadSha,
32282
+ allowedHeadRelationship: request.allowedHeadRelationship,
32283
+ expectedIssueNumber: request.expectedIssueNumber,
32284
+ expectedFeatureFolder: request.expectedFeatureFolder,
32285
+ expectedWorkMode: request.expectedWorkMode,
32286
+ expectedPlanPath: request.expectedPlanPath,
32287
+ expectedPlanSha256: request.expectedPlanSha256
32288
+ };
32289
+ }
32290
+ function blockedResult(request, primaryFailureCode, options = {}) {
32291
+ return {
32292
+ status: "blocked",
32293
+ handoffId: options.handoffId ?? null,
32294
+ sourceCheckpointSha256: request.expectedSourceCheckpointSha256,
32295
+ handoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
32296
+ handoffHistorySha256: options.handoffHistorySha256 ?? null,
32297
+ requestedTransition: "prepared_to_atomic_execution",
32298
+ destinationCheckpointPath: null,
32299
+ destinationCheckpointSha256: null,
32300
+ primaryFailureCode,
32301
+ affectedPaths: options.affectedPaths ?? [],
32302
+ unsupportedCapabilities: options.unsupportedCapabilities ?? [],
32303
+ ...options.failureCause === void 0 ? {} : { failureCause: options.failureCause }
32304
+ };
32305
+ }
32306
+ function authorityFailure(request, authority, handoffHistorySha256) {
32307
+ if (authority.status === "validated") return null;
32308
+ return blockedResult(
32309
+ request,
32310
+ authority.primaryFailureCode ?? "HANDOFF_VALIDATOR_UNAVAILABLE",
32311
+ {
32312
+ handoffId: authority.handoffId,
32313
+ handoffHistorySha256,
32314
+ affectedPaths: authority.affectedPaths,
32315
+ unsupportedCapabilities: authority.unsupportedCapabilities,
32316
+ ...authority.failureCause === void 0 ? {} : { failureCause: authority.failureCause }
32317
+ }
32318
+ );
32319
+ }
32320
+
31788
32321
  // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-path-boundary.ts
31789
32322
  var fs6 = __toESM(require("node:fs"));
31790
32323
  var path11 = __toESM(require("node:path"));
@@ -31813,6 +32346,13 @@ function normalizedRepositorySegments(repositoryPath2) {
31813
32346
  function missingPath(error2) {
31814
32347
  return typeof error2 === "object" && error2 !== null && "code" in error2 && error2.code === "ENOENT";
31815
32348
  }
32349
+ function guardedResolution(stage, operation) {
32350
+ try {
32351
+ return { ok: true, value: operation() };
32352
+ } catch (error2) {
32353
+ return { ok: false, cause: describeHandoffFailureCause(stage, error2) };
32354
+ }
32355
+ }
31816
32356
  function lexicalCandidate(canonicalWorkspaceRoot, repositoryPath2, caseSensitive) {
31817
32357
  if (!path11.isAbsolute(canonicalWorkspaceRoot)) return null;
31818
32358
  const segments = normalizedRepositorySegments(repositoryPath2);
@@ -31823,14 +32363,13 @@ function lexicalCandidate(canonicalWorkspaceRoot, repositoryPath2, caseSensitive
31823
32363
  function createHandoffPathBoundary(fileSystem, caseSensitive = process.platform !== "win32") {
31824
32364
  const resolveWorkspaceRoot = (workspaceRoot) => {
31825
32365
  if (!path11.isAbsolute(workspaceRoot)) return null;
31826
- try {
32366
+ const resolution = guardedResolution("workspace-root", () => {
31827
32367
  const canonicalRoot = normalizedAbsolutePath(
31828
32368
  fileSystem.realpath(path11.resolve(workspaceRoot))
31829
32369
  );
31830
32370
  return fileSystem.stat(canonicalRoot).isDirectory() ? canonicalRoot : null;
31831
- } catch {
31832
- return null;
31833
- }
32371
+ });
32372
+ return resolution.ok ? resolution.value : null;
31834
32373
  };
31835
32374
  const resolveExistingTarget = (canonicalWorkspaceRoot, repositoryPath2) => {
31836
32375
  const candidate = lexicalCandidate(
@@ -31839,14 +32378,12 @@ function createHandoffPathBoundary(fileSystem, caseSensitive = process.platform
31839
32378
  caseSensitive
31840
32379
  );
31841
32380
  if (candidate === null) return null;
31842
- try {
31843
- const canonicalTarget = normalizedAbsolutePath(
31844
- fileSystem.realpath(candidate)
31845
- );
31846
- return isContained(canonicalWorkspaceRoot, canonicalTarget, caseSensitive) ? canonicalTarget : null;
31847
- } catch {
31848
- return null;
31849
- }
32381
+ const resolution = guardedResolution(
32382
+ "target-path",
32383
+ () => normalizedAbsolutePath(fileSystem.realpath(candidate))
32384
+ );
32385
+ if (!resolution.ok) return null;
32386
+ return isContained(canonicalWorkspaceRoot, resolution.value, caseSensitive) ? resolution.value : null;
31850
32387
  };
31851
32388
  const resolveCreatableTarget = (canonicalWorkspaceRoot, repositoryPath2) => {
31852
32389
  const candidate = lexicalCandidate(
@@ -31949,7 +32486,8 @@ function blocked(request, code, options = {}) {
31949
32486
  primaryFailureCode: code,
31950
32487
  affectedPaths: options.affectedPaths ?? [],
31951
32488
  unsupportedCapabilities: options.unsupportedCapabilities ?? [],
31952
- resolution: null
32489
+ resolution: null,
32490
+ ...options.failureCause === void 0 ? {} : { failureCause: options.failureCause }
31953
32491
  };
31954
32492
  }
31955
32493
  function readEnvelope(fileSystem, request, pathBoundary, canonicalWorkspaceRoot) {
@@ -31958,13 +32496,17 @@ function readEnvelope(fileSystem, request, pathBoundary, canonicalWorkspaceRoot)
31958
32496
  request.handoffEnvelopePath
31959
32497
  );
31960
32498
  if (envelopePath === null) {
31961
- return blocked(request, "HANDOFF_PLAN_PATH_INVALID");
32499
+ return blocked(request, "HANDOFF_PLAN_PATH_INVALID", {
32500
+ failureCause: "target-path: unresolved"
32501
+ });
31962
32502
  }
31963
32503
  let envelopeText;
31964
32504
  try {
31965
32505
  envelopeText = fileSystem.readTextFile(envelopePath);
31966
- } catch {
31967
- return blocked(request, "HANDOFF_VALIDATOR_UNAVAILABLE");
32506
+ } catch (error2) {
32507
+ return blocked(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32508
+ failureCause: describeHandoffFailureCause("envelope-read", error2)
32509
+ });
31968
32510
  }
31969
32511
  if (sha256(envelopeText) !== request.expectedHandoffEnvelopeSha256) {
31970
32512
  return blocked(request, "HANDOFF_SOURCE_HASH_MISMATCH");
@@ -31972,10 +32514,10 @@ function readEnvelope(fileSystem, request, pathBoundary, canonicalWorkspaceRoot)
31972
32514
  try {
31973
32515
  return parseHandoffEnvelopeText(envelopeText);
31974
32516
  } catch (error2) {
31975
- return blocked(
31976
- request,
31977
- error2 instanceof HandoffContractError ? error2.code : "HANDOFF_UNSUPPORTED_VERSION"
31978
- );
32517
+ const failure = describeEnvelopeParseFailure(error2);
32518
+ return blocked(request, failure.code, {
32519
+ failureCause: failure.failureCause
32520
+ });
31979
32521
  }
31980
32522
  }
31981
32523
  function observedPlanSha256(fileSystem, expectedPlanPath, pathBoundary, canonicalWorkspaceRoot) {
@@ -31983,11 +32525,11 @@ function observedPlanSha256(fileSystem, expectedPlanPath, pathBoundary, canonica
31983
32525
  canonicalWorkspaceRoot,
31984
32526
  expectedPlanPath
31985
32527
  );
31986
- if (planPath === null) return null;
32528
+ if (planPath === null) return { failureCause: "target-path: unresolved" };
31987
32529
  try {
31988
- return sha256(fileSystem.readTextFile(planPath));
31989
- } catch {
31990
- return null;
32530
+ return { sha256: sha256(fileSystem.readTextFile(planPath)) };
32531
+ } catch (error2) {
32532
+ return { failureCause: describeHandoffFailureCause("plan-read", error2) };
31991
32533
  }
31992
32534
  }
31993
32535
  function canonicalizeObservedPath(value) {
@@ -32047,7 +32589,9 @@ function resolvePortableHandoffAuthority(fileSystem, request, kind, pathBoundary
32047
32589
  request.workspaceRoot
32048
32590
  );
32049
32591
  if (canonicalWorkspaceRoot === null) {
32050
- return blocked(request, "HANDOFF_PLAN_PATH_INVALID");
32592
+ return blocked(request, "HANDOFF_PLAN_PATH_INVALID", {
32593
+ failureCause: "workspace-root: unresolved"
32594
+ });
32051
32595
  }
32052
32596
  const effectiveCheckoutContext = checkoutContext ?? createGitCheckoutContext(new SubprocessRunner());
32053
32597
  const observation = effectiveCheckoutContext.observe(
@@ -32085,17 +32629,19 @@ function resolvePortableHandoffAuthority(fileSystem, request, kind, pathBoundary
32085
32629
  handoffId: envelope.handoffId
32086
32630
  });
32087
32631
  }
32088
- const planSha256 = observedPlanSha256(
32632
+ const planObservation = observedPlanSha256(
32089
32633
  fileSystem,
32090
32634
  request.expectedPlanPath,
32091
32635
  effectivePathBoundary,
32092
32636
  canonicalWorkspaceRoot
32093
32637
  );
32094
- if (planSha256 === null) {
32638
+ if ("failureCause" in planObservation) {
32095
32639
  return blocked(request, "HANDOFF_PLAN_PATH_INVALID", {
32096
- handoffId: envelope.handoffId
32640
+ handoffId: envelope.handoffId,
32641
+ failureCause: planObservation.failureCause
32097
32642
  });
32098
32643
  }
32644
+ const planSha256 = planObservation.sha256;
32099
32645
  const validation = collectHandoffValidationFailures(envelope, {
32100
32646
  repositoryId: request.expectedRepositoryId,
32101
32647
  workspaceRoot: request.expectedWorkspaceRoot,
@@ -32199,54 +32745,6 @@ function porcelainAffectedPaths(output) {
32199
32745
  return [...paths].sort((left, right) => left.localeCompare(right));
32200
32746
  }
32201
32747
 
32202
- // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-materializer-request.ts
32203
- function toReferenceRequest(request) {
32204
- return {
32205
- workspaceRoot: request.workspaceRoot,
32206
- handoffEnvelopePath: request.handoffEnvelopePath,
32207
- expectedHandoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
32208
- destinationProvider: request.destinationProvider,
32209
- expectedRepositoryId: request.expectedRepositoryId,
32210
- expectedWorkspaceRoot: request.expectedWorkspaceRoot,
32211
- expectedBranch: request.expectedBranch,
32212
- expectedSourceHeadSha: request.expectedSourceHeadSha,
32213
- allowedHeadRelationship: request.allowedHeadRelationship,
32214
- expectedIssueNumber: request.expectedIssueNumber,
32215
- expectedFeatureFolder: request.expectedFeatureFolder,
32216
- expectedWorkMode: request.expectedWorkMode,
32217
- expectedPlanPath: request.expectedPlanPath,
32218
- expectedPlanSha256: request.expectedPlanSha256
32219
- };
32220
- }
32221
- function blockedResult(request, primaryFailureCode, options = {}) {
32222
- return {
32223
- status: "blocked",
32224
- handoffId: options.handoffId ?? null,
32225
- sourceCheckpointSha256: request.expectedSourceCheckpointSha256,
32226
- handoffEnvelopeSha256: request.expectedHandoffEnvelopeSha256,
32227
- handoffHistorySha256: options.handoffHistorySha256 ?? null,
32228
- requestedTransition: "prepared_to_atomic_execution",
32229
- destinationCheckpointPath: null,
32230
- destinationCheckpointSha256: null,
32231
- primaryFailureCode,
32232
- affectedPaths: options.affectedPaths ?? [],
32233
- unsupportedCapabilities: options.unsupportedCapabilities ?? []
32234
- };
32235
- }
32236
- function authorityFailure(request, authority, handoffHistorySha256) {
32237
- if (authority.status === "validated") return null;
32238
- return blockedResult(
32239
- request,
32240
- authority.primaryFailureCode ?? "HANDOFF_VALIDATOR_UNAVAILABLE",
32241
- {
32242
- handoffId: authority.handoffId,
32243
- handoffHistorySha256,
32244
- affectedPaths: authority.affectedPaths,
32245
- unsupportedCapabilities: authority.unsupportedCapabilities
32246
- }
32247
- );
32248
- }
32249
-
32250
32748
  // ../../extensions/drm-copilot/src/lib/validate/orchestration-handoff-provider-adapters.ts
32251
32749
  var PROVIDER_ADAPTERS = {
32252
32750
  claude: {
@@ -32412,7 +32910,9 @@ var OrchestrationHandoffMaterializer = class {
32412
32910
  request.workspaceRoot
32413
32911
  );
32414
32912
  if (canonicalWorkspaceRoot === null) {
32415
- return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID");
32913
+ return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID", {
32914
+ failureCause: "workspace-root: unresolved"
32915
+ });
32416
32916
  }
32417
32917
  const sourcePath = pathBoundary.resolveExistingTarget(
32418
32918
  canonicalWorkspaceRoot,
@@ -32423,15 +32923,19 @@ var OrchestrationHandoffMaterializer = class {
32423
32923
  request.handoffEnvelopePath
32424
32924
  );
32425
32925
  if (sourcePath === null || envelopePath === null) {
32426
- return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID");
32926
+ return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID", {
32927
+ failureCause: "target-path: unresolved"
32928
+ });
32427
32929
  }
32428
32930
  let sourceBytes;
32429
32931
  let envelopeBytes;
32430
32932
  try {
32431
32933
  sourceBytes = this.dependencies.fileSystem.readFile(sourcePath);
32432
32934
  envelopeBytes = this.dependencies.fileSystem.readFile(envelopePath);
32433
- } catch {
32434
- return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE");
32935
+ } catch (error2) {
32936
+ return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32937
+ failureCause: describeHandoffFailureCause("checkpoint-read", error2)
32938
+ });
32435
32939
  }
32436
32940
  if (sha2562(sourceBytes) !== request.expectedSourceCheckpointSha256 || sha2562(envelopeBytes) !== request.expectedHandoffEnvelopeSha256) {
32437
32941
  return blockedResult(request, "HANDOFF_SOURCE_HASH_MISMATCH");
@@ -32439,8 +32943,10 @@ var OrchestrationHandoffMaterializer = class {
32439
32943
  let envelopeText;
32440
32944
  try {
32441
32945
  envelopeText = textDecoder.decode(envelopeBytes);
32442
- } catch {
32443
- return blockedResult(request, "HANDOFF_UNSUPPORTED_VERSION");
32946
+ } catch (error2) {
32947
+ return blockedResult(request, "HANDOFF_UNSUPPORTED_VERSION", {
32948
+ failureCause: describeHandoffFailureCause("envelope-decode", error2)
32949
+ });
32444
32950
  }
32445
32951
  const validation = this.dependencies.validator.validateEnvelope(envelopeText);
32446
32952
  if (validation.primaryFailureCode !== null || validation.envelope === null) {
@@ -32449,7 +32955,8 @@ var OrchestrationHandoffMaterializer = class {
32449
32955
  validation.primaryFailureCode ?? "HANDOFF_VALIDATOR_UNAVAILABLE",
32450
32956
  {
32451
32957
  affectedPaths: validation.affectedPaths,
32452
- unsupportedCapabilities: validation.unsupportedCapabilities
32958
+ unsupportedCapabilities: validation.unsupportedCapabilities,
32959
+ failureCause: validation.failureCause
32453
32960
  }
32454
32961
  );
32455
32962
  }
@@ -32496,7 +33003,8 @@ var OrchestrationHandoffMaterializer = class {
32496
33003
  if (archivePath === null || destinationPath === null || candidatePath === null) {
32497
33004
  return blockedResult(request, "HANDOFF_PLAN_PATH_INVALID", {
32498
33005
  handoffId: envelope.handoffId,
32499
- handoffHistorySha256: lastHistoryEntry.entrySha256
33006
+ handoffHistorySha256: lastHistoryEntry.entrySha256,
33007
+ failureCause: "target-path: unresolved"
32500
33008
  });
32501
33009
  }
32502
33010
  const referenceRequest = toReferenceRequest(request);
@@ -32529,7 +33037,11 @@ var OrchestrationHandoffMaterializer = class {
32529
33037
  error2 instanceof Error && "code" in error2 ? error2.code : "HANDOFF_VALIDATOR_UNAVAILABLE",
32530
33038
  {
32531
33039
  handoffId: envelope.handoffId,
32532
- handoffHistorySha256: lastHistoryEntry.entrySha256
33040
+ handoffHistorySha256: lastHistoryEntry.entrySha256,
33041
+ failureCause: describeHandoffFailureCause(
33042
+ "destination-projection",
33043
+ error2
33044
+ )
32533
33045
  }
32534
33046
  );
32535
33047
  }
@@ -32538,7 +33050,8 @@ var OrchestrationHandoffMaterializer = class {
32538
33050
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32539
33051
  handoffId: envelope.handoffId,
32540
33052
  handoffHistorySha256: lastHistoryEntry.entrySha256,
32541
- affectedPaths: [envelope.destinationCheckpointPath]
33053
+ affectedPaths: [envelope.destinationCheckpointPath],
33054
+ failureCause: "destination-projection: invalid"
32542
33055
  });
32543
33056
  }
32544
33057
  let porcelainStatus;
@@ -32546,10 +33059,11 @@ var OrchestrationHandoffMaterializer = class {
32546
33059
  porcelainStatus = await this.dependencies.git.readPorcelainStatus(
32547
33060
  canonicalWorkspaceRoot
32548
33061
  );
32549
- } catch {
33062
+ } catch (error2) {
32550
33063
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32551
33064
  handoffId: envelope.handoffId,
32552
- handoffHistorySha256: lastHistoryEntry.entrySha256
33065
+ handoffHistorySha256: lastHistoryEntry.entrySha256,
33066
+ failureCause: describeHandoffFailureCause("git-status", error2)
32553
33067
  });
32554
33068
  }
32555
33069
  const affectedPaths = porcelainAffectedPaths(porcelainStatus);
@@ -32595,24 +33109,30 @@ var OrchestrationHandoffMaterializer = class {
32595
33109
  preparation.sourceBytes,
32596
33110
  { exclusive: true }
32597
33111
  );
32598
- } catch {
33112
+ } catch (writeError) {
33113
+ const writeCause = describeHandoffFailureCause(
33114
+ "archive-write",
33115
+ writeError
33116
+ );
32599
33117
  let archivedBytes;
32600
33118
  try {
32601
33119
  archivedBytes = this.dependencies.fileSystem.readFile(
32602
33120
  preparation.archivePath
32603
33121
  );
32604
- } catch {
33122
+ } catch (readError) {
32605
33123
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32606
33124
  handoffId: preparation.result.handoffId,
32607
33125
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32608
- affectedPaths: [preparation.archivePath]
33126
+ affectedPaths: [preparation.archivePath],
33127
+ failureCause: `${writeCause}; ${describeHandoffFailureCause("archive-readback", readError)}`
32609
33128
  });
32610
33129
  }
32611
33130
  if (sha2562(archivedBytes) !== expectedSourceSha256) {
32612
33131
  return blockedResult(request, "HANDOFF_SOURCE_HASH_MISMATCH", {
32613
33132
  handoffId: preparation.result.handoffId,
32614
33133
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32615
- affectedPaths: [preparation.archivePath]
33134
+ affectedPaths: [preparation.archivePath],
33135
+ failureCause: writeCause
32616
33136
  });
32617
33137
  }
32618
33138
  }
@@ -32622,24 +33142,30 @@ var OrchestrationHandoffMaterializer = class {
32622
33142
  preparation.projectionBytes,
32623
33143
  { exclusive: true }
32624
33144
  );
32625
- } catch {
33145
+ } catch (writeError) {
33146
+ const writeCause = describeHandoffFailureCause(
33147
+ "candidate-write",
33148
+ writeError
33149
+ );
32626
33150
  let existingCandidate;
32627
33151
  try {
32628
33152
  existingCandidate = this.dependencies.fileSystem.readFile(
32629
33153
  preparation.candidatePath
32630
33154
  );
32631
- } catch {
33155
+ } catch (readError) {
32632
33156
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32633
33157
  handoffId: preparation.result.handoffId,
32634
33158
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32635
- affectedPaths: [preparation.candidatePath]
33159
+ affectedPaths: [preparation.candidatePath],
33160
+ failureCause: `${writeCause}; ${describeHandoffFailureCause("candidate-readback", readError)}`
32636
33161
  });
32637
33162
  }
32638
33163
  if (sha2562(existingCandidate) !== sha2562(preparation.projectionBytes)) {
32639
33164
  return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32640
33165
  handoffId: preparation.result.handoffId,
32641
33166
  handoffHistorySha256: preparation.result.handoffHistorySha256,
32642
- affectedPaths: [preparation.candidatePath]
33167
+ affectedPaths: [preparation.candidatePath],
33168
+ failureCause: writeCause
32643
33169
  });
32644
33170
  }
32645
33171
  }
@@ -32649,35 +33175,51 @@ var OrchestrationHandoffMaterializer = class {
32649
33175
  );
32650
33176
  const writtenText = textDecoder.decode(writtenCandidate);
32651
33177
  if (sha2562(writtenCandidate) !== sha2562(preparation.projectionBytes) || this.dependencies.validator.validateDestinationProjection(writtenText).length > 0) {
32652
- throw new Error("Candidate validation failed.");
33178
+ throw Object.assign(new Error("Candidate validation failed."), {
33179
+ code: "HANDOFF_CANDIDATE_MISMATCH"
33180
+ });
32653
33181
  }
32654
- } catch {
32655
- this.discardCandidate(preparation.candidatePath);
32656
- return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32657
- handoffId: preparation.result.handoffId,
32658
- handoffHistorySha256: preparation.result.handoffHistorySha256,
32659
- affectedPaths: [preparation.candidatePath]
32660
- });
33182
+ } catch (error2) {
33183
+ return this.discardedCandidateResult(
33184
+ request,
33185
+ preparation,
33186
+ describeHandoffFailureCause("candidate-validate", error2)
33187
+ );
32661
33188
  }
32662
33189
  try {
32663
33190
  this.dependencies.fileSystem.replaceFile(
32664
33191
  preparation.candidatePath,
32665
33192
  preparation.destinationPath
32666
33193
  );
32667
- } catch {
32668
- this.discardCandidate(preparation.candidatePath);
32669
- return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
32670
- handoffId: preparation.result.handoffId,
32671
- handoffHistorySha256: preparation.result.handoffHistorySha256,
32672
- affectedPaths: [preparation.candidatePath]
32673
- });
33194
+ } catch (error2) {
33195
+ return this.discardedCandidateResult(
33196
+ request,
33197
+ preparation,
33198
+ describeHandoffFailureCause("candidate-replace", error2)
33199
+ );
32674
33200
  }
32675
33201
  return { ...preparation.result, status: "materialized" };
32676
33202
  }
33203
+ /** Discard the candidate and block, appending any cleanup failure cause. */
33204
+ discardedCandidateResult(request, preparation, cause) {
33205
+ const cleanupCause = this.discardCandidate(preparation.candidatePath);
33206
+ return blockedResult(request, "HANDOFF_VALIDATOR_UNAVAILABLE", {
33207
+ handoffId: preparation.result.handoffId,
33208
+ handoffHistorySha256: preparation.result.handoffHistorySha256,
33209
+ affectedPaths: [preparation.candidatePath],
33210
+ failureCause: cleanupCause === null ? cause : `${cause}; ${cleanupCause}`
33211
+ });
33212
+ }
33213
+ /**
33214
+ * Remove the candidate. Returns `null` on success, otherwise the cleanup
33215
+ * cause; the blocked result names the retained candidate for explicit cleanup.
33216
+ */
32677
33217
  discardCandidate(candidatePath) {
32678
33218
  try {
32679
33219
  this.dependencies.fileSystem.removeFile(candidatePath);
32680
- } catch {
33220
+ return null;
33221
+ } catch (error2) {
33222
+ return describeHandoffFailureCause("candidate-cleanup", error2);
32681
33223
  }
32682
33224
  }
32683
33225
  };
@@ -32695,11 +33237,13 @@ function validateEnvelope(text2) {
32695
33237
  unsupportedCapabilities: []
32696
33238
  };
32697
33239
  } catch (error2) {
33240
+ const failure = describeEnvelopeParseFailure(error2);
32698
33241
  return {
32699
33242
  envelope: null,
32700
- primaryFailureCode: error2 instanceof HandoffContractError ? error2.code : "HANDOFF_UNSUPPORTED_VERSION",
33243
+ primaryFailureCode: failure.code,
32701
33244
  affectedPaths: [],
32702
- unsupportedCapabilities: []
33245
+ unsupportedCapabilities: [],
33246
+ failureCause: failure.failureCause
32703
33247
  };
32704
33248
  }
32705
33249
  }
@@ -32707,8 +33251,10 @@ function validateDestinationProjection(text2) {
32707
33251
  let value;
32708
33252
  try {
32709
33253
  value = JSON.parse(text2);
32710
- } catch {
32711
- return ["destination checkpoint must be valid JSON"];
33254
+ } catch (error2) {
33255
+ return [
33256
+ `destination checkpoint must be valid JSON (${describeHandoffFailureCause("destination-projection", error2)})`
33257
+ ];
32712
33258
  }
32713
33259
  if (!isRecord4(value)) return ["destination checkpoint must be an object"];
32714
33260
  const provider = value["provider"];
@@ -33024,7 +33570,7 @@ function truncate(text2, limit = 800) {
33024
33570
  }
33025
33571
  return rstrip3(text2.slice(0, limit - 3)) + "...";
33026
33572
  }
33027
- function splitLines3(value) {
33573
+ function splitLines2(value) {
33028
33574
  if (value === "") {
33029
33575
  return [];
33030
33576
  }
@@ -33035,7 +33581,7 @@ function splitLines3(value) {
33035
33581
  return lines;
33036
33582
  }
33037
33583
  function truncateLines(text2, limit) {
33038
- const lines = splitLines3(text2);
33584
+ const lines = splitLines2(text2);
33039
33585
  if (lines.length <= limit) {
33040
33586
  return text2;
33041
33587
  }
@@ -33075,14 +33621,11 @@ function formatList(values, emptyText) {
33075
33621
  }
33076
33622
  return valuesList.map((item) => `- ${item}`).join("\n");
33077
33623
  }
33078
- function compareCodePoint(left, right) {
33079
- if (left < right) {
33080
- return -1;
33081
- }
33082
- if (left > right) {
33083
- return 1;
33084
- }
33085
- return 0;
33624
+ function sortedSet(values) {
33625
+ return [...new Set(values)].sort(compareCodePoint);
33626
+ }
33627
+ function escapeRegExp4(value) {
33628
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
33086
33629
  }
33087
33630
 
33088
33631
  // ../../extensions/drm-copilot/src/lib/pr-context/git-client.ts
@@ -33275,9 +33818,6 @@ function extractClosingNumbers(raw) {
33275
33818
  }
33276
33819
  return numbers;
33277
33820
  }
33278
- function sortedSet(values) {
33279
- return [...new Set(values)].sort(compareCodePoint);
33280
- }
33281
33821
  function authorLogin(record3, key) {
33282
33822
  const raw = record3[key];
33283
33823
  if (isRecord5(raw)) {
@@ -33933,7 +34473,7 @@ function convertNumstat(numstatText) {
33933
34473
  let adds = 0;
33934
34474
  let dels = 0;
33935
34475
  const files = [];
33936
- for (const rawLine of splitLines4(numstatText)) {
34476
+ for (const rawLine of splitLines2(numstatText)) {
33937
34477
  if (!rawLine.trim()) {
33938
34478
  continue;
33939
34479
  }
@@ -33996,70 +34536,199 @@ function summarizeConventionalCommits(subjects) {
33996
34536
  }
33997
34537
  counts.set("other", 0);
33998
34538
  const typePattern = /^(feat|fix|refactor|perf|docs|test|chore|build|ci|style)(\(|!|:)/u;
33999
- for (const rawLine of splitLines4(subjects)) {
34539
+ for (const rawLine of splitLines2(subjects)) {
34000
34540
  const line = rawLine.trim();
34001
34541
  if (!line) {
34002
34542
  continue;
34003
34543
  }
34004
- const match = typePattern.exec(line);
34005
- const label = match ? match[1] : "other";
34006
- counts.set(label, (counts.get(label) ?? 0) + 1);
34007
- }
34008
- const nonZero = [...counts.entries()].filter(([, value]) => value > 0);
34009
- if (nonZero.length === 0) {
34010
- return "(no recognizable conventional commit types)";
34544
+ const match = typePattern.exec(line);
34545
+ const label = match ? match[1] : "other";
34546
+ counts.set(label, (counts.get(label) ?? 0) + 1);
34547
+ }
34548
+ const nonZero = [...counts.entries()].filter(([, value]) => value > 0);
34549
+ if (nonZero.length === 0) {
34550
+ return "(no recognizable conventional commit types)";
34551
+ }
34552
+ return nonZero.map(([name, value]) => `${padName(name)} : ${value}`).join("\n");
34553
+ }
34554
+ function extractChangedPaths(contextText) {
34555
+ const paths = [];
34556
+ let capture = false;
34557
+ for (const line of splitLines2(contextText)) {
34558
+ if (line.startsWith("===== Changed files")) {
34559
+ capture = true;
34560
+ continue;
34561
+ }
34562
+ if (capture) {
34563
+ if (line.startsWith("=====")) {
34564
+ break;
34565
+ }
34566
+ if (line.trim() && line.includes(" ")) {
34567
+ const partsArr = line.split(" ");
34568
+ const pathPart = partsArr[partsArr.length - 1];
34569
+ paths.push(formatDiffPath(pathPart.trim()));
34570
+ } else if (line.trim()) {
34571
+ paths.push(formatDiffPath(line.trim()));
34572
+ }
34573
+ }
34574
+ }
34575
+ return paths;
34576
+ }
34577
+ function pathSuffix(name) {
34578
+ const segment = name.split(/[/\\]/u).pop() ?? "";
34579
+ const dotIndex = segment.lastIndexOf(".");
34580
+ if (dotIndex <= 0 || dotIndex === segment.length - 1) {
34581
+ return "";
34582
+ }
34583
+ return segment.slice(dotIndex);
34584
+ }
34585
+ function padCount(count) {
34586
+ return String(count).padStart(8, " ");
34587
+ }
34588
+ function padName(name) {
34589
+ return name.padEnd(9, " ");
34590
+ }
34591
+ function isDigits(value) {
34592
+ return value.length > 0 && /^\d+$/u.test(value);
34593
+ }
34594
+
34595
+ // ../../extensions/drm-copilot/src/lib/pr-context/feature-docs-parsers.ts
34596
+ function parseSection(markdown, heading) {
34597
+ const escaped = escapeRegExp4(heading);
34598
+ const pattern = new RegExp(
34599
+ `^##\\s+${escaped}\\s*\\r?\\n([\\s\\S]*?)(?=^##\\s+|$(?![\\s\\S]))`,
34600
+ "m"
34601
+ );
34602
+ const match = pattern.exec(markdown);
34603
+ if (!match) {
34604
+ return "";
34605
+ }
34606
+ return match[1].trim();
34607
+ }
34608
+ function completedPlanTasks(markdown, limit = 10) {
34609
+ const tasks = [];
34610
+ for (const line of splitLines2(markdown)) {
34611
+ if (/\[x\]/iu.test(line)) {
34612
+ const cleaned = line.replace(/^[-*]\s*\[[xX]\]\s*/u, "").trim();
34613
+ tasks.push(cleaned);
34614
+ }
34615
+ if (tasks.length >= limit) {
34616
+ break;
34617
+ }
34618
+ }
34619
+ return tasks;
34620
+ }
34621
+ function extractIssueReferences2(text2) {
34622
+ if (!text2) {
34623
+ return [];
34624
+ }
34625
+ const matches = text2.match(new RegExp(ISSUE_REFERENCE_PATTERN, "gu")) ?? [];
34626
+ const seen = /* @__PURE__ */ new Set();
34627
+ const ordered = [];
34628
+ for (const item of matches) {
34629
+ if (!seen.has(item)) {
34630
+ seen.add(item);
34631
+ ordered.push(item);
34632
+ }
34633
+ }
34634
+ return ordered;
34635
+ }
34636
+ function resolveFeatureDir(fs12, baseDir, feature) {
34637
+ const direct = `${baseDir}/${feature}`;
34638
+ if (fs12.exists(direct)) {
34639
+ return direct;
34640
+ }
34641
+ const pattern = new RegExp(
34642
+ `(?:^|[-_])${escapeRegExp4(feature)}(?:[-_]|$)`,
34643
+ "u"
34644
+ );
34645
+ const strongMatches = [];
34646
+ const weakMatches = [];
34647
+ for (const name of fs12.listDirectory(baseDir)) {
34648
+ const candidate = `${baseDir}/${name}`;
34649
+ if (!fs12.isDirectory(candidate)) {
34650
+ continue;
34651
+ }
34652
+ if (pattern.test(name)) {
34653
+ strongMatches.push(candidate);
34654
+ } else if (name.includes(feature)) {
34655
+ weakMatches.push(candidate);
34656
+ }
34657
+ }
34658
+ if (strongMatches.length > 0) {
34659
+ return strongMatches[0];
34660
+ }
34661
+ if (weakMatches.length > 0) {
34662
+ return weakMatches[0];
34663
+ }
34664
+ return null;
34665
+ }
34666
+ function readText(fs12, path16) {
34667
+ return fs12.exists(path16) ? fs12.readTextFile(path16) : "";
34668
+ }
34669
+ function latestGlobPath(fs12, directory, pattern) {
34670
+ const matches = [...fs12.glob(directory, pattern)].sort(compareCodePoint);
34671
+ return matches.length > 0 ? matches[matches.length - 1] : null;
34672
+ }
34673
+ function verificationText(planText) {
34674
+ for (const heading of ["Verification", "Test Plan"]) {
34675
+ const sectionText = parseSection(planText, heading);
34676
+ if (sectionText) {
34677
+ return sectionText;
34678
+ }
34011
34679
  }
34012
- return nonZero.map(([name, value]) => `${padName(name)} : ${value}`).join("\n");
34680
+ return "";
34013
34681
  }
34014
- function extractChangedPaths(contextText) {
34015
- const paths = [];
34016
- let capture = false;
34017
- for (const line of splitLines4(contextText)) {
34018
- if (line.startsWith("===== Changed files")) {
34019
- capture = true;
34020
- continue;
34021
- }
34022
- if (capture) {
34023
- if (line.startsWith("=====")) {
34024
- break;
34025
- }
34026
- if (line.trim() && line.includes(" ")) {
34027
- const partsArr = line.split(" ");
34028
- const pathPart = partsArr[partsArr.length - 1];
34029
- paths.push(formatDiffPath(pathPart.trim()));
34030
- } else if (line.trim()) {
34031
- paths.push(formatDiffPath(line.trim()));
34682
+ function parsePrimaryIssueFromMetadata(params) {
34683
+ const pattern = /^\s*[-*]?\s*Issue:\s*(#\d+)\s*$/iu;
34684
+ for (const sourceText of [
34685
+ params.specText,
34686
+ params.storyText,
34687
+ params.issueText
34688
+ ]) {
34689
+ for (const line of splitLines2(sourceText)) {
34690
+ const match = pattern.exec(line);
34691
+ if (match) {
34692
+ return match[1];
34032
34693
  }
34033
34694
  }
34034
34695
  }
34035
- return paths;
34696
+ return null;
34036
34697
  }
34037
- function pathSuffix(name) {
34038
- const segment = name.split(/[/\\]/u).pop() ?? "";
34039
- const dotIndex = segment.lastIndexOf(".");
34040
- if (dotIndex <= 0 || dotIndex === segment.length - 1) {
34041
- return "";
34698
+ function parseReadinessValue(text2) {
34699
+ const normalized = text2.replaceAll("**", "");
34700
+ const match = /^\s*(?:Readiness|Overall feature readiness):\s*(.+?)\s*$/im.exec(
34701
+ normalized
34702
+ );
34703
+ if (!match) {
34704
+ return null;
34042
34705
  }
34043
- return segment.slice(dotIndex);
34044
- }
34045
- function padCount(count) {
34046
- return String(count).padStart(8, " ");
34047
- }
34048
- function padName(name) {
34049
- return name.padEnd(9, " ");
34050
- }
34051
- function isDigits(value) {
34052
- return value.length > 0 && /^\d+$/u.test(value);
34706
+ const value = match[1].trim().toUpperCase();
34707
+ if (value === "PASS" || value === "NEEDS REVISION" || value === "BLOCKED") {
34708
+ return value;
34709
+ }
34710
+ return null;
34053
34711
  }
34054
- function splitLines4(value) {
34055
- if (value === "") {
34056
- return [];
34712
+ function resolveReadinessSignal(fs12, featureDir) {
34713
+ const auditFiles = [...fs12.glob(featureDir, "feature-audit.*.md")].sort(
34714
+ compareCodePoint
34715
+ );
34716
+ for (let index = auditFiles.length - 1; index >= 0; index -= 1) {
34717
+ const auditPath = auditFiles[index];
34718
+ const readiness = parseReadinessValue(readText(fs12, auditPath));
34719
+ if (readiness) {
34720
+ return [readiness, auditPath];
34721
+ }
34057
34722
  }
34058
- const lines = value.split(/\r\n|\r|\n/u);
34059
- if (lines.length > 0 && lines[lines.length - 1] === "" && /(\r\n|\r|\n)$/u.test(value)) {
34060
- lines.pop();
34723
+ return [null, null];
34724
+ }
34725
+ function relativeToPosix8(root, path16) {
34726
+ const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
34727
+ const normalized = toPosixPath2(path16);
34728
+ if (normalized.startsWith(`${normalizedRoot}/`)) {
34729
+ return normalized.slice(normalizedRoot.length + 1);
34061
34730
  }
34062
- return lines;
34731
+ return normalized.replace(/^\/+/u, "");
34063
34732
  }
34064
34733
 
34065
34734
  // ../../extensions/drm-copilot/src/lib/pr-context/render.ts
@@ -34120,8 +34789,8 @@ function buildPrContext(options) {
34120
34789
  const oneline = git.log("--pretty=format:%h %ad %an %s", revRange);
34121
34790
  const subjects = git.log("--pretty=%s", revRange);
34122
34791
  const authors = git.log("--format=%an <%ae>", revRange);
34123
- const authorsList = sortedSet2(
34124
- splitLines5(authors).map((line) => line.trim()).filter((line) => line)
34792
+ const authorsList = sortedSet(
34793
+ splitLines2(authors).map((line) => line.trim()).filter((line) => line)
34125
34794
  );
34126
34795
  const nameStatus = git.diffRange(["--name-status", mergeBase, headSha]);
34127
34796
  const numstat = git.diffRange(["--numstat", mergeBase, headSha]);
@@ -34129,7 +34798,7 @@ function buildPrContext(options) {
34129
34798
  const stat = git.diffRange(["--stat", mergeBase, headSha]);
34130
34799
  const [additions, deletions, files] = convertNumstat(numstat);
34131
34800
  const extSummary = extensionSummary(files);
34132
- const mergePrs = extractMergePrNumbers(splitLines5(oneline));
34801
+ const mergePrs = extractMergePrNumbers(splitLines2(oneline));
34133
34802
  const issueCandidates = extractIssueReferences(
34134
34803
  oneline + "\n" + subjects
34135
34804
  ).filter((ref) => !mergePrs.includes(ref));
@@ -34149,9 +34818,9 @@ function buildPrContext(options) {
34149
34818
  issues.push(formattedRef);
34150
34819
  }
34151
34820
  }
34152
- referencedIssues = sortedSet2(issues);
34153
- referencedPrs = sortedSet2([...prs, ...mergePrs]);
34154
- let issuesDisplay = sortedSet2([
34821
+ referencedIssues = sortedSet(issues);
34822
+ referencedPrs = sortedSet([...prs, ...mergePrs]);
34823
+ let issuesDisplay = sortedSet([
34155
34824
  ...referencedIssues,
34156
34825
  ...featureIssueList
34157
34826
  ]).join(", ");
@@ -34261,8 +34930,8 @@ Deletions: ${deletions}
34261
34930
  text: combinedText,
34262
34931
  referencedIssues,
34263
34932
  referencedPrs,
34264
- verifiedClosing: sortedSet2(verifiedClosing),
34265
- invalidReferences: sortedSet2(invalidReferences),
34933
+ verifiedClosing: sortedSet(verifiedClosing),
34934
+ invalidReferences: sortedSet(invalidReferences),
34266
34935
  baseRef,
34267
34936
  resolvedBase,
34268
34937
  baseSha,
@@ -34276,161 +34945,6 @@ Deletions: ${deletions}
34276
34945
  function errorMessage(exc) {
34277
34946
  return exc instanceof Error ? exc.message : String(exc);
34278
34947
  }
34279
- function sortedSet2(values) {
34280
- return [...new Set(values)].sort(compareCodePoint);
34281
- }
34282
- function splitLines5(value) {
34283
- if (value === "") {
34284
- return [];
34285
- }
34286
- const lines = value.split(/\r\n|\r|\n/u);
34287
- if (lines.length > 0 && lines[lines.length - 1] === "" && /(\r\n|\r|\n)$/u.test(value)) {
34288
- lines.pop();
34289
- }
34290
- return lines;
34291
- }
34292
-
34293
- // ../../extensions/drm-copilot/src/lib/pr-context/feature-docs-parsers.ts
34294
- function parseSection2(markdown, heading) {
34295
- const escaped = escapeRegExp4(heading);
34296
- const pattern = new RegExp(
34297
- `^##\\s+${escaped}\\s*\\r?\\n([\\s\\S]*?)(?=^##\\s+|$(?![\\s\\S]))`,
34298
- "m"
34299
- );
34300
- const match = pattern.exec(markdown);
34301
- if (!match) {
34302
- return "";
34303
- }
34304
- return match[1].trim();
34305
- }
34306
- function completedPlanTasks2(markdown, limit = 10) {
34307
- const tasks = [];
34308
- for (const line of splitLines3(markdown)) {
34309
- if (/\[x\]/iu.test(line)) {
34310
- const cleaned = line.replace(/^[-*]\s*\[[xX]\]\s*/u, "").trim();
34311
- tasks.push(cleaned);
34312
- }
34313
- if (tasks.length >= limit) {
34314
- break;
34315
- }
34316
- }
34317
- return tasks;
34318
- }
34319
- function extractIssueReferences2(text2) {
34320
- if (!text2) {
34321
- return [];
34322
- }
34323
- const matches = text2.match(new RegExp(ISSUE_REFERENCE_PATTERN, "gu")) ?? [];
34324
- const seen = /* @__PURE__ */ new Set();
34325
- const ordered = [];
34326
- for (const item of matches) {
34327
- if (!seen.has(item)) {
34328
- seen.add(item);
34329
- ordered.push(item);
34330
- }
34331
- }
34332
- return ordered;
34333
- }
34334
- function resolveFeatureDir2(fs12, baseDir, feature) {
34335
- const direct = `${baseDir}/${feature}`;
34336
- if (fs12.exists(direct)) {
34337
- return direct;
34338
- }
34339
- const pattern = new RegExp(
34340
- `(?:^|[-_])${escapeRegExp4(feature)}(?:[-_]|$)`,
34341
- "u"
34342
- );
34343
- const strongMatches = [];
34344
- const weakMatches = [];
34345
- for (const name of fs12.listDirectory(baseDir)) {
34346
- const candidate = `${baseDir}/${name}`;
34347
- if (!fs12.isDirectory(candidate)) {
34348
- continue;
34349
- }
34350
- if (pattern.test(name)) {
34351
- strongMatches.push(candidate);
34352
- } else if (name.includes(feature)) {
34353
- weakMatches.push(candidate);
34354
- }
34355
- }
34356
- if (strongMatches.length > 0) {
34357
- return strongMatches[0];
34358
- }
34359
- if (weakMatches.length > 0) {
34360
- return weakMatches[0];
34361
- }
34362
- return null;
34363
- }
34364
- function readText(fs12, path16) {
34365
- return fs12.exists(path16) ? fs12.readTextFile(path16) : "";
34366
- }
34367
- function latestGlobPath(fs12, directory, pattern) {
34368
- const matches = [...fs12.glob(directory, pattern)].sort(compareCodePoint);
34369
- return matches.length > 0 ? matches[matches.length - 1] : null;
34370
- }
34371
- function verificationText(planText) {
34372
- for (const heading of ["Verification", "Test Plan"]) {
34373
- const sectionText = parseSection2(planText, heading);
34374
- if (sectionText) {
34375
- return sectionText;
34376
- }
34377
- }
34378
- return "";
34379
- }
34380
- function parsePrimaryIssueFromMetadata(params) {
34381
- const pattern = /^\s*[-*]?\s*Issue:\s*(#\d+)\s*$/iu;
34382
- for (const sourceText of [
34383
- params.specText,
34384
- params.storyText,
34385
- params.issueText
34386
- ]) {
34387
- for (const line of splitLines3(sourceText)) {
34388
- const match = pattern.exec(line);
34389
- if (match) {
34390
- return match[1];
34391
- }
34392
- }
34393
- }
34394
- return null;
34395
- }
34396
- function parseReadinessValue(text2) {
34397
- const normalized = text2.replaceAll("**", "");
34398
- const match = /^\s*(?:Readiness|Overall feature readiness):\s*(.+?)\s*$/im.exec(
34399
- normalized
34400
- );
34401
- if (!match) {
34402
- return null;
34403
- }
34404
- const value = match[1].trim().toUpperCase();
34405
- if (value === "PASS" || value === "NEEDS REVISION" || value === "BLOCKED") {
34406
- return value;
34407
- }
34408
- return null;
34409
- }
34410
- function resolveReadinessSignal(fs12, featureDir) {
34411
- const auditFiles = [...fs12.glob(featureDir, "feature-audit.*.md")].sort(
34412
- compareCodePoint
34413
- );
34414
- for (let index = auditFiles.length - 1; index >= 0; index -= 1) {
34415
- const auditPath = auditFiles[index];
34416
- const readiness = parseReadinessValue(readText(fs12, auditPath));
34417
- if (readiness) {
34418
- return [readiness, auditPath];
34419
- }
34420
- }
34421
- return [null, null];
34422
- }
34423
- function relativeToPosix8(root, path16) {
34424
- const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
34425
- const normalized = toPosixPath2(path16);
34426
- if (normalized.startsWith(`${normalizedRoot}/`)) {
34427
- return normalized.slice(normalizedRoot.length + 1);
34428
- }
34429
- return normalized.replace(/^\/+/u, "");
34430
- }
34431
- function escapeRegExp4(value) {
34432
- return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
34433
- }
34434
34948
 
34435
34949
  // ../../extensions/drm-copilot/src/lib/pr-context/verification-evidence.ts
34436
34950
  var REQUIRED_FIELDS = ["Timestamp", "Command", "EXIT_CODE"];
@@ -34453,7 +34967,7 @@ function discoverCanonicalEvidenceFiles(fs12, root, feature) {
34453
34967
  for (const pattern of CANONICAL_GLOBS) {
34454
34968
  for (const candidate of fs12.glob(featureRoot, pattern)) {
34455
34969
  if (fs12.isFile(candidate)) {
34456
- discovered.add(relativeToPosix9(normalizedRoot, candidate));
34970
+ discovered.add(relativeToPosix8(normalizedRoot, candidate));
34457
34971
  }
34458
34972
  }
34459
34973
  }
@@ -34462,7 +34976,7 @@ function discoverCanonicalEvidenceFiles(fs12, root, feature) {
34462
34976
  function parseVerificationEvidenceMarkdown(params) {
34463
34977
  const { feature, sourceFile, markdown } = params;
34464
34978
  const parsed = /* @__PURE__ */ new Map();
34465
- for (const rawLine of splitLines6(markdown)) {
34979
+ for (const rawLine of splitLines2(markdown)) {
34466
34980
  const colonIndex = rawLine.indexOf(":");
34467
34981
  if (colonIndex === -1) {
34468
34982
  continue;
@@ -34530,9 +35044,9 @@ function parseVerificationEvidenceMarkdown(params) {
34530
35044
  };
34531
35045
  }
34532
35046
  function parseVerificationEvidenceFile(params) {
34533
- const { fs: fs12, root, feature, relativePath: relativePath2 } = params;
35047
+ const { fs: fs12, root, feature, relativePath } = params;
34534
35048
  const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
34535
- const relPosix = toPosixPath2(relativePath2).replace(/^\/+/u, "");
35049
+ const relPosix = toPosixPath2(relativePath).replace(/^\/+/u, "");
34536
35050
  const markdown = fs12.readTextFile(`${normalizedRoot}/${relPosix}`);
34537
35051
  return parseVerificationEvidenceMarkdown({
34538
35052
  feature,
@@ -34546,23 +35060,6 @@ function parseIntegerStrict(value) {
34546
35060
  }
34547
35061
  return Number.parseInt(value, 10);
34548
35062
  }
34549
- function relativeToPosix9(root, absolute) {
34550
- const normalized = toPosixPath2(absolute);
34551
- if (normalized.startsWith(`${root}/`)) {
34552
- return normalized.slice(root.length + 1);
34553
- }
34554
- return normalized.replace(/^\/+/u, "");
34555
- }
34556
- function splitLines6(value) {
34557
- if (value === "") {
34558
- return [];
34559
- }
34560
- const lines = value.split(/\r\n|\r|\n/u);
34561
- if (lines.length > 0 && lines[lines.length - 1] === "" && /(\r\n|\r|\n)$/u.test(value)) {
34562
- lines.pop();
34563
- }
34564
- return lines;
34565
- }
34566
35063
 
34567
35064
  // ../../extensions/drm-copilot/src/lib/pr-context/feature-docs.ts
34568
35065
  var SPEC_HEADINGS = [
@@ -34593,8 +35090,8 @@ function gatherFeatureExcerpts2(fs12, root, changedFiles) {
34593
35090
  const baseDir = `${normalizedRoot}/docs/features/active`;
34594
35091
  const promotedDir = `${normalizedRoot}/docs/features/potential/promoted`;
34595
35092
  for (const feature of [...features].sort(compareCodePoint)) {
34596
- const featureDir = resolveFeatureDir2(fs12, baseDir, feature);
34597
- const promotedFeatureDir = resolveFeatureDir2(fs12, promotedDir, feature);
35093
+ const featureDir = resolveFeatureDir(fs12, baseDir, feature);
35094
+ const promotedFeatureDir = resolveFeatureDir(fs12, promotedDir, feature);
34598
35095
  if (featureDir === null && promotedFeatureDir === null) {
34599
35096
  continue;
34600
35097
  }
@@ -34669,7 +35166,7 @@ function gatherFeatureExcerpts2(fs12, root, changedFiles) {
34669
35166
  function buildSpecParts(specText) {
34670
35167
  const specParts = [];
34671
35168
  for (const heading of SPEC_HEADINGS) {
34672
- const sectionText = parseSection2(specText, heading);
35169
+ const sectionText = parseSection(specText, heading);
34673
35170
  if (sectionText) {
34674
35171
  specParts.push(`${heading}: ${truncate(sectionText)}`);
34675
35172
  }
@@ -34677,7 +35174,7 @@ function buildSpecParts(specText) {
34677
35174
  return specParts;
34678
35175
  }
34679
35176
  function buildPlanSection(planText) {
34680
- const planTasks = completedPlanTasks2(planText);
35177
+ const planTasks = completedPlanTasks(planText);
34681
35178
  return planTasks.length > 0 ? planTasks.map((task) => `- ${task}`).join("\n") : "";
34682
35179
  }
34683
35180
  function buildVerificationBlock(planText) {
@@ -34686,7 +35183,7 @@ function buildVerificationBlock(planText) {
34686
35183
  }
34687
35184
  function buildStoryParts(userStoryText, promotedStoryText) {
34688
35185
  const storyParts = [];
34689
- const storyStatements = parseSection2(userStoryText, "Story Statement");
35186
+ const storyStatements = parseSection(userStoryText, "Story Statement");
34690
35187
  if (storyStatements) {
34691
35188
  const storyLines = storyStatements.split(/\r\n|\r|\n/u).filter((line) => line.trim()).map((line) => line.replace(/^[- ]+|[- ]+$/gu, ""));
34692
35189
  if (storyLines.length > 0) {
@@ -34695,14 +35192,14 @@ function buildStoryParts(userStoryText, promotedStoryText) {
34695
35192
  );
34696
35193
  }
34697
35194
  }
34698
- const problemSection = parseSection2(userStoryText, "Problem / Why");
35195
+ const problemSection = parseSection(userStoryText, "Problem / Why");
34699
35196
  if (problemSection) {
34700
35197
  storyParts.push("Problem / Why:\n" + truncate(problemSection));
34701
35198
  }
34702
35199
  if (storyParts.length === 0 && promotedStoryText) {
34703
- let promotedProblem = parseSection2(promotedStoryText, "Problem / Why");
35200
+ let promotedProblem = parseSection(promotedStoryText, "Problem / Why");
34704
35201
  if (!promotedProblem) {
34705
- promotedProblem = parseSection2(promotedStoryText, "Summary");
35202
+ promotedProblem = parseSection(promotedStoryText, "Summary");
34706
35203
  }
34707
35204
  if (promotedProblem) {
34708
35205
  storyParts.push("Problem / Why:\n" + truncate(promotedProblem));
@@ -34775,7 +35272,7 @@ function extractDigestBullets(body, headings, limit) {
34775
35272
  if (!sectionText) {
34776
35273
  continue;
34777
35274
  }
34778
- for (const line of splitLines3(sectionText)) {
35275
+ for (const line of splitLines2(sectionText)) {
34779
35276
  if (!line.trim()) {
34780
35277
  continue;
34781
35278
  }
@@ -34916,7 +35413,7 @@ function parseNumstatDetailed(numstatText) {
34916
35413
  let addsTotal = 0;
34917
35414
  let delsTotal = 0;
34918
35415
  const perFile = /* @__PURE__ */ new Map();
34919
- for (const rawLine of splitLines3(numstatText)) {
35416
+ for (const rawLine of splitLines2(numstatText)) {
34920
35417
  if (!rawLine.trim()) {
34921
35418
  continue;
34922
35419
  }
@@ -34935,7 +35432,7 @@ function parseNumstatDetailed(numstatText) {
34935
35432
  }
34936
35433
  function parseNameStatusMap(nameStatusText) {
34937
35434
  const mapping = /* @__PURE__ */ new Map();
34938
- for (const rawLine of splitLines3(nameStatusText)) {
35435
+ for (const rawLine of splitLines2(nameStatusText)) {
34939
35436
  if (!rawLine.trim()) {
34940
35437
  continue;
34941
35438
  }
@@ -34983,7 +35480,7 @@ function scopingDocChanges(options) {
34983
35480
  path16
34984
35481
  ]);
34985
35482
  let headingTouched = false;
34986
- for (const line of splitLines3(diffText)) {
35483
+ for (const line of splitLines2(diffText)) {
34987
35484
  if (!line.startsWith("+") || line.startsWith("+++")) {
34988
35485
  continue;
34989
35486
  }
@@ -34999,7 +35496,7 @@ function scopingDocChanges(options) {
34999
35496
  material = true;
35000
35497
  reasons.push("key section touched");
35001
35498
  }
35002
- const addedLines = splitLines3(diffText).filter((line) => line.startsWith("+") && !line.startsWith("+++")).map((line) => line.replace(/^\++/u, "").trim());
35499
+ const addedLines = splitLines2(diffText).filter((line) => line.startsWith("+") && !line.startsWith("+++")).map((line) => line.replace(/^\++/u, "").trim());
35003
35500
  if (addedLines.length > 0 && addedLines.every(
35004
35501
  (line) => !line || line.startsWith("[") || line.startsWith("http")
35005
35502
  )) {
@@ -35149,10 +35646,10 @@ function collectPrContext(options) {
35149
35646
  });
35150
35647
  const changedPaths = extractChangedPaths(contextResult.text);
35151
35648
  const featureDocs = gatherFeatureExcerpts2(fs12, resolvedRoot, changedPaths);
35152
- const additionalContextFiles = sortedSet3(
35649
+ const additionalContextFiles = sortedSet(
35153
35650
  featureDocs.flatMap((doc) => doc.contextFiles).filter((path16) => path16)
35154
35651
  );
35155
- const featureIssueRefs = sortedSet3(
35652
+ const featureIssueRefs = sortedSet(
35156
35653
  featureDocs.flatMap((doc) => doc.issueRefs).filter((ref) => ref.trim())
35157
35654
  );
35158
35655
  if (featureIssueRefs.length > 0) {
@@ -35210,7 +35707,7 @@ function collectPrContext(options) {
35210
35707
  pendingPrimary.push(featureDoc.primaryIssueRef);
35211
35708
  }
35212
35709
  }
35213
- const readinessSignals = sortedSet3(
35710
+ const readinessSignals = sortedSet(
35214
35711
  featureDocs.map((doc) => doc.readinessSignal).filter((signal) => Boolean(signal))
35215
35712
  );
35216
35713
  const selection = selectPendingPrimary({ gh, ghAvailable, pendingPrimary });
@@ -35221,7 +35718,7 @@ function collectPrContext(options) {
35221
35718
  ghAvailable,
35222
35719
  pendingPrimaryExcluded: selection.excluded
35223
35720
  });
35224
- const issuesToFetch = sortedSet3([
35721
+ const issuesToFetch = sortedSet([
35225
35722
  ...verified,
35226
35723
  ...referencedIssues,
35227
35724
  ...selection.kept
@@ -35309,7 +35806,7 @@ function collectPrContext(options) {
35309
35806
  verified,
35310
35807
  verifiedReason,
35311
35808
  authorReason,
35312
- authorAsserted: sortedSet3(authorAsserted),
35809
+ authorAsserted: sortedSet(authorAsserted),
35313
35810
  issuesToAutocloseSection,
35314
35811
  issueDetails,
35315
35812
  prDetailsList,
@@ -35330,9 +35827,6 @@ function collectPrContext(options) {
35330
35827
  function errorMessage2(exc) {
35331
35828
  return exc instanceof Error ? exc.message : String(exc);
35332
35829
  }
35333
- function sortedSet3(values) {
35334
- return [...new Set(values)].sort(compareCodePoint);
35335
- }
35336
35830
 
35337
35831
  // ../../extensions/drm-copilot/src/lib/pr-context/collector-output.ts
35338
35832
  function renderVerificationEvidenceSection(fs12, resolvedRoot, featureDocs) {
@@ -35365,7 +35859,7 @@ function renderVerificationEvidenceSection(fs12, resolvedRoot, featureDocs) {
35365
35859
  }
35366
35860
  const lines = [];
35367
35861
  const sorted = [...parseableRecords].sort(
35368
- (left, right) => left.sourceFile < right.sourceFile ? -1 : left.sourceFile > right.sourceFile ? 1 : 0
35862
+ (left, right) => compareCodePoint(left.sourceFile, right.sourceFile)
35369
35863
  );
35370
35864
  for (const record3 of sorted) {
35371
35865
  const expected = record3.expectedExitCode;
@@ -35898,7 +36392,7 @@ function getSection(content, heading) {
35898
36392
  }
35899
36393
  return match[1].trim();
35900
36394
  }
35901
- function buildBody(workMode, problem, behavior, criteria, constraints, tests, relativePath2) {
36395
+ function buildBody(workMode, problem, behavior, criteria, constraints, tests, relativePath) {
35902
36396
  return `- Work Mode: ${workMode}
35903
36397
  ## Problem / Why
35904
36398
  ${problem}
@@ -35916,20 +36410,20 @@ ${constraints}
35916
36410
  ${tests}
35917
36411
 
35918
36412
  ## Source
35919
- From: ${relativePath2}
36413
+ From: ${relativePath}
35920
36414
  `;
35921
36415
  }
35922
- function buildBugBody(workMode, sections, relativePath2) {
36416
+ function buildBugBody(workMode, sections, relativePath) {
35923
36417
  const parts = [`- Work Mode: ${workMode}`];
35924
36418
  for (const heading of BUG_SECTION_HEADINGS) {
35925
36419
  parts.push(`## ${heading}
35926
36420
  ${sections[heading] ?? ""}`);
35927
36421
  }
35928
36422
  parts.push(`## Source
35929
- From: ${relativePath2}`);
36423
+ From: ${relativePath}`);
35930
36424
  return parts.join("\n\n") + "\n";
35931
36425
  }
35932
- function buildMinorAuditBody(workMode, problem, implementationIntent, acceptanceCriteria, dependenciesRisks, verificationSteps, evidenceChecklist, relativePath2) {
36426
+ function buildMinorAuditBody(workMode, problem, implementationIntent, acceptanceCriteria, dependenciesRisks, verificationSteps, evidenceChecklist, relativePath) {
35933
36427
  return `- Work Mode: ${workMode}
35934
36428
  ## Problem / Why
35935
36429
  ${problem}
@@ -35950,7 +36444,7 @@ ${verificationSteps}
35950
36444
  ${evidenceChecklist}
35951
36445
 
35952
36446
  ## Source
35953
- From: ${relativePath2}
36447
+ From: ${relativePath}
35954
36448
  `;
35955
36449
  }
35956
36450
  function parseIssueReference(output) {
@@ -36115,13 +36609,13 @@ function posixBasename(pathStr) {
36115
36609
  const lastSlash = normalized.lastIndexOf("/");
36116
36610
  return lastSlash === -1 ? normalized : normalized.slice(lastSlash + 1);
36117
36611
  }
36118
- function buildIssueBody(content, selectedMode, promotionType, relativePath2) {
36612
+ function buildIssueBody(content, selectedMode, promotionType, relativePath) {
36119
36613
  if (promotionType === "bug") {
36120
36614
  const bugSections = {};
36121
36615
  for (const heading of BUG_SECTION_HEADINGS) {
36122
36616
  bugSections[heading] = getSection(content, heading) || PLACEHOLDER;
36123
36617
  }
36124
- return buildBugBody(selectedMode, bugSections, relativePath2);
36618
+ return buildBugBody(selectedMode, bugSections, relativePath);
36125
36619
  }
36126
36620
  if (selectedMode === "minor-audit") {
36127
36621
  const problem2 = getSection(content, "Problem / Why") || PLACEHOLDER;
@@ -36141,7 +36635,7 @@ function buildIssueBody(content, selectedMode, promotionType, relativePath2) {
36141
36635
  dependenciesRisks,
36142
36636
  verificationSteps,
36143
36637
  evidenceChecklist,
36144
- relativePath2
36638
+ relativePath
36145
36639
  );
36146
36640
  }
36147
36641
  const problem = getSection(content, "Problem / Why") || PLACEHOLDER;
@@ -36156,7 +36650,7 @@ function buildIssueBody(content, selectedMode, promotionType, relativePath2) {
36156
36650
  criteria,
36157
36651
  constraints,
36158
36652
  tests,
36159
- relativePath2
36653
+ relativePath
36160
36654
  );
36161
36655
  }
36162
36656
  function promotePotential(options) {
@@ -36191,7 +36685,7 @@ function promotePotential(options) {
36191
36685
  const featurePath = getFeaturePath(featureName);
36192
36686
  const prefix = TITLE_PREFIXES[promotionType] ?? "Feature";
36193
36687
  const issueTitle = normalizeSmartPunctuation(`${prefix}: ${featureName}`);
36194
- const relativePath2 = computeRelativePath(resolved, workspacePath);
36688
+ const relativePath = computeRelativePath(resolved, workspacePath);
36195
36689
  let selectedMode;
36196
36690
  try {
36197
36691
  selectedMode = normalizeRequestedWorkMode(workMode, promotionType);
@@ -36200,7 +36694,7 @@ function promotePotential(options) {
36200
36694
  throw new PromotionError(message);
36201
36695
  }
36202
36696
  const fallbackReason = "";
36203
- let body = buildIssueBody(content, selectedMode, promotionType, relativePath2);
36697
+ let body = buildIssueBody(content, selectedMode, promotionType, relativePath);
36204
36698
  body = normalizeSmartPunctuation(body);
36205
36699
  const messages = [];
36206
36700
  const emitLine = (message) => {
@@ -36582,12 +37076,12 @@ function validateFeatureName2(featureName) {
36582
37076
  function escapeRegExp6(value) {
36583
37077
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
36584
37078
  }
36585
- function splitLines7(text2) {
37079
+ function splitLines3(text2) {
36586
37080
  return text2.split(/\r\n|\r|\n/);
36587
37081
  }
36588
37082
  function formatChecklist(text2) {
36589
37083
  const lines = [];
36590
- for (const rawLine of splitLines7(text2)) {
37084
+ for (const rawLine of splitLines3(text2)) {
36591
37085
  const trimmed = rawLine.trim();
36592
37086
  if (!trimmed) {
36593
37087
  continue;
@@ -36616,7 +37110,7 @@ function getSection2(content, name) {
36616
37110
  function upsertWorkModeMarker(content, mode) {
36617
37111
  const markerLine = `- Work Mode: ${mode}`;
36618
37112
  const markerPattern = /^- Work Mode:\s*(minor-audit|full-feature|full-bug|full)\s*$/;
36619
- const lines = splitLines7(content).filter((line) => !markerPattern.test(line));
37113
+ const lines = splitLines3(content).filter((line) => !markerPattern.test(line));
36620
37114
  for (let idx = 0; idx < lines.length; idx += 1) {
36621
37115
  const line = lines[idx] ?? "";
36622
37116
  if (line.replace(/^\s+/, "").startsWith("## ")) {
@@ -37609,13 +38103,7 @@ function findParentKey(toolUseId, transcriptsByKey) {
37609
38103
  return void 0;
37610
38104
  }
37611
38105
  function compareByAgentId(a, b) {
37612
- if (a.meta.agentId < b.meta.agentId) {
37613
- return -1;
37614
- }
37615
- if (a.meta.agentId > b.meta.agentId) {
37616
- return 1;
37617
- }
37618
- return 0;
38106
+ return compareCodePoint(a.meta.agentId, b.meta.agentId);
37619
38107
  }
37620
38108
  function sortBySpawnIndex(children, parentTranscript) {
37621
38109
  return [...children].sort((a, b) => {
@@ -37659,7 +38147,7 @@ function buildNode(input) {
37659
38147
  agentType,
37660
38148
  description,
37661
38149
  depth,
37662
- models: [...models].sort(),
38150
+ models: [...models].sort(compareCodePoint),
37663
38151
  children
37664
38152
  };
37665
38153
  }
@@ -37789,7 +38277,7 @@ function formatTree(node) {
37789
38277
  }
37790
38278
  function renderLines(node) {
37791
38279
  const indent = " ".repeat(node.depth);
37792
- const sortedModels = [...node.models].sort();
38280
+ const sortedModels = [...node.models].sort(compareCodePoint);
37793
38281
  const line = `${indent}${node.agentType} \xB7 [${sortedModels.join(",")}] \xB7 ${node.depth} \xB7 ${node.description}`;
37794
38282
  const childLines = node.children.flatMap((child) => renderLines(child));
37795
38283
  return [line, ...childLines];