@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/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate-command.ps1
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Scope predicate and pull-request selector reader for the epic merge gate (issue #952).
|
|
4
|
+
.DESCRIPTION
|
|
5
|
+
Dot-sourced by enforce-epic-merge-gate.ps1 on both runtimes; this file is byte-identical in
|
|
6
|
+
.claude/hooks and .codex/hooks. Under a merge queue every gh pr merge spelling (--merge, -m,
|
|
7
|
+
--squash, -s, --rebase, -r, --auto, --admin, or no method flag) adds the pull request to the
|
|
8
|
+
queue, and the gh api mutations enqueuePullRequest, enablePullRequestAutoMerge, and
|
|
9
|
+
mergePullRequest and the REST pulls/<n>/merge endpoint also reach the base branch. All of
|
|
10
|
+
them are in scope. A gh pr merge whose only action flag is --disable-auto is out of scope.
|
|
11
|
+
|
|
12
|
+
Pure string logic only: no disk, process, network, clock, or environment access. The file
|
|
13
|
+
dot-sources and imports nothing; it consumes Get-CommandLineInvocation and
|
|
14
|
+
Get-CommandLineStructuralMatch, which the gate loads from hook-command-invocation.ps1 first.
|
|
15
|
+
|
|
16
|
+
Known limitation (issue #952 code review CR-5): the gh api scope reads the command text
|
|
17
|
+
only. A GraphQL mutation supplied from a file (gh api graphql -F query=@mutation.graphql,
|
|
18
|
+
or gh api --input payload.json) is not visible to this text-based scope and is not gated.
|
|
19
|
+
#>
|
|
20
|
+
|
|
21
|
+
# gh pr merge flags that perform or schedule a merge. Any of them keeps a command in scope even
|
|
22
|
+
# when it also carries --disable-auto.
|
|
23
|
+
$script:EpicMergeGateActionFlags = @('--merge', '-m', '--squash', '-s', '--rebase', '-r', '--auto', '--admin')
|
|
24
|
+
|
|
25
|
+
# gh pr merge flags, including the inherited --repo, that consume the following token as a value.
|
|
26
|
+
$script:EpicMergeGateValueFlags = @('-b', '--body', '-F', '--body-file', '-t', '--subject', '-A', '--author-email', '--match-head-commit', '-R', '--repo')
|
|
27
|
+
|
|
28
|
+
# GraphQL mutations that merge, enqueue, or schedule the merge of a pull request.
|
|
29
|
+
$script:EpicMergeGateMutationNames = @('enqueuePullRequest', 'enablePullRequestAutoMerge', 'mergePullRequest')
|
|
30
|
+
|
|
31
|
+
# The REST merge endpoint path; group 1 is the pull-request number.
|
|
32
|
+
$script:EpicMergeGateRestMergePattern = '(?:^|/)pulls/(\d+)/merge(?:$|[^\w-])'
|
|
33
|
+
|
|
34
|
+
function Get-EpicMergeGateFlagName {
|
|
35
|
+
<#
|
|
36
|
+
.SYNOPSIS
|
|
37
|
+
Return the flag name of a dash-led token without any '=value' suffix.
|
|
38
|
+
.OUTPUTS
|
|
39
|
+
System.String
|
|
40
|
+
#>
|
|
41
|
+
[CmdletBinding()]
|
|
42
|
+
[OutputType([string])]
|
|
43
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Token)
|
|
44
|
+
|
|
45
|
+
$split = $Token.IndexOf('=')
|
|
46
|
+
if ($split -gt 0) { return $Token.Substring(0, $split) }
|
|
47
|
+
return $Token
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function ConvertFrom-EpicMergeGateSelector {
|
|
51
|
+
<#
|
|
52
|
+
.SYNOPSIS
|
|
53
|
+
Convert a gh pr merge selector to a pull-request number, or $null.
|
|
54
|
+
.DESCRIPTION
|
|
55
|
+
Accepts an all-digit selector or a URL whose path ends in /pull/<n>. A branch-name
|
|
56
|
+
selector carries no number and yields $null.
|
|
57
|
+
.OUTPUTS
|
|
58
|
+
System.Nullable[int]
|
|
59
|
+
#>
|
|
60
|
+
[CmdletBinding()]
|
|
61
|
+
[OutputType([int])]
|
|
62
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Selector)
|
|
63
|
+
|
|
64
|
+
$digits = $null
|
|
65
|
+
if ($Selector -match '^\d+$') {
|
|
66
|
+
$digits = $Selector
|
|
67
|
+
} elseif ($Selector -match '/pull/(\d+)/?(?:[?#].*)?$') {
|
|
68
|
+
$digits = $Matches[1]
|
|
69
|
+
}
|
|
70
|
+
$number = 0
|
|
71
|
+
if ($null -ne $digits -and [int]::TryParse($digits, [ref] $number)) { return $number }
|
|
72
|
+
return $null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function Test-EpicMergeGateDisableAutoOnly {
|
|
76
|
+
<#
|
|
77
|
+
.SYNOPSIS
|
|
78
|
+
Report whether a Structural gh pr merge match carries --disable-auto and no action flag.
|
|
79
|
+
.OUTPUTS
|
|
80
|
+
System.Boolean
|
|
81
|
+
#>
|
|
82
|
+
[CmdletBinding()]
|
|
83
|
+
[OutputType([bool])]
|
|
84
|
+
param([Parameter(Mandatory)][pscustomobject] $Match)
|
|
85
|
+
|
|
86
|
+
$tokens = [string[]]@($Match.Segment.Tokens)
|
|
87
|
+
$hasDisableAuto = $false
|
|
88
|
+
for ($index = $Match.OperandIndex; $index -lt $tokens.Count; $index++) {
|
|
89
|
+
$name = Get-EpicMergeGateFlagName -Token $tokens[$index]
|
|
90
|
+
if ($script:EpicMergeGateActionFlags -ccontains $name) { return $false }
|
|
91
|
+
if ($name -ceq '--disable-auto') { $hasDisableAuto = $true }
|
|
92
|
+
}
|
|
93
|
+
return $hasDisableAuto
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function Test-EpicMergeGateApiMutationText {
|
|
97
|
+
<#
|
|
98
|
+
.SYNOPSIS
|
|
99
|
+
Report whether gh api text names a merge or enqueue mutation or the REST merge endpoint.
|
|
100
|
+
.OUTPUTS
|
|
101
|
+
System.Boolean
|
|
102
|
+
#>
|
|
103
|
+
[CmdletBinding()]
|
|
104
|
+
[OutputType([bool])]
|
|
105
|
+
param([Parameter(Mandatory)][AllowEmptyString()][AllowNull()][string] $Text)
|
|
106
|
+
|
|
107
|
+
if ([string]::IsNullOrEmpty($Text)) { return $false }
|
|
108
|
+
foreach ($name in $script:EpicMergeGateMutationNames) {
|
|
109
|
+
if ($Text.IndexOf($name, [System.StringComparison]::OrdinalIgnoreCase) -ge 0) { return $true }
|
|
110
|
+
}
|
|
111
|
+
return [regex]::IsMatch($Text, $script:EpicMergeGateRestMergePattern)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function Test-EpicMergeGateCommandInScope {
|
|
115
|
+
<#
|
|
116
|
+
.SYNOPSIS
|
|
117
|
+
Report whether a command line is a gated merge or enqueue action (issue #952).
|
|
118
|
+
.DESCRIPTION
|
|
119
|
+
True for any gh pr merge match, Structural or Indeterminate, unless the match is Structural
|
|
120
|
+
and its only action flag is --disable-auto; true for any gh api match whose tokens name a
|
|
121
|
+
merge or enqueue mutation or a pulls/<n>/merge path. Text that only mentions these words
|
|
122
|
+
produces no match and stays out of scope. An Indeterminate gh pr merge match stays in scope
|
|
123
|
+
(fail closed).
|
|
124
|
+
.OUTPUTS
|
|
125
|
+
System.Boolean
|
|
126
|
+
#>
|
|
127
|
+
[CmdletBinding()]
|
|
128
|
+
[OutputType([bool])]
|
|
129
|
+
param([Parameter(Mandatory)][AllowEmptyString()][AllowNull()][string] $CommandText)
|
|
130
|
+
|
|
131
|
+
foreach ($match in @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge'))) {
|
|
132
|
+
if ($match.Status -ne 'Structural' -or -not (Test-EpicMergeGateDisableAutoOnly -Match $match)) { return $true }
|
|
133
|
+
}
|
|
134
|
+
foreach ($match in @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('api'))) {
|
|
135
|
+
if (Test-EpicMergeGateApiMutationText -Text (@($match.Segment.Tokens) -join ' ')) { return $true }
|
|
136
|
+
}
|
|
137
|
+
return $false
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function Get-EpicMergeGateSelectorPrNumber {
|
|
141
|
+
<#
|
|
142
|
+
.SYNOPSIS
|
|
143
|
+
Resolve the pull-request number of a gated merge or enqueue command, or $null.
|
|
144
|
+
.DESCRIPTION
|
|
145
|
+
For gh pr merge, only the first Structural match is read. Value flags are skipped with
|
|
146
|
+
their values, other flags are skipped, an equals-joined --merge=<digits> yields its
|
|
147
|
+
digits (an equals-joined value that is not a number is skipped like any other flag),
|
|
148
|
+
and the first non-flag token (or the token after a bare '--') is the selector.
|
|
149
|
+
For gh api, the number comes from a pulls/<n>/merge token. Any other command yields
|
|
150
|
+
$null, which the gate handles through its no-number branches.
|
|
151
|
+
.OUTPUTS
|
|
152
|
+
System.Nullable[int]
|
|
153
|
+
#>
|
|
154
|
+
[CmdletBinding()]
|
|
155
|
+
[OutputType([int])]
|
|
156
|
+
param([Parameter(Mandatory)][AllowEmptyString()][AllowNull()][string] $CommandText)
|
|
157
|
+
|
|
158
|
+
$match = Get-CommandLineStructuralMatch -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'merge')
|
|
159
|
+
if ($null -ne $match) {
|
|
160
|
+
$tokens = [string[]]@($match.Segment.Tokens)
|
|
161
|
+
$index = $match.OperandIndex
|
|
162
|
+
while ($index -lt $tokens.Count) {
|
|
163
|
+
$token = $tokens[$index]
|
|
164
|
+
if ($token -ceq '--') {
|
|
165
|
+
if ($index + 1 -lt $tokens.Count) { return ConvertFrom-EpicMergeGateSelector -Selector $tokens[$index + 1] }
|
|
166
|
+
return $null
|
|
167
|
+
}
|
|
168
|
+
if ($token.StartsWith('-') -and $token.Length -gt 1) {
|
|
169
|
+
$name = Get-EpicMergeGateFlagName -Token $token
|
|
170
|
+
if ($name -ceq '--merge' -and $token.Length -gt $name.Length) {
|
|
171
|
+
$equalsNumber = ConvertFrom-EpicMergeGateSelector -Selector $token.Substring($name.Length + 1)
|
|
172
|
+
if ($null -ne $equalsNumber) { return $equalsNumber }
|
|
173
|
+
}
|
|
174
|
+
$index += if ($script:EpicMergeGateValueFlags -ccontains $token) { 2 } else { 1 }
|
|
175
|
+
continue
|
|
176
|
+
}
|
|
177
|
+
return ConvertFrom-EpicMergeGateSelector -Selector $token
|
|
178
|
+
}
|
|
179
|
+
return $null
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
foreach ($apiMatch in @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('api'))) {
|
|
183
|
+
foreach ($token in @($apiMatch.Segment.Tokens)) {
|
|
184
|
+
$rest = [regex]::Match([string]$token, $script:EpicMergeGateRestMergePattern)
|
|
185
|
+
$number = 0
|
|
186
|
+
if ($rest.Success -and [int]::TryParse($rest.Groups[1].Value, [ref] $number)) { return $number }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return $null
|
|
190
|
+
}
|
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
<#
|
|
2
2
|
.SYNOPSIS
|
|
3
3
|
Gates epic child and integration PR merges behind checkpointed green state.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Trigger scope (issue #952): every gh pr merge invocation (any merge method, --auto, --admin,
|
|
7
|
+
or no method flag) and every gh api merge or enqueue mutation is gated, because under a merge
|
|
8
|
+
queue each of them reaches the base branch; only a pure --disable-auto is out of scope. The
|
|
9
|
+
predicate and the PR selector reader live in enforce-epic-merge-gate-command.ps1.
|
|
10
|
+
|
|
11
|
+
Docs-only branch (issue #927): after the standalone branch denies an explicit PR number,
|
|
12
|
+
and only when no checkpoint is present at the repository root (both checkpoint texts are
|
|
13
|
+
blank; operator decision OD-1, stricter than the Claude per-PR rule), the gate calls
|
|
14
|
+
Get-DocsOnlyMergeExemption from hook-docs-only-diff.ps1 with the repository root. That
|
|
15
|
+
function runs gh pr view and git there and allows the merge when its conditions M1-M9
|
|
16
|
+
hold; otherwise the deny gains " (docs-only exemption not applied: <Reason>)", where the
|
|
17
|
+
reason may be DOCS_ONLY_EXEMPTION_PR_UNRESOLVED. A blank RepositoryRoot denies at M2
|
|
18
|
+
before any process starts. The hook never fetches; --match-head-commit, when present,
|
|
19
|
+
must equal headRefOid (OD-2). Residual limits: an ambient GH_REPO or GH_HOST is not
|
|
20
|
+
visible in the command text; gh and git run in the repository root, so a cd made by an
|
|
21
|
+
earlier shell call is not visible either; a push after the lookup can change the head
|
|
22
|
+
unless --match-head-commit is passed; and the control is policy-level, not cryptographic.
|
|
4
23
|
#>
|
|
5
24
|
[CmdletBinding()]
|
|
6
25
|
param()
|
|
26
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
7
27
|
|
|
8
28
|
# Shared command-line parser (issue #545). The scope filter and the PR-number resolver below
|
|
9
29
|
# both run against the segment that structurally invokes `gh pr merge`, which is what keeps
|
|
10
30
|
# the two runtimes on one implementation of the same concern.
|
|
11
|
-
. (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
|
|
12
|
-
. (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
|
|
31
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
32
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
33
|
+
# Merge and enqueue scope predicate and the PR selector reader (issue #952), byte-identical to the
|
|
34
|
+
# Claude copy.
|
|
35
|
+
try { . (Join-Path $PSScriptRoot 'enforce-epic-merge-gate-command.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-epic-merge-gate-command.ps1' -ErrorRecord $_ }
|
|
36
|
+
# Shared docs-only diff classification and the merge-side docs-only exemption (issue #927).
|
|
37
|
+
try { . (Join-Path $PSScriptRoot 'hook-docs-only-diff.ps1') } catch { Add-HookDependencyFailure -Name 'hook-docs-only-diff.ps1' -ErrorRecord $_ }
|
|
13
38
|
|
|
14
39
|
# Reason codes for the standalone-merge authorization branch (issue #670), spelled
|
|
15
40
|
# byte-identically to the Claude helpers file. Each of the four assignments below is the only
|
|
@@ -44,15 +69,11 @@ function Get-CodexMergeCommandPrNumber {
|
|
|
44
69
|
.SYNOPSIS
|
|
45
70
|
Resolve the explicit pull-request number of a gh pr merge invocation, or $null.
|
|
46
71
|
.DESCRIPTION
|
|
47
|
-
The number is
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
72
|
+
The number is resolved by Get-EpicMergeGateSelectorPrNumber in
|
|
73
|
+
enforce-epic-merge-gate-command.ps1 (issue #952), the file shared byte-identically with
|
|
74
|
+
the Claude runtime, from the segment that structurally invokes gh pr merge or gh api and
|
|
75
|
+
from nowhere else. A leading cd <path> segment contributes no selector, so no digit run
|
|
51
76
|
outside the merge segment can be mistaken for a pull-request number.
|
|
52
|
-
|
|
53
|
-
This copy has never carried the Claude copy's unanchored whole-text digit scan and
|
|
54
|
-
deliberately does not acquire one. No regular expression matching a bare digit run
|
|
55
|
-
is introduced here; the only pattern below anchors an all-digit token end to end.
|
|
56
77
|
.OUTPUTS
|
|
57
78
|
System.Nullable[int]
|
|
58
79
|
#>
|
|
@@ -60,18 +81,7 @@ function Get-CodexMergeCommandPrNumber {
|
|
|
60
81
|
[OutputType([int])]
|
|
61
82
|
param([Parameter(Mandatory)][string] $Command)
|
|
62
83
|
|
|
63
|
-
|
|
64
|
-
if ($operand -match '^\d+$') {
|
|
65
|
-
return [int]$operand
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
$flagValue = Get-CommandLineFlagValue -CommandText $Command -CommandWord 'gh' -SubcommandPath @('pr', 'merge') -FlagName '--merge'
|
|
70
|
-
if ($null -ne $flagValue -and $flagValue -match '^\d+$') {
|
|
71
|
-
return [int]$flagValue
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return $null
|
|
84
|
+
return Get-EpicMergeGateSelectorPrNumber -CommandText $Command
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
function Test-CodexChildMergeReady {
|
|
@@ -125,31 +135,20 @@ function Invoke-CodexEpicMergeDecision {
|
|
|
125
135
|
param(
|
|
126
136
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
127
137
|
[AllowNull()][AllowEmptyString()][string] $ChildCheckpointRaw,
|
|
128
|
-
[AllowNull()][AllowEmptyString()][string] $EpicCheckpointRaw
|
|
138
|
+
[AllowNull()][AllowEmptyString()][string] $EpicCheckpointRaw,
|
|
139
|
+
[AllowNull()][AllowEmptyString()][string] $RepositoryRoot
|
|
129
140
|
)
|
|
141
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_MERGE_GATE_BLOCKED:'
|
|
142
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
130
143
|
|
|
131
144
|
$payload = ConvertFrom-CodexMergeJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
132
145
|
if ([string]$payload.tool_name -ne 'Bash') {
|
|
133
146
|
return $null
|
|
134
147
|
}
|
|
135
148
|
$command = [string]$payload.tool_input.command
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
# inside it is never read as a token, and the token-only read took
|
|
140
|
-
# bash -c "gh pr merge --merge 688" out of scope.
|
|
141
|
-
$isMergeInvocation = Test-CommandLineInvocation -CommandText $command -CommandWord 'gh' -SubcommandPath @('pr', 'merge')
|
|
142
|
-
$hasMergeFlag = Test-CommandLineFlag -CommandText $command -CommandWord 'gh' -SubcommandPath @('pr', 'merge') -FlagName '--merge'
|
|
143
|
-
if (-not $hasMergeFlag) {
|
|
144
|
-
foreach ($segment in @(Read-CommandLineSegment -CommandText $command)) {
|
|
145
|
-
if ((Test-CommandLineSegmentRawScan -Segment $segment) -and
|
|
146
|
-
$segment.ScanText.IndexOf('--merge', [System.StringComparison]::OrdinalIgnoreCase) -ge 0) {
|
|
147
|
-
$hasMergeFlag = $true
|
|
148
|
-
break
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
if (-not $isMergeInvocation -or -not $hasMergeFlag) {
|
|
149
|
+
# Scope (issue #952): every gh pr merge invocation except a pure --disable-auto, and every gh api
|
|
150
|
+
# merge or enqueue mutation, is gated; Test-EpicMergeGateCommandInScope holds the predicate.
|
|
151
|
+
if (-not (Test-EpicMergeGateCommandInScope -CommandText $command)) {
|
|
153
152
|
return $null
|
|
154
153
|
}
|
|
155
154
|
|
|
@@ -172,11 +171,20 @@ function Invoke-CodexEpicMergeDecision {
|
|
|
172
171
|
if ($verdict.Allowed) {
|
|
173
172
|
return $null
|
|
174
173
|
}
|
|
174
|
+
# Docs-only branch (issue #927, OD-1): only when no checkpoint is present at the root.
|
|
175
|
+
$docsOnlySuffix = ''
|
|
176
|
+
if ([string]::IsNullOrWhiteSpace($ChildCheckpointRaw) -and [string]::IsNullOrWhiteSpace($EpicCheckpointRaw)) {
|
|
177
|
+
$docsOnly = Get-DocsOnlyMergeExemption -CommandText $command -PrNumber $prNumber -WorktreeRoot $RepositoryRoot
|
|
178
|
+
if ($docsOnly.Exempt) {
|
|
179
|
+
return $null
|
|
180
|
+
}
|
|
181
|
+
$docsOnlySuffix = ' (docs-only exemption not applied: ' + $docsOnly.Reason + ')'
|
|
182
|
+
}
|
|
175
183
|
return [ordered]@{
|
|
176
184
|
hookSpecificOutput = [ordered]@{
|
|
177
185
|
hookEventName = 'PreToolUse'
|
|
178
186
|
permissionDecision = 'deny'
|
|
179
|
-
permissionDecisionReason = 'EPIC_MERGE_GATE_BLOCKED: ' + $verdict.ReasonCode + ': ' + $verdict.Message
|
|
187
|
+
permissionDecisionReason = 'EPIC_MERGE_GATE_BLOCKED: ' + $verdict.ReasonCode + ': ' + $verdict.Message + $docsOnlySuffix
|
|
180
188
|
}
|
|
181
189
|
}
|
|
182
190
|
}
|
|
@@ -185,7 +193,7 @@ function Invoke-CodexEpicMergeDecision {
|
|
|
185
193
|
hookSpecificOutput = [ordered]@{
|
|
186
194
|
hookEventName = 'PreToolUse'
|
|
187
195
|
permissionDecision = 'deny'
|
|
188
|
-
permissionDecisionReason = 'EPIC_MERGE_GATE_BLOCKED: gh pr merge --merge requires a safe epic child checkpoint or a successful final epic CI gate with a matching PR number.'
|
|
196
|
+
permissionDecisionReason = '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 a safe epic child checkpoint or a successful final epic CI gate with a matching PR number.'
|
|
189
197
|
}
|
|
190
198
|
}
|
|
191
199
|
}
|
|
@@ -360,6 +368,9 @@ function Test-CodexStandaloneMergeAuthorization {
|
|
|
360
368
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
361
369
|
return
|
|
362
370
|
}
|
|
371
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_MERGE_GATE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
372
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_MERGE_GATE_BLOCKED:'
|
|
373
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
363
374
|
|
|
364
375
|
try {
|
|
365
376
|
$payloadRaw = [Console]::In.ReadToEnd()
|
|
@@ -368,7 +379,7 @@ try {
|
|
|
368
379
|
$epicPath = Join-Path $repositoryRoot 'artifacts/orchestration/epic-orchestrator-state.json'
|
|
369
380
|
$childRaw = if (Test-Path -LiteralPath $childPath -PathType Leaf) { Get-Content -Raw -LiteralPath $childPath } else { '' }
|
|
370
381
|
$epicRaw = if (Test-Path -LiteralPath $epicPath -PathType Leaf) { Get-Content -Raw -LiteralPath $epicPath } else { '' }
|
|
371
|
-
$decision = Invoke-CodexEpicMergeDecision -PayloadRaw $payloadRaw -ChildCheckpointRaw $childRaw -EpicCheckpointRaw $epicRaw
|
|
382
|
+
$decision = Invoke-CodexEpicMergeDecision -PayloadRaw $payloadRaw -ChildCheckpointRaw $childRaw -EpicCheckpointRaw $epicRaw -RepositoryRoot $repositoryRoot
|
|
372
383
|
if ($null -ne $decision) {
|
|
373
384
|
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
374
385
|
}
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#>
|
|
10
10
|
[CmdletBinding()]
|
|
11
11
|
param()
|
|
12
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
12
13
|
|
|
13
14
|
$script:AllowedPreparationMcpTools = @(
|
|
14
15
|
'mcp__drm-copilot__new_potential_entry',
|
|
@@ -209,6 +210,8 @@ function Invoke-EpicPlanningOnlyDecision {
|
|
|
209
210
|
[AllowNull()][AllowEmptyString()][string] $CurrentBranch,
|
|
210
211
|
[string] $RegistryPath = (Join-Path $script:EpicPlanningRepositoryRoot 'config/orchestration-handoff-registry.json')
|
|
211
212
|
)
|
|
213
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_PLANNING_ONLY_BLOCKED:'
|
|
214
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
212
215
|
|
|
213
216
|
$payload = ConvertFrom-EpicPlanningJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
214
217
|
$attestedPreparation = $EpicExecutionContext -eq 'epic_preparation_child'
|
|
@@ -325,6 +328,9 @@ function Get-EpicPlanningCurrentBranch {
|
|
|
325
328
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
326
329
|
return
|
|
327
330
|
}
|
|
331
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_PLANNING_ONLY_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
332
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_PLANNING_ONLY_BLOCKED:'
|
|
333
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
328
334
|
|
|
329
335
|
try {
|
|
330
336
|
$payloadRaw = [Console]::In.ReadToEnd()
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
#>
|
|
9
9
|
[CmdletBinding()]
|
|
10
10
|
param()
|
|
11
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
11
12
|
|
|
12
|
-
. (Join-Path $PSScriptRoot 'codex-authority-store.ps1')
|
|
13
|
+
try { . (Join-Path $PSScriptRoot 'codex-authority-store.ps1') } catch { Add-HookDependencyFailure -Name 'codex-authority-store.ps1' -ErrorRecord $_ }
|
|
13
14
|
|
|
14
15
|
function ConvertFrom-EpicRootGatePayload {
|
|
15
16
|
[CmdletBinding()]
|
|
@@ -54,6 +55,8 @@ function Invoke-EpicRootInvocationDecision {
|
|
|
54
55
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
55
56
|
[AllowNull()][AllowEmptyString()][string] $AttestationRaw
|
|
56
57
|
)
|
|
58
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_INVOCATION_ORIGIN_BLOCKED:'
|
|
59
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
57
60
|
|
|
58
61
|
$payload = ConvertFrom-EpicRootGatePayload -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
59
62
|
if ([string]::IsNullOrWhiteSpace($AttestationRaw)) {
|
|
@@ -87,6 +90,9 @@ function Invoke-EpicRootInvocationDecision {
|
|
|
87
90
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
88
91
|
return
|
|
89
92
|
}
|
|
93
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_INVOCATION_ORIGIN_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
94
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_INVOCATION_ORIGIN_BLOCKED:'
|
|
95
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
90
96
|
|
|
91
97
|
try {
|
|
92
98
|
$payloadRaw = [Console]::In.ReadToEnd()
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
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
|
-
. (Join-Path $PSScriptRoot 'codex-epic-child-launch-attestation.ps1')
|
|
15
|
+
try { . (Join-Path $PSScriptRoot 'codex-epic-child-launch-attestation.ps1') } catch { Add-HookDependencyFailure -Name 'codex-epic-child-launch-attestation.ps1' -ErrorRecord $_ }
|
|
15
16
|
|
|
16
17
|
$script:AllowedDependencyStatuses = @('merged', 'worktree_removed')
|
|
17
18
|
|
|
@@ -178,6 +179,8 @@ function Invoke-CodexEpicWaveDecision {
|
|
|
178
179
|
[AllowEmptyString()][string] $RepositoryRoot = '',
|
|
179
180
|
[datetimeoffset] $Now = [datetimeoffset]::UtcNow
|
|
180
181
|
)
|
|
182
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WAVE_BARRIER_BLOCKED:'
|
|
183
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
181
184
|
|
|
182
185
|
$payload = ConvertFrom-CodexWaveJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
183
186
|
if (-not (Test-CodexWaveMutation -Payload $payload)) {
|
|
@@ -252,6 +255,9 @@ function Get-CodexPrimaryWorktreeRoot {
|
|
|
252
255
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
253
256
|
return
|
|
254
257
|
}
|
|
258
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_WAVE_BARRIER_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
259
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WAVE_BARRIER_BLOCKED:'
|
|
260
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
255
261
|
|
|
256
262
|
try {
|
|
257
263
|
$payloadRaw = [Console]::In.ReadToEnd()
|
|
@@ -4,12 +4,13 @@
|
|
|
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
9
|
# Shared command-line parser (issue #545). The scope filter and the operand extractor below
|
|
9
10
|
# both run against the segment that structurally invokes `git worktree remove`, which is what
|
|
10
11
|
# keeps the two runtimes on one implementation of the same concern.
|
|
11
|
-
. (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
|
|
12
|
-
. (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
|
|
12
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
13
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
13
14
|
|
|
14
15
|
$script:SafeWorktreeStatuses = @('merged', 'worktree_removed')
|
|
15
16
|
|
|
@@ -33,40 +34,6 @@ function ConvertFrom-CodexWorktreeJson {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
function Get-CodexWorktreeRemovalPath {
|
|
37
|
-
<#
|
|
38
|
-
.SYNOPSIS
|
|
39
|
-
Extract the target worktree path from a git worktree remove command.
|
|
40
|
-
.DESCRIPTION
|
|
41
|
-
The operand comes from the segment that structurally invokes git worktree remove, so
|
|
42
|
-
a chained 'cd <path> &&' segment contributes nothing and a quoted mention of the
|
|
43
|
-
phrase resolves to no operand. The tokenizer strips balanced double and single
|
|
44
|
-
quotes, which is what the previous pattern's `double` and `single` alternatives did.
|
|
45
|
-
|
|
46
|
-
The previous pattern accepted '--force' only immediately after 'remove'. That
|
|
47
|
-
spelling is preserved and the trailing spelling now works too, because '--force' is a
|
|
48
|
-
zero-argument flag that never contributes an operand wherever it is written. Its
|
|
49
|
-
presence is read structurally through Test-CommandLineFlag rather than by a raw-text
|
|
50
|
-
search. The empty-string-on-miss contract is unchanged: callers test `if ($target)`.
|
|
51
|
-
.OUTPUTS
|
|
52
|
-
System.String
|
|
53
|
-
#>
|
|
54
|
-
[CmdletBinding()]
|
|
55
|
-
[OutputType([string])]
|
|
56
|
-
param([Parameter(Mandatory)][AllowEmptyString()][string] $Command)
|
|
57
|
-
|
|
58
|
-
$hasForce = Test-CommandLineFlag -CommandText $Command -CommandWord 'git' -SubcommandPath @('worktree', 'remove') -FlagName '--force'
|
|
59
|
-
$operands = @(Get-CommandLineOperand -CommandText $Command -CommandWord 'git' -SubcommandPath @('worktree', 'remove'))
|
|
60
|
-
|
|
61
|
-
if ($operands.Count -gt 0) {
|
|
62
|
-
return [string]$operands[0]
|
|
63
|
-
}
|
|
64
|
-
if ($hasForce) {
|
|
65
|
-
return '--force'
|
|
66
|
-
}
|
|
67
|
-
return ''
|
|
68
|
-
}
|
|
69
|
-
|
|
70
37
|
function Get-NormalizedCodexWorktreePath {
|
|
71
38
|
[CmdletBinding()]
|
|
72
39
|
[OutputType([string])]
|
|
@@ -114,6 +81,8 @@ function Invoke-CodexWorktreeRemovalDecision {
|
|
|
114
81
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
115
82
|
[AllowNull()][AllowEmptyString()][string] $EpicCheckpointRaw
|
|
116
83
|
)
|
|
84
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_REMOVAL_BLOCKED:'
|
|
85
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
117
86
|
|
|
118
87
|
$payload = ConvertFrom-CodexWorktreeJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
119
88
|
if ([string]$payload.tool_name -ne 'Bash') {
|
|
@@ -126,18 +95,59 @@ function Invoke-CodexWorktreeRemovalDecision {
|
|
|
126
95
|
if (-not (Test-CommandLineInvocation -CommandText $command -CommandWord 'git' -SubcommandPath @('worktree', 'remove'))) {
|
|
127
96
|
return $null
|
|
128
97
|
}
|
|
129
|
-
|
|
98
|
+
# Issue #824: the removal targets are derived structurally from every invocation. A
|
|
99
|
+
# target that cannot be derived denies before the checkpoint is read, and every derived
|
|
100
|
+
# target must be authorized on its own.
|
|
101
|
+
$resolution = Resolve-CommandLineInvocationTarget -CommandText $command -CommandWord 'git' -SubcommandPath @('worktree', 'remove')
|
|
102
|
+
if ($resolution.Status -eq 'NoMatch') {
|
|
103
|
+
return $null
|
|
104
|
+
}
|
|
105
|
+
if ($resolution.Status -ne 'Targets') {
|
|
106
|
+
return [ordered]@{
|
|
107
|
+
hookSpecificOutput = [ordered]@{
|
|
108
|
+
hookEventName = 'PreToolUse'
|
|
109
|
+
permissionDecision = 'deny'
|
|
110
|
+
permissionDecisionReason = 'EPIC_WORKTREE_REMOVAL_BLOCKED: TARGET_WORKTREE_NOT_DERIVABLE: the git worktree remove target cannot be derived from the command text. No checkpoint can authorize this removal.'
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
130
114
|
$checkpoint = ConvertFrom-CodexWorktreeJson -Raw $EpicCheckpointRaw -Name 'epic checkpoint' -Optional
|
|
131
115
|
$workingDirectory = if ([string]::IsNullOrWhiteSpace([string]$payload.cwd)) {
|
|
132
116
|
(Get-Location).Path
|
|
133
117
|
} else {
|
|
134
118
|
[string]$payload.cwd
|
|
135
119
|
}
|
|
136
|
-
$
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
120
|
+
foreach ($target in @($resolution.Targets)) {
|
|
121
|
+
$denial = Get-CodexWorktreeRemovalTargetDenial -Target $target -Checkpoint $checkpoint -WorkingDirectory $workingDirectory
|
|
122
|
+
if ($null -ne $denial) {
|
|
123
|
+
return $denial
|
|
124
|
+
}
|
|
140
125
|
}
|
|
126
|
+
return $null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function Get-CodexWorktreeRemovalTargetDenial {
|
|
130
|
+
<#
|
|
131
|
+
.SYNOPSIS
|
|
132
|
+
Evaluate one derived removal target and return its deny decision, or $null when authorized.
|
|
133
|
+
.PARAMETER Target
|
|
134
|
+
One removal target derived by Resolve-CommandLineInvocationTarget.
|
|
135
|
+
.PARAMETER Checkpoint
|
|
136
|
+
The parsed epic checkpoint, or $null when absent or unreadable.
|
|
137
|
+
.PARAMETER WorkingDirectory
|
|
138
|
+
The directory a relative target resolves against.
|
|
139
|
+
.OUTPUTS
|
|
140
|
+
System.Collections.Specialized.OrderedDictionary or $null
|
|
141
|
+
#>
|
|
142
|
+
[CmdletBinding()]
|
|
143
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
144
|
+
param(
|
|
145
|
+
[Parameter(Mandatory)][string] $Target,
|
|
146
|
+
[AllowNull()] $Checkpoint,
|
|
147
|
+
[Parameter(Mandatory)][string] $WorkingDirectory
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
$feature = Find-CodexWorktreeFeature -Checkpoint $Checkpoint -TargetPath $Target -WorkingDirectory $WorkingDirectory
|
|
141
151
|
if ($null -ne $feature -and
|
|
142
152
|
@($feature.PSObject.Properties.Name) -contains 'merge_status' -and
|
|
143
153
|
$script:SafeWorktreeStatuses -contains [string]$feature.merge_status) {
|
|
@@ -156,6 +166,9 @@ function Invoke-CodexWorktreeRemovalDecision {
|
|
|
156
166
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
157
167
|
return
|
|
158
168
|
}
|
|
169
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_WORKTREE_REMOVAL_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
170
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_REMOVAL_BLOCKED:'
|
|
171
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
159
172
|
|
|
160
173
|
try {
|
|
161
174
|
$payloadRaw = [Console]::In.ReadToEnd()
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1
CHANGED
|
@@ -40,10 +40,11 @@
|
|
|
40
40
|
#>
|
|
41
41
|
[CmdletBinding()]
|
|
42
42
|
param()
|
|
43
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
43
44
|
|
|
44
45
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
45
46
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
46
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
47
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
47
48
|
|
|
48
49
|
function Test-EvidenceLocationForbidden {
|
|
49
50
|
<#
|
|
@@ -122,6 +123,8 @@ function Invoke-EvidenceLocationDecision {
|
|
|
122
123
|
param(
|
|
123
124
|
[string] $ToolInputRaw
|
|
124
125
|
)
|
|
126
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EVIDENCE_LOCATION_BLOCKED:'
|
|
127
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
125
128
|
|
|
126
129
|
if (-not $ToolInputRaw) {
|
|
127
130
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
@@ -192,5 +195,8 @@ function Invoke-EvidenceLocationEntryPoint {
|
|
|
192
195
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
193
196
|
return
|
|
194
197
|
}
|
|
198
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EVIDENCE_LOCATION_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
199
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EVIDENCE_LOCATION_BLOCKED:'
|
|
200
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
195
201
|
|
|
196
202
|
exit (Invoke-EvidenceLocationEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()))
|