@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
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Per-segment target resolution for the epic-scope decision of the preimplementation gate (issue #738).
|
|
4
|
+
.DESCRIPTION
|
|
5
|
+
Pure string logic only: no disk, process, network, clock, or environment access, and no
|
|
6
|
+
dot-source of its own. Every command segment and every path of a gated call is resolved to
|
|
7
|
+
the absolute worktree target it operates on, or the call is reported unresolvable with one
|
|
8
|
+
rule token, so the epic-scope decision can evaluate every target instead of the first
|
|
9
|
+
segment only. Resolution rules R0 to R7 and verdict rules V1 to V7 are defined in the
|
|
10
|
+
issue #732 feature folder plan, section 4.
|
|
11
|
+
|
|
12
|
+
Dot-sourced by enforce-orchestration-preimplementation-gate-epic-scope.ps1 on both the
|
|
13
|
+
Claude and the Codex surface; the four copies are byte-identical.
|
|
14
|
+
.NOTES
|
|
15
|
+
PowerShell 7+. Call-time dependencies, loaded by each gate's existing dot-source of
|
|
16
|
+
hook-command-invocation.ps1 (which itself dot-sources hook-command-scanner.ps1 and
|
|
17
|
+
hook-command-payload.ps1): Read-CommandLineSegment (segment records with IsWrapperLed and
|
|
18
|
+
HasLiveSubstitution), Get-CommandLineGlobalOption (the git global-option table), and
|
|
19
|
+
Get-CommandLineInvocation (the token-aware git add and git commit matcher, read for its
|
|
20
|
+
match count only). Never calls the command-line splitter or the command-line tokenizer
|
|
21
|
+
of the sibling helpers file.
|
|
22
|
+
#>
|
|
23
|
+
|
|
24
|
+
# Command words that change the working directory of later segments (rule R3).
|
|
25
|
+
$script:OrchestrationTargetDirectoryChangeWords = @(
|
|
26
|
+
'cd', 'pushd', 'popd', 'chdir', 'Set-Location', 'sl', 'Push-Location', 'Pop-Location'
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Environment names that relocate the git directory or work tree (rule R5).
|
|
30
|
+
$script:OrchestrationTargetRelocationNames = @('GIT_DIR', 'GIT_WORK_TREE', 'GIT_COMMON_DIR', 'GIT_INDEX_FILE')
|
|
31
|
+
# A relocation name not embedded in a longer identifier (issue #903, #732 CR-2).
|
|
32
|
+
$script:OrchestrationTargetRelocationPattern = '(?i)(?<![A-Za-z0-9_])(?:' +
|
|
33
|
+
($script:OrchestrationTargetRelocationNames -join '|') + ')(?![A-Za-z0-9_])'
|
|
34
|
+
|
|
35
|
+
# An absolute target: a drive-lettered or a rooted, non-UNC path after separator normalization.
|
|
36
|
+
$script:OrchestrationTargetAbsolutePattern = '^([A-Za-z]:/|/(?!/))'
|
|
37
|
+
|
|
38
|
+
# A non-local path-leg spelling, tested before normalization (issue #937): UNC, extended-length,
|
|
39
|
+
# device, or NT-object prefixes in either separator style, a drive-relative drive letter, a
|
|
40
|
+
# current-drive-rooted single backslash, a URI scheme, a ~-prefixed home path, or surrounding whitespace.
|
|
41
|
+
$script:OrchestrationTargetNonLocalPattern = '^(?:\s|[\\/]{2}|[\\/]\?\?[\\/]|\\(?![\\/])|[A-Za-z]:(?![\\/])' +
|
|
42
|
+
'|[A-Za-z][A-Za-z0-9+.-]+:|~)|\s$'
|
|
43
|
+
|
|
44
|
+
# The apply_patch markers whose path names a file the patch writes (Codex path leg).
|
|
45
|
+
$script:OrchestrationPatchMarkers = @('*** Add File:', '*** Update File:', '*** Delete File:', '*** Move to:')
|
|
46
|
+
|
|
47
|
+
function ConvertTo-OrchestrationTargetPath {
|
|
48
|
+
<#
|
|
49
|
+
.SYNOPSIS
|
|
50
|
+
Normalizes a session root or a path-leg input to forward slashes.
|
|
51
|
+
.DESCRIPTION
|
|
52
|
+
Replaces every backslash with a forward slash and removes one trailing slash, except
|
|
53
|
+
from a bare root. Never applied to a -C selector value, which is judged as written.
|
|
54
|
+
.OUTPUTS
|
|
55
|
+
System.String
|
|
56
|
+
#>
|
|
57
|
+
[CmdletBinding()]
|
|
58
|
+
[OutputType([string])]
|
|
59
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Path)
|
|
60
|
+
|
|
61
|
+
$normalized = $Path.Replace('\', '/')
|
|
62
|
+
if ($normalized.Length -gt 1 -and $normalized.EndsWith('/') -and $normalized -notmatch '^[A-Za-z]:/$') {
|
|
63
|
+
$normalized = $normalized.Substring(0, $normalized.Length - 1)
|
|
64
|
+
}
|
|
65
|
+
return $normalized
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function Get-OrchestrationPatchMarkerPath {
|
|
69
|
+
<#
|
|
70
|
+
.SYNOPSIS
|
|
71
|
+
Returns the file paths an apply_patch text names, or an empty array.
|
|
72
|
+
.DESCRIPTION
|
|
73
|
+
Recognized only when the first non-empty line is `*** Begin Patch`. Each Add File,
|
|
74
|
+
Update File, Delete File, and Move to marker contributes its trimmed path.
|
|
75
|
+
.OUTPUTS
|
|
76
|
+
System.String[]
|
|
77
|
+
#>
|
|
78
|
+
[CmdletBinding()]
|
|
79
|
+
[OutputType([string[]])]
|
|
80
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $PatchText)
|
|
81
|
+
|
|
82
|
+
$lines = @($PatchText -split "`r?`n")
|
|
83
|
+
$first = @($lines | Where-Object { $_.Trim() }) | Select-Object -First 1
|
|
84
|
+
if ($null -eq $first -or $first.Trim() -cne '*** Begin Patch') {
|
|
85
|
+
return [string[]]@()
|
|
86
|
+
}
|
|
87
|
+
$paths = [System.Collections.Generic.List[string]]::new()
|
|
88
|
+
foreach ($line in $lines) {
|
|
89
|
+
foreach ($marker in $script:OrchestrationPatchMarkers) {
|
|
90
|
+
if ($line.StartsWith($marker, [System.StringComparison]::Ordinal)) {
|
|
91
|
+
$paths.Add($line.Substring($marker.Length).Trim())
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [string[]]$paths.ToArray()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function Test-OrchestrationTargetDotSegment {
|
|
99
|
+
# True when a forward-slash path carries a '.' or '..' segment.
|
|
100
|
+
[CmdletBinding()]
|
|
101
|
+
[OutputType([bool])]
|
|
102
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Path)
|
|
103
|
+
|
|
104
|
+
$segments = @($Path -split '/')
|
|
105
|
+
return ($segments -contains '.' -or $segments -contains '..')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function New-OrchestrationTargetResult {
|
|
109
|
+
# Builds the FR-3 result object; an unresolved result carries no targets.
|
|
110
|
+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
|
111
|
+
'PSUseShouldProcessForStateChangingFunctions', '',
|
|
112
|
+
Justification = 'Pure in-memory factory that changes no system state.')]
|
|
113
|
+
[CmdletBinding()]
|
|
114
|
+
[OutputType([pscustomobject])]
|
|
115
|
+
param(
|
|
116
|
+
[AllowEmptyCollection()][string[]] $Targets = @(),
|
|
117
|
+
[AllowEmptyString()][string] $Rule = '',
|
|
118
|
+
[AllowEmptyString()][string] $Value = ''
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if ($Rule) {
|
|
122
|
+
Write-Debug "PREIMPL_TARGET_UNRESOLVABLE: ${Rule}: $Value"
|
|
123
|
+
return [pscustomobject]@{
|
|
124
|
+
Resolved = $false; Targets = [string[]]@(); ReasonCode = 'target-unresolvable'; Detail = "${Rule}: $Value"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return [pscustomobject]@{ Resolved = $true; Targets = [string[]]$Targets; ReasonCode = ''; Detail = '' }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function Get-OrchestrationGitSelectorTarget {
|
|
131
|
+
<#
|
|
132
|
+
.SYNOPSIS
|
|
133
|
+
Walks the git global options of one segment record and returns its -C targets or a failure.
|
|
134
|
+
.DESCRIPTION
|
|
135
|
+
Rules R5 (option form) and R6. Returns an object with Rule and Value set on failure, and
|
|
136
|
+
Selectors holding every -C value otherwise (empty when the segment has no -C).
|
|
137
|
+
.OUTPUTS
|
|
138
|
+
System.Management.Automation.PSCustomObject
|
|
139
|
+
#>
|
|
140
|
+
[CmdletBinding()]
|
|
141
|
+
[OutputType([pscustomobject])]
|
|
142
|
+
param([Parameter(Mandatory)][AllowEmptyCollection()][AllowEmptyString()][string[]] $Token)
|
|
143
|
+
|
|
144
|
+
$table = Get-CommandLineGlobalOption -CommandWord 'git'
|
|
145
|
+
$gitIndex = [array]::IndexOf($Token, 'git')
|
|
146
|
+
if ($gitIndex -lt 0) {
|
|
147
|
+
return [pscustomobject]@{ Rule = 'git-command-word-missing'; Value = ''; Selectors = [string[]]@() }
|
|
148
|
+
}
|
|
149
|
+
$start = $gitIndex + 1
|
|
150
|
+
$selectors = [System.Collections.Generic.List[string]]::new()
|
|
151
|
+
$relocation = ''
|
|
152
|
+
$unmodeled = ''
|
|
153
|
+
$missing = $false
|
|
154
|
+
$index = $start
|
|
155
|
+
while ($index -lt $Token.Count -and $Token[$index].StartsWith('-')) {
|
|
156
|
+
$name = $Token[$index]
|
|
157
|
+
$value = $null
|
|
158
|
+
$equals = $name.IndexOf('=')
|
|
159
|
+
if ($name.StartsWith('--') -and $equals -gt 0) {
|
|
160
|
+
$value = $name.Substring($equals + 1)
|
|
161
|
+
$name = $name.Substring(0, $equals)
|
|
162
|
+
}
|
|
163
|
+
if ($table.WithArgument -ccontains $name) {
|
|
164
|
+
if ($null -eq $value) {
|
|
165
|
+
$index++
|
|
166
|
+
if ($index -lt $Token.Count) {
|
|
167
|
+
$value = $Token[$index]
|
|
168
|
+
}
|
|
169
|
+
elseif ($name -ceq '-C') {
|
|
170
|
+
$missing = $true
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
$value = ''
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} elseif ($table.Standalone -notcontains $name -and $table.Terminal -notcontains $name) {
|
|
177
|
+
$unmodeled = $name
|
|
178
|
+
break
|
|
179
|
+
}
|
|
180
|
+
$isWorktreeConfig = $name -ceq '-c' -and $null -ne $value -and
|
|
181
|
+
$value.StartsWith('core.worktree', [System.StringComparison]::OrdinalIgnoreCase)
|
|
182
|
+
if ($name -ceq '--git-dir' -or $name -ceq '--work-tree' -or $isWorktreeConfig) {
|
|
183
|
+
if (-not $relocation) { $relocation = "$name $value".Trim() }
|
|
184
|
+
}
|
|
185
|
+
if ($name -ceq '-C' -and -not $missing) { $selectors.Add($value) }
|
|
186
|
+
$index++
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
$rule = ''; $value = ''
|
|
190
|
+
if ($relocation) { $rule = 'git-relocation'; $value = $relocation }
|
|
191
|
+
elseif ($unmodeled) { $rule = 'git-option-unmodeled'; $value = $unmodeled }
|
|
192
|
+
elseif ($missing) { $rule = 'selector-missing-value'; $value = '-C' }
|
|
193
|
+
foreach ($selector in $selectors) {
|
|
194
|
+
if ($rule) { break }
|
|
195
|
+
if ($selector.Contains('\')) { $rule = 'selector-backslash' }
|
|
196
|
+
elseif ($selector -notmatch $script:OrchestrationTargetAbsolutePattern) { $rule = 'selector-not-absolute' }
|
|
197
|
+
elseif (Test-OrchestrationTargetDotSegment -Path $selector) { $rule = 'selector-dot-segment' }
|
|
198
|
+
$value = $selector
|
|
199
|
+
}
|
|
200
|
+
if ($rule) { return [pscustomobject]@{ Rule = $rule; Value = $value; Selectors = [string[]]@() } }
|
|
201
|
+
return [pscustomobject]@{ Rule = ''; Value = ''; Selectors = [string[]]$selectors.ToArray() }
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function Get-OrchestrationCommandTarget {
|
|
205
|
+
<#
|
|
206
|
+
.SYNOPSIS
|
|
207
|
+
Resolves every command segment and path of a gated call to its absolute target worktree.
|
|
208
|
+
.DESCRIPTION
|
|
209
|
+
Rules R0 to R7 (first failing rule decides). Returns Resolved, Targets (ordinal
|
|
210
|
+
case-insensitive distinct, first-seen order), ReasonCode ('' or target-unresolvable),
|
|
211
|
+
and Detail (a rule token, ': ', and the offending text or value).
|
|
212
|
+
.OUTPUTS
|
|
213
|
+
System.Management.Automation.PSCustomObject
|
|
214
|
+
#>
|
|
215
|
+
[CmdletBinding()]
|
|
216
|
+
[OutputType([pscustomobject])]
|
|
217
|
+
param(
|
|
218
|
+
[AllowNull()][AllowEmptyString()][string] $Command = '',
|
|
219
|
+
[AllowNull()][AllowEmptyCollection()][string[]] $FilePath = @(),
|
|
220
|
+
[Parameter(Mandatory)][AllowEmptyString()][string] $SessionRoot
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
$root = ConvertTo-OrchestrationTargetPath -Path $SessionRoot
|
|
224
|
+
if ($root -notmatch $script:OrchestrationTargetAbsolutePattern) {
|
|
225
|
+
return (New-OrchestrationTargetResult -Rule 'session-root-not-absolute' -Value $SessionRoot)
|
|
226
|
+
}
|
|
227
|
+
$targets = [System.Collections.Generic.List[string]]::new()
|
|
228
|
+
|
|
229
|
+
foreach ($rawPath in @($FilePath | Where-Object { $_ })) {
|
|
230
|
+
if ($rawPath -match $script:OrchestrationTargetNonLocalPattern) {
|
|
231
|
+
return (New-OrchestrationTargetResult -Rule 'path-not-local' -Value $rawPath)
|
|
232
|
+
}
|
|
233
|
+
$path = ConvertTo-OrchestrationTargetPath -Path $rawPath
|
|
234
|
+
if ($path -notmatch $script:OrchestrationTargetAbsolutePattern) { $targets.Add($root); continue }
|
|
235
|
+
if (Test-OrchestrationTargetDotSegment -Path $path) {
|
|
236
|
+
return (New-OrchestrationTargetResult -Rule 'path-dot-segment' -Value $rawPath)
|
|
237
|
+
}
|
|
238
|
+
$targets.Add($path)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if ($Command) {
|
|
242
|
+
$records = @(Read-CommandLineSegment -CommandText $Command)
|
|
243
|
+
if ($records.Count -eq 0) { $targets.Add($root) }
|
|
244
|
+
foreach ($record in $records) {
|
|
245
|
+
$text = ([string]$record.RawText).Trim()
|
|
246
|
+
if ($record.Unbalanced) { return (New-OrchestrationTargetResult -Rule 'segment-unbalanced' -Value $text) }
|
|
247
|
+
if ($script:OrchestrationTargetDirectoryChangeWords -contains [string]$record.CommandWord) {
|
|
248
|
+
return (New-OrchestrationTargetResult -Rule 'directory-change' -Value $text)
|
|
249
|
+
}
|
|
250
|
+
$wrapped = [bool]$record.IsWrapperLed -or [bool]$record.HasLiveSubstitution
|
|
251
|
+
if ($wrapped) {
|
|
252
|
+
$matchCount = 0
|
|
253
|
+
foreach ($sub in @('add', 'commit')) {
|
|
254
|
+
$invocationArguments = @{
|
|
255
|
+
CommandText = $record.RawText; CommandWord = 'git'; SubcommandPath = @($sub)
|
|
256
|
+
}
|
|
257
|
+
$matchCount += @(Get-CommandLineInvocation @invocationArguments).Count
|
|
258
|
+
}
|
|
259
|
+
if ($matchCount -gt 0) { return (New-OrchestrationTargetResult -Rule 'wrapper-git' -Value $text) }
|
|
260
|
+
}
|
|
261
|
+
if ($text -match $script:OrchestrationTargetRelocationPattern) {
|
|
262
|
+
return (New-OrchestrationTargetResult -Rule 'git-relocation' -Value $text)
|
|
263
|
+
}
|
|
264
|
+
if ($wrapped -or [string]$record.CommandWord -cne 'git') { $targets.Add($root); continue }
|
|
265
|
+
$git = Get-OrchestrationGitSelectorTarget -Token ([string[]]@($record.Tokens))
|
|
266
|
+
if ($git.Rule) { return (New-OrchestrationTargetResult -Rule $git.Rule -Value $git.Value) }
|
|
267
|
+
if ($git.Selectors.Count -eq 0) {
|
|
268
|
+
$targets.Add($root)
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
foreach ($selector in $git.Selectors) { $targets.Add($selector) }
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
$distinct = [System.Collections.Generic.List[string]]::new()
|
|
277
|
+
foreach ($target in $targets) {
|
|
278
|
+
$seen = $distinct | Where-Object { [string]::Equals($_, $target, [System.StringComparison]::OrdinalIgnoreCase) }
|
|
279
|
+
if (-not $seen) { $distinct.Add($target) }
|
|
280
|
+
}
|
|
281
|
+
return (New-OrchestrationTargetResult -Targets $distinct.ToArray())
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function Resolve-OrchestrationEpicTargetVerdict {
|
|
285
|
+
<#
|
|
286
|
+
.SYNOPSIS
|
|
287
|
+
Decides the epic-scope verdict for a resolved or unresolved target result.
|
|
288
|
+
.DESCRIPTION
|
|
289
|
+
Verdict rules V1 to V7. Resolves the session-root scope with an empty selector and each
|
|
290
|
+
target scope with the target as selector, each distinct key (ordinal
|
|
291
|
+
case-insensitive) at most once; a target equal to the session root reuses its scope.
|
|
292
|
+
Returns Verdict ('none', 'deny', or 'evaluate'), ReasonCode, Detail, and Evaluations
|
|
293
|
+
(one Target, IsSessionRoot, Scope entry per target when the verdict is evaluate).
|
|
294
|
+
.OUTPUTS
|
|
295
|
+
System.Management.Automation.PSCustomObject
|
|
296
|
+
#>
|
|
297
|
+
[CmdletBinding()]
|
|
298
|
+
[OutputType([pscustomobject])]
|
|
299
|
+
param(
|
|
300
|
+
[Parameter(Mandatory)][AllowEmptyString()][string] $SessionRoot,
|
|
301
|
+
[Parameter(Mandatory)][pscustomobject] $TargetResult,
|
|
302
|
+
[Parameter(Mandatory)][scriptblock] $ScopeResolver
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
$root = ConvertTo-OrchestrationTargetPath -Path $SessionRoot
|
|
306
|
+
$cache = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
|
307
|
+
$cache[$root] = & $ScopeResolver ''
|
|
308
|
+
$evaluations = [System.Collections.Generic.List[pscustomobject]]::new()
|
|
309
|
+
if ($TargetResult.Resolved) {
|
|
310
|
+
foreach ($target in @($TargetResult.Targets)) {
|
|
311
|
+
if (-not $cache.ContainsKey($target)) { $cache[$target] = & $ScopeResolver $target }
|
|
312
|
+
$isSessionRoot = [string]::Equals($target, $root, [System.StringComparison]::OrdinalIgnoreCase)
|
|
313
|
+
$evaluations.Add([pscustomobject]@{
|
|
314
|
+
Target = $target; IsSessionRoot = $isSessionRoot; Scope = $cache[$target]
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
$relevant = @($cache.Values | Where-Object { $_.IsEpicScope -or $_.Reason -eq 'target-worktree-ambiguous' })
|
|
320
|
+
$code = ''; $detail = ''
|
|
321
|
+
if ($relevant.Count -eq 0) {
|
|
322
|
+
return [pscustomobject]@{ Verdict = 'none'; ReasonCode = ''; Detail = ''; Evaluations = @() }
|
|
323
|
+
}
|
|
324
|
+
if (-not $TargetResult.Resolved) {
|
|
325
|
+
$code = 'target-unresolvable'; $detail = [string]$TargetResult.Detail
|
|
326
|
+
}
|
|
327
|
+
$ambiguous = @($evaluations | Where-Object { $_.Scope.Reason -eq 'target-worktree-ambiguous' })
|
|
328
|
+
$unresolved = @($evaluations | Where-Object { $_.Scope.Reason -eq 'selector-unresolved' })
|
|
329
|
+
$mixed = @($evaluations | Where-Object { -not $_.Scope.IsEpicScope })
|
|
330
|
+
if (-not $code -and $ambiguous.Count -gt 0) { $code = 'target-ambiguous'; $detail = $ambiguous[0].Target }
|
|
331
|
+
if (-not $code -and $unresolved.Count -gt 0) {
|
|
332
|
+
$code = 'target-unresolvable'; $detail = "selector-unresolved: $($unresolved[0].Target)"
|
|
333
|
+
}
|
|
334
|
+
if (-not $code -and $mixed.Count -gt 0) { $code = 'target-mixed'; $detail = $mixed[0].Target }
|
|
335
|
+
if ($code) {
|
|
336
|
+
return [pscustomobject]@{ Verdict = 'deny'; ReasonCode = $code; Detail = $detail; Evaluations = @() }
|
|
337
|
+
}
|
|
338
|
+
return [pscustomobject]@{ Verdict = 'evaluate'; ReasonCode = ''; Detail = ''; Evaluations = $evaluations.ToArray() }
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function Get-OrchestrationEpicTargetDenyReason {
|
|
342
|
+
<#
|
|
343
|
+
.SYNOPSIS
|
|
344
|
+
Builds the deny reason of an epic-scope target verdict or a not-ready target.
|
|
345
|
+
.DESCRIPTION
|
|
346
|
+
One string per code, behind the unchanged PREIMPLEMENTATION_GATE_BLOCKED prefix:
|
|
347
|
+
target-unresolvable (Detail is the rule detail), target-ambiguous and target-mixed
|
|
348
|
+
(Detail is the target), and target-not-ready (Detail is the target, with the
|
|
349
|
+
consulted checkpoint path and the failed readiness predicate).
|
|
350
|
+
.OUTPUTS
|
|
351
|
+
System.String
|
|
352
|
+
#>
|
|
353
|
+
[CmdletBinding()]
|
|
354
|
+
[OutputType([string])]
|
|
355
|
+
param(
|
|
356
|
+
[Parameter(Mandatory)][string] $ReasonCode,
|
|
357
|
+
[AllowEmptyString()][string] $Detail = '',
|
|
358
|
+
[AllowEmptyString()][string] $CheckpointPath = '',
|
|
359
|
+
[AllowEmptyString()][string] $Failure = ''
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
$prefix = "PREIMPLEMENTATION_GATE_BLOCKED: ${ReasonCode}: "
|
|
363
|
+
switch ($ReasonCode) {
|
|
364
|
+
'target-ambiguous' {
|
|
365
|
+
return $prefix + "more than one worktree claims the epic integration branch for target $Detail. " +
|
|
366
|
+
'Implementation operations in epic scope require an unambiguous target worktree.'
|
|
367
|
+
}
|
|
368
|
+
'target-mixed' {
|
|
369
|
+
return $prefix + "target $Detail is not in the epic scope that governs this operation. " +
|
|
370
|
+
'Implementation operations in epic scope may not also target a worktree outside it.'
|
|
371
|
+
}
|
|
372
|
+
'target-not-ready' {
|
|
373
|
+
return $prefix + "the epic-scope target $Detail was evaluated against $CheckpointPath, " +
|
|
374
|
+
"and the failed readiness predicate is '$Failure'. " +
|
|
375
|
+
'Implementation operations in epic scope require that checkpoint to satisfy every ' +
|
|
376
|
+
'readiness predicate, and a production path may be staged or edited only while a merge is in progress.'
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return $prefix + "the target worktree of this epic-scope operation cannot be resolved ($Detail). " +
|
|
380
|
+
'Implementation operations in epic scope require every command segment and path to name ' +
|
|
381
|
+
'an absolute, resolvable target.'
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function Resolve-OrchestrationEpicTargetOutcome {
|
|
385
|
+
<#
|
|
386
|
+
.SYNOPSIS
|
|
387
|
+
Decides the shared epic-scope outcome of a target verdict (issue #903, #732 CR-3).
|
|
388
|
+
.DESCRIPTION
|
|
389
|
+
Pure decision logic shared by the Claude and the Codex epic-scope gates; reads no file,
|
|
390
|
+
process, or environment value. Returns Outcome 'none' (not epic scope), 'deny' (with
|
|
391
|
+
the deny Reason), or 'allow' (empty Reason). The caller supplies the readiness predicate,
|
|
392
|
+
invoked as & $ReadinessFailure $evaluation.Scope; the first evaluation with a non-empty
|
|
393
|
+
failure denies, and the session-root wording is unchanged.
|
|
394
|
+
.OUTPUTS
|
|
395
|
+
System.Management.Automation.PSCustomObject
|
|
396
|
+
#>
|
|
397
|
+
[CmdletBinding()]
|
|
398
|
+
[OutputType([pscustomobject])]
|
|
399
|
+
param(
|
|
400
|
+
[Parameter(Mandatory)][pscustomobject] $Verdict,
|
|
401
|
+
[Parameter(Mandatory)][scriptblock] $ReadinessFailure
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
if ($Verdict.Verdict -eq 'none') {
|
|
405
|
+
return [pscustomobject]@{ Outcome = 'none'; Reason = '' }
|
|
406
|
+
}
|
|
407
|
+
if ($Verdict.Verdict -eq 'deny') {
|
|
408
|
+
$reason = Get-OrchestrationEpicTargetDenyReason -ReasonCode $Verdict.ReasonCode -Detail $Verdict.Detail
|
|
409
|
+
return [pscustomobject]@{ Outcome = 'deny'; Reason = $reason }
|
|
410
|
+
}
|
|
411
|
+
foreach ($evaluation in $Verdict.Evaluations) {
|
|
412
|
+
$scope = $evaluation.Scope
|
|
413
|
+
$failure = & $ReadinessFailure $evaluation.Scope
|
|
414
|
+
if (-not $failure) {
|
|
415
|
+
continue
|
|
416
|
+
}
|
|
417
|
+
if ($evaluation.IsSessionRoot) {
|
|
418
|
+
$reason = 'PREIMPLEMENTATION_GATE_BLOCKED: this epic-scope operation was evaluated against ' +
|
|
419
|
+
"$($scope.CheckpointPath), and the failed readiness predicate is '$failure'. " +
|
|
420
|
+
'Implementation operations in epic scope require that checkpoint to satisfy every ' +
|
|
421
|
+
'readiness predicate, and a production path may be staged or edited only while a merge is in progress.'
|
|
422
|
+
return [pscustomobject]@{ Outcome = 'deny'; Reason = $reason }
|
|
423
|
+
}
|
|
424
|
+
$reasonArguments = @{
|
|
425
|
+
ReasonCode = 'target-not-ready'
|
|
426
|
+
Detail = $evaluation.Target
|
|
427
|
+
CheckpointPath = $scope.CheckpointPath
|
|
428
|
+
Failure = $failure
|
|
429
|
+
}
|
|
430
|
+
return [pscustomobject]@{ Outcome = 'deny'; Reason = (Get-OrchestrationEpicTargetDenyReason @reasonArguments) }
|
|
431
|
+
}
|
|
432
|
+
return [pscustomobject]@{ Outcome = 'allow'; Reason = '' }
|
|
433
|
+
}
|
|
@@ -1,32 +1,38 @@
|
|
|
1
|
-
|
|
2
1
|
<#
|
|
3
2
|
.SYNOPSIS
|
|
4
3
|
Blocks implementation operations before orchestration readiness exists.
|
|
4
|
+
.DESCRIPTION
|
|
5
|
+
Executing shell (issue #735): Codex runs a command through PowerShell by default on native
|
|
6
|
+
Windows, but the model may choose another shell per call, and the PreToolUse payload carries
|
|
7
|
+
only the raw command string, so the executing shell is undetermined per command and every
|
|
8
|
+
shell-divergent command shape denies (research/research.2026-10-08T14-00.md in the issue
|
|
9
|
+
#732 feature folder). The payload carries no workdir either, so the session root is the
|
|
10
|
+
default target of a segment without an explicit -C (issue #738, decision D4).
|
|
5
11
|
#>
|
|
6
12
|
[CmdletBinding()]
|
|
7
13
|
param()
|
|
14
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
8
15
|
|
|
9
16
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
10
17
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
11
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
18
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
12
19
|
|
|
13
20
|
# Pure pathspec classifier for the issue #539 orchestration-bookkeeping staging exemption.
|
|
14
21
|
# Extracted to a dot-sourced sibling so this file stays inside the 500-line cap, following
|
|
15
22
|
# the headroom-split precedent already used on this side by enforce-completion-helpers.ps1.
|
|
16
|
-
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-helpers.ps1')
|
|
23
|
+
try { . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-helpers.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-orchestration-preimplementation-gate-helpers.ps1' -ErrorRecord $_ }
|
|
17
24
|
|
|
18
25
|
# Pure mode dispatch and per-mode readiness predicates for issue #554. A new sibling
|
|
19
26
|
# rather than an addition to the helpers file above, whose header declares a different
|
|
20
27
|
# normative contract and which lacks headroom; leaving that file byte-untouched is the
|
|
21
28
|
# proof the issue #539 exemption is behaviourally unchanged.
|
|
22
|
-
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-modes.ps1')
|
|
29
|
+
try { . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-modes.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-orchestration-preimplementation-gate-modes.ps1' -ErrorRecord $_ }
|
|
23
30
|
# Epic-scope command and path legs (issue #707, porting issue #663 decision D2), plus the
|
|
24
31
|
# two per-mode read seams relocated from this file to keep it inside the 500-line cap.
|
|
25
|
-
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-epic-scope.ps1')
|
|
32
|
+
try { . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-epic-scope.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-orchestration-preimplementation-gate-epic-scope.ps1' -ErrorRecord $_ }
|
|
26
33
|
# Shared command-line parser (issue #545): per-segment scan text and structural matching.
|
|
27
|
-
. (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
|
|
28
|
-
. (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
|
|
29
|
-
|
|
34
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
35
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
30
36
|
# The readiness checkpoint this gate reads and names in its block message.
|
|
31
37
|
$script:CheckpointPath = 'artifacts/orchestration/orchestrator-state.json'
|
|
32
38
|
|
|
@@ -357,6 +363,8 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
357
363
|
[AllowEmptyString()]
|
|
358
364
|
[string] $ParallelCheckpointRaw
|
|
359
365
|
)
|
|
366
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PREIMPLEMENTATION_GATE_BLOCKED:'
|
|
367
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
360
368
|
|
|
361
369
|
if (-not $ToolInputRaw) {
|
|
362
370
|
return Get-OrchestrationPreimplementationGateAllowDecision
|
|
@@ -424,11 +432,13 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
424
432
|
$modeCheckpoint = ConvertFrom-CheckpointJson -Json ([string]$modeRaw)
|
|
425
433
|
} catch { $modeCheckpoint = $null }
|
|
426
434
|
$folder = Find-OrchestrationDelegationTargetFolder -Prompt $prompt
|
|
427
|
-
|
|
435
|
+
# Only the keyed issue number breaks a tie among cited folders (#565 CR-1); the bare hash form feeds the D3 record lookup only.
|
|
436
|
+
$issue = Find-OrchestrationDelegationIssueNumber -Prompt $prompt -KeyedOnly
|
|
437
|
+
$fallbackIssue = Find-OrchestrationDelegationIssueNumber -Prompt $prompt
|
|
428
438
|
$failure = if ($isEpic) {
|
|
429
|
-
Get-EpicOrchestrationReadinessFailure -Checkpoint $modeCheckpoint -TargetFolder $folder -IssueNumber $issue
|
|
439
|
+
Get-EpicOrchestrationReadinessFailure -Checkpoint $modeCheckpoint -TargetFolder $folder -IssueNumber $issue -FallbackIssueNumber $fallbackIssue
|
|
430
440
|
} else {
|
|
431
|
-
Get-ParallelOrchestrationReadinessFailure -Checkpoint $modeCheckpoint -TargetFolder $folder -IssueNumber $issue
|
|
441
|
+
Get-ParallelOrchestrationReadinessFailure -Checkpoint $modeCheckpoint -TargetFolder $folder -IssueNumber $issue -FallbackIssueNumber $fallbackIssue
|
|
432
442
|
}
|
|
433
443
|
if (-not $failure) { return Get-OrchestrationPreimplementationGateAllowDecision }
|
|
434
444
|
return Get-OrchestrationPreimplementationGateBlockDecision -Reason (
|
|
@@ -453,6 +463,9 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
453
463
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
454
464
|
return
|
|
455
465
|
}
|
|
466
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PREIMPLEMENTATION_GATE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
467
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PREIMPLEMENTATION_GATE_BLOCKED:'
|
|
468
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
456
469
|
|
|
457
470
|
try {
|
|
458
471
|
$payload = ConvertFrom-CodexPreToolUsePayload -PayloadRaw ([Console]::In.ReadToEnd()) -HookName 'enforce-orchestration-preimplementation-gate'
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1
CHANGED
|
@@ -45,13 +45,14 @@
|
|
|
45
45
|
#>
|
|
46
46
|
[CmdletBinding()]
|
|
47
47
|
param()
|
|
48
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
48
49
|
|
|
49
50
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
50
51
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
51
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
52
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
52
53
|
|
|
53
54
|
# Shared route helpers; this file is byte-identical to the Claude runtime copy.
|
|
54
|
-
. (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1')
|
|
55
|
+
try { . (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-batch-budget-route.ps1' -ErrorRecord $_ }
|
|
55
56
|
|
|
56
57
|
function Get-PowerShellBatchBudgetState {
|
|
57
58
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'TestCap', Justification = 'Accepted and ignored for callers written against the removed test-file cap.')]
|
|
@@ -134,6 +135,8 @@ function Invoke-PowerShellBatchBudgetDecision {
|
|
|
134
135
|
[AllowEmptyString()]
|
|
135
136
|
[string] $ObservedRoute = ''
|
|
136
137
|
)
|
|
138
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'POWERSHELL_LARGE_PATH_REQUIRED:'
|
|
139
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
137
140
|
|
|
138
141
|
$normalized = $FilePath -replace '\\', '/'
|
|
139
142
|
if ($normalized -notmatch '\.(ps1|psm1|psd1)$') {
|
|
@@ -330,6 +333,9 @@ function Invoke-PowerShellBatchBudgetCodexEntryPoint {
|
|
|
330
333
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
331
334
|
return
|
|
332
335
|
}
|
|
336
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('POWERSHELL_LARGE_PATH_REQUIRED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
337
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'POWERSHELL_LARGE_PATH_REQUIRED:'
|
|
338
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
333
339
|
|
|
334
340
|
# The entry point returns its [int] exit code as the last pipeline element and any
|
|
335
341
|
# deny JSON before it, so the JSON is written explicitly before the process exits.
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1
CHANGED
|
@@ -28,12 +28,13 @@
|
|
|
28
28
|
#>
|
|
29
29
|
[CmdletBinding()]
|
|
30
30
|
param()
|
|
31
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
31
32
|
|
|
32
33
|
# Shared command-line parser (issue #545). Every forbidden-token scan and both `gh`
|
|
33
34
|
# expressions below run against each segment's clause-ordered scan text, and the
|
|
34
35
|
# structural matcher reaches the relocating `gh` spellings adjacency cannot.
|
|
35
|
-
. (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
|
|
36
|
-
. (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
|
|
36
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
37
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
37
38
|
|
|
38
39
|
$script:PromotionMcpOnlyBlockedReason = 'PROMOTION_MCP_ONLY_BLOCKED: Direct Bash promotion-script execution is not allowed in agent sessions. Use the drm-copilot MCP promotion tools instead.'
|
|
39
40
|
|
|
@@ -109,9 +110,12 @@ function Get-PromotionBypassReason {
|
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
# `gh issue create` and `gh issue new` are direct bypasses of the MCP
|
|
112
|
-
# promotion path. Tolerate any flags after the subcommand.
|
|
113
|
+
# promotion path. Tolerate any flags after the subcommand. The adjacency
|
|
114
|
+
# expression reads the masked text, so a quoted mention is not a match; wrapper
|
|
115
|
+
# payloads and substitution bodies are covered by the structural check below
|
|
116
|
+
# (issue #824).
|
|
113
117
|
foreach ($segment in $segments) {
|
|
114
|
-
if ($segment.
|
|
118
|
+
if ($segment.MaskedText -match '(?i)\bgh\s+issue\s+(?:create|new)\b') {
|
|
115
119
|
return (Get-PromotionMcpOnlyGhIssueBlockedReason)
|
|
116
120
|
}
|
|
117
121
|
}
|
|
@@ -224,6 +228,8 @@ function Invoke-PromotionMcpOnlyDecision {
|
|
|
224
228
|
param(
|
|
225
229
|
[string] $ToolInputRaw
|
|
226
230
|
)
|
|
231
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PROMOTION_MCP_ONLY_BLOCKED:'
|
|
232
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
227
233
|
|
|
228
234
|
if (-not $ToolInputRaw) {
|
|
229
235
|
return Get-PromotionMcpOnlyAllowDecision
|
|
@@ -273,6 +279,9 @@ function ConvertFrom-CodexPromotionHookPayload {
|
|
|
273
279
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
274
280
|
return
|
|
275
281
|
}
|
|
282
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PROMOTION_MCP_ONLY_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
283
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PROMOTION_MCP_ONLY_BLOCKED:'
|
|
284
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
276
285
|
|
|
277
286
|
try {
|
|
278
287
|
$payload = ConvertFrom-CodexPromotionHookPayload -PayloadRaw ([Console]::In.ReadToEnd())
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1
CHANGED
|
@@ -45,13 +45,14 @@
|
|
|
45
45
|
#>
|
|
46
46
|
[CmdletBinding()]
|
|
47
47
|
param()
|
|
48
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
48
49
|
|
|
49
50
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
50
51
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
51
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
52
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
52
53
|
|
|
53
54
|
# Shared route helpers; this file is byte-identical to the Claude runtime copy.
|
|
54
|
-
. (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1')
|
|
55
|
+
try { . (Join-Path $PSScriptRoot 'enforce-batch-budget-route.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-batch-budget-route.ps1' -ErrorRecord $_ }
|
|
55
56
|
|
|
56
57
|
function Get-PythonBatchBudgetState {
|
|
57
58
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'TestCap', Justification = 'Accepted and ignored for callers written against the removed test-file cap.')]
|
|
@@ -137,6 +138,8 @@ function Invoke-PythonBatchBudgetDecision {
|
|
|
137
138
|
[AllowEmptyString()]
|
|
138
139
|
[string] $ObservedRoute = ''
|
|
139
140
|
)
|
|
141
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PYTHON_LARGE_PATH_REQUIRED:'
|
|
142
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
140
143
|
|
|
141
144
|
$normalized = $FilePath -replace '\\', '/'
|
|
142
145
|
if ($normalized -notmatch '\.py$') {
|
|
@@ -333,6 +336,9 @@ function Invoke-PythonBatchBudgetCodexEntryPoint {
|
|
|
333
336
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
334
337
|
return
|
|
335
338
|
}
|
|
339
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('PYTHON_LARGE_PATH_REQUIRED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
340
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'PYTHON_LARGE_PATH_REQUIRED:'
|
|
341
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
336
342
|
|
|
337
343
|
# The entry point returns its [int] exit code as the last pipeline element and any
|
|
338
344
|
# deny JSON before it, so the JSON is written explicitly before the process exits.
|