@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
@@ -0,0 +1,224 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Docs-only exemption from the checkpoint preflight of enforce-pr-author-skill.ps1 (issue #901).
4
+
5
+ .DESCRIPTION
6
+ Dot-sourced by enforce-pr-author-skill-helpers.ps1. Get-PrAuthorBypassReason calls
7
+ Get-PrAuthorDocsOnlyExemption only in its non-epic branch and only after
8
+ Invoke-OrchestratorStatePreflight reports errors. The exemption lets a gh pr create call
9
+ continue to the receipt checks when the branch changes nothing outside docs/. It fails
10
+ closed: every condition below must hold, and the first that does not names the sub-code
11
+ the caller appends to its ORCHESTRATOR_STATE_PREFLIGHT_FAILED denial.
12
+
13
+ E1 DOCS_ONLY_EXEMPTION_NOT_CREATE - the command is a structural gh pr create.
14
+ E2 DOCS_ONLY_EXEMPTION_CHECKPOINT_PRESENT - no checkpoint file exists at the resolved path.
15
+ E3 DOCS_ONLY_EXEMPTION_BASE_UNRESOLVED - exactly one explicit --base, a conservative branch
16
+ spelling without '..', and no base or repository
17
+ override: no single-dash token whose letters
18
+ include B or R (-B, -R, -dB, -Rx), no --repo or
19
+ --repo= token, and no inline GH_REPO= prefix.
20
+ E4 DOCS_ONLY_EXEMPTION_BASE_UNRESOLVED - refs/remotes/origin/<base> resolves to a commit.
21
+ E5 DOCS_ONLY_EXEMPTION_DIFF_FAILED - git diff <commit>...HEAD exits 0 without throwing,
22
+ and non-empty output ends with NUL.
23
+ E6 DOCS_ONLY_EXEMPTION_EMPTY_DIFF - the diff lists at least one path.
24
+ E7 DOCS_ONLY_EXEMPTION_NON_DOCS_PATH - every path starts with docs/ (ordinal).
25
+
26
+ The diff runs with --no-renames so a rename from outside docs/ reports its old path, with -z
27
+ so no path is quoted, and with --no-relative, --no-color, and --no-ext-diff so repository
28
+ configuration cannot change the listing.
29
+
30
+ Residual limit: a GH_REPO value exported by an earlier shell command or inherited from the
31
+ session environment is not visible in the command text, so this file cannot detect it.
32
+
33
+ .NOTES
34
+ PowerShell 7+. Depends, at call time, on Test-CommandLineInvocation,
35
+ Get-CommandLineStructuralMatch, and Get-CommandLineFlagValue from the command parsers the
36
+ helpers file loads. It reads no file content. The git executable runs only through
37
+ Invoke-PrAuthorDocsOnlyGitExe, the single executable seam, which never throws. Mirrored
38
+ byte-identically under extensions/drm-copilot/resources/claude-customizations/.
39
+ Dot-sources hook-docs-only-diff.ps1 (issue #927), whose Get-DocsOnlyDiffTextViolation
40
+ performs the E5 NUL check and the E6 and E7 path classification.
41
+ #>
42
+ [CmdletBinding()]
43
+ param()
44
+ . (Join-Path $PSScriptRoot 'hook-docs-only-diff.ps1')
45
+
46
+ function Invoke-PrAuthorDocsOnlyGitExe {
47
+ <#
48
+ .SYNOPSIS
49
+ Run git -C <root> with the given arguments. The single executable seam; tests mock it.
50
+ .DESCRIPTION
51
+ Never throws: an uncaught error ends the hook with exit 1, which PreToolUse treats as
52
+ non-blocking, so a throw here would allow the call. A root that is not an existing
53
+ directory, or a git that cannot start, returns ExitCode -1. Standard error is discarded
54
+ so that it is never read as path data.
55
+ .PARAMETER WorktreeRoot
56
+ The resolved worktree root git runs in.
57
+ .PARAMETER GitArgs
58
+ The git arguments that follow -C <root>.
59
+ .PARAMETER GitInvoker
60
+ The scriptblock that runs git; a unit test passes a test-local stand-in so that this
61
+ body runs without starting a process.
62
+ .OUTPUTS
63
+ System.Management.Automation.PSCustomObject with ExitCode and Output.
64
+ #>
65
+ [CmdletBinding()]
66
+ [OutputType([pscustomobject])]
67
+ param(
68
+ [AllowNull()][AllowEmptyString()][string] $WorktreeRoot,
69
+ [Parameter(Mandatory)][string[]] $GitArgs,
70
+ [ValidateNotNull()][scriptblock] $GitInvoker = { git @args 2>$null }
71
+ )
72
+
73
+ $failure = [pscustomobject]@{ ExitCode = -1; Output = '' }
74
+ if ([string]::IsNullOrWhiteSpace($WorktreeRoot) -or -not (Test-Path -LiteralPath $WorktreeRoot -PathType Container)) {
75
+ return $failure
76
+ }
77
+ try {
78
+ $lines = @(& $GitInvoker -C $WorktreeRoot @GitArgs 2>$null)
79
+ $code = $LASTEXITCODE
80
+ }
81
+ catch {
82
+ return $failure
83
+ }
84
+ return [pscustomobject]@{ ExitCode = [int]$code; Output = ($lines -join "`n") }
85
+ }
86
+
87
+ function Test-PrAuthorDocsOnlyCheckpointPresence {
88
+ <#
89
+ .SYNOPSIS
90
+ Return $true when a checkpoint file exists at the path, and also for a blank path.
91
+ .DESCRIPTION
92
+ A blank path cannot prove that no checkpoint exists, so it reports presence (fail closed).
93
+ .PARAMETER CheckpointPath
94
+ The absolute checkpoint path identity resolution composed.
95
+ .OUTPUTS
96
+ System.Boolean
97
+ #>
98
+ [CmdletBinding()]
99
+ [OutputType([bool])]
100
+ param(
101
+ [AllowNull()][AllowEmptyString()][string] $CheckpointPath
102
+ )
103
+
104
+ if ([string]::IsNullOrWhiteSpace($CheckpointPath)) {
105
+ return $true
106
+ }
107
+ return (Test-Path -LiteralPath $CheckpointPath -PathType Leaf)
108
+ }
109
+
110
+ function Get-PrAuthorDocsOnlyBaseName {
111
+ <#
112
+ .SYNOPSIS
113
+ Return the single explicit --base value of a gh pr create command, or $null.
114
+ .DESCRIPTION
115
+ Returns $null when the command is not a structural gh pr create; when a single-dash
116
+ token has B or R among its letters (-B base and -R repository, alone or clustered as in
117
+ -dB or -dR); when a token is --repo, starts with --repo=, or starts with GH_REPO=; when
118
+ --base appears other than exactly once; when its value is missing or dash-leading; when
119
+ the value is not a conservative branch spelling; or when it contains '..'.
120
+ .PARAMETER CommandText
121
+ The Bash command text under evaluation.
122
+ .OUTPUTS
123
+ System.String or $null
124
+ #>
125
+ [CmdletBinding()]
126
+ [OutputType([string])]
127
+ param(
128
+ [Parameter(Mandatory)][AllowEmptyString()][string] $CommandText
129
+ )
130
+
131
+ $subcommandPath = @('pr', 'create')
132
+ $match = Get-CommandLineStructuralMatch -CommandText $CommandText -CommandWord 'gh' -SubcommandPath $subcommandPath
133
+ if ($null -eq $match) {
134
+ return $null
135
+ }
136
+ $baseTokenCount = 0
137
+ foreach ($token in @($match.Segment.Tokens)) {
138
+ $text = [string]$token
139
+ if ($text.Length -ge 2 -and $text[0] -eq '-' -and $text[1] -ne '-' -and $text.Substring(1).IndexOfAny([char[]]@('B', 'R')) -ge 0) {
140
+ return $null
141
+ }
142
+ if ($text -eq '--repo' -or $text.StartsWith('--repo=', [System.StringComparison]::OrdinalIgnoreCase) -or $text.StartsWith('GH_REPO=', [System.StringComparison]::OrdinalIgnoreCase)) {
143
+ return $null
144
+ }
145
+ if ($text -eq '--base' -or $text.StartsWith('--base=', [System.StringComparison]::OrdinalIgnoreCase)) {
146
+ $baseTokenCount++
147
+ }
148
+ }
149
+ if ($baseTokenCount -ne 1) {
150
+ return $null
151
+ }
152
+ $base = Get-CommandLineFlagValue -CommandText $CommandText -CommandWord 'gh' -SubcommandPath $subcommandPath -FlagName '--base'
153
+ if ($null -eq $base -or $base -cnotmatch '^[A-Za-z0-9][A-Za-z0-9._/-]*$' -or $base.Contains('..')) {
154
+ return $null
155
+ }
156
+ return $base
157
+ }
158
+
159
+ function Get-PrAuthorDocsOnlyExemption {
160
+ <#
161
+ .SYNOPSIS
162
+ Decide whether a failed preflight is exempt because the branch changes only docs/.
163
+ .DESCRIPTION
164
+ Evaluates E1 to E7 of the file header in order and returns at the first failure.
165
+ Each git call is wrapped so that a throwing seam denies rather than escapes.
166
+ .PARAMETER CommandText
167
+ The Bash command text under evaluation.
168
+ .PARAMETER WorktreeRoot
169
+ The resolved worktree root the diff is computed in.
170
+ .PARAMETER CheckpointPath
171
+ The resolved checkpoint path whose absence E2 requires.
172
+ .OUTPUTS
173
+ System.Collections.Specialized.OrderedDictionary with Exempt and Reason.
174
+ #>
175
+ [CmdletBinding()]
176
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
177
+ param(
178
+ [Parameter(Mandatory)][string] $CommandText,
179
+ [AllowNull()][AllowEmptyString()][string] $WorktreeRoot,
180
+ [AllowNull()][AllowEmptyString()][string] $CheckpointPath
181
+ )
182
+
183
+ if (-not (Test-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'create'))) {
184
+ return [ordered]@{ Exempt = $false; Reason = 'DOCS_ONLY_EXEMPTION_NOT_CREATE: only gh pr create is eligible.' }
185
+ }
186
+ if (Test-PrAuthorDocsOnlyCheckpointPresence -CheckpointPath $CheckpointPath) {
187
+ return [ordered]@{ Exempt = $false; Reason = "DOCS_ONLY_EXEMPTION_CHECKPOINT_PRESENT: a checkpoint file exists at '$CheckpointPath', so its preflight governs." }
188
+ }
189
+ $base = Get-PrAuthorDocsOnlyBaseName -CommandText $CommandText
190
+ if ($null -eq $base) {
191
+ return [ordered]@{ Exempt = $false; Reason = 'DOCS_ONLY_EXEMPTION_BASE_UNRESOLVED: pass exactly one explicit --base <branch>; -B, -R, --repo, a single-dash shorthand cluster containing B or R, and an inline GH_REPO= prefix are not accepted.' }
192
+ }
193
+
194
+ $baseRef = 'refs/remotes/origin/' + $base + '^{commit}'
195
+ try {
196
+ $revParse = Invoke-PrAuthorDocsOnlyGitExe -WorktreeRoot $WorktreeRoot -GitArgs @('rev-parse', '--verify', '--quiet', $baseRef)
197
+ }
198
+ catch {
199
+ $revParse = $null
200
+ }
201
+ $commit = ''
202
+ if ($null -ne $revParse) {
203
+ $commit = ([string]$revParse.Output).Trim()
204
+ }
205
+ if ($null -eq $revParse -or $revParse.ExitCode -ne 0 -or $commit -cnotmatch '^[0-9a-f]{40}([0-9a-f]{24})?$') {
206
+ return [ordered]@{ Exempt = $false; Reason = "DOCS_ONLY_EXEMPTION_BASE_UNRESOLVED: refs/remotes/origin/$base does not resolve to a commit in the target worktree." }
207
+ }
208
+
209
+ try {
210
+ $diff = Invoke-PrAuthorDocsOnlyGitExe -WorktreeRoot $WorktreeRoot -GitArgs @('diff', '--name-only', '-z', '--no-renames', '--no-color', '--no-ext-diff', '--no-relative', ($commit + '...HEAD'))
211
+ }
212
+ catch {
213
+ $diff = $null
214
+ }
215
+ if ($null -eq $diff -or $diff.ExitCode -ne 0) {
216
+ return [ordered]@{ Exempt = $false; Reason = "DOCS_ONLY_EXEMPTION_DIFF_FAILED: git diff against origin/$base could not be computed." }
217
+ }
218
+
219
+ $violation = Get-DocsOnlyDiffTextViolation -DiffText ([string]$diff.Output) -BaseName $base
220
+ if ($violation) {
221
+ return [ordered]@{ Exempt = $false; Reason = $violation }
222
+ }
223
+ return [ordered]@{ Exempt = $true; Reason = $null }
224
+ }
@@ -19,18 +19,49 @@
19
19
  Block cases:
20
20
  Case A - gh pr create or gh pr edit with --body (inline, no --body-file): blocked.
21
21
  Case B - gh pr create with neither --body nor --body-file: blocked.
22
- Case C - gh pr create or gh pr edit with --body-file but context artifact absent: blocked.
22
+ Case C - gh pr create or gh pr edit with --body-file but context artifact absent beneath
23
+ the resolved worktree: blocked.
23
24
  Preflight - --body-file/context present: orchestrator-state checkpoint must pass
24
25
  --require-pr-creation-ready before receipt verification runs, else blocked.
25
- Receipt - preflight passed: the SHA-256 receipt is verified in five ordered checks
26
- (Section below). The first failing check blocks.
26
+ Docs-only - issue #901: when the preflight fails, gh pr create proceeds to receipt
27
+ verification only when every condition holds: no checkpoint file exists
28
+ beneath the resolved worktree; the command carries exactly one explicit
29
+ --base <branch> and no base or repository override (issue #927: no
30
+ single-dash token whose letters include B or R, such as -B, -R, or -dB; no
31
+ --repo or --repo= token; no inline GH_REPO= prefix); refs/remotes/origin/<branch>
32
+ resolves to a commit; git diff --name-only -z --no-renames <commit>...HEAD
33
+ exits 0, ends its non-empty output with NUL, and lists at least one path; and
34
+ every listed path starts with docs/ (ordinal, case-sensitive). Otherwise the
35
+ deny keeps ORCHESTRATOR_STATE_PREFLIGHT_FAILED and appends one sub-code:
36
+ DOCS_ONLY_EXEMPTION_NOT_CREATE - gh pr edit is never exempt.
37
+ DOCS_ONLY_EXEMPTION_CHECKPOINT_PRESENT - a checkpoint file exists.
38
+ DOCS_ONLY_EXEMPTION_BASE_UNRESOLVED - no single explicit --base, a base or
39
+ repository override is present, or
40
+ the base does not resolve on origin.
41
+ DOCS_ONLY_EXEMPTION_DIFF_FAILED - the diff exits non-zero, throws, or
42
+ returns output not ending with NUL.
43
+ DOCS_ONLY_EXEMPTION_EMPTY_DIFF - the diff lists no path.
44
+ DOCS_ONLY_EXEMPTION_NON_DOCS_PATH - a listed path is outside docs/.
45
+ The exemption never applies under epic scope.
46
+ Receipt - preflight passed or docs-only exemption applied: the SHA-256 receipt is
47
+ verified in the ordered checks (Section below). The first failing check blocks.
27
48
 
28
49
  Receipt verification decision order on the --body-file-with-context path:
29
50
  PR_BODY_PATH_NONCANONICAL -> PR_AUTHOR_RECEIPT_MISSING -> PR_AUTHOR_RECEIPT_NUMBER_MISMATCH
30
51
  -> PR_AUTHOR_RECEIPT_HASH_MISMATCH -> PR_AUTHOR_RECEIPT_STALE -> allow.
31
52
 
53
+ Issue #850: the context summary, the body, and the receipt are read beneath the worktree
54
+ the call resolves to (the item worktree, or the epic checkpoint's worktree under epic
55
+ scope), not beneath the process directory, so a gate running in the session worktree
56
+ validates the artifacts of the item it gates.
57
+
32
58
  .NOTES
33
- Compatible with PowerShell 7+. No external module dependencies.
59
+ Compatible with PowerShell 7+. Dependencies are in-repository only: hook-dependency-guard.ps1,
60
+ the HookPayload, OrchestratorState, and OrchestratorStateUnconditional modules, and the
61
+ epic-base-branch and helpers siblings; the helpers load the command parsers, the
62
+ worktree-resolution modules, and the artifact-root and docs-only siblings.
63
+ No PowerShell Gallery module is required.
64
+ The docs-only exemption runs the git executable at call time (issue #901).
34
65
 
35
66
  Enforcement strength: the SHA-256 receipt is a policy-level integrity check that binds the
36
67
  PR body bytes to the receipt the pr-author agent wrote. It is not a cryptographic or security
@@ -42,28 +73,34 @@
42
73
  #>
43
74
  [CmdletBinding()]
44
75
  param()
76
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
45
77
 
46
78
 
47
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
79
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
48
80
  $script:PrContextArtifactPath = 'artifacts/pr_context.summary.txt'
49
81
  # Null until the resolution step assigns the absolute path of the resolved worktree's
50
82
  # checkpoint (issue #673); a relative default here was the process-directory binding.
51
83
  $script:OrchestratorStateCheckpointPath = $null
52
84
 
53
- Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorState.psm1') -Force
85
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorState.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorState.psm1' -ErrorRecord $_ }
54
86
 
55
87
  function Get-PrContextArtifactExistence {
56
88
  <#
57
89
  .SYNOPSIS
58
90
  Wrapper around Test-Path for the PR context artifact. Tests mock this function.
91
+ .PARAMETER Path
92
+ The absolute path of artifacts/pr_context.summary.txt beneath the resolved worktree.
59
93
  .OUTPUTS
60
94
  System.Boolean
61
95
  #>
62
96
  [CmdletBinding()]
63
97
  [OutputType([bool])]
64
- param()
98
+ param(
99
+ [Parameter(Mandatory)]
100
+ [string] $Path
101
+ )
65
102
 
66
- return [bool](Test-Path -LiteralPath $script:PrContextArtifactPath)
103
+ return [bool](Test-Path -LiteralPath $Path)
67
104
  }
68
105
 
69
106
  function Get-PrBodyFileBytes {
@@ -75,7 +112,8 @@ function Get-PrBodyFileBytes {
75
112
  This is the injectable boundary for body-file bytes in tests; no test writes the body file
76
113
  to disk. The bytes are hashed inline by the receipt verification function.
77
114
  .PARAMETER BodyFilePath
78
- The relative path to the PR body file (for example artifacts/pr_body_5.md).
115
+ The absolute path to the PR body file beneath the resolved worktree (for example
116
+ <worktree>/artifacts/pr_body_5.md).
79
117
  .OUTPUTS
80
118
  System.Byte[] or $null
81
119
  #>
@@ -103,7 +141,8 @@ function Get-PrAuthorReceiptContent {
103
141
  or $null when the receipt file is absent. This is the injectable boundary for receipt
104
142
  content in tests; no test writes the receipt file to disk.
105
143
  .PARAMETER ReceiptFilePath
106
- The relative path to the receipt file (for example artifacts/pr_body_5.receipt.json).
144
+ The absolute path to the receipt file beneath the resolved worktree (for example
145
+ <worktree>/artifacts/pr_body_5.receipt.json).
107
146
  .OUTPUTS
108
147
  System.String or $null
109
148
  #>
@@ -129,25 +168,32 @@ function Get-PrContextSummaryLastWriteUtc {
129
168
  Returns the LastWriteTimeUtc of artifacts/pr_context.summary.txt, or $null when the file is
130
169
  absent. The staleness check compares the receipt's created_at against this value; both are
131
170
  artifact metadata, so no wall-clock seam is required.
171
+ .PARAMETER Path
172
+ The absolute path of artifacts/pr_context.summary.txt beneath the resolved worktree.
132
173
  .OUTPUTS
133
174
  System.DateTime or $null
134
175
  #>
135
176
  [CmdletBinding()]
136
177
  [OutputType([datetime])]
137
- param()
178
+ param(
179
+ [Parameter(Mandatory)]
180
+ [string] $Path
181
+ )
138
182
 
139
- if (-not (Test-Path -LiteralPath $script:PrContextArtifactPath)) {
183
+ if (-not (Test-Path -LiteralPath $Path)) {
140
184
  return $null
141
185
  }
142
186
 
143
- return (Get-Item -LiteralPath $script:PrContextArtifactPath).LastWriteTimeUtc
187
+ return (Get-Item -LiteralPath $Path).LastWriteTimeUtc
144
188
  }
145
189
 
146
- . (Join-Path $PSScriptRoot 'enforce-pr-author-skill.epic-base-branch.ps1')
190
+ try { . (Join-Path $PSScriptRoot 'enforce-pr-author-skill.epic-base-branch.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-pr-author-skill.epic-base-branch.ps1' -ErrorRecord $_ }
147
191
 
148
192
  # Dot-source the receipt-verification and bypass-reason helpers. Guarded so dot-sourcing this
149
193
  # hook in tests loads the helpers too (issue #501 headroom split).
150
- . (Join-Path $PSScriptRoot 'enforce-pr-author-skill-helpers.ps1')
194
+ try { . (Join-Path $PSScriptRoot 'enforce-pr-author-skill-helpers.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-pr-author-skill-helpers.ps1' -ErrorRecord $_ }
195
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorStateUnconditional.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorStateUnconditional.psm1' -ErrorRecord $_ }
196
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorState.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorState.psm1' -ErrorRecord $_ }
151
197
 
152
198
  function Invoke-PrAuthorSkillDecision {
153
199
  <#
@@ -168,6 +214,8 @@ function Invoke-PrAuthorSkillDecision {
168
214
  [AllowEmptyString()]
169
215
  [string] $ToolInputRaw
170
216
  )
217
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PR_AUTHOR_SKILL_BLOCKED:'
218
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
171
219
 
172
220
  $payload = Resolve-ClaudeHookToolInput -Raw $ToolInputRaw
173
221
  if (-not $payload.IsValid) {
@@ -182,8 +230,7 @@ function Invoke-PrAuthorSkillDecision {
182
230
  return Get-PrAuthorSkillAllowDecision
183
231
  }
184
232
 
185
- $contextExists = Get-PrContextArtifactExistence
186
- $reason = Get-PrAuthorBypassReason -CommandText $commandText -ContextExists $contextExists
233
+ $reason = Get-PrAuthorBypassReason -CommandText $commandText
187
234
 
188
235
  if ($reason) {
189
236
  return Get-PrAuthorSkillBlockDecision -Reason $reason
@@ -242,8 +289,6 @@ function Test-PrAuthorBypassRequired {
242
289
  Return $true when a Bash command requires the pr-author skill to run first.
243
290
  .PARAMETER CommandText
244
291
  The Bash command text extracted from the envelope's tool_input.
245
- .PARAMETER ContextExists
246
- Whether artifacts/pr_context.summary.txt currently exists on disk.
247
292
  .OUTPUTS
248
293
  System.Boolean
249
294
  #>
@@ -251,13 +296,10 @@ function Test-PrAuthorBypassRequired {
251
296
  [OutputType([bool])]
252
297
  param(
253
298
  [Parameter(Mandatory)]
254
- [string] $CommandText,
255
-
256
- [Parameter(Mandatory)]
257
- [bool] $ContextExists
299
+ [string] $CommandText
258
300
  )
259
301
 
260
- return ($null -ne (Get-PrAuthorBypassReason -CommandText $CommandText -ContextExists $ContextExists))
302
+ return ($null -ne (Get-PrAuthorBypassReason -CommandText $CommandText))
261
303
  }
262
304
 
263
305
  function Invoke-PrAuthorSkillEntryPoint {
@@ -302,6 +344,9 @@ function Invoke-PrAuthorSkillEntryPoint {
302
344
  if ($MyInvocation.InvocationName -eq '.') {
303
345
  return
304
346
  }
347
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PR_AUTHOR_SKILL_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
348
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PR_AUTHOR_SKILL_BLOCKED:'
349
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
305
350
 
306
351
  # The entry point returns its [int] exit code as the last pipeline element and the
307
352
  # decision JSON before it. `exit (<call>)` would capture BOTH into the exit
@@ -10,13 +10,16 @@
10
10
  cap as target resolution grows.
11
11
 
12
12
  The file declares no file-scope parameter block, no requires directive, and no
13
- entrypoint. Apart from its function declarations,
14
- its only file-scope statement is the resolution-module import
15
- that follows this block, which brings in issue #669's path normalisation and
16
- ambiguity reason code. That import is deliberately unguarded, for the same
17
- reason the parent hook's is: a resolution module that cannot be loaded is
18
- itself the target-not-resolvable state, so letting the failure surface fails
19
- the gate closed rather than degrading it to a permissive path.
13
+ entrypoint. Apart from its function declarations, its file-scope statements are
14
+ the resolution-module import that follows this block, which brings in issue
15
+ #669's path normalisation and ambiguity reason code, and the guarded dot-source
16
+ of the pure shared resolver feature-folder-resolution.ps1 (issue #565), which
17
+ owns the single work-mode parser. The module import is deliberately unguarded,
18
+ for the same reason the parent hook's is: a resolution module that cannot be
19
+ loaded is itself the target-not-resolvable state, so letting the failure surface
20
+ fails the gate closed rather than degrading it to a permissive path. A failed
21
+ dot-source of the shared resolver makes Resolve-PrdFeatureWorkMode return $null,
22
+ which the planner gate's deny-on-unknown branch treats as an unreadable marker.
20
23
  .NOTES
21
24
  Compatible with PowerShell 7+. Read-only resolution logic.
22
25
  #>
@@ -24,7 +27,17 @@
24
27
  # Issue #669 owns path normalisation and the ambiguity reason code. The import is
25
28
  # unguarded for the same reason the parent's is: a resolution module that cannot be
26
29
  # loaded is itself the target-not-resolvable state.
27
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeResolution.psm1') -Force
30
+ Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeResolution.psm1') -Force -ErrorAction Stop
31
+
32
+ # Shared work-mode parser (issue #565). Guarded so a failed dot-source fails closed
33
+ # through the planner gate's deny-on-unknown branch.
34
+ $script:PrdFeatureFolderResolutionImportFailure = $null
35
+ try {
36
+ . (Join-Path $PSScriptRoot 'feature-folder-resolution.ps1')
37
+ }
38
+ catch {
39
+ $script:PrdFeatureFolderResolutionImportFailure = 'feature-folder-resolution.ps1'
40
+ }
28
41
 
29
42
  function Resolve-PrdFeatureWorkMode {
30
43
  <#
@@ -36,7 +49,10 @@ function Resolve-PrdFeatureWorkMode {
36
49
  Recognizes minor-audit, full-feature, full-bug, and the legacy full
37
50
  marker (normalized to full-feature), mirroring the regex convention
38
51
  used by scripts/dev_tools/prompt_mode_contract.py so both runtimes
39
- agree on what counts as a valid marker line.
52
+ agree on what counts as a valid marker line. Delegates to the single
53
+ shared parser, Resolve-FeatureFolderWorkMode (issue #565), with an empty
54
+ -UnresolvedMode so an unresolved marker still returns $null here; a
55
+ failed dot-source of the shared resolver also returns $null.
40
56
  #>
41
57
  [CmdletBinding()]
42
58
  [OutputType([string])]
@@ -45,20 +61,15 @@ function Resolve-PrdFeatureWorkMode {
45
61
  [string] $IssueContent
46
62
  )
47
63
 
48
- if ([string]::IsNullOrWhiteSpace($IssueContent)) {
64
+ if ($script:PrdFeatureFolderResolutionImportFailure) {
49
65
  return $null
50
66
  }
51
67
 
52
- $match = [regex]::Match($IssueContent, '(?im)^-\s*Work Mode:\s*(minor-audit|full-feature|full-bug|full)\s*$')
53
- if (-not $match.Success) {
68
+ $mode = Resolve-FeatureFolderWorkMode -IssueContent $IssueContent -UnresolvedMode ''
69
+ if (-not $mode) {
54
70
  return $null
55
71
  }
56
-
57
- $rawMode = $match.Groups[1].Value
58
- if ($rawMode -eq 'full') {
59
- return 'full-feature'
60
- }
61
- return $rawMode
72
+ return $mode
62
73
  }
63
74
 
64
75
  function Get-PrdFeatureRequiredFile {
@@ -98,9 +98,10 @@
98
98
  #>
99
99
  [CmdletBinding()]
100
100
  param()
101
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
101
102
 
102
103
 
103
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
104
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
104
105
  # Issue #669 owns worktree location and path normalisation; issue #673 owns the
105
106
  # portable-identity resolution this gate now selects a worktree with. Both imports are
106
107
  # unguarded on purpose: a resolution module that cannot be loaded is itself the
@@ -108,9 +109,9 @@ Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -
108
109
  # a permissive path. Both are required rather than one: the absolute-path join the probe
109
110
  # step below calls is exported only by the first, because a module whose exports are pinned
110
111
  # by an explicit list does not re-export a sibling's functions to its own importer.
111
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeTargetResolution.psm1') -Force
112
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force
113
- . (Join-Path $PSScriptRoot 'enforce-prd-feature-before-planner-helpers.ps1')
112
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeTargetResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeTargetResolution.psm1' -ErrorRecord $_ }
113
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeItemResolution.psm1' -ErrorRecord $_ }
114
+ try { . (Join-Path $PSScriptRoot 'enforce-prd-feature-before-planner-helpers.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-prd-feature-before-planner-helpers.ps1' -ErrorRecord $_ }
114
115
  function Get-PrdFeatureFileExistence {
115
116
  <#
116
117
  .SYNOPSIS
@@ -316,6 +317,8 @@ function Invoke-PrdFeatureBeforePlannerDecision {
316
317
  [AllowNull()]
317
318
  [object] $ResolvedTarget
318
319
  )
320
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PRD_FEATURE_BLOCKED:'
321
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
319
322
 
320
323
  $envelope = Resolve-ClaudeHookToolInput -Raw $ToolInputRaw
321
324
  if (-not $envelope.IsValid) {
@@ -469,6 +472,9 @@ function Invoke-PrdFeatureBeforePlannerDecision {
469
472
  if ($MyInvocation.InvocationName -eq '.') {
470
473
  return
471
474
  }
475
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PRD_FEATURE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
476
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PRD_FEATURE_BLOCKED:'
477
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
472
478
 
473
479
  $decision = Invoke-PrdFeatureBeforePlannerDecision -ToolInputRaw (Read-ClaudeHookRawPayload)
474
480
 
@@ -28,15 +28,16 @@
28
28
  #>
29
29
  [CmdletBinding()]
30
30
  param()
31
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
31
32
 
32
33
 
33
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
34
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
34
35
 
35
36
  # Shared command-line parser (issue #545). Every forbidden-token scan and both `gh`
36
37
  # expressions below run against each segment's clause-ordered scan text, and the
37
38
  # structural matcher reaches the relocating `gh` spellings adjacency cannot.
38
- . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
39
- . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
39
+ try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
40
+ try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
40
41
 
41
42
  $script:PromotionMcpOnlyBlockedReason = 'PROMOTION_MCP_ONLY_BLOCKED: Direct Bash promotion-script execution is not allowed in agent sessions. Use the drm-copilot MCP promotion tools instead.'
42
43
 
@@ -112,9 +113,12 @@ function Get-PromotionBypassReason {
112
113
  }
113
114
 
114
115
  # `gh issue create` and `gh issue new` are direct bypasses of the MCP
115
- # promotion path. Tolerate any flags after the subcommand.
116
+ # promotion path. Tolerate any flags after the subcommand. The adjacency
117
+ # expression reads the masked text, so a quoted mention is not a match; wrapper
118
+ # payloads and substitution bodies are covered by the structural check below
119
+ # (issue #824).
116
120
  foreach ($segment in $segments) {
117
- if ($segment.ScanText -match '(?i)\bgh\s+issue\s+(?:create|new)\b') {
121
+ if ($segment.MaskedText -match '(?i)\bgh\s+issue\s+(?:create|new)\b') {
118
122
  return (Get-PromotionMcpOnlyGhIssueBlockedReason)
119
123
  }
120
124
  }
@@ -227,6 +231,8 @@ function Invoke-PromotionMcpOnlyDecision {
227
231
  param(
228
232
  [string] $ToolInputRaw
229
233
  )
234
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PROMOTION_MCP_ONLY_BLOCKED:'
235
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
230
236
 
231
237
  $payload = Resolve-ClaudeHookToolInput -Raw $ToolInputRaw
232
238
  if (-not $payload.IsValid) {
@@ -291,6 +297,9 @@ function Invoke-PromotionMcpOnlyEntryPoint {
291
297
  if ($MyInvocation.InvocationName -eq '.') {
292
298
  return
293
299
  }
300
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PROMOTION_MCP_ONLY_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
301
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PROMOTION_MCP_ONLY_BLOCKED:'
302
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
294
303
 
295
304
  # The entry point returns its [int] exit code as the last pipeline element and the
296
305
  # decision JSON before it. `exit (<call>)` would capture BOTH into the exit
@@ -57,10 +57,11 @@
57
57
  #>
58
58
  [CmdletBinding()]
59
59
  param()
60
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
60
61
 
61
62
 
62
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
63
- . (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1')
63
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
64
+ try { . (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-batch-budget-route.ps1' -ErrorRecord $_ }
64
65
 
65
66
  function Test-PythonBatchBudgetPathInRoot {
66
67
  <#
@@ -280,6 +281,8 @@ function Invoke-PythonBatchBudgetDecision {
280
281
  [AllowEmptyString()]
281
282
  [string] $ObservedRoute = ''
282
283
  )
284
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PYTHON_LARGE_PATH_REQUIRED:'
285
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
283
286
 
284
287
  $normalized = $FilePath -replace '\\', '/'
285
288
  if ($normalized -notmatch '\.py$') {
@@ -477,6 +480,9 @@ function Invoke-PythonBatchBudgetEntryPoint {
477
480
  if ($MyInvocation.InvocationName -eq '.') {
478
481
  return
479
482
  }
483
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PYTHON_LARGE_PATH_REQUIRED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
484
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PYTHON_LARGE_PATH_REQUIRED:'
485
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
480
486
 
481
487
  # The entry point returns its [int] exit code as the last pipeline element and the
482
488
  # decision JSON before it. `exit (<call>)` would capture BOTH into the exit