@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
@@ -1,32 +1,59 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Pre-tool-use hook that blocks writes to a feature folder's plan.md when issue.md,
4
- spec.md, or user-story.md are not yet present in that same folder.
3
+ Pre-tool-use hook that blocks writes to a feature folder's plan file until the
4
+ prerequisite documents its persisted work mode requires exist in that same folder.
5
5
 
6
6
  .DESCRIPTION
7
7
  Invoked by the Claude Code PreToolUse hook on Write or Edit operations. Acquires
8
8
  the hook payload through the shared reader and reads file_path from the envelope's
9
- nested tool_input. When the
10
- target file_path matches a feature-folder plan.md path under
11
- docs/features/(active|archive)/<folder>/plan.md, the script verifies that
12
- each of issue.md, spec.md, and user-story.md exists in the same folder.
13
-
14
- If any of the three sibling files is missing, the script emits a PreToolUse
15
- JSON response with hookSpecificOutput.permissionDecision='deny' and exits 0 so
16
- Claude Code surfaces the reason. All other paths pass through with
9
+ nested tool_input. The gate applies to a feature-folder plan file under
10
+ docs/features/(active|archive)/<folder>/: a literal plan.md or a timestamped
11
+ plan.<yyyy-MM-ddTHH-mm>.md (issue #568). Other paths pass through with
17
12
  permissionDecision='allow'.
18
13
 
19
- Filesystem reads go through Get-FeatureFolderFileExistence so tests can
20
- inject a fake without touching disk.
14
+ For a plan file, the script reads the folder's issue.md through
15
+ Get-FeatureFolderIssueContent, resolves the persisted '- Work Mode:' marker with the
16
+ shared Resolve-FeatureFolderWorkMode, and takes the required set from the shared
17
+ Get-FeatureFolderPlanPrerequisite:
18
+ - minor-audit -> issue.md
19
+ - full-bug -> issue.md, spec.md
20
+ - full-feature and legacy full -> issue.md, spec.md, user-story.md
21
+ A missing, empty, malformed, or unrecognized marker, or an unreadable issue.md,
22
+ fails closed to the full-feature set. Because issue.md is in every set, an absent
23
+ issue.md always denies.
24
+
25
+ If any required file is missing, the script emits a PreToolUse JSON response with
26
+ hookSpecificOutput.permissionDecision='deny' whose reason names the plan file, the
27
+ resolved work mode, and the missing files, and exits 0 so Claude Code surfaces it.
28
+
29
+ Filesystem reads go through Get-FeatureFolderFileExistence and
30
+ Get-FeatureFolderIssueContent so tests can inject fakes without touching disk.
21
31
 
22
32
  .NOTES
23
- Compatible with PowerShell 7+. Read-only validation gate; no state mutation.
33
+ Compatible with PowerShell 7+. Read-only validation gate; no state mutation. The pure
34
+ sibling feature-folder-resolution.ps1 (issue #565) is dot-sourced inside a guard: when
35
+ it cannot be loaded, every plan-file write denies and every other path stays allowed.
24
36
  #>
25
37
  [CmdletBinding()]
26
38
  param()
39
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
40
+
41
+
42
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
43
+
44
+ # Shared work-mode parser and prerequisite map (issue #565). Guarded so a failed
45
+ # dot-source denies plan writes rather than failing open.
46
+ $script:FeatureFolderOrderResolutionImportFailure = $null
47
+ try {
48
+ . (Join-Path $PSScriptRoot 'feature-folder-resolution.ps1')
49
+ }
50
+ catch {
51
+ $script:FeatureFolderOrderResolutionImportFailure = 'feature-folder-resolution.ps1'
52
+ }
27
53
 
54
+ # The plan leaf a gated path ends in: plan.md or plan.<yyyy-MM-ddTHH-mm>.md (issue #568).
55
+ $script:FeaturePlanLeafPattern = '/plan(\.\d{4}-\d{2}-\d{2}T\d{2}-\d{2})?\.md$'
28
56
 
29
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
30
57
  function Get-FeatureFolderFileExistence {
31
58
  <#
32
59
  .SYNOPSIS
@@ -44,25 +71,57 @@ function Get-FeatureFolderFileExistence {
44
71
  return [bool](Test-Path -LiteralPath $Path -PathType Leaf)
45
72
  }
46
73
 
74
+ function Get-FeatureFolderIssueContent {
75
+ <#
76
+ .SYNOPSIS
77
+ Reads a feature folder's issue.md, or returns $null when the file is absent or
78
+ cannot be read. Tests mock this seam; a $null result fails closed to the
79
+ full-feature prerequisite set.
80
+ .PARAMETER FeatureFolder
81
+ Normalized (forward-slash) feature-folder path.
82
+ #>
83
+ [CmdletBinding()]
84
+ [OutputType([string])]
85
+ param(
86
+ [Parameter(Mandatory)]
87
+ [string] $FeatureFolder
88
+ )
89
+
90
+ $issuePath = "$FeatureFolder/issue.md"
91
+ if (-not (Test-Path -LiteralPath $issuePath -PathType Leaf)) {
92
+ return $null
93
+ }
94
+
95
+ try {
96
+ return Get-Content -LiteralPath $issuePath -Raw -ErrorAction Stop
97
+ }
98
+ catch {
99
+ return $null
100
+ }
101
+ }
102
+
47
103
  function Get-FeatureFolderMissingFile {
48
104
  <#
49
105
  .SYNOPSIS
50
- Returns the list of required sibling files missing alongside plan.md.
106
+ Returns the list of required sibling files missing alongside the plan file.
51
107
  .PARAMETER PlanFilePath
52
- Normalized (forward-slash) path to the plan.md target.
108
+ Normalized (forward-slash) path to the plan.md or plan.<timestamp>.md target.
109
+ .PARAMETER RequiredFile
110
+ The prerequisite file names to probe. Defaults to the full-feature set.
53
111
  #>
54
112
  [CmdletBinding()]
55
113
  [OutputType([string[]])]
56
114
  param(
57
115
  [Parameter(Mandatory)]
58
- [string] $PlanFilePath
116
+ [string] $PlanFilePath,
117
+
118
+ [string[]] $RequiredFile = @('issue.md', 'spec.md', 'user-story.md')
59
119
  )
60
120
 
61
- $folder = $PlanFilePath -replace '/plan\.md$', ''
62
- $required = @('issue.md', 'spec.md', 'user-story.md')
121
+ $folder = $PlanFilePath -replace $script:FeaturePlanLeafPattern, ''
63
122
  [System.Collections.Generic.List[string]] $missing = [System.Collections.Generic.List[string]]::new()
64
123
 
65
- foreach ($name in $required) {
124
+ foreach ($name in $RequiredFile) {
66
125
  $siblingPath = "$folder/$name"
67
126
  if (-not (Get-FeatureFolderFileExistence -Path $siblingPath)) {
68
127
  $missing.Add($name)
@@ -75,7 +134,9 @@ function Get-FeatureFolderMissingFile {
75
134
  function Test-IsFeaturePlanPath {
76
135
  <#
77
136
  .SYNOPSIS
78
- Returns $true if the normalized path targets a feature-folder plan.md.
137
+ Returns $true if the normalized path targets a feature-folder plan.md or a
138
+ timestamped plan.<yyyy-MM-ddTHH-mm>.md directly inside an active or archive
139
+ feature folder.
79
140
  #>
80
141
  [CmdletBinding()]
81
142
  [OutputType([bool])]
@@ -84,7 +145,30 @@ function Test-IsFeaturePlanPath {
84
145
  [string] $NormalizedPath
85
146
  )
86
147
 
87
- return $NormalizedPath -match '(^|/)docs/features/(active|archive)/[^/]+/plan\.md$'
148
+ return $NormalizedPath -match '(^|/)docs/features/(active|archive)/[^/]+/plan(\.\d{4}-\d{2}-\d{2}T\d{2}-\d{2})?\.md$'
149
+ }
150
+
151
+ function Get-FeatureFolderOrderDenyDecision {
152
+ <#
153
+ .SYNOPSIS
154
+ Builds the PreToolUse deny decision carrying the given reason.
155
+ .PARAMETER Reason
156
+ The deny reason, beginning with FEATURE_FOLDER_ORDER_BLOCKED:.
157
+ #>
158
+ [CmdletBinding()]
159
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
160
+ param(
161
+ [Parameter(Mandatory)]
162
+ [string] $Reason
163
+ )
164
+
165
+ return [ordered]@{
166
+ hookSpecificOutput = [ordered]@{
167
+ hookEventName = 'PreToolUse'
168
+ permissionDecision = 'deny'
169
+ permissionDecisionReason = $Reason
170
+ }
171
+ }
88
172
  }
89
173
 
90
174
  function Invoke-FeatureFolderOrderDecision {
@@ -103,18 +187,15 @@ function Invoke-FeatureFolderOrderDecision {
103
187
  [AllowEmptyString()]
104
188
  [string] $ToolInputRaw
105
189
  )
190
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FEATURE_FOLDER_ORDER_BLOCKED:'
191
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
106
192
 
107
193
  $payload = Resolve-ClaudeHookToolInput -Raw $ToolInputRaw
108
194
  if (-not $payload.IsValid) {
109
- return [ordered]@{
110
- hookSpecificOutput = [ordered]@{
111
- hookEventName = 'PreToolUse'
112
- permissionDecision = 'deny'
113
- permissionDecisionReason = 'FEATURE_FOLDER_ORDER_BLOCKED: payload anomaly - ' +
114
- (Get-ClaudeHookPayloadAnomalyReason -Anomaly $payload.Anomaly) +
115
- '. The gate fails closed on an envelope it cannot read.'
116
- }
117
- }
195
+ return Get-FeatureFolderOrderDenyDecision -Reason (
196
+ 'FEATURE_FOLDER_ORDER_BLOCKED: payload anomaly - ' +
197
+ (Get-ClaudeHookPayloadAnomalyReason -Anomaly $payload.Anomaly) +
198
+ '. The gate fails closed on an envelope it cannot read.')
118
199
  }
119
200
 
120
201
  $filePath = Get-ClaudeHookToolInputString -ToolInput $payload.Value -Name 'file_path'
@@ -128,19 +209,25 @@ function Invoke-FeatureFolderOrderDecision {
128
209
  return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
129
210
  }
130
211
 
131
- $missing = Get-FeatureFolderMissingFile -PlanFilePath $normalized
212
+ $planLeaf = ($normalized -split '/')[-1]
213
+ if ($script:FeatureFolderOrderResolutionImportFailure) {
214
+ return Get-FeatureFolderOrderDenyDecision -Reason (
215
+ "FEATURE_FOLDER_ORDER_BLOCKED: the shared resolver '$($script:FeatureFolderOrderResolutionImportFailure)' " +
216
+ "failed to load, so the prerequisite documents for $planLeaf cannot be determined; the gate fails closed.")
217
+ }
218
+
219
+ $folder = $normalized -replace $script:FeaturePlanLeafPattern, ''
220
+ $workMode = Resolve-FeatureFolderWorkMode -IssueContent (Get-FeatureFolderIssueContent -FeatureFolder $folder)
221
+ $required = @(Get-FeatureFolderPlanPrerequisite -WorkMode $workMode)
222
+ $missing = @(Get-FeatureFolderMissingFile -PlanFilePath $normalized -RequiredFile $required)
132
223
  if ($missing.Count -eq 0) {
133
224
  return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
134
225
  }
135
226
 
136
227
  $list = ($missing -join ', ')
137
- return [ordered]@{
138
- hookSpecificOutput = [ordered]@{
139
- hookEventName = 'PreToolUse'
140
- permissionDecision = 'deny'
141
- permissionDecisionReason = "FEATURE_FOLDER_ORDER_BLOCKED: cannot write plan.md before producing prerequisite documents. Missing in feature folder: $list. Invoke the prd-feature subagent to generate the missing file(s) before authoring plan.md."
142
- }
143
- }
228
+ return Get-FeatureFolderOrderDenyDecision -Reason (
229
+ "FEATURE_FOLDER_ORDER_BLOCKED: cannot write $planLeaf before producing prerequisite documents for work mode '$workMode'. " +
230
+ "Missing in feature folder: $list. Invoke the prd-feature subagent to generate the missing file(s) before authoring the plan.")
144
231
  }
145
232
 
146
233
  function Invoke-FeatureFolderOrderEntryPoint {
@@ -185,6 +272,9 @@ function Invoke-FeatureFolderOrderEntryPoint {
185
272
  if ($MyInvocation.InvocationName -eq '.') {
186
273
  return
187
274
  }
275
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('FEATURE_FOLDER_ORDER_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
276
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FEATURE_FOLDER_ORDER_BLOCKED:'
277
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
188
278
 
189
279
  # The entry point returns its [int] exit code as the last pipeline element and the
190
280
  # decision JSON before it. `exit (<call>)` would capture BOTH into the exit
@@ -56,10 +56,11 @@
56
56
  #>
57
57
  [CmdletBinding()]
58
58
  param()
59
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
59
60
 
60
61
  Set-StrictMode -Version Latest
61
62
 
62
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
63
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
63
64
 
64
65
  $script:MermaidModulePath = Join-Path -Path $PSScriptRoot -ChildPath '../lib/mermaid/MermaidValidation.psm1'
65
66
  $script:MermaidSkillPointer = 'See .claude/skills/mermaid-diagram/SKILL.md.'
@@ -303,6 +304,8 @@ function Invoke-MermaidValidationDecision {
303
304
  [AllowNull()]
304
305
  [string] $ToolInputRaw
305
306
  )
307
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MERMAID_VALIDATION_BLOCKED:'
308
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
306
309
 
307
310
  # Envelope-level anomaly: fail closed. See the ENVELOPE VERSUS CONTENT note in
308
311
  # this file's header before changing this back to a silent allow.
@@ -394,6 +397,9 @@ function Invoke-MermaidValidationEntryPoint {
394
397
  if ($MyInvocation.InvocationName -eq '.') {
395
398
  return
396
399
  }
400
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('MERMAID_VALIDATION_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
401
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MERMAID_VALIDATION_BLOCKED:'
402
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
397
403
 
398
404
  Invoke-MermaidValidationEntryPoint -ToolInputRaw (Read-ClaudeHookRawPayload)
399
405
 
@@ -45,14 +45,15 @@
45
45
  #>
46
46
  [CmdletBinding()]
47
47
  param()
48
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
48
49
 
49
50
 
50
- Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force
51
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
51
52
  # Portable-identity resolution (issue #673). Unguarded and fail-closed on purpose: a gate
52
53
  # that cannot load its resolver must not degrade into the cwd-relative read it replaces.
53
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop
54
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeItemResolution.psm1' -ErrorRecord $_ }
54
55
  # Epic scope (issue #663): a delegation for the epic integration branch is gated against the epic checkpoint.
55
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeResolution.psm1') -Force -ErrorAction Stop
56
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'EpicScopeResolution.psm1' -ErrorRecord $_ }
56
57
  function Get-ModelRoutingCheckpoint {
57
58
  <#
58
59
  .SYNOPSIS
@@ -207,6 +208,8 @@ function Invoke-ModelRoutingReceiptDecision {
207
208
  param(
208
209
  [string] $ToolInputRaw
209
210
  )
211
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MODEL_ROUTING_RECEIPT_BLOCKED:'
212
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
210
213
 
211
214
  $allow = [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
212
215
 
@@ -287,6 +290,9 @@ function Invoke-ModelRoutingReceiptDecision {
287
290
  if ($MyInvocation.InvocationName -eq '.') {
288
291
  return
289
292
  }
293
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('MODEL_ROUTING_RECEIPT_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
294
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MODEL_ROUTING_RECEIPT_BLOCKED:'
295
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
290
296
 
291
297
  $decision = Invoke-ModelRoutingReceiptDecision -ToolInputRaw (Read-ClaudeHookRawPayload)
292
298
 
@@ -6,9 +6,9 @@
6
6
  Dot-sourced by enforce-orchestration-preimplementation-gate.ps1. Holds four groups of
7
7
  functions:
8
8
 
9
- - The import guard for the worktree-resolution modules (issue #690). A failed import
10
- is recorded in $script:OrchestrationGateResolutionImportFailure, and
11
- Get-OrchestrationGateImportFailureDecision turns that record into a deny, so a
9
+ - The import guards for the worktree-resolution modules (issue #690). A failed import
10
+ is recorded in $script:HookDependencyFailures, and the gate's call to
11
+ Get-HookDependencyFailureDecision turns that record into a deny, so a
12
12
  missing module cannot make the gate exit non-zero and fail open.
13
13
  - The three checkpoint read seams, Get-CheckpointContent, Get-EpicCheckpointContent,
14
14
  and Get-ParallelCheckpointContent. Each takes a mandatory absolute path, so no
@@ -31,44 +31,22 @@
31
31
  .NOTES
32
32
  PowerShell 7+. Depends on functions the gate defines or dot-sources before any call:
33
33
  Split-OrchestrationCommandLine and ConvertTo-OrchestrationCommandToken (helpers file),
34
- Get-OrchestrationDelegationCheckpointPath (modes file), and the gate's allow and block
35
- decision constructors. Imports WorktreeItemResolution.psm1 and WorktreeRunResolution.psm1
36
- before EpicScopeResolution.psm1, so the nested import inside EpicScopeResolution reuses
37
- the same module instance. Mirrored byte-identically under
34
+ Get-OrchestrationDelegationCheckpointPath (modes file), the gate's allow and block
35
+ decision constructors, and, through the targets file this file dot-sources (issue #738),
36
+ Read-CommandLineSegment, Get-CommandLineGlobalOption, and Get-CommandLineInvocation
37
+ (loaded by the gate's dot-source of hook-command-invocation.ps1). Imports
38
+ WorktreeItemResolution.psm1 and WorktreeRunResolution.psm1 before
39
+ EpicScopeResolution.psm1, so the nested import inside EpicScopeResolution reuses the
40
+ same module instance. Mirrored byte-identically under
38
41
  extensions/drm-copilot/resources/claude-customizations/.
39
42
  #>
40
43
 
41
- # Import guard (issue #690). Each worktree-resolution import is attempted in order; the
42
- # first failure is recorded by file name and the decision function denies on it.
43
- $script:OrchestrationGateResolutionImportFailure = $null
44
- foreach ($resolutionModule in @('WorktreeItemResolution.psm1', 'WorktreeRunResolution.psm1', 'EpicScopeResolution.psm1')) {
45
- try {
46
- Import-Module (Join-Path $PSScriptRoot "../lib/worktree-resolution/$resolutionModule") -Force -ErrorAction Stop
47
- }
48
- catch {
49
- if (-not $script:OrchestrationGateResolutionImportFailure) { $script:OrchestrationGateResolutionImportFailure = $resolutionModule }
50
- }
51
- }
52
- Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeReadiness.psm1') -Force -ErrorAction Stop
53
-
54
- function Get-OrchestrationGateImportFailureDecision {
55
- <#
56
- .SYNOPSIS
57
- Returns the deny for a failed worktree-resolution import, or $null.
58
- .OUTPUTS
59
- System.Collections.Specialized.OrderedDictionary, or $null when every import succeeded.
60
- #>
61
- [CmdletBinding()]
62
- [OutputType([System.Collections.Specialized.OrderedDictionary])]
63
- param()
64
-
65
- if (-not $script:OrchestrationGateResolutionImportFailure) {
66
- return $null
67
- }
68
- return Get-OrchestrationPreimplementationGateBlockDecision -Reason (
69
- "PREIMPLEMENTATION_GATE_BLOCKED: the worktree-resolution module '$($script:OrchestrationGateResolutionImportFailure)' " +
70
- 'failed to import, so the checkpoint that governs this call cannot be located; the gate fails closed.')
71
- }
44
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeItemResolution.psm1' -ErrorRecord $_ }
45
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeRunResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeRunResolution.psm1' -ErrorRecord $_ }
46
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'EpicScopeResolution.psm1' -ErrorRecord $_ }
47
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeReadiness.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'EpicScopeReadiness.psm1' -ErrorRecord $_ }
48
+ # Per-segment target resolution for the epic-scope decision (issue #738).
49
+ . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-targets.ps1')
72
50
 
73
51
  # The three checkpoint read seams. Each takes the absolute path composed beneath a
74
52
  # resolved worktree root; an absent file returns an empty string, which the readiness
@@ -242,11 +220,13 @@ function Get-OrchestrationEpicScopeDecision {
242
220
  .SYNOPSIS
243
221
  Returns the epic-scope decision for an implementation-classified command or path, or $null.
244
222
  .DESCRIPTION
245
- Resolves epic scope with worktree-HEAD matching and the command's -C selector. When
246
- the call is not epic scope, returns $null so the caller's single-feature path runs
247
- unchanged. In epic scope, returns an allow decision when the epic command-leg
248
- readiness predicate passes, and otherwise a deny naming the epic checkpoint and the
249
- failed conjunct.
223
+ Resolves the target of every command segment and path (issue #738) with
224
+ Get-OrchestrationCommandTarget, then the epic scope of the session root and of each
225
+ target with worktree-HEAD matching. When neither is epic scope, returns $null so the
226
+ caller's single-feature path runs unchanged. In epic scope, denies an unresolvable,
227
+ ambiguous, or out-of-scope target, and otherwise evaluates the epic command-leg
228
+ readiness predicate against every target: the first failure denies (the session-root
229
+ wording is unchanged), and no failure allows.
250
230
  .PARAMETER Command
251
231
  The Bash command line; empty for a path leg.
252
232
  .PARAMETER FilePath
@@ -265,15 +245,23 @@ function Get-OrchestrationEpicScopeDecision {
265
245
  if (-not $Command -and -not $FilePath) {
266
246
  return $null
267
247
  }
268
- $selector = if ($Command) { Get-OrchestrationEpicScopeSelector -Command $Command } else { $null }
269
- $scope = Resolve-EpicScopeCheckpoint -Text ([string]$Command) -SessionRoot (Get-Location).Path -WorktreeSelector $selector -MatchWorktreeHead
270
- if (-not $scope.IsEpicScope) {
248
+ $epicScopeSessionRoot = (Get-Location).Path
249
+ $epicScopeText = [string]$Command
250
+ $targetResult = Get-OrchestrationCommandTarget -Command $epicScopeText -FilePath @($FilePath) -SessionRoot $epicScopeSessionRoot
251
+ $scopeResolver = {
252
+ param([string] $Selector)
253
+ Resolve-EpicScopeCheckpoint -Text $epicScopeText -SessionRoot $epicScopeSessionRoot -WorktreeSelector $Selector -MatchWorktreeHead
254
+ }
255
+ $verdict = Resolve-OrchestrationEpicTargetVerdict -SessionRoot $epicScopeSessionRoot -TargetResult $targetResult -ScopeResolver $scopeResolver
256
+ $outcome = Resolve-OrchestrationEpicTargetOutcome -Verdict $verdict -ReadinessFailure {
257
+ param($Scope)
258
+ Get-EpicCommandLegReadinessFailure -Checkpoint $Scope.Checkpoint -MergeInProgress $Scope.MergeInProgress
259
+ }
260
+ if ($outcome.Outcome -eq 'none') {
271
261
  return $null
272
262
  }
273
-
274
- $failure = Get-EpicCommandLegReadinessFailure -Checkpoint $scope.Checkpoint -MergeInProgress $scope.MergeInProgress
275
- if (-not $failure) {
276
- return Get-OrchestrationPreimplementationGateAllowDecision
263
+ if ($outcome.Outcome -eq 'deny') {
264
+ return Get-OrchestrationPreimplementationGateBlockDecision -Reason $outcome.Reason
277
265
  }
278
- return Get-OrchestrationPreimplementationGateBlockDecision -Reason ("PREIMPLEMENTATION_GATE_BLOCKED: this epic-scope operation was evaluated against $($scope.CheckpointPath), and the failed readiness predicate is '$failure'. Implementation operations in epic scope require that checkpoint to satisfy every readiness predicate, and a production path may be staged or edited only while a merge is in progress.")
266
+ return Get-OrchestrationPreimplementationGateAllowDecision
279
267
  }
@@ -9,6 +9,11 @@
9
9
  tree? Every parse ambiguity answers false, so the caller's pre-change deny is the
10
10
  fallback for every unmodeled form.
11
11
 
12
+ Shell-agnostic parsing (issue #735): the shell that executes a hooked command is
13
+ undetermined per command, so every shape whose meaning differs between a POSIX shell
14
+ and PowerShell denies - a backslash anywhere, and { } , ( ) @ outside quotes. Evidence:
15
+ research/research.2026-10-08T14-00.md (Q1) in the issue #732 feature folder.
16
+
12
17
  The normative contract is the D4 fail-closed rule table in
13
18
  docs/features/active/2026-08-24-preimplementation-gate-blocks-planner-integration-commits-539/spec.md.
14
19
  Rule-table row numbers are cited inline against the code that realizes them.
@@ -28,15 +33,15 @@ $script:OrchestrationBookkeepingTrees = @(
28
33
  )
29
34
 
30
35
  # Characters that make a command line statically unresolvable (D4 row 12, as narrowed by
31
- # issues #663 and #713): interpolation characters outside single quotes; outside-quote
32
- # characters (`<`, `>`, and the `#` comment introducer) outside any quote; and typographic
33
- # quotes (U+2018 to U+201E) anywhere, because a PowerShell host reads them as quotes.
36
+ # issues #663, #713, #732, and #735): interpolation characters outside single quotes;
37
+ # outside-quote characters (`<`, `>`, the `#` comment introducer, and the shell-divergent
38
+ # `{ } , ( ) @`) outside any quote; and typographic quotes (U+2018 to U+201E) anywhere.
34
39
  $script:InterpolationCommandCharacters = [char[]]@('$', '`')
35
- $script:OutsideQuoteCommandCharacters = [char[]]@('>', '<', '#')
40
+ $script:OutsideQuoteCommandCharacters = [char[]]@('>', '<', '#', '{', '}', ',', '(', ')', '@')
36
41
  $script:TypographicQuoteCharacters = [char[]]@(0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E)
37
42
 
38
- # Wildcards that make an operand a glob (D4 row 15). Only the literal prefix before the
39
- # first of these is prefix-tested.
43
+ # Wildcards a selector value may not carry (LACS L6). An operand carrying one fails the
44
+ # operand allowlist (issue #732).
40
45
  $script:PathspecWildcardCharacters = [char[]]@('*', '?', '[')
41
46
 
42
47
  # The single repository selector modelled between the command name and the subcommand: D4
@@ -112,12 +117,12 @@ function Test-OrchestrationCommandTextUnresolvable {
112
117
  .SYNOPSIS
113
118
  Reports whether a command line carries a statically unresolvable character.
114
119
  .DESCRIPTION
115
- Realizes D4 row 12 as narrowed by issues #663 and #713, with quote state tracked as in
116
- Split-OrchestrationCommandLine. `$` or backtick answers true outside quotes or inside
117
- double quotes (single quotes keep it literal); `<`, `>`, or a `#` comment answers true
118
- only outside a quoted span. A typographic quote (U+2018 to U+201E), a backslash before
119
- any quote character, or a backslash inside a double-quoted span answers true anywhere:
120
- a shell may end the span where this scan does not (fail closed).
120
+ Realizes D4 row 12 as narrowed by issues #663, #713, #732, and #735, with quote state
121
+ tracked as in Split-OrchestrationCommandLine. `$` or backtick answers true outside
122
+ quotes or inside double quotes (single quotes keep it literal); `<`, `>`, `#`, and
123
+ `{ } , ( ) @` answer true only outside a quoted span. A typographic quote (U+2018 to
124
+ U+201E) or a backslash answers true anywhere, because POSIX shells and PowerShell read
125
+ them differently and the executing shell is undetermined (fail closed).
121
126
  .PARAMETER CommandText
122
127
  The full command line as the shell would receive it.
123
128
  .OUTPUTS
@@ -127,8 +132,8 @@ function Test-OrchestrationCommandTextUnresolvable {
127
132
  [OutputType([bool])]
128
133
  param([Parameter(Mandatory)][AllowEmptyString()][string] $CommandText)
129
134
 
130
- # An escaped or typographic quote moves a span boundary the scan cannot model (#663, #713).
131
- if ($CommandText.Contains('\"') -or $CommandText.Contains("\'") -or $CommandText.IndexOfAny($script:TypographicQuoteCharacters) -ge 0) {
135
+ # A backslash or typographic quote is read differently by POSIX shells and PowerShell (#735).
136
+ if ($CommandText.Contains('\') -or $CommandText.IndexOfAny($script:TypographicQuoteCharacters) -ge 0) {
132
137
  return $true
133
138
  }
134
139
 
@@ -141,13 +146,9 @@ function Test-OrchestrationCommandTextUnresolvable {
141
146
  return $true
142
147
  }
143
148
 
144
- # Decide by quote state: inside a span only the closing quote matters, and any
145
- # backslash inside a double-quoted span is an unmodelled escape; outside a span a
146
- # quote opens one and a redirection character is unresolvable.
149
+ # Decide by quote state: inside a span only the closing quote matters; outside a
150
+ # span a quote opens one and an outside-quote character is unresolvable.
147
151
  if ($openQuote -ne [char]0) {
148
- if ($openQuote -eq '"' -and $character -eq '\') {
149
- return $true
150
- }
151
152
  if ($character -eq $openQuote) {
152
153
  $openQuote = [char]0
153
154
  }
@@ -222,9 +223,10 @@ function Test-ExemptOrchestrationOperand {
222
223
  .SYNOPSIS
223
224
  Tests one pathspec operand against the five exempt orchestration trees.
224
225
  .DESCRIPTION
225
- Realizes D4 rows 3, 9, 15, 16, 17, and 18. Backslashes normalize to forward slashes
226
- before the prefix test (row 18); pathspec magic, absolute spellings, parent-directory
227
- segments, and globs whose literal prefix escapes the exempt set all deny.
226
+ Realizes D4 rows 3, 9, 15, 16, and 17 as narrowed by issues #732 and #735. An operand
227
+ is exempt only when it matches the plain ASCII allowlist A-Z a-z 0-9 . _ / - (which
228
+ excludes pathspec magic, drive letters, backslashes, globs, braces, and non-ASCII
229
+ look-alikes), is not rooted, carries no '..' segment, and starts with an exempt tree.
228
230
  .OUTPUTS
229
231
  System.Boolean
230
232
  #>
@@ -232,43 +234,14 @@ function Test-ExemptOrchestrationOperand {
232
234
  [OutputType([bool])]
233
235
  param([Parameter(Mandatory)][AllowEmptyString()][string] $Operand)
234
236
 
235
- if (-not $Operand) {
236
- return $false
237
- }
238
-
239
- # Row 3b and row 9: any leading colon is pathspec magic, which can escape or invert the
240
- # tree scope, so no colon-led operand is ever resolvable by a prefix test.
241
- if ($Operand.StartsWith(':')) {
237
+ if ($Operand -cnotmatch '^[A-Za-z0-9._/-]+$' -or $Operand.StartsWith('/')) {
242
238
  return $false
243
239
  }
244
-
245
- # Row 18: separator normalization precedes every prefix comparison below.
246
- $normalized = $Operand -replace '\\', '/'
247
-
248
- # Row 16: rooted, drive-lettered, and UNC spellings all deny; the exempt prefixes stay
249
- # repo-relative (this is the posture issue #516 later composes with).
250
- if ($normalized.StartsWith('/')) {
240
+ if (($Operand -split '/') -contains '..') {
251
241
  return $false
252
242
  }
253
- if ($normalized -match '^[A-Za-z]:') {
254
- return $false
255
- }
256
-
257
- # Rows 15c and 17: any parent-directory component escapes the prefix.
258
- if (($normalized -split '/') -contains '..') {
259
- return $false
260
- }
261
-
262
- # Row 15: only the literal prefix before the first wildcard is prefix-tested, so a glob
263
- # whose wildcard occupies or truncates an ancestor segment cannot pass.
264
- $literalPrefix = $normalized
265
- $wildcardIndex = $normalized.IndexOfAny($script:PathspecWildcardCharacters)
266
- if ($wildcardIndex -ge 0) {
267
- $literalPrefix = $normalized.Substring(0, $wildcardIndex)
268
- }
269
-
270
243
  foreach ($tree in $script:OrchestrationBookkeepingTrees) {
271
- if ($literalPrefix.StartsWith($tree)) {
244
+ if ($Operand.StartsWith($tree)) {
272
245
  return $true
273
246
  }
274
247
  }
@@ -444,7 +417,7 @@ function Test-ExemptOrchestrationStagingCommand {
444
417
  command line splits cleanly into segments and EVERY segment parses as a complete,
445
418
  recognized staging or integration invocation carrying at least one pathspec operand,
446
419
  with every operand resolving inside one of the five exempt orchestration-bookkeeping
447
- trees after balanced-quote stripping and separator normalization.
420
+ trees after balanced-quote stripping.
448
421
 
449
422
  The all-segments reading is deliberate and fail-closed: a chained line denies unless
450
423
  each of its segments is independently a recognized all-exempt invocation, so a
@@ -464,8 +437,8 @@ function Test-ExemptOrchestrationStagingCommand {
464
437
  return $false
465
438
  }
466
439
 
467
- # Row 12: `$` or backtick outside single quotes, `<`, `>`, or `#` outside quotes, any
468
- # typographic quote, and unmodelled backslash escapes make the operand list untrustworthy.
440
+ # Row 12: `$` or backtick outside single quotes, `< > # { } , ( ) @` outside quotes, and
441
+ # any typographic quote or backslash make the operand list untrustworthy (#732, #735).
469
442
  if (Test-OrchestrationCommandTextUnresolvable -CommandText $CommandText) {
470
443
  return $false
471
444
  }