@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
@@ -6,53 +6,36 @@
6
6
  Dot-sourced by enforce-epic-merge-gate.ps1 immediately after the authorization sibling.
7
7
  Holds:
8
8
 
9
- - The import guard for WorktreeRunResolution.psm1. A failed import is recorded in
10
- $script:EpicMergeGateResolutionImportFailure, and
11
- Get-EpicMergeGateImportFailureDecision turns it into a deny, so a missing module
9
+ - The import guards for WorktreeRunResolution.psm1 and, after it,
10
+ WorktreeItemResolution.psm1 (issue #850). A failed import is recorded in
11
+ $script:HookDependencyFailures, and the gate's call to
12
+ Get-HookDependencyFailureDecision turns it into a deny, so a missing module
12
13
  cannot make the gate exit non-zero and fail open.
13
14
  - The three checkpoint read seams, relocated from the gate file with their names kept.
14
15
  Each takes a mandatory absolute path composed beneath a resolved worktree root.
15
- - The session worktree root, used for the child branch and for a bare command.
16
+ - The session worktree root, used for a bare command.
16
17
  - The resolution seam Resolve-EpicMergeGateRunTarget, which locates the epic or
17
18
  parallel checkpoint that records the command's pull request number.
19
+ - The item seam Resolve-EpicMergeGateItemTarget (issue #850), which locates the live
20
+ worktree whose per-feature checkpoint records the command's pull request number in
21
+ pr_gate.pr_number or a standalone_merge_authorizations entry.
18
22
  - Test-ChildCheckpointPrGateBinding, which binds the command's pull request number to
19
- the per-feature checkpoint's pr_gate.pr_number when that field is recorded.
20
- - Get-EpicMergeGateUnresolvedReason, the reason prefix used when neither run branch
21
- resolves.
23
+ the per-feature checkpoint: pr_gate.pr_number must equal it when recorded, and
24
+ otherwise a positive-integer standalone record must name it (issue #788).
25
+ - Get-EpicMergeGateUnresolvedReason, the reason prefix used when neither the item
26
+ target nor either run branch resolves.
27
+ - Test-EpicMergeGateNoRecordingTarget, the precondition of the docs-only merge branch:
28
+ the item, epic, and parallel targets all resolve NoTarget (issue #927).
22
29
 
23
30
  .NOTES
24
- PowerShell 7+. Depends on Get-EpicMergeGateBlockDecision from the authorization
25
- sibling, dot-sourced by the gate before this file. Mirrored byte-identically under
31
+ PowerShell 7+. Depends on Get-EpicMergeGateBlockDecision and
32
+ Test-StandalonePositiveJsonInteger from the authorization sibling, dot-sourced by the
33
+ gate before this file. Mirrored byte-identically under
26
34
  extensions/drm-copilot/resources/claude-customizations/.
27
35
  #>
28
36
 
29
- # Import guard (issue #690): a failed import denies instead of failing open.
30
- $script:EpicMergeGateResolutionImportFailure = $null
31
- try {
32
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeRunResolution.psm1') -Force -ErrorAction Stop
33
- }
34
- catch {
35
- $script:EpicMergeGateResolutionImportFailure = 'WorktreeRunResolution.psm1'
36
- }
37
-
38
- function Get-EpicMergeGateImportFailureDecision {
39
- <#
40
- .SYNOPSIS
41
- Returns the deny for a failed worktree-resolution import, or $null.
42
- .OUTPUTS
43
- System.Collections.Specialized.OrderedDictionary, or $null when the import succeeded.
44
- #>
45
- [CmdletBinding()]
46
- [OutputType([System.Collections.Specialized.OrderedDictionary])]
47
- param()
48
-
49
- if (-not $script:EpicMergeGateResolutionImportFailure) {
50
- return $null
51
- }
52
- return Get-EpicMergeGateBlockDecision -Reason (
53
- "EPIC_MERGE_GATE_BLOCKED: the worktree-resolution module '$($script:EpicMergeGateResolutionImportFailure)' " +
54
- 'failed to import, so the run checkpoint that governs this merge cannot be located; the gate fails closed.')
55
- }
37
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeRunResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeRunResolution.psm1' -ErrorRecord $_ }
38
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeItemResolution.psm1' -ErrorRecord $_ }
56
39
 
57
40
  function Get-ChildOrchestratorCheckpointContent {
58
41
  <#
@@ -60,7 +43,7 @@ function Get-ChildOrchestratorCheckpointContent {
60
43
  Read the raw JSON text of the per-feature orchestrator checkpoint. Tests mock
61
44
  this function (read seam).
62
45
  .PARAMETER Path
63
- The absolute checkpoint path composed beneath the session worktree root.
46
+ The absolute checkpoint path composed beneath the item or session worktree root.
64
47
  .OUTPUTS
65
48
  System.String or $null
66
49
  #>
@@ -117,7 +100,7 @@ function Get-ParallelOrchestratorCheckpointContent {
117
100
  function Get-EpicMergeGateSessionWorktreeRoot {
118
101
  <#
119
102
  .SYNOPSIS
120
- Return the worktree root the session runs in (the child branch and bare-command root).
103
+ Return the worktree root the session runs in (the bare-command root).
121
104
  .OUTPUTS
122
105
  System.String
123
106
  #>
@@ -149,14 +132,35 @@ function Resolve-EpicMergeGateRunTarget {
149
132
  return Resolve-WorktreeRunTargetByRecord -Kind $Kind -RecordField pr_number -Value ([string]$PrNumber) -SessionRoot (Get-Location).Path
150
133
  }
151
134
 
135
+ function Resolve-EpicMergeGateItemTarget {
136
+ <#
137
+ .SYNOPSIS
138
+ Resolve the worktree whose per-feature checkpoint records a pull request number (issue #850 seam).
139
+ .PARAMETER PrNumber
140
+ The explicit pull request number the command names.
141
+ .OUTPUTS
142
+ System.Management.Automation.PSCustomObject (the worktree-resolution target result).
143
+ #>
144
+ [CmdletBinding()]
145
+ [OutputType([pscustomobject])]
146
+ param(
147
+ [Parameter(Mandatory)][int] $PrNumber
148
+ )
149
+
150
+ return Resolve-WorktreeItemTargetByPrNumber -PrNumber $PrNumber -SessionRoot (Get-Location).Path
151
+ }
152
+
152
153
  function Test-ChildCheckpointPrGateBinding {
153
154
  <#
154
155
  .SYNOPSIS
155
- True unless the per-feature checkpoint records a pr_gate.pr_number that differs from the command's.
156
+ True when the per-feature checkpoint binds the command's pull request number (issue #788).
156
157
  .DESCRIPTION
157
- A bare command, an absent checkpoint, and a checkpoint without pr_gate.pr_number
158
- keep today's unbound child-branch decision. When both numbers are present they must
159
- parse as integers and be equal.
158
+ Pure. A bare command is unbound and returns $true. An explicit number requires a
159
+ checkpoint: when it records pr_gate.pr_number, that value must parse as an integer
160
+ equal to the number; otherwise a standalone_merge_authorizations entry whose
161
+ pr_number is a positive JSON integer equal to the number must exist. Every other
162
+ case returns $false, so a checkpoint that names neither field cannot authorize an
163
+ explicit-number merge through the child branch.
160
164
  .PARAMETER Checkpoint
161
165
  Parsed per-feature checkpoint, or $null.
162
166
  .PARAMETER CommandPrNumber
@@ -171,30 +175,45 @@ function Test-ChildCheckpointPrGateBinding {
171
175
  [AllowNull()][Nullable[int]] $CommandPrNumber
172
176
  )
173
177
 
174
- if ($null -eq $CommandPrNumber -or $null -eq $Checkpoint) {
178
+ if ($null -eq $CommandPrNumber) {
175
179
  return $true
176
180
  }
177
- if (@($Checkpoint.PSObject.Properties.Name) -notcontains 'pr_gate' -or $null -eq $Checkpoint.pr_gate) {
178
- return $true
181
+ if ($null -eq $Checkpoint) {
182
+ return $false
179
183
  }
180
- $prGate = $Checkpoint.pr_gate
181
- if (@($prGate.PSObject.Properties.Name) -notcontains 'pr_number' -or $null -eq $prGate.pr_number) {
182
- return $true
184
+ $props = @($Checkpoint.PSObject.Properties.Name)
185
+ if ($props -contains 'pr_gate' -and $null -ne $Checkpoint.pr_gate -and
186
+ @($Checkpoint.pr_gate.PSObject.Properties.Name) -contains 'pr_number' -and $null -ne $Checkpoint.pr_gate.pr_number) {
187
+ $recorded = 0
188
+ if (-not [int]::TryParse([string]$Checkpoint.pr_gate.pr_number, [ref] $recorded)) {
189
+ return $false
190
+ }
191
+ return ($recorded -eq $CommandPrNumber)
183
192
  }
184
- $recorded = 0
185
- if (-not [int]::TryParse([string]$prGate.pr_number, [ref] $recorded)) {
193
+ if ($props -notcontains 'standalone_merge_authorizations') {
186
194
  return $false
187
195
  }
188
- return ($recorded -eq $CommandPrNumber)
196
+ foreach ($entry in @($Checkpoint.standalone_merge_authorizations)) {
197
+ if ($null -eq $entry -or @($entry.PSObject.Properties.Name) -notcontains 'pr_number') {
198
+ continue
199
+ }
200
+ if ((Test-StandalonePositiveJsonInteger -Value $entry.pr_number) -and [long]$entry.pr_number -eq $CommandPrNumber) {
201
+ return $true
202
+ }
203
+ }
204
+ return $false
189
205
  }
190
206
 
191
207
  function Get-EpicMergeGateUnresolvedReason {
192
208
  <#
193
209
  .SYNOPSIS
194
- Returns '<code>: <epic detail>; <parallel detail>' when neither run branch resolved, or $null.
210
+ Returns '<code>: <item detail>; <epic detail>; <parallel detail>' when no target resolved, or $null.
195
211
  .DESCRIPTION
196
- The ambiguity code wins when either target is Ambiguous. Returns $null when either
197
- target is absent (a bare command) or either target resolved.
212
+ The ambiguity code of the first Ambiguous target among item, epic, and parallel
213
+ wins; otherwise the item target's code is used. Returns $null when any target is
214
+ absent (a bare command) or any target resolved.
215
+ .PARAMETER ItemTarget
216
+ The item target, or $null.
198
217
  .PARAMETER EpicTarget
199
218
  The epic run target, or $null.
200
219
  .PARAMETER ParallelTarget
@@ -205,17 +224,55 @@ function Get-EpicMergeGateUnresolvedReason {
205
224
  [CmdletBinding()]
206
225
  [OutputType([string])]
207
226
  param(
227
+ [AllowNull()] $ItemTarget,
208
228
  [AllowNull()] $EpicTarget,
209
229
  [AllowNull()] $ParallelTarget
210
230
  )
211
231
 
212
- if ($null -eq $EpicTarget -or $null -eq $ParallelTarget) {
232
+ if ($null -eq $ItemTarget -or $null -eq $EpicTarget -or $null -eq $ParallelTarget) {
213
233
  return $null
214
234
  }
235
+ $targets = @($ItemTarget, $EpicTarget, $ParallelTarget)
215
236
  $unresolved = @('NoTarget', 'Ambiguous')
216
- if ($unresolved -notcontains $EpicTarget.Status -or $unresolved -notcontains $ParallelTarget.Status) {
217
- return $null
237
+ foreach ($target in $targets) {
238
+ if ($unresolved -notcontains $target.Status) {
239
+ return $null
240
+ }
241
+ }
242
+ $ambiguous = @($targets | Where-Object { $_.Status -eq 'Ambiguous' })
243
+ $code = if ($ambiguous.Count -gt 0) { $ambiguous[0].ReasonCode } else { $ItemTarget.ReasonCode }
244
+ return ('{0}: {1}; {2}; {3}' -f $code, $ItemTarget.Detail, $EpicTarget.Detail, $ParallelTarget.Detail)
245
+ }
246
+
247
+ function Test-EpicMergeGateNoRecordingTarget {
248
+ <#
249
+ .SYNOPSIS
250
+ True only when the item, epic, and parallel targets all have status NoTarget (issue #927).
251
+ .DESCRIPTION
252
+ Pure. That combination means no checkpoint records the command's pull request number,
253
+ which is the only case the docs-only merge branch evaluates. A $null target (a bare
254
+ command), an Ambiguous target, and any resolved target return $false.
255
+ .PARAMETER ItemTarget
256
+ The item target, or $null.
257
+ .PARAMETER EpicTarget
258
+ The epic run target, or $null.
259
+ .PARAMETER ParallelTarget
260
+ The parallel run target, or $null.
261
+ .OUTPUTS
262
+ System.Boolean
263
+ #>
264
+ [CmdletBinding()]
265
+ [OutputType([bool])]
266
+ param(
267
+ [AllowNull()] $ItemTarget,
268
+ [AllowNull()] $EpicTarget,
269
+ [AllowNull()] $ParallelTarget
270
+ )
271
+
272
+ foreach ($target in @($ItemTarget, $EpicTarget, $ParallelTarget)) {
273
+ if ($null -eq $target -or [string]$target.Status -cne 'NoTarget') {
274
+ return $false
275
+ }
218
276
  }
219
- $code = if ($EpicTarget.Status -eq 'Ambiguous') { $EpicTarget.ReasonCode } elseif ($ParallelTarget.Status -eq 'Ambiguous') { $ParallelTarget.ReasonCode } else { $EpicTarget.ReasonCode }
220
- return ('{0}: {1}; {2}' -f $code, $EpicTarget.Detail, $ParallelTarget.Detail)
277
+ return $true
221
278
  }
@@ -1,11 +1,12 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Pre-tool-use hook that gates gh pr merge --merge behind epic-mode checkpoint state.
3
+ Pre-tool-use hook that gates every pull-request merge or merge-queue enqueue behind checkpoint state.
4
4
 
5
5
  .DESCRIPTION
6
6
  Invoked by the Claude Code PreToolUse hook on the "Bash" matcher before any Bash
7
- command runs. Regex-matches gh pr merge with a --merge flag against
8
- the envelope's tool_input.command and, when matched, allows the merge only when one of four
7
+ command runs. Brings every gh pr merge invocation except a pure --disable-auto, and every gh
8
+ api merge or enqueue mutation, into scope from the envelope's tool_input.command and, when
9
+ matched, allows the action only when one of four
9
10
  checkpoint-only conditions holds:
10
11
 
11
12
  1. Child-feature path: artifacts/orchestration/orchestrator-state.json exists,
@@ -31,17 +32,30 @@
31
32
  non-parallel) run never satisfies conditions 1-3, so its only route to a merge is an
32
33
  explicit, PR-specific, session-bound record under condition 4; a bare command with no
33
34
  PR number never satisfies condition 4, and a blanket flag is rejected rather than read.
34
- Trigger scope: --squash is out of scope for this gate and is allowed on both runtimes.
35
-
36
- Design decision: this gate trusts the on-disk checkpoint rather than shelling out live
37
- to gh pr view for a real-time head-SHA check, matching the same non-adversarial,
38
- policy-level-not-cryptographic posture already accepted for
39
- enforce-pr-author-skill.ps1's own receipt mechanism. It is not a cryptographic control.
35
+ Trigger scope (issue #952): every merge method (--merge/-m, --squash/-s, --rebase/-r), --auto,
36
+ --admin, and a bare gh pr merge are gated alike, because under a merge queue each spelling
37
+ enqueues the pull request; only a pure --disable-auto is out of scope. The predicate and the
38
+ PR selector reader live in enforce-epic-merge-gate-command.ps1.
39
+
40
+ Design decision: branches 1-4 trust the on-disk checkpoint and never call gh. Issue #927
41
+ adds a docs-only branch after branch 4 fails, only for an explicit PR number whose item,
42
+ epic, and parallel targets are all NoTarget (no checkpoint records the PR): it calls
43
+ Get-DocsOnlyMergeExemption (hook-docs-only-diff.ps1), which runs gh pr view and git in the
44
+ session worktree and allows the merge when conditions M1-M9 of that file hold. Otherwise
45
+ the deny gains " (docs-only exemption not applied: <Reason>)", where the reason may be
46
+ DOCS_ONLY_EXEMPTION_PR_UNRESOLVED. The hook never fetches; --match-head-commit, when
47
+ present, must equal headRefOid (OD-2). Residual limits: an ambient GH_REPO or GH_HOST is
48
+ not visible in the command text; gh and git run in the session worktree root, so a cd
49
+ made by an earlier Bash call is not visible either; and a push after the lookup can
50
+ change the head unless --match-head-commit is passed. Like the receipt mechanism of
51
+ enforce-pr-author-skill.ps1, this is a policy-level control, not a cryptographic one.
40
52
 
41
53
  Issue #690: with an explicit PR number, the epic and parallel checkpoints are read
42
- beneath the live worktree whose run checkpoint records that number, and the child
43
- branch binds the number to pr_gate.pr_number when the per-feature checkpoint records
44
- it. A bare command reads every checkpoint beneath the session worktree.
54
+ beneath the live worktree whose run checkpoint records that number. Issue #850: with
55
+ an explicit PR number, the per-feature checkpoint is read beneath the live worktree
56
+ whose checkpoint records the number in pr_gate.pr_number or a standalone record, and
57
+ the child branch requires that checkpoint to bind the number (issue #788). A bare
58
+ command reads every checkpoint beneath the session worktree.
45
59
 
46
60
  .NOTES
47
61
  Compatible with PowerShell 7+. Depends on WorktreeRunResolution.psm1 through the
@@ -57,16 +71,21 @@
57
71
  #>
58
72
  [CmdletBinding()]
59
73
  param()
74
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
60
75
 
61
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
76
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
62
77
  # Shared command-line parser (issue #545), consumed by the scope filter in
63
78
  # Invoke-EpicMergeGateDecision and by Get-EpicMergeGateCommandPrNumber.
64
- . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
65
- . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
79
+ try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
80
+ try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
66
81
  # Standalone-merge authorization predicates and the two decision-envelope factories (issue #670).
67
- . (Join-Path $PSScriptRoot 'enforce-epic-merge-gate-authorization.ps1')
82
+ try { . (Join-Path $PSScriptRoot 'enforce-epic-merge-gate-authorization.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-epic-merge-gate-authorization.ps1' -ErrorRecord $_ }
68
83
  # Checkpoint read seams, the import guard, and run-target resolution (issue #690).
69
- . (Join-Path $PSScriptRoot 'enforce-epic-merge-gate-resolution.ps1')
84
+ try { . (Join-Path $PSScriptRoot 'enforce-epic-merge-gate-resolution.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-epic-merge-gate-resolution.ps1' -ErrorRecord $_ }
85
+ # Merge and enqueue scope predicate and the PR selector reader (issue #952).
86
+ try { . (Join-Path $PSScriptRoot 'enforce-epic-merge-gate-command.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-epic-merge-gate-command.ps1' -ErrorRecord $_ }
87
+ # Shared docs-only diff classification and the merge-side docs-only exemption (issue #927).
88
+ try { . (Join-Path $PSScriptRoot 'hook-docs-only-diff.ps1') } catch { Add-HookDependencyFailure -Name 'hook-docs-only-diff.ps1' -ErrorRecord $_ }
70
89
 
71
90
  function ConvertFrom-EpicMergeGateJson {
72
91
  <#
@@ -98,21 +117,13 @@ function Get-EpicMergeGateCommandPrNumber {
98
117
  .SYNOPSIS
99
118
  Extract an explicit PR number argument from a gh pr merge command, or $null.
100
119
  .DESCRIPTION
101
- Both spellings are read from the segment that structurally invokes gh pr merge,
102
- never from the whole command line. The positional form ("gh pr merge 410 --merge")
103
- resolves through Get-CommandLineOperand and takes the first all-digit operand; the
104
- flag-led forms ("gh pr merge --merge 410" and "gh pr merge --merge=410") resolve
105
- through Get-CommandLineFlagValue. A bare "gh pr merge --merge" yields $null, which
106
- the parallel branch treats as fail-closed.
107
-
108
- The deleted unanchored branch scanned the WHOLE command text for the first run of
109
- digits once "gh pr merge" appeared anywhere in it, and that failed in both
110
- directions. Fail-closed: a leading "cd <path>" whose path carries a timestamp
111
- component supplied a digit run that was not a pull request number, so an authorized
112
- merge was blocked. False-allow: with authorized item 501 and unauthorized item 777,
113
- "cd /repo/worktrees/501 && gh pr merge --merge 777" extracted 501, matched the
114
- authorized item, and permitted the merge of PR 777. Taking the number from the
115
- matched segment's own operand or flag value closes both directions.
120
+ The number is resolved by Get-EpicMergeGateSelectorPrNumber in
121
+ enforce-epic-merge-gate-command.ps1 (issue #952), from the segment that structurally
122
+ invokes gh pr merge or gh api and never from the whole command line: value flags are
123
+ skipped with their values, an all-digit or /pull/<n> URL selector is accepted, and a
124
+ pulls/<n>/merge path supplies the number for gh api. A command with no resolvable number
125
+ yields $null, which the parallel and standalone branches treat as fail-closed. No
126
+ whole-line digit scan exists, so a cd path component can never supply the number.
116
127
  .PARAMETER CommandText
117
128
  The Bash command text under evaluation.
118
129
  .OUTPUTS
@@ -125,18 +136,7 @@ function Get-EpicMergeGateCommandPrNumber {
125
136
  [string] $CommandText
126
137
  )
127
138
 
128
- foreach ($operand in @(Get-CommandLineOperand -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge'))) {
129
- if ($operand -match '^\d+$') {
130
- return [int]$operand
131
- }
132
- }
133
-
134
- $flagValue = Get-CommandLineFlagValue -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge') -FlagName '--merge'
135
- if ($null -ne $flagValue -and $flagValue -match '^\d+$') {
136
- return [int]$flagValue
137
- }
138
-
139
- return $null
139
+ return Get-EpicMergeGateSelectorPrNumber -CommandText $CommandText
140
140
  }
141
141
 
142
142
  function Test-ChildCheckpointAllowsEpicMerge {
@@ -312,10 +312,8 @@ function Invoke-EpicMergeGateDecision {
312
312
  )
313
313
 
314
314
  # A failed worktree-resolution import denies before any other logic (issue #690).
315
- $importFailure = Get-EpicMergeGateImportFailureDecision
316
- if ($null -ne $importFailure) {
317
- return $importFailure
318
- }
315
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_MERGE_GATE_BLOCKED:'
316
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
319
317
 
320
318
  $payload = Resolve-ClaudeHookToolInput -Raw $ToolInputRaw
321
319
  if (-not $payload.IsValid) {
@@ -330,36 +328,26 @@ function Invoke-EpicMergeGateDecision {
330
328
  return Get-EpicMergeGateAllowDecision
331
329
  }
332
330
 
333
- # Only a gh pr merge invocation carrying --merge is in scope for this gate; every
334
- # other Bash command is unaffected. Both legs are read structurally from the segment
335
- # that invokes the command, so a quoted mention of the phrase and a --merge token
336
- # belonging to some other segment no longer bring a command into scope.
337
- #
338
- # The flag leg needs a raw-scan fallback: a wrapper's quoted argument collapses into ONE
339
- # token, so a flag inside it is never read as a token, and the token-only read took
340
- # bash -c "gh pr merge --merge 688" out of scope. The fallback reads only the segments the
341
- # scanner already scans raw, so a masked mention in a non-wrapper segment stays out.
342
- $isMergeInvocation = Test-CommandLineInvocation -CommandText $commandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge')
343
- $hasMergeFlag = Test-CommandLineFlag -CommandText $commandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge') -FlagName '--merge'
344
- if (-not $hasMergeFlag) {
345
- foreach ($segment in @(Read-CommandLineSegment -CommandText $commandText)) {
346
- if ((Test-CommandLineSegmentRawScan -Segment $segment) -and
347
- $segment.ScanText.IndexOf('--merge', [System.StringComparison]::OrdinalIgnoreCase) -ge 0) {
348
- $hasMergeFlag = $true
349
- break
350
- }
351
- }
352
- }
353
- if (-not $isMergeInvocation -or -not $hasMergeFlag) {
331
+ # Scope (issue #952): every gh pr merge invocation except a pure --disable-auto, and every gh api
332
+ # merge or enqueue mutation, is gated; Test-EpicMergeGateCommandInScope holds the predicate.
333
+ if (-not (Test-EpicMergeGateCommandInScope -CommandText $commandText)) {
354
334
  return Get-EpicMergeGateAllowDecision
355
335
  }
356
336
 
357
337
  $commandPrNumber = Get-EpicMergeGateCommandPrNumber -CommandText $commandText
358
338
  $sessionRoot = Get-EpicMergeGateSessionWorktreeRoot
359
339
 
360
- # The child merges from its own worktree, so its checkpoint is the session worktree's;
361
- # a recorded pr_gate.pr_number must match an explicit command PR number (issue #690).
362
- $childCheckpoint = ConvertFrom-EpicMergeGateJson -Raw (Get-ChildOrchestratorCheckpointContent -Path (Get-WorktreeRunCheckpointPath -Kind item -WorktreeRoot $sessionRoot))
340
+ # With an explicit PR number, the per-feature checkpoint is read beneath the live
341
+ # worktree whose checkpoint records the number in pr_gate.pr_number or a standalone
342
+ # record (issue #850); an unresolved item target reads none. A bare command reads the
343
+ # session worktree. The checkpoint read must still bind the number (issue #788).
344
+ $itemTarget = $null
345
+ $childRoot = $sessionRoot
346
+ if ($null -ne $commandPrNumber) {
347
+ $itemTarget = Resolve-EpicMergeGateItemTarget -PrNumber $commandPrNumber
348
+ $childRoot = if (@('SessionRoot', 'OtherWorktree') -contains $itemTarget.Status) { $itemTarget.WorktreeRoot } else { $null }
349
+ }
350
+ $childCheckpoint = if ($childRoot) { ConvertFrom-EpicMergeGateJson -Raw (Get-ChildOrchestratorCheckpointContent -Path (Get-WorktreeRunCheckpointPath -Kind item -WorktreeRoot $childRoot)) } else { $null }
363
351
  if ((Test-ChildCheckpointAllowsEpicMerge -Checkpoint $childCheckpoint) -and
364
352
  (Test-ChildCheckpointPrGateBinding -Checkpoint $childCheckpoint -CommandPrNumber $commandPrNumber)) {
365
353
  return Get-EpicMergeGateAllowDecision
@@ -396,13 +384,23 @@ function Invoke-EpicMergeGateDecision {
396
384
  if ($standalone.Allowed) {
397
385
  return Get-EpicMergeGateAllowDecision
398
386
  }
399
- # When neither run branch resolved, its reason code and detail precede the standalone reason.
400
- $unresolved = Get-EpicMergeGateUnresolvedReason -EpicTarget $epicTarget -ParallelTarget $parallelTarget
387
+ # Docs-only branch (issue #927): evaluated only when no checkpoint records the PR.
388
+ $docsOnlySuffix = ''
389
+ if (Test-EpicMergeGateNoRecordingTarget -ItemTarget $itemTarget -EpicTarget $epicTarget -ParallelTarget $parallelTarget) {
390
+ $docsOnly = Get-DocsOnlyMergeExemption -CommandText $commandText -PrNumber $commandPrNumber -WorktreeRoot $sessionRoot
391
+ if ($docsOnly.Exempt) {
392
+ return Get-EpicMergeGateAllowDecision
393
+ }
394
+ $docsOnlySuffix = ' (docs-only exemption not applied: ' + $docsOnly.Reason + ')'
395
+ }
396
+ # When neither the item target nor a run branch resolved, the reason code and the
397
+ # three details precede the standalone reason (issue #850).
398
+ $unresolved = Get-EpicMergeGateUnresolvedReason -ItemTarget $itemTarget -EpicTarget $epicTarget -ParallelTarget $parallelTarget
401
399
  $prefix = if ($unresolved) { $unresolved + '; ' } else { '' }
402
- return Get-EpicMergeGateBlockDecision -Reason ('EPIC_MERGE_GATE_BLOCKED: ' + $prefix + $standalone.ReasonCode + ': ' + $standalone.Message)
400
+ return Get-EpicMergeGateBlockDecision -Reason ('EPIC_MERGE_GATE_BLOCKED: ' + $prefix + $standalone.ReasonCode + ': ' + $standalone.Message + $docsOnlySuffix)
403
401
  }
404
402
 
405
- return Get-EpicMergeGateBlockDecision -Reason 'EPIC_MERGE_GATE_BLOCKED: gh pr merge --merge requires either a per-feature checkpoint with epic_mode == true and step9_status == "passed", an epic checkpoint with epic_merge_pr.ci_gate.conclusion == "success" and a matching pr_number, or a parallel-orchestrator checkpoint with route_id == "parallel" whose target item (matched by pr_number) has merge_status == "ci_green". No checkpoint satisfied this gate.'
403
+ return Get-EpicMergeGateBlockDecision -Reason 'EPIC_MERGE_GATE_BLOCKED: a pull-request merge or merge-queue enqueue (gh pr merge with any method, --auto, or --admin, or a gh api merge or enqueue mutation) requires either a per-feature checkpoint with epic_mode == true and step9_status == "passed", an epic checkpoint with epic_merge_pr.ci_gate.conclusion == "success" and a matching pr_number, or a parallel-orchestrator checkpoint with route_id == "parallel" whose target item (matched by pr_number) has merge_status == "ci_green". No checkpoint satisfied this gate.'
406
404
  }
407
405
 
408
406
  function Invoke-EpicMergeGateEntryPoint {
@@ -447,6 +445,9 @@ function Invoke-EpicMergeGateEntryPoint {
447
445
  if ($MyInvocation.InvocationName -eq '.') {
448
446
  return
449
447
  }
448
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_MERGE_GATE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
449
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_MERGE_GATE_BLOCKED:'
450
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
450
451
 
451
452
  # The entry point returns its [int] exit code as the last pipeline element and the
452
453
  # decision JSON before it. `exit (<call>)` would capture BOTH into the exit
@@ -456,4 +457,4 @@ if ($entryPointResult.Count -gt 1) {
456
457
  $entryPointResult[0..($entryPointResult.Count - 2)] | Write-Output
457
458
  }
458
459
 
459
- exit ([int]$entryPointResult[-1])
460
+ exit ([int]$entryPointResult[-1])