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