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