@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
@@ -2,7 +2,7 @@ default_permissions = ":danger-full-access"
2
2
 
3
3
  [mcp_servers.drm-copilot]
4
4
  command = "npx"
5
- args = ["-y", "@danmoisan/drm-copilot-mcp@1.1.18"]
5
+ args = ["-y", "@danmoisan/drm-copilot-mcp@1.1.20"]
6
6
  required = true
7
7
  enabled_tools = [
8
8
  "collect_commit_context",
@@ -32,10 +32,11 @@
32
32
  #>
33
33
  [CmdletBinding()]
34
34
  param()
35
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
35
36
 
36
37
  # Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
37
38
  # mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
38
- . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
39
+ try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
39
40
 
40
41
  function Get-PowerShellTestPurityBlockDecision {
41
42
  [CmdletBinding()]
@@ -72,6 +73,8 @@ function Invoke-PowerShellTestPurityDecision {
72
73
  param(
73
74
  [string] $ToolInputRaw
74
75
  )
76
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-powershell-test-purity:'
77
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
75
78
 
76
79
  if (-not $ToolInputRaw) {
77
80
  return $null
@@ -145,6 +148,9 @@ function Invoke-PowerShellTestPurityDecision {
145
148
  if ($MyInvocation.InvocationName -eq '.') {
146
149
  return
147
150
  }
151
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('check-powershell-test-purity: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
152
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-powershell-test-purity:'
153
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
148
154
 
149
155
  try {
150
156
  # Transport and mapping come from the shared module. A well-formed payload
@@ -29,10 +29,11 @@
29
29
  #>
30
30
  [CmdletBinding()]
31
31
  param()
32
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
32
33
 
33
34
  # Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
34
35
  # mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
35
- . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
36
+ try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
36
37
 
37
38
  function Get-PythonTestPurityBlockDecision {
38
39
  [CmdletBinding()]
@@ -69,6 +70,8 @@ function Invoke-PythonTestPurityDecision {
69
70
  param(
70
71
  [string] $ToolInputRaw
71
72
  )
73
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-python-test-purity:'
74
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
72
75
 
73
76
  if (-not $ToolInputRaw) {
74
77
  return $null
@@ -145,6 +148,9 @@ function Invoke-PythonTestPurityDecision {
145
148
  if ($MyInvocation.InvocationName -eq '.') {
146
149
  return
147
150
  }
151
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('check-python-test-purity: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
152
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-python-test-purity:'
153
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
148
154
 
149
155
  try {
150
156
  # Transport and mapping come from the shared module. A well-formed payload
@@ -2,7 +2,7 @@
2
2
 
3
3
  $contractPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'scripts/epic-child-launch-contract.ps1'
4
4
  if (Test-Path -LiteralPath $contractPath -PathType Leaf) {
5
- . $contractPath
5
+ try { . $contractPath } catch { Add-HookDependencyFailure -Name 'epic-child-launch-contract.ps1' -ErrorRecord $_ }
6
6
  }
7
7
 
8
8
  $script:CodexEpicChildContexts = @('epic_preparation_child', 'epic_execution_child')
@@ -43,10 +43,11 @@
43
43
  #>
44
44
  [CmdletBinding()]
45
45
  param()
46
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
46
47
 
47
48
  # Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
48
49
  # mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
49
- . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
50
+ try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
50
51
 
51
52
  # The only path this hook governs. On-disk reconstruction of an apply_patch
52
53
  # Update is requested for this path alone, so a patch that merely happens to
@@ -214,6 +215,8 @@ function Invoke-CheckpointMonotonicDecision {
214
215
  param(
215
216
  [string] $ToolInputRaw
216
217
  )
218
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'CHECKPOINT_ORDER_BLOCKED:'
219
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
217
220
 
218
221
  if (-not $ToolInputRaw) {
219
222
  return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
@@ -312,6 +315,9 @@ function Invoke-CheckpointMonotonicDecision {
312
315
  if ($MyInvocation.InvocationName -eq '.') {
313
316
  return
314
317
  }
318
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('CHECKPOINT_ORDER_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
319
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'CHECKPOINT_ORDER_BLOCKED:'
320
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
315
321
 
316
322
  try {
317
323
  # Transport and mapping come from the shared module. Update reconstruction is
@@ -4,9 +4,10 @@
4
4
  #>
5
5
  [CmdletBinding()]
6
6
  param()
7
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
7
8
 
8
- . (Join-Path $PSScriptRoot 'codex-authority-store.ps1')
9
- . (Join-Path $PSScriptRoot 'codex-agent-profile-attestation.ps1')
9
+ try { . (Join-Path $PSScriptRoot 'codex-authority-store.ps1') } catch { Add-HookDependencyFailure -Name 'codex-authority-store.ps1' -ErrorRecord $_ }
10
+ try { . (Join-Path $PSScriptRoot 'codex-agent-profile-attestation.ps1') } catch { Add-HookDependencyFailure -Name 'codex-agent-profile-attestation.ps1' -ErrorRecord $_ }
10
11
 
11
12
  $script:CodexModelGateRepositoryRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
12
13
 
@@ -91,6 +92,8 @@ function Invoke-CodexModelRoutingDecision {
91
92
  [Parameter(Mandatory)][string] $PayloadRaw,
92
93
  [AllowNull()][AllowEmptyString()][string] $AttestationRaw
93
94
  )
95
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MODEL_ROUTING_ATTESTATION_BLOCKED:'
96
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
94
97
 
95
98
  $payload = ConvertFrom-CodexModelGateJson -Raw $PayloadRaw -Name 'PreToolUse input'
96
99
  if ([string]::IsNullOrWhiteSpace($AttestationRaw)) {
@@ -150,6 +153,9 @@ function Get-CodexModelGateDenyDecision {
150
153
  if ($MyInvocation.InvocationName -eq '.') {
151
154
  return
152
155
  }
156
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('MODEL_ROUTING_ATTESTATION_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
157
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MODEL_ROUTING_ATTESTATION_BLOCKED:'
158
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
153
159
 
154
160
  try {
155
161
  $payloadRaw = [Console]::In.ReadToEnd()
@@ -29,32 +29,37 @@
29
29
  completion is not asserted, the write is allowed via
30
30
  hookSpecificOutput.permissionDecision='allow' (backward compatibility).
31
31
 
32
- Edit tool calls supply only old_string/new_string (a partial patch) and
33
- cannot be reliably validated without the full target file content, so they
34
- are allowed by this hook, matching enforce-checkpoint-monotonic.ps1. For
35
- Write calls whose content is not valid JSON, the hook allows the operation
36
- and defers to downstream tools to surface the error.
32
+ Edit tool calls supply only old_string/new_string (a partial patch). An Edit
33
+ call is validated by reading the checkpoint at the Edit's targeted file_path
34
+ through the injectable CheckpointReader seam and applying the old_string ->
35
+ new_string replacement in memory; the resulting content is then evaluated
36
+ like a Write. One occurrence of old_string is replaced unless replace_all is
37
+ true. The hook fails closed: a missing, empty, or unreadable targeted
38
+ checkpoint, an absent or empty old_string, zero or ambiguous occurrences of
39
+ old_string, and a Write with empty content all deny, and the deny reason
40
+ names the cause. Write content or patched content that is not valid JSON is
41
+ also denied, because the canonical checkpoint is required to stay valid JSON.
37
42
 
38
43
  .NOTES
39
44
  Compatible with PowerShell 7+. Read-only validation gate.
40
45
  #>
41
46
  [CmdletBinding()]
42
47
  param()
48
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
43
49
 
44
50
  # Reuse the adjacent hook's shared checkpoint policy logic. This dot-source is by
45
51
  # design, not a copy-paste defect, so the hook is not renamed.
46
- . (Join-Path $PSScriptRoot 'enforce-checkpoint-monotonic.ps1')
52
+ try { . (Join-Path $PSScriptRoot 'enforce-checkpoint-monotonic.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-checkpoint-monotonic.ps1' -ErrorRecord $_ }
47
53
 
48
54
  # Shared Codex PreToolUse transport. Dot-sourced explicitly rather than relying on
49
55
  # the transitive load above, so this hook's transport does not depend on its
50
56
  # neighbour's internals. Every transport error it raises names this hook, because
51
57
  # the shared parser is called with -HookName 'enforce-completion-consistency'.
52
- . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
58
+ try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
53
59
 
54
60
  # Dot-source the shared validation helpers. Guarded so a missing file produces a
55
61
  # clear error and so dot-sourcing this hook in tests loads the helpers too.
56
- $script:CompletionHelpersPath = Join-Path $PSScriptRoot 'enforce-completion-helpers.ps1'
57
- . $script:CompletionHelpersPath
62
+ try { . (Join-Path $PSScriptRoot 'enforce-completion-helpers.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-completion-helpers.ps1' -ErrorRecord $_ }
58
63
 
59
64
  function ConvertFrom-CheckpointJson {
60
65
  <#
@@ -76,9 +81,10 @@ function Get-CheckpointFileContent {
76
81
  Reads the on-disk checkpoint content for the read-then-validate Edit path.
77
82
  .DESCRIPTION
78
83
  Returns the full file text when the path resolves to a file on disk, or
79
- $null when the file does not exist. Tests inject a CheckpointReader
80
- scriptblock instead of mocking this function so no temporary files are
81
- required.
84
+ $null when the file does not exist. An existing empty file yields an
85
+ empty string, never $null, so a missing checkpoint and an empty
86
+ checkpoint stay distinct. Tests inject a CheckpointReader scriptblock
87
+ instead of mocking this function so no temporary files are required.
82
88
  #>
83
89
  [CmdletBinding()]
84
90
  [OutputType([string])]
@@ -90,7 +96,9 @@ function Get-CheckpointFileContent {
90
96
  if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
91
97
  return $null
92
98
  }
93
- return Get-Content -LiteralPath $Path -Raw -ErrorAction Stop
99
+ $text = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop
100
+ if ($null -eq $text) { return '' }
101
+ return [string]$text
94
102
  }
95
103
 
96
104
  function Test-IsCheckpointPath {
@@ -270,26 +278,34 @@ function Get-MissingCompletionEvidence {
270
278
  function Resolve-EditedCheckpointContent {
271
279
  <#
272
280
  .SYNOPSIS
273
- Returns the patched checkpoint content for an Edit-tool call, or $null
274
- when the patch cannot be applied against the on-disk checkpoint.
281
+ Returns an object with Content and Failure for an Edit-tool call: the
282
+ patched checkpoint content on success, or a failure cause when the patch
283
+ cannot be applied against the targeted checkpoint.
275
284
  .DESCRIPTION
276
- Implements the read-then-validate Edit path. When the tool input carries
277
- an old_string (an Edit patch), the on-disk checkpoint is read through the
278
- injectable CheckpointReader seam and the old_string -> new_string
279
- replacement is applied in memory (no on-disk mutation). Returns $null
280
- when there is no old_string, the on-disk file does not exist, or the
281
- old_string is not present in the on-disk content, signalling the caller
282
- to allow (defer).
285
+ Implements the read-then-validate Edit path. The checkpoint at the
286
+ caller-supplied CheckpointPath (the Edit's targeted file_path, passed to
287
+ the reader unchanged) is read through the injectable CheckpointReader seam
288
+ and the old_string -> new_string replacement is applied in memory (no
289
+ on-disk mutation). One occurrence of old_string is replaced unless
290
+ replace_all is true. Failure is one of no-old_string (absent or empty
291
+ old_string), checkpoint-unreadable (the reader threw), checkpoint-missing
292
+ (the reader returned $null), checkpoint-empty (the reader returned an
293
+ empty string), old_string-not-found, or old_string-ambiguous. Content is
294
+ $null on failure and Failure is $null on success. The caller denies on
295
+ any Failure.
283
296
  #>
284
297
  [CmdletBinding()]
285
- [OutputType([string])]
298
+ [OutputType([pscustomobject])]
286
299
  param(
287
300
  [Parameter(Mandatory)]
288
301
  [AllowNull()]
289
302
  $ToolInput,
290
303
 
291
304
  [Parameter(Mandatory)]
292
- [scriptblock] $CheckpointReader
305
+ [scriptblock] $CheckpointReader,
306
+
307
+ [Parameter(Mandatory)]
308
+ [string] $CheckpointPath
293
309
  )
294
310
 
295
311
  $oldString = $null
@@ -297,7 +313,7 @@ function Resolve-EditedCheckpointContent {
297
313
  $oldString = [string]$ToolInput.old_string
298
314
  }
299
315
  if ([string]::IsNullOrEmpty($oldString)) {
300
- return $null
316
+ return [pscustomobject]@{ Content = $null; Failure = 'no-old_string' }
301
317
  }
302
318
 
303
319
  $newString = ''
@@ -305,20 +321,46 @@ function Resolve-EditedCheckpointContent {
305
321
  $newString = [string]$ToolInput.new_string
306
322
  }
307
323
 
308
- $onDisk = & $CheckpointReader 'artifacts/orchestration/orchestrator-state.json'
309
- if ([string]::IsNullOrEmpty([string]$onDisk)) {
310
- # The on-disk checkpoint does not exist (or is empty); cannot patch.
311
- return $null
324
+ try {
325
+ $onDisk = & $CheckpointReader $CheckpointPath
326
+ }
327
+ catch {
328
+ # A reader exception must not escape the gate; report it as a failure cause.
329
+ return [pscustomobject]@{ Content = $null; Failure = 'checkpoint-unreadable' }
330
+ }
331
+ if ($null -eq $onDisk) {
332
+ return [pscustomobject]@{ Content = $null; Failure = 'checkpoint-missing' }
312
333
  }
313
334
 
314
335
  $onDiskText = [string]$onDisk
315
- if (-not $onDiskText.Contains($oldString)) {
316
- # The old_string is not present, so the patch does not apply here.
317
- return $null
336
+ if ($onDiskText.Length -eq 0) {
337
+ return [pscustomobject]@{ Content = $null; Failure = 'checkpoint-empty' }
318
338
  }
319
339
 
320
- # Apply the patch in memory using a literal (non-regex) replacement.
321
- return $onDiskText.Replace($oldString, $newString)
340
+ # Apply the patch in memory; one occurrence unless replace_all is true.
341
+ $replaceAll = Get-EditReplaceAllFlag -ToolInput $ToolInput
342
+ return Invoke-SingleOccurrenceEdit -Text $onDiskText -OldString $oldString -NewString $newString -ReplaceAll $replaceAll
343
+ }
344
+
345
+ function ConvertTo-CompletionDenyDecision {
346
+ <#
347
+ .SYNOPSIS
348
+ Builds the PreToolUse deny decision for the given reason.
349
+ #>
350
+ [CmdletBinding()]
351
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
352
+ param(
353
+ [Parameter(Mandatory)]
354
+ [string] $Reason
355
+ )
356
+
357
+ return [ordered]@{
358
+ hookSpecificOutput = [ordered]@{
359
+ hookEventName = 'PreToolUse'
360
+ permissionDecision = 'deny'
361
+ permissionDecisionReason = $Reason
362
+ }
363
+ }
322
364
  }
323
365
 
324
366
  function Invoke-CompletionConsistencyDecision {
@@ -341,6 +383,8 @@ function Invoke-CompletionConsistencyDecision {
341
383
  [Parameter(Mandatory = $false)]
342
384
  [scriptblock] $RoutingMatrixReader
343
385
  )
386
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'COMPLETION_CONSISTENCY_BLOCKED:'
387
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
344
388
 
345
389
  if (-not $ToolInputRaw) {
346
390
  return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
@@ -363,19 +407,25 @@ function Invoke-CompletionConsistencyDecision {
363
407
  return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
364
408
  }
365
409
 
366
- # Write tool: validate the content payload directly. Edit tool: no content is
367
- # supplied, so read the on-disk checkpoint through the injectable seam and
368
- # apply the old_string -> new_string patch in memory (read-then-validate).
369
- $content = $toolInput.content
370
- if (-not $content) {
371
- $content = Resolve-EditedCheckpointContent -ToolInput $toolInput -CheckpointReader $CheckpointReader
410
+ # Write tool: a present content property is validated directly, and empty
411
+ # content is denied. Edit tool: no content property is supplied, so read the
412
+ # targeted checkpoint through the injectable seam and apply the old_string ->
413
+ # new_string patch in memory (read-then-validate). Any failure cause denies.
414
+ $cause = $null
415
+ if ($toolInput.PSObject.Properties.Name -contains 'content') {
416
+ $content = $toolInput.content
372
417
  if (-not $content) {
373
- return [ordered]@{ hookSpecificOutput = [ordered]@{
374
- hookEventName = 'PreToolUse'; permissionDecision = 'deny'
375
- permissionDecisionReason = 'COMPLETION_CONSISTENCY_BLOCKED: the canonical checkpoint cannot be deleted, emptied, or replaced through an unresolved patch.'
376
- } }
418
+ $cause = 'write-content-empty'
377
419
  }
378
420
  }
421
+ else {
422
+ $edit = Resolve-EditedCheckpointContent -ToolInput $toolInput -CheckpointReader $CheckpointReader -CheckpointPath $filePath
423
+ $content = $edit.Content
424
+ $cause = $edit.Failure
425
+ }
426
+ if ($cause) {
427
+ return ConvertTo-CompletionDenyDecision -Reason "COMPLETION_CONSISTENCY_BLOCKED: the canonical checkpoint cannot be deleted, emptied, or replaced through an unresolved patch ($cause)."
428
+ }
379
429
 
380
430
  try {
381
431
  $payload = ConvertFrom-CheckpointJson -Json $content
@@ -414,6 +464,9 @@ function Invoke-CompletionConsistencyDecision {
414
464
  if ($MyInvocation.InvocationName -eq '.') {
415
465
  return
416
466
  }
467
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('COMPLETION_CONSISTENCY_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
468
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'COMPLETION_CONSISTENCY_BLOCKED:'
469
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
417
470
 
418
471
  try {
419
472
  # -HookName makes every transport error name this hook rather than the
@@ -11,6 +11,12 @@
11
11
  - Test-IsValidFeatureFolder: rejects sentinel/placeholder feature folders
12
12
  and folders not anchored under docs/features/active/<segment>; optionally
13
13
  verifies on-disk existence through an injectable scriptblock seam.
14
+ - Get-EditReplaceAllFlag: returns the boolean value of the replace_all
15
+ property of an Edit tool input; the string 'true' is honoured and the
16
+ string 'false' is not.
17
+ - Invoke-SingleOccurrenceEdit: pure single-occurrence patch of a text;
18
+ reports a failure cause instead of replacing when old_string is empty,
19
+ absent, or ambiguous.
14
20
 
15
21
  This script is dot-sourced by enforce-completion-consistency.ps1. It contains
16
22
  no entrypoint logic, so dot-sourcing it in tests has no side effects.
@@ -161,3 +167,102 @@ function Test-RouteRequiresPrGate {
161
167
  }
162
168
  return ([bool]$route.requires_pr_gate -eq $true)
163
169
  }
170
+
171
+ function Get-EditReplaceAllFlag {
172
+ <#
173
+ .SYNOPSIS
174
+ Returns the boolean value of the replace_all property of an Edit tool input.
175
+ .DESCRIPTION
176
+ Returns $false when the tool input is null or has no replace_all property.
177
+ Returns the value when it is already a boolean. Returns $true for a string
178
+ whose trimmed, case-insensitive value is 'true'. Returns $false for every
179
+ other value. No [bool] cast is used because [bool]'false' is $true in
180
+ PowerShell.
181
+ #>
182
+ [CmdletBinding()]
183
+ [OutputType([bool])]
184
+ param(
185
+ [Parameter(Mandatory)]
186
+ [AllowNull()]
187
+ $ToolInput
188
+ )
189
+
190
+ if ($null -eq $ToolInput -or -not ($ToolInput.PSObject.Properties.Name -contains 'replace_all')) {
191
+ return $false
192
+ }
193
+
194
+ $value = $ToolInput.replace_all
195
+ if ($value -is [bool]) {
196
+ return $value
197
+ }
198
+ if ($value -is [string]) {
199
+ return $value.Trim() -ieq 'true'
200
+ }
201
+ return $false
202
+ }
203
+
204
+ function Invoke-SingleOccurrenceEdit {
205
+ <#
206
+ .SYNOPSIS
207
+ Applies an old_string to new_string patch to a text in memory and reports
208
+ a failure cause when the patch cannot be applied unambiguously.
209
+ .DESCRIPTION
210
+ Pure function with no I/O. Normalizes CRLF to LF in all three strings. An
211
+ empty OldString yields Failure 'no-old_string'. Zero ordinal occurrences
212
+ yield Failure 'old_string-not-found'. When ReplaceAll is true every
213
+ occurrence is replaced by ordinal String.Replace. Otherwise a second
214
+ ordinal search that starts after the end of the first match yields Failure
215
+ 'old_string-ambiguous' when it finds a match (overlapping candidates are
216
+ counted once), and no match yields a single splice by Substring. No regular
217
+ expression is used, so a '$' in NewString stays literal. Returns an object
218
+ with Content and Failure; Content is $null on failure and Failure is $null
219
+ on success.
220
+ #>
221
+ [CmdletBinding()]
222
+ [OutputType([pscustomobject])]
223
+ param(
224
+ [Parameter(Mandatory)]
225
+ [AllowNull()]
226
+ [AllowEmptyString()]
227
+ [string] $Text,
228
+
229
+ [Parameter(Mandatory)]
230
+ [AllowNull()]
231
+ [AllowEmptyString()]
232
+ [string] $OldString,
233
+
234
+ [Parameter(Mandatory)]
235
+ [AllowNull()]
236
+ [AllowEmptyString()]
237
+ [string] $NewString,
238
+
239
+ [Parameter(Mandatory = $false)]
240
+ [bool] $ReplaceAll = $false
241
+ )
242
+
243
+ $normalizedText = $Text.Replace("`r`n", "`n")
244
+ $normalizedOld = $OldString.Replace("`r`n", "`n")
245
+ $normalizedNew = $NewString.Replace("`r`n", "`n")
246
+
247
+ if ($normalizedOld.Length -eq 0) {
248
+ return [pscustomobject]@{ Content = $null; Failure = 'no-old_string' }
249
+ }
250
+
251
+ $comparison = [System.StringComparison]::Ordinal
252
+ $firstIndex = $normalizedText.IndexOf($normalizedOld, $comparison)
253
+ if ($firstIndex -lt 0) {
254
+ return [pscustomobject]@{ Content = $null; Failure = 'old_string-not-found' }
255
+ }
256
+
257
+ if ($ReplaceAll) {
258
+ return [pscustomobject]@{ Content = $normalizedText.Replace($normalizedOld, $normalizedNew); Failure = $null }
259
+ }
260
+
261
+ $afterFirst = $firstIndex + $normalizedOld.Length
262
+ if ($normalizedText.IndexOf($normalizedOld, $afterFirst, $comparison) -ge 0) {
263
+ return [pscustomobject]@{ Content = $null; Failure = 'old_string-ambiguous' }
264
+ }
265
+
266
+ $spliced = $normalizedText.Substring(0, $firstIndex) + $normalizedNew + $normalizedText.Substring($afterFirst)
267
+ return [pscustomobject]@{ Content = $spliced; Failure = $null }
268
+ }
@@ -10,10 +10,11 @@
10
10
  #>
11
11
  [CmdletBinding()]
12
12
  param()
13
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
13
14
 
14
15
  $contractPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'scripts/epic-child-launch-contract.ps1'
15
16
  if (Test-Path -LiteralPath $contractPath -PathType Leaf) {
16
- . $contractPath
17
+ try { . $contractPath } catch { Add-HookDependencyFailure -Name 'epic-child-launch-contract.ps1' -ErrorRecord $_ }
17
18
  }
18
19
 
19
20
  function ConvertFrom-CodexChildGuardJson {
@@ -218,6 +219,8 @@ function Invoke-CodexEpicChildGuardDecision {
218
219
  [Parameter(Mandatory)][AllowEmptyString()][string] $ActualSpecSha256,
219
220
  [Parameter(Mandatory)][AllowEmptyString()][string] $ActualProfileSha256
220
221
  )
222
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_BINDING_BLOCKED:'
223
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
221
224
 
222
225
  $payload = ConvertFrom-CodexChildGuardJson -Raw $PayloadRaw -Name 'PreToolUse input'
223
226
  if ([string]::IsNullOrWhiteSpace([string]$Attestation.launch_id)) {
@@ -282,6 +285,9 @@ function Get-CodexChildGuardLiveBranch {
282
285
  if ($MyInvocation.InvocationName -eq '.') {
283
286
  return
284
287
  }
288
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_WORKTREE_BINDING_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
289
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_BINDING_BLOCKED:'
290
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
285
291
 
286
292
  try {
287
293
  $payloadRaw = [Console]::In.ReadToEnd()