@danmoisan/drm-copilot-mcp 0.0.1
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/LICENSE +21 -0
- package/README.md +50 -0
- package/out/mcp-server.js +17323 -0
- package/package.json +36 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/MEMORY.md +3 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_repo_root_is_source_of_truth.md +11 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_vsce_verify_package_location.md +19 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/project_extension_location.md +11 -0
- package/resources/claude-customizations/.claude/agent-memory/prd-feature/MEMORY.md +1 -0
- package/resources/claude-customizations/.claude/agent-memory/prd-feature/project_push_down_pattern.md +13 -0
- package/resources/claude-customizations/.claude/agent-memory/task-researcher/MEMORY.md +3 -0
- package/resources/claude-customizations/.claude/agent-memory/task-researcher/project_push_down_claude_dir.md +11 -0
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +135 -0
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +71 -0
- package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +69 -0
- package/resources/claude-customizations/.claude/agents/epic-review.md +40 -0
- package/resources/claude-customizations/.claude/agents/feature-review.md +136 -0
- package/resources/claude-customizations/.claude/agents/orchestrator.md +83 -0
- package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +80 -0
- package/resources/claude-customizations/.claude/agents/prd-feature.md +42 -0
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +72 -0
- package/resources/claude-customizations/.claude/agents/staged-review.md +41 -0
- package/resources/claude-customizations/.claude/agents/status-updater.md +41 -0
- package/resources/claude-customizations/.claude/agents/task-researcher.md +81 -0
- package/resources/claude-customizations/.claude/agents/typescript-engineer.md +24 -0
- package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +111 -0
- package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +146 -0
- package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +150 -0
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +238 -0
- package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +147 -0
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +235 -0
- package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +69 -0
- package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +296 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +389 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +141 -0
- package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +288 -0
- package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +171 -0
- package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +142 -0
- package/resources/claude-customizations/.claude/rules/csharp.md +62 -0
- package/resources/claude-customizations/.claude/rules/general-code-change.md +71 -0
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +60 -0
- package/resources/claude-customizations/.claude/rules/powershell.md +97 -0
- package/resources/claude-customizations/.claude/rules/python-suppressions.md +143 -0
- package/resources/claude-customizations/.claude/rules/python.md +99 -0
- package/resources/claude-customizations/.claude/rules/self-explanatory-code-commenting.md +97 -0
- package/resources/claude-customizations/.claude/rules/tonality.md +80 -0
- package/resources/claude-customizations/.claude/rules/typescript-suppressions.md +66 -0
- package/resources/claude-customizations/.claude/rules/typescript.md +45 -0
- package/resources/claude-customizations/.claude/settings.json +144 -0
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +102 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +189 -0
- package/resources/claude-customizations/.claude/skills/commit-message/SKILL.md +65 -0
- package/resources/claude-customizations/.claude/skills/csharp-change-budget-router/SKILL.md +90 -0
- package/resources/claude-customizations/.claude/skills/csharp-orchestration-state-machine/SKILL.md +58 -0
- package/resources/claude-customizations/.claude/skills/csharp-qa-gate/SKILL.md +77 -0
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +164 -0
- package/resources/claude-customizations/.claude/skills/execute-hard-lock/SKILL.md +82 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +115 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +167 -0
- package/resources/claude-customizations/.claude/skills/fill-feature-docs/SKILL.md +22 -0
- package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +64 -0
- package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +65 -0
- package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +64 -0
- package/resources/claude-customizations/.claude/skills/make-skill-template/SKILL.md +147 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +132 -0
- package/resources/claude-customizations/.claude/skills/policy-audit-template-usage/SKILL.md +49 -0
- package/resources/claude-customizations/.claude/skills/policy-compliance-order/SKILL.md +40 -0
- package/resources/claude-customizations/.claude/skills/powershell-change-budget-router/SKILL.md +49 -0
- package/resources/claude-customizations/.claude/skills/powershell-orchestration-state-machine/SKILL.md +58 -0
- package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +77 -0
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +50 -0
- package/resources/claude-customizations/.claude/skills/pr-base-branch-merge-base/SKILL.md +56 -0
- package/resources/claude-customizations/.claude/skills/pr-context-artifacts/SKILL.md +30 -0
- package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +79 -0
- package/resources/claude-customizations/.claude/skills/python-qa-gate/SKILL.md +77 -0
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +40 -0
- package/resources/claude-customizations/.claude/skills/research-issue/SKILL.md +67 -0
- package/resources/claude-customizations/.claude/skills/review-epic/SKILL.md +21 -0
- package/resources/claude-customizations/.claude/skills/review-feature/SKILL.md +25 -0
- package/resources/claude-customizations/.claude/skills/review-staged/SKILL.md +21 -0
- package/resources/claude-customizations/.claude/skills/skill-canonical-location-audit/SKILL.md +49 -0
- package/resources/claude-customizations/.claude/skills/translate-copilot-to-claude/SKILL.md +295 -0
- package/resources/claude-customizations/.claude/skills/update-status/SKILL.md +21 -0
- package/resources/claude-dir-customizations/.mcp.json +8 -0
- package/resources/codex-and-agents-customizations/.agents/README.md +86 -0
- package/resources/codex-and-agents-customizations/.agents/skills/README.md +49 -0
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +107 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +73 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +194 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +87 -0
- package/resources/codex-and-agents-customizations/.agents/skills/commit-message/SKILL.md +70 -0
- package/resources/codex-and-agents-customizations/.agents/skills/commit-message-conventions/SKILL.md +95 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +67 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-change-budget-router/SKILL.md +94 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-orchestration-state-machine/SKILL.md +64 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +82 -0
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +168 -0
- package/resources/codex-and-agents-customizations/.agents/skills/execute-hard-lock/SKILL.md +88 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +129 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +106 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +181 -0
- package/resources/codex-and-agents-customizations/.agents/skills/fill-feature-docs/SKILL.md +27 -0
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-csharp-engineer/SKILL.md +73 -0
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +74 -0
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +73 -0
- package/resources/codex-and-agents-customizations/.agents/skills/make-skill-template/SKILL.md +152 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +143 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +317 -0
- package/resources/codex-and-agents-customizations/.agents/skills/policy-audit-template-usage/SKILL.md +53 -0
- package/resources/codex-and-agents-customizations/.agents/skills/policy-compliance-order/SKILL.md +49 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +102 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-change-budget-router/SKILL.md +53 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-orchestration-state-machine/SKILL.md +64 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-qa-gate/SKILL.md +83 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-author/SKILL.md +55 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-authoring/SKILL.md +124 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-base-branch-merge-base/SKILL.md +60 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-context-artifacts/SKILL.md +34 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python/SKILL.md +104 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +84 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python-qa-gate/SKILL.md +82 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python-suppressions/SKILL.md +148 -0
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +49 -0
- package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/SKILL.md +142 -0
- package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/agents/openai.yaml +5 -0
- package/resources/codex-and-agents-customizations/.agents/skills/research-issue/SKILL.md +72 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-epic/SKILL.md +26 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-feature/SKILL.md +30 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-staged/SKILL.md +26 -0
- package/resources/codex-and-agents-customizations/.agents/skills/self-explanatory-code-commenting/SKILL.md +102 -0
- package/resources/codex-and-agents-customizations/.agents/skills/skill-canonical-location-audit/SKILL.md +52 -0
- package/resources/codex-and-agents-customizations/.agents/skills/translate-copilot-to-claude/SKILL.md +317 -0
- package/resources/codex-and-agents-customizations/.agents/skills/typescript/SKILL.md +50 -0
- package/resources/codex-and-agents-customizations/.agents/skills/typescript-suppressions/SKILL.md +71 -0
- package/resources/codex-and-agents-customizations/.agents/skills/update-status/SKILL.md +26 -0
- package/resources/codex-and-agents-customizations/.codex/agents/5.1-beast-adjusted.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/5.1-thinking-beast-mode-adjusted.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/api-architect.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +151 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +93 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planning.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/commentary-remediation.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward.toml +20 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-executor.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +25 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-orchestrator.toml +56 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +97 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-review.toml +52 -0
- package/resources/codex-and-agents-customizations/.codex/agents/expert-nextjs-developer.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/expert-react-frontend-engineer.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +149 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +60 -0
- package/resources/codex-and-agents-customizations/.codex/agents/gpt-5-beast-mode.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/hlbpa.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/mentor.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +121 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-executor.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +25 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-di-unit-test-engineer.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-orchestrator.toml +56 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +108 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author.toml +26 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature.toml +53 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pytest-unit-test-coding.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-executor.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.toml +25 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-execution-only-typed.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +54 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +100 -0
- package/resources/codex-and-agents-customizations/.codex/agents/staged-review.toml +53 -0
- package/resources/codex-and-agents-customizations/.codex/agents/status-updater.toml +53 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher.toml +103 -0
- package/resources/codex-and-agents-customizations/.codex/agents/tdd-green.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/tdd-red.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/tdd-refactor.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer.toml +48 -0
- package/resources/codex-and-agents-customizations/.codex/agents/voidbeast-gpt41enhanced.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.plan.md +26 -0
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +384 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +137 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +113 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +149 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +153 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +241 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +150 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +238 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +72 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +265 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/feature-review-remediate.md +10 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/generate-commit-message-repo.md +11 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/generate-pr.md +15 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/orchestrate-work.md +22 -0
- package/resources/codex-and-agents-customizations/AGENTS.md +317 -0
- package/resources/customizations/.github/agents/5.1-Beast-adjusted.agent.md +181 -0
- package/resources/customizations/.github/agents/5.1-Thinking-Beast-Mode-adjusted.agent.md +361 -0
- package/resources/customizations/.github/agents/Powershell DI Unit Test Engineer.agent.md +192 -0
- package/resources/customizations/.github/agents/api-architect.agent.md +40 -0
- package/resources/customizations/.github/agents/atomic_executor.agent.md +251 -0
- package/resources/customizations/.github/agents/atomic_planning.agent.md +658 -0
- package/resources/customizations/.github/agents/commentary-remediation.agent.md +35 -0
- package/resources/customizations/.github/agents/commit-steward.agent.md +200 -0
- package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +288 -0
- package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +354 -0
- package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +375 -0
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +285 -0
- package/resources/customizations/.github/agents/epic-review.agent.md +374 -0
- package/resources/customizations/.github/agents/expert-nextjs-developer.agent.md +477 -0
- package/resources/customizations/.github/agents/expert-react-frontend-engineer.agent.md +739 -0
- package/resources/customizations/.github/agents/feature-review.agent.md +49 -0
- package/resources/customizations/.github/agents/gpt-5-beast-mode.agent.md +116 -0
- package/resources/customizations/.github/agents/hlbpa.agent.md +219 -0
- package/resources/customizations/.github/agents/mentor.agent.md +32 -0
- package/resources/customizations/.github/agents/orchestrator.agent.md +449 -0
- package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +287 -0
- package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +647 -0
- package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +382 -0
- package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +293 -0
- package/resources/customizations/.github/agents/pr-author.agent.md +138 -0
- package/resources/customizations/.github/agents/prd-feature.agent.md +52 -0
- package/resources/customizations/.github/agents/prd.agent.md +202 -0
- package/resources/customizations/.github/agents/pytest-unit-test-coding.agent.md +202 -0
- package/resources/customizations/.github/agents/python-atomic-executor.agent.md +289 -0
- package/resources/customizations/.github/agents/python-atomic-planning.agent.md +429 -0
- package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +217 -0
- package/resources/customizations/.github/agents/python-orchestrator.agent.md +380 -0
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +271 -0
- package/resources/customizations/.github/agents/staged-review.agent.md +246 -0
- package/resources/customizations/.github/agents/status_updater.agent.md +279 -0
- package/resources/customizations/.github/agents/task-researcher.agent.md +298 -0
- package/resources/customizations/.github/agents/tdd-green.agent.md +60 -0
- package/resources/customizations/.github/agents/tdd-red.agent.md +66 -0
- package/resources/customizations/.github/agents/tdd-refactor.agent.md +94 -0
- package/resources/customizations/.github/agents/typescript-engineer.agent.md +167 -0
- package/resources/customizations/.github/agents/voidbeast-gpt41enhanced.agent.md +230 -0
- package/resources/customizations/.github/codex/execute-hard-lock.prompt.md +105 -0
- package/resources/customizations/.github/codex/resume-hard-lock.prompt.md +92 -0
- package/resources/customizations/.github/copilot-instructions.md +7 -0
- package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +184 -0
- package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +52 -0
- package/resources/customizations/.github/instructions/general-code-change.instructions.md +290 -0
- package/resources/customizations/.github/instructions/general-unit-test.instructions.md +106 -0
- package/resources/customizations/.github/instructions/github-actions-ci-cd-best-practices.instructions.md +607 -0
- package/resources/customizations/.github/instructions/github-actions.instructions.md +23 -0
- package/resources/customizations/.github/instructions/powershell-code-change.instructions.md +81 -0
- package/resources/customizations/.github/instructions/powershell-unit-test.instructions.md +69 -0
- package/resources/customizations/.github/instructions/python-code-change.instructions.md +232 -0
- package/resources/customizations/.github/instructions/python-suppressions.instructions.md +609 -0
- package/resources/customizations/.github/instructions/python-unit-test.instructions.md +71 -0
- package/resources/customizations/.github/instructions/self-explanatory-code-commenting.instructions.md +238 -0
- package/resources/customizations/.github/instructions/tonality.instructions.md +133 -0
- package/resources/customizations/.github/instructions/typescript-code-change.instructions.md +203 -0
- package/resources/customizations/.github/instructions/typescript-suppressions.instructions.md +157 -0
- package/resources/customizations/.github/instructions/typescript-unit-test.instructions.md +112 -0
- package/resources/customizations/.github/prompts/add-educational-comments.prompt.md +129 -0
- package/resources/customizations/.github/prompts/breakdown-bug-prd.prompt.md +29 -0
- package/resources/customizations/.github/prompts/breakdown-epic-arch.prompt.md +66 -0
- package/resources/customizations/.github/prompts/breakdown-epic-pm.prompt.md +58 -0
- package/resources/customizations/.github/prompts/breakdown-feature-implementation.prompt.md +128 -0
- package/resources/customizations/.github/prompts/breakdown-feature-prd.prompt.md +61 -0
- package/resources/customizations/.github/prompts/code-exemplars-blueprint-generator.prompt.md +126 -0
- package/resources/customizations/.github/prompts/drafts/create-github-issues-feature-from-implementation-plan.prompt.md +28 -0
- package/resources/customizations/.github/prompts/drafts/create-implementation-plan.prompt.md +158 -0
- package/resources/customizations/.github/prompts/drafts/create-technical-spike.prompt.md +231 -0
- package/resources/customizations/.github/prompts/drafts/potential-feature-prd.prompt.md +19 -0
- package/resources/customizations/.github/prompts/drafts/update-implementation-plan.prompt.md +158 -0
- package/resources/customizations/.github/prompts/execute-plan-template.md +21 -0
- package/resources/customizations/.github/prompts/export-chat.prompt.md +7 -0
- package/resources/customizations/.github/prompts/fillout-prd-feature.prompt.md +46 -0
- package/resources/customizations/.github/prompts/generate-atomic-plan.prompt.md +96 -0
- package/resources/customizations/.github/prompts/generate-commit-message-repo.prompt.md +108 -0
- package/resources/customizations/.github/prompts/generate-pr.prompt.md +151 -0
- package/resources/customizations/.github/prompts/javascript-typescript-jest.prompt.md +44 -0
- package/resources/customizations/.github/prompts/orchestrate-csharp-work.prompt.md +66 -0
- package/resources/customizations/.github/prompts/orchestrate-powershell-work.prompt.md +50 -0
- package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +50 -0
- package/resources/customizations/.github/prompts/orchestrate-work.prompt.md +66 -0
- package/resources/customizations/.github/prompts/remediate-comments.prompt.md +53 -0
- package/resources/customizations/.github/prompts/research-issue.prompt.md +125 -0
- package/resources/customizations/.github/prompts/review-epic.prompt.md +94 -0
- package/resources/customizations/.github/prompts/review-feature.prompt.md +130 -0
- package/resources/customizations/.github/prompts/review-staged.prompt.md +43 -0
- package/resources/customizations/.github/prompts/update_status.prompt.md +68 -0
- package/resources/customizations/.github/skills/README.md +26 -0
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +102 -0
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +174 -0
- package/resources/customizations/.github/skills/csharp-change-budget-router/SKILL.md +48 -0
- package/resources/customizations/.github/skills/csharp-orchestration-state-machine/SKILL.md +57 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +135 -0
- package/resources/customizations/.github/skills/feature-promotion-lifecycle/SKILL.md +121 -0
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +153 -0
- package/resources/customizations/.github/skills/make-skill-template/SKILL.md +147 -0
- package/resources/customizations/.github/skills/policy-audit-template-usage/SKILL.md +48 -0
- package/resources/customizations/.github/skills/policy-compliance-order/SKILL.md +37 -0
- package/resources/customizations/.github/skills/powershell-change-budget-router/SKILL.md +48 -0
- package/resources/customizations/.github/skills/powershell-orchestration-state-machine/SKILL.md +57 -0
- package/resources/customizations/.github/skills/pr-base-branch-merge-base/SKILL.md +55 -0
- package/resources/customizations/.github/skills/pr-context-artifacts/SKILL.md +29 -0
- package/resources/customizations/.github/skills/remediation-handoff-atomic-planner/SKILL.md +39 -0
- package/resources/customizations/.github/skills/skill-canonical-location-audit/SKILL.md +48 -0
- package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +44 -0
- package/resources/feature-templates/bug/potential_bug.md +59 -0
- package/resources/feature-templates/bug/spec.md +99 -0
- package/resources/feature-templates/epic/initiative.md +43 -0
- package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +53 -0
- package/resources/feature-templates/feature/spec.md +66 -0
- package/resources/feature-templates/feature/user-story.md +42 -0
- package/resources/feature-templates/potential/template.md +33 -0
- package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +52 -0
- package/resources/feature-templates/refactor/spec.md +69 -0
- package/resources/powershell/PoshQC/PoshQC.Analyzer.psm1 +254 -0
- package/resources/powershell/PoshQC/PoshQC.FileDiscovery.psm1 +138 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +409 -0
- package/resources/powershell/PoshQC/PoshQC.psd1 +31 -0
- package/resources/powershell/PoshQC/PoshQC.psm1 +101 -0
- package/resources/powershell/PoshQC/README.md +80 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +59 -0
- package/resources/powershell/PoshQC/settings/pssa.settings.psd1 +55 -0
- package/resources/scripts/dev_tools/__init__.py +0 -0
- package/resources/scripts/dev_tools/agentic_sync.py +819 -0
- package/resources/scripts/dev_tools/codex_native_converter/__init__.py +11 -0
- package/resources/scripts/dev_tools/codex_native_converter/__main__.py +6 -0
- package/resources/scripts/dev_tools/codex_native_converter/cli.py +11 -0
- package/resources/scripts/dev_tools/new_active_feature_folder.py +79 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_docs.py +268 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_flow.py +366 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_io.py +306 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_markdown.py +252 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_models.py +136 -0
- package/resources/scripts/dev_tools/new_potential_bug_entry.py +465 -0
- package/resources/scripts/dev_tools/potential_to_issue.py +421 -0
- package/resources/scripts/dev_tools/potential_to_issue_content.py +212 -0
- package/resources/scripts/dev_tools/pr_context/__init__.py +0 -0
- package/resources/scripts/dev_tools/pr_context/collector.py +619 -0
- package/resources/scripts/dev_tools/pr_context/feature_docs.py +349 -0
- package/resources/scripts/dev_tools/pr_context/git.py +153 -0
- package/resources/scripts/dev_tools/pr_context/github.py +549 -0
- package/resources/scripts/dev_tools/pr_context/models.py +198 -0
- package/resources/scripts/dev_tools/pr_context/render.py +342 -0
- package/resources/scripts/dev_tools/pr_context/render_feature_excerpts.py +256 -0
- package/resources/scripts/dev_tools/pr_context/render_pr_helpers.py +291 -0
- package/resources/scripts/dev_tools/pr_context/summary_helpers.py +386 -0
- package/resources/scripts/dev_tools/pr_context/verification_evidence.py +171 -0
- package/resources/scripts/dev_tools/prompt_mode_contract.py +152 -0
- package/resources/scripts/dev_tools/push_down_claude_customizations.py +188 -0
- package/resources/scripts/dev_tools/push_down_codex_and_agents_customizations.py +139 -0
- package/resources/scripts/dev_tools/push_down_copilot_customizations.py +504 -0
- package/resources/scripts/dev_tools/push_down_copilot_customizations_filesystem.py +217 -0
- package/resources/scripts/dev_tools/push_down_copilot_customizations_rewrites.py +293 -0
- package/resources/scripts/dev_tools/resolve_file_prompt.py +457 -0
- package/resources/scripts/dev_tools/resolve_hard_lock_prompt.py +444 -0
- package/resources/scripts/dev_tools/validate_orchestration_artifacts.py +554 -0
- package/resources/templates/codex_native_converter.py +35 -0
- package/resources/templates/collect_commit_context.py +212 -0
- package/resources/templates/collect_pr_context.py +74 -0
- package/resources/templates/hello_pwsh.ps1 +3 -0
- package/resources/templates/hello_python.py +11 -0
- package/resources/templates/link-parent-child.ps1 +480 -0
- package/resources/templates/new-claude-worktree-session.ps1 +232 -0
- package/resources/templates/new-potential-entry.ps1 +187 -0
- package/resources/templates/new_active_feature_folder.py +67 -0
- package/resources/templates/new_potential_bug_entry.py +54 -0
- package/resources/templates/policy_audit/AGENTS.md +117 -0
- package/resources/templates/policy_audit/code-review.yyyy-MM-ddTHH-mm.md +165 -0
- package/resources/templates/policy_audit/feature-audit.yyyy-MM-ddTHH-mm.md +124 -0
- package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +649 -0
- package/resources/templates/potential_to_issue.py +55 -0
- package/resources/templates/push_down_claude_customizations.py +188 -0
- package/resources/templates/push_down_codex_and_agents_customizations.py +95 -0
- package/resources/templates/push_down_copilot_customizations.py +124 -0
- package/resources/templates/resolve_atomic_plan_prompt.py +75 -0
- package/resources/templates/resolve_hard_lock_prompt.py +65 -0
- package/resources/templates/run-poshqc-analyze-autofix.ps1 +16 -0
- package/resources/templates/run-poshqc-analyze.ps1 +26 -0
- package/resources/templates/run-poshqc-format.ps1 +26 -0
- package/resources/templates/run-poshqc-suite.ps1 +24 -0
- package/resources/templates/run-poshqc-test.ps1 +32 -0
- package/resources/templates/sync-agents-from-instructions.ps1 +400 -0
- package/resources/templates/validate_orchestration_artifacts.py +55 -0
- package/resources/templates/vscode-cli.helpers.ps1 +63 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Pre-tool-use hook for Claude Code that blocks forbidden patterns in Python unit tests.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
This script is invoked by the Claude Code PreToolUse hook before any Write or Edit
|
|
7
|
+
operation on a file path matching tests/**/*.py. It reads the tool input from the
|
|
8
|
+
CLAUDE_TOOL_INPUT environment variable (JSON with 'file_path' and a content field:
|
|
9
|
+
'content' for Write, 'new_string' for Edit) and rejects the operation when the
|
|
10
|
+
proposed content introduces forbidden runtime dependencies.
|
|
11
|
+
|
|
12
|
+
Forbidden patterns in unit tests include:
|
|
13
|
+
- temporary filesystem usage (tempfile, NamedTemporaryFile, TemporaryDirectory,
|
|
14
|
+
mkstemp, mkdtemp, Path.touch)
|
|
15
|
+
- network access (requests, httpx, urllib.request, socket, http.client)
|
|
16
|
+
- subprocess execution (subprocess, os.system, os.popen)
|
|
17
|
+
- time-based flakiness (time.sleep)
|
|
18
|
+
- real database drivers (psycopg2, pymysql, sqlite3.connect on real files)
|
|
19
|
+
|
|
20
|
+
If the content contains any forbidden pattern, the script writes a JSON response
|
|
21
|
+
to stdout with 'decision': 'block' and exits with code 0 to let Claude Code surface
|
|
22
|
+
the reason.
|
|
23
|
+
|
|
24
|
+
.NOTES
|
|
25
|
+
Compatible with PowerShell 7+.
|
|
26
|
+
This script must not modify any state; it is a read-only validation gate.
|
|
27
|
+
It only inspects tool inputs targeting tests/ paths; all other paths pass through.
|
|
28
|
+
#>
|
|
29
|
+
[CmdletBinding()]
|
|
30
|
+
param()
|
|
31
|
+
|
|
32
|
+
function Get-PythonTestPurityBlockDecision {
|
|
33
|
+
[CmdletBinding()]
|
|
34
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
35
|
+
param(
|
|
36
|
+
[Parameter(Mandatory)]
|
|
37
|
+
[string] $Reason
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
[ordered]@{
|
|
41
|
+
decision = 'block'
|
|
42
|
+
reason = $Reason
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function Test-PythonTestFilePath {
|
|
47
|
+
[CmdletBinding()]
|
|
48
|
+
[OutputType([bool])]
|
|
49
|
+
param(
|
|
50
|
+
[Parameter(Mandatory)]
|
|
51
|
+
[string] $FilePath
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
$normalized = $FilePath -replace '\\', '/'
|
|
55
|
+
return (($normalized -match '(^|/)tests/.*\.py$') -or ($normalized -match '(^|/)test_[^/]+\.py$'))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function Invoke-PythonTestPurityDecision {
|
|
59
|
+
[CmdletBinding()]
|
|
60
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
61
|
+
param(
|
|
62
|
+
[string] $ToolInputRaw
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if (-not $ToolInputRaw) {
|
|
66
|
+
return [ordered]@{ decision = 'allow' }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
71
|
+
} catch {
|
|
72
|
+
return Get-PythonTestPurityBlockDecision -Reason 'Python unit test purity hook received malformed JSON in CLAUDE_TOOL_INPUT.'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
$filePath = $toolInput.file_path
|
|
76
|
+
if (-not $filePath) {
|
|
77
|
+
return [ordered]@{ decision = 'allow' }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (-not (Test-PythonTestFilePath -FilePath $filePath)) {
|
|
81
|
+
return [ordered]@{ decision = 'allow' }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
$content = $null
|
|
85
|
+
if ($null -ne $toolInput.content) {
|
|
86
|
+
$content = [string]$toolInput.content
|
|
87
|
+
} elseif ($null -ne $toolInput.new_string) {
|
|
88
|
+
$content = [string]$toolInput.new_string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (-not $content) {
|
|
92
|
+
return [ordered]@{ decision = 'allow' }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
$forbiddenPatterns = @(
|
|
96
|
+
@{ Pattern = 'import\s+tempfile'; Reason = 'tempfile usage forbidden in unit tests' },
|
|
97
|
+
@{ Pattern = 'from\s+tempfile\s+import'; Reason = 'tempfile usage forbidden in unit tests' },
|
|
98
|
+
@{ Pattern = 'NamedTemporaryFile'; Reason = 'temporary files forbidden in unit tests' },
|
|
99
|
+
@{ Pattern = 'TemporaryDirectory'; Reason = 'temporary directories forbidden in unit tests' },
|
|
100
|
+
@{ Pattern = '\bmkstemp\s*\('; Reason = 'temporary files forbidden in unit tests' },
|
|
101
|
+
@{ Pattern = '\bmkdtemp\s*\('; Reason = 'temporary directories forbidden in unit tests' },
|
|
102
|
+
@{ Pattern = '\.touch\s*\('; Reason = 'Path.touch forbidden in unit tests' },
|
|
103
|
+
@{ Pattern = 'import\s+requests\b'; Reason = 'network access forbidden in unit tests' },
|
|
104
|
+
@{ Pattern = 'from\s+requests\b'; Reason = 'network access forbidden in unit tests' },
|
|
105
|
+
@{ Pattern = 'import\s+httpx\b'; Reason = 'network access forbidden in unit tests' },
|
|
106
|
+
@{ Pattern = 'from\s+httpx\b'; Reason = 'network access forbidden in unit tests' },
|
|
107
|
+
@{ Pattern = 'urllib\.request'; Reason = 'network access forbidden in unit tests' },
|
|
108
|
+
@{ Pattern = 'import\s+socket\b'; Reason = 'raw socket access forbidden in unit tests' },
|
|
109
|
+
@{ Pattern = 'from\s+http\.client'; Reason = 'network access forbidden in unit tests' },
|
|
110
|
+
@{ Pattern = 'import\s+subprocess\b'; Reason = 'subprocess execution forbidden in unit tests' },
|
|
111
|
+
@{ Pattern = 'from\s+subprocess\s+import'; Reason = 'subprocess execution forbidden in unit tests' },
|
|
112
|
+
@{ Pattern = 'os\.system\s*\('; Reason = 'os.system forbidden in unit tests' },
|
|
113
|
+
@{ Pattern = 'os\.popen\s*\('; Reason = 'os.popen forbidden in unit tests' },
|
|
114
|
+
@{ Pattern = 'time\.sleep\s*\('; Reason = 'time.sleep forbidden in unit tests; avoid timing hacks' },
|
|
115
|
+
@{ Pattern = 'import\s+psycopg2\b'; Reason = 'real database drivers forbidden in unit tests' },
|
|
116
|
+
@{ Pattern = 'import\s+pymysql\b'; Reason = 'real database drivers forbidden in unit tests' },
|
|
117
|
+
@{ Pattern = 'sqlite3\.connect\s*\('; Reason = 'sqlite3.connect on real files forbidden in unit tests' }
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
$violations = @()
|
|
121
|
+
foreach ($entry in $forbiddenPatterns) {
|
|
122
|
+
if ($content -match $entry.Pattern) {
|
|
123
|
+
$violations += $entry.Reason
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if ($violations.Count -eq 0) {
|
|
128
|
+
return [ordered]@{ decision = 'allow' }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
$uniqueViolations = $violations | Select-Object -Unique
|
|
132
|
+
$reason = "Python unit test purity violations in '$filePath': " + ($uniqueViolations -join '; ') + ". Replace with pure code paths, dependency-injection seams, or in-memory fakes per .claude/rules/python.md."
|
|
133
|
+
|
|
134
|
+
return Get-PythonTestPurityBlockDecision -Reason $reason
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
$decision = Invoke-PythonTestPurityDecision -ToolInputRaw $env:CLAUDE_TOOL_INPUT
|
|
142
|
+
if ($decision.decision -eq 'block') {
|
|
143
|
+
$decision | ConvertTo-Json -Compress | Write-Output
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
exit 0
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Pre-tool-use hook that blocks writes to non-canonical evidence storage locations.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
This script is invoked by the Claude Code PreToolUse hook before any Write or Edit
|
|
7
|
+
operation. It reads the tool input from the CLAUDE_TOOL_INPUT environment variable
|
|
8
|
+
(JSON with a 'file_path' field) and rejects the operation when the target path is
|
|
9
|
+
a non-canonical evidence location.
|
|
10
|
+
|
|
11
|
+
Forbidden path prefixes (case-sensitive, normalized to forward-slash):
|
|
12
|
+
- artifacts/baselines/
|
|
13
|
+
- artifacts/baseline/
|
|
14
|
+
- artifacts/qa/
|
|
15
|
+
- artifacts/qa-gates/
|
|
16
|
+
- artifacts/coverage/
|
|
17
|
+
- artifacts/evidence/
|
|
18
|
+
- artifacts/regression-testing/
|
|
19
|
+
- artifacts/post-change/
|
|
20
|
+
|
|
21
|
+
All other paths pass through, including canonical evidence paths of the form
|
|
22
|
+
<FEATURE>/evidence/<kind>/ and permitted artifacts/ sub-paths such as
|
|
23
|
+
artifacts/orchestration/, artifacts/research/, artifacts/pr_context,
|
|
24
|
+
artifacts/reviews/, artifacts/status/, artifacts/python/, artifacts/pester/,
|
|
25
|
+
and artifacts/csharp/.
|
|
26
|
+
|
|
27
|
+
If the file_path resolves to a forbidden prefix, the script writes a JSON response
|
|
28
|
+
to stdout with 'decision': 'block' and exits with code 0 so Claude Code surfaces
|
|
29
|
+
the reason. For allowed paths, 'decision': 'allow' is written to stdout and the
|
|
30
|
+
script exits 0. On hard failure (malformed JSON input), the script exits 1.
|
|
31
|
+
|
|
32
|
+
.NOTES
|
|
33
|
+
Compatible with PowerShell 7+.
|
|
34
|
+
This script must not modify any state; it is a read-only validation gate.
|
|
35
|
+
#>
|
|
36
|
+
[CmdletBinding()]
|
|
37
|
+
param()
|
|
38
|
+
|
|
39
|
+
function Test-EvidenceLocationForbidden {
|
|
40
|
+
<#
|
|
41
|
+
.SYNOPSIS
|
|
42
|
+
Returns $true when the supplied file path targets a forbidden evidence sub-path.
|
|
43
|
+
.PARAMETER FilePath
|
|
44
|
+
The raw file_path value from the Claude Code tool-input JSON.
|
|
45
|
+
#>
|
|
46
|
+
[CmdletBinding()]
|
|
47
|
+
[OutputType([bool])]
|
|
48
|
+
param(
|
|
49
|
+
[Parameter(Mandatory)]
|
|
50
|
+
[string] $FilePath
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Normalize separators so both absolute Windows paths and relative POSIX paths match.
|
|
54
|
+
$normalized = $FilePath -replace '\\', '/'
|
|
55
|
+
|
|
56
|
+
$forbiddenPrefixes = @(
|
|
57
|
+
'artifacts/baselines/',
|
|
58
|
+
'artifacts/baseline/',
|
|
59
|
+
'artifacts/qa/',
|
|
60
|
+
'artifacts/qa-gates/',
|
|
61
|
+
'artifacts/coverage/',
|
|
62
|
+
'artifacts/evidence/',
|
|
63
|
+
'artifacts/regression-testing/',
|
|
64
|
+
'artifacts/post-change/'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Match the prefix either at the start of the string or after any directory separator,
|
|
68
|
+
# to handle both relative and absolute path forms.
|
|
69
|
+
foreach ($prefix in $forbiddenPrefixes) {
|
|
70
|
+
$escapedPrefix = [regex]::Escape($prefix)
|
|
71
|
+
if ($normalized -match "(^|/)$escapedPrefix") {
|
|
72
|
+
return $true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return $false
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function Get-EvidenceLocationBlockDecision {
|
|
80
|
+
<#
|
|
81
|
+
.SYNOPSIS
|
|
82
|
+
Constructs a block-decision ordered dictionary for the supplied forbidden path.
|
|
83
|
+
.PARAMETER FilePath
|
|
84
|
+
The file path that triggered the block.
|
|
85
|
+
#>
|
|
86
|
+
[CmdletBinding()]
|
|
87
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
88
|
+
param(
|
|
89
|
+
[Parameter(Mandatory)]
|
|
90
|
+
[string] $FilePath
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
[ordered]@{
|
|
94
|
+
decision = 'block'
|
|
95
|
+
reason = "EVIDENCE_LOCATION_BLOCKED: '$FilePath' is not a canonical evidence location. Use <FEATURE>/evidence/<kind>/ instead. See .claude/skills/evidence-and-timestamp-conventions/SKILL.md for the canonical scheme."
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function Invoke-EvidenceLocationDecision {
|
|
100
|
+
<#
|
|
101
|
+
.SYNOPSIS
|
|
102
|
+
Parses the Claude Code tool-input JSON and returns an allow-or-block decision.
|
|
103
|
+
.PARAMETER ToolInputRaw
|
|
104
|
+
The raw JSON string from $env:CLAUDE_TOOL_INPUT. An empty or null value
|
|
105
|
+
results in an allow decision (non-file tool calls have no file_path).
|
|
106
|
+
#>
|
|
107
|
+
[CmdletBinding()]
|
|
108
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
109
|
+
param(
|
|
110
|
+
[string] $ToolInputRaw
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if (-not $ToolInputRaw) {
|
|
114
|
+
return [ordered]@{ decision = 'allow' }
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
119
|
+
} catch {
|
|
120
|
+
# Malformed JSON is a hard failure; caller exits 1 to surface the issue.
|
|
121
|
+
throw "enforce-evidence-locations hook received malformed JSON in CLAUDE_TOOL_INPUT: $_"
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
$filePath = $toolInput.file_path
|
|
125
|
+
if (-not $filePath) {
|
|
126
|
+
return [ordered]@{ decision = 'allow' }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (Test-EvidenceLocationForbidden -FilePath $filePath) {
|
|
130
|
+
return Get-EvidenceLocationBlockDecision -FilePath $filePath
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return [ordered]@{ decision = 'allow' }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Guard allows dot-sourcing in tests without executing the entrypoint.
|
|
137
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
$decision = Invoke-EvidenceLocationDecision -ToolInputRaw $env:CLAUDE_TOOL_INPUT
|
|
143
|
+
} catch {
|
|
144
|
+
Write-Error $_
|
|
145
|
+
exit 1
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
$decision | ConvertTo-Json -Compress | Write-Output
|
|
149
|
+
|
|
150
|
+
exit 0
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Pre-tool-use hook that enforces the PowerShell per-batch change budget.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
This script is invoked by the Claude Code PreToolUse hook before any Write or Edit
|
|
7
|
+
operation. When the target file is a PowerShell source file (.ps1, .psm1, .psd1),
|
|
8
|
+
it classifies the file as either production or test and checks the running count
|
|
9
|
+
against the per-batch cap:
|
|
10
|
+
- 3 production PowerShell files per batch
|
|
11
|
+
- 3 test PowerShell files per batch
|
|
12
|
+
|
|
13
|
+
A "batch" is scoped to the current Claude Code session. The running count is
|
|
14
|
+
persisted under .claude/state/powershell-batch-budget.<session_id>.json. Only
|
|
15
|
+
distinct file paths are counted; repeated edits to the same file consume one slot.
|
|
16
|
+
|
|
17
|
+
Test files are those matching:
|
|
18
|
+
- tests/**/*.ps1
|
|
19
|
+
- *.Tests.ps1
|
|
20
|
+
|
|
21
|
+
All other .ps1/.psm1/.psd1 files are treated as production files. Non-PowerShell
|
|
22
|
+
paths pass through.
|
|
23
|
+
|
|
24
|
+
The cap may be overridden per session by setting the environment variable
|
|
25
|
+
CLAUDE_POWERSHELL_BUDGET_PROD or CLAUDE_POWERSHELL_BUDGET_TEST to a positive integer
|
|
26
|
+
before the session starts, or by writing {"prodCap": N, "testCap": M} into the
|
|
27
|
+
state file.
|
|
28
|
+
|
|
29
|
+
When the cap would be exceeded by a new file, the script emits a JSON response with
|
|
30
|
+
'decision': 'block' and exits 0. The session must explicitly reset the counter by
|
|
31
|
+
deleting the state file before starting a new batch. Files already counted are
|
|
32
|
+
always allowed through.
|
|
33
|
+
|
|
34
|
+
.NOTES
|
|
35
|
+
Compatible with PowerShell 7+.
|
|
36
|
+
#>
|
|
37
|
+
[CmdletBinding()]
|
|
38
|
+
param()
|
|
39
|
+
|
|
40
|
+
function Get-PowerShellBatchBudgetState {
|
|
41
|
+
[CmdletBinding()]
|
|
42
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
43
|
+
param(
|
|
44
|
+
[Parameter(Mandatory)]
|
|
45
|
+
[int] $ProdCap,
|
|
46
|
+
|
|
47
|
+
[Parameter(Mandatory)]
|
|
48
|
+
[int] $TestCap
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
[ordered]@{
|
|
52
|
+
prodCap = $ProdCap
|
|
53
|
+
testCap = $TestCap
|
|
54
|
+
prodFiles = @()
|
|
55
|
+
testFiles = @()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function ConvertTo-PowerShellBatchBudgetState {
|
|
60
|
+
[CmdletBinding()]
|
|
61
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
62
|
+
param(
|
|
63
|
+
[Parameter(Mandatory)]
|
|
64
|
+
$InputObject,
|
|
65
|
+
|
|
66
|
+
[Parameter(Mandatory)]
|
|
67
|
+
[int] $ProdCap,
|
|
68
|
+
|
|
69
|
+
[Parameter(Mandatory)]
|
|
70
|
+
[int] $TestCap
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
$state = Get-PowerShellBatchBudgetState -ProdCap $ProdCap -TestCap $TestCap
|
|
74
|
+
if ($null -ne $InputObject.prodCap) { $state.prodCap = [int]$InputObject.prodCap }
|
|
75
|
+
if ($null -ne $InputObject.testCap) { $state.testCap = [int]$InputObject.testCap }
|
|
76
|
+
if ($null -ne $InputObject.prodFiles) { $state.prodFiles = @($InputObject.prodFiles) }
|
|
77
|
+
if ($null -ne $InputObject.testFiles) { $state.testFiles = @($InputObject.testFiles) }
|
|
78
|
+
|
|
79
|
+
return $state
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function Get-PowerShellBatchBudgetBlockDecision {
|
|
83
|
+
[CmdletBinding()]
|
|
84
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
85
|
+
param(
|
|
86
|
+
[Parameter(Mandatory)]
|
|
87
|
+
[string] $Reason,
|
|
88
|
+
|
|
89
|
+
[System.Collections.IDictionary] $State
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
$decision = [ordered]@{
|
|
93
|
+
decision = 'block'
|
|
94
|
+
reason = $Reason
|
|
95
|
+
}
|
|
96
|
+
if ($State) {
|
|
97
|
+
$decision.state = $State
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return $decision
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function Invoke-PowerShellBatchBudgetDecision {
|
|
104
|
+
[CmdletBinding()]
|
|
105
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
106
|
+
param(
|
|
107
|
+
[Parameter(Mandatory)]
|
|
108
|
+
[string] $FilePath,
|
|
109
|
+
|
|
110
|
+
[Parameter(Mandatory)]
|
|
111
|
+
[System.Collections.IDictionary] $State,
|
|
112
|
+
|
|
113
|
+
[Parameter(Mandatory)]
|
|
114
|
+
[string] $StateFile
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
$normalized = $FilePath -replace '\\', '/'
|
|
118
|
+
if ($normalized -notmatch '\.(ps1|psm1|psd1)$') {
|
|
119
|
+
return [ordered]@{ decision = 'allow'; state = $State; shouldWriteState = $false }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
$isTestFile = ($normalized -match '(^|/)tests/.*\.ps1$') -or ($normalized -match '\.Tests\.ps1$')
|
|
123
|
+
$targetList = if ($isTestFile) { @($State.testFiles) } else { @($State.prodFiles) }
|
|
124
|
+
$cap = if ($isTestFile) { [int]$State.testCap } else { [int]$State.prodCap }
|
|
125
|
+
$kind = if ($isTestFile) { 'test' } else { 'production' }
|
|
126
|
+
|
|
127
|
+
if ($targetList -contains $normalized) {
|
|
128
|
+
return [ordered]@{ decision = 'allow'; state = $State; shouldWriteState = $false }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if ($targetList.Count -ge $cap) {
|
|
132
|
+
$currentFiles = ($targetList -join ', ')
|
|
133
|
+
$kindUpper = $kind.ToUpperInvariant()
|
|
134
|
+
$reason = "PowerShell per-batch budget exceeded: $kind file cap is $cap and is already full ($currentFiles). Requested new file: $normalized. Split the work into a new batch, raise the cap via CLAUDE_POWERSHELL_BUDGET_$kindUpper environment variable with approved scope, or reset the batch by deleting $StateFile."
|
|
135
|
+
return Get-PowerShellBatchBudgetBlockDecision -Reason $reason -State $State
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if ($isTestFile) {
|
|
139
|
+
$State.testFiles = @($State.testFiles) + @($normalized)
|
|
140
|
+
} else {
|
|
141
|
+
$State.prodFiles = @($State.prodFiles) + @($normalized)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return [ordered]@{ decision = 'allow'; state = $State; shouldWriteState = $true }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function Invoke-PowerShellBatchBudgetHook {
|
|
148
|
+
[CmdletBinding()]
|
|
149
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
150
|
+
param(
|
|
151
|
+
[string] $ToolInputRaw,
|
|
152
|
+
[string] $SessionId = 'default',
|
|
153
|
+
[string] $Root = (Get-Location).Path,
|
|
154
|
+
[int] $ProdCap = 3,
|
|
155
|
+
[int] $TestCap = 3,
|
|
156
|
+
[scriptblock] $TestPathExists = { param([string] $Path) Test-Path -Path $Path },
|
|
157
|
+
[scriptblock] $EnsureDirectory = { param([string] $Path) New-Item -ItemType Directory -Path $Path -Force | Out-Null },
|
|
158
|
+
[scriptblock] $ReadState = { param([string] $Path) Get-Content -Path $Path -Raw },
|
|
159
|
+
[scriptblock] $WriteState = {
|
|
160
|
+
param([string] $Path, [System.Collections.IDictionary] $State)
|
|
161
|
+
$State | ConvertTo-Json -Depth 5 | Set-Content -Path $Path -Encoding UTF8
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
if (-not $ToolInputRaw) {
|
|
166
|
+
return [ordered]@{ decision = 'allow' }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
171
|
+
} catch {
|
|
172
|
+
return Get-PowerShellBatchBudgetBlockDecision -Reason 'PowerShell batch-budget hook received malformed JSON in CLAUDE_TOOL_INPUT.'
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
$filePath = $toolInput.file_path
|
|
176
|
+
if (-not $filePath) {
|
|
177
|
+
return [ordered]@{ decision = 'allow' }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
$normalized = $filePath -replace '\\', '/'
|
|
181
|
+
if ($normalized -notmatch '\.(ps1|psm1|psd1)$') {
|
|
182
|
+
return [ordered]@{ decision = 'allow' }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
$stateDir = Join-Path -Path $Root -ChildPath '.claude/state'
|
|
186
|
+
if (-not (& $TestPathExists $stateDir)) {
|
|
187
|
+
& $EnsureDirectory $stateDir
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
$stateFile = Join-Path -Path $stateDir -ChildPath ("powershell-batch-budget.$SessionId.json")
|
|
191
|
+
$state = Get-PowerShellBatchBudgetState -ProdCap $ProdCap -TestCap $TestCap
|
|
192
|
+
|
|
193
|
+
if (& $TestPathExists $stateFile) {
|
|
194
|
+
try {
|
|
195
|
+
$loaded = & $ReadState $stateFile | ConvertFrom-Json -ErrorAction Stop
|
|
196
|
+
$state = ConvertTo-PowerShellBatchBudgetState -InputObject $loaded -ProdCap $ProdCap -TestCap $TestCap
|
|
197
|
+
} catch {
|
|
198
|
+
Write-Verbose "Ignoring unreadable PowerShell batch-budget state file '$stateFile': $($_.Exception.Message)"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
$decision = Invoke-PowerShellBatchBudgetDecision -FilePath $filePath -State $state -StateFile $stateFile
|
|
203
|
+
if ($decision.shouldWriteState) {
|
|
204
|
+
try {
|
|
205
|
+
& $WriteState $stateFile $decision.state
|
|
206
|
+
} catch {
|
|
207
|
+
Write-Verbose "Unable to write PowerShell batch-budget state file '$stateFile': $($_.Exception.Message)"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return $decision
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
$sessionId = $env:CLAUDE_SESSION_ID
|
|
219
|
+
if (-not $sessionId) {
|
|
220
|
+
$sessionId = 'default'
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
$prodCap = 3
|
|
224
|
+
$testCap = 3
|
|
225
|
+
if ($env:CLAUDE_POWERSHELL_BUDGET_PROD -match '^\d+$') {
|
|
226
|
+
$prodCap = [int]$env:CLAUDE_POWERSHELL_BUDGET_PROD
|
|
227
|
+
}
|
|
228
|
+
if ($env:CLAUDE_POWERSHELL_BUDGET_TEST -match '^\d+$') {
|
|
229
|
+
$testCap = [int]$env:CLAUDE_POWERSHELL_BUDGET_TEST
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
$decision = Invoke-PowerShellBatchBudgetHook -ToolInputRaw $env:CLAUDE_TOOL_INPUT -SessionId $sessionId -ProdCap $prodCap -TestCap $testCap
|
|
233
|
+
if ($decision.decision -eq 'block') {
|
|
234
|
+
$decision.Remove('state')
|
|
235
|
+
$decision | ConvertTo-Json -Compress | Write-Output
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
exit 0
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Pre-tool-use hook that blocks Bash promotion-script bypass attempts.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
This script is invoked by the Claude Code PreToolUse hook before any Bash
|
|
7
|
+
command runs. It reads the tool input from the CLAUDE_TOOL_INPUT environment
|
|
8
|
+
variable, inspects the attempted command text, and blocks direct promotion
|
|
9
|
+
script execution that would bypass the repository's MCP-only promotion path.
|
|
10
|
+
|
|
11
|
+
Forbidden command tokens:
|
|
12
|
+
- new-potential-entry.ps1
|
|
13
|
+
- new_potential_bug_entry
|
|
14
|
+
- potential_to_issue
|
|
15
|
+
- new_active_feature_folder
|
|
16
|
+
|
|
17
|
+
The hook is read-only: it inspects the attempted command and emits a JSON
|
|
18
|
+
allow-or-block decision without mutating the command text.
|
|
19
|
+
|
|
20
|
+
.NOTES
|
|
21
|
+
Compatible with PowerShell 7+.
|
|
22
|
+
#>
|
|
23
|
+
[CmdletBinding()]
|
|
24
|
+
param()
|
|
25
|
+
|
|
26
|
+
$script:PromotionMcpOnlyBlockedReason = 'PROMOTION_MCP_ONLY_BLOCKED: Direct Bash promotion-script execution is not allowed in agent sessions. Use the drmCopilotExtension MCP promotion tools instead.'
|
|
27
|
+
|
|
28
|
+
function Get-PromotionMcpOnlyBlockedReason {
|
|
29
|
+
<#
|
|
30
|
+
.SYNOPSIS
|
|
31
|
+
Return the canonical deny message for promotion-script bypass attempts.
|
|
32
|
+
.OUTPUTS
|
|
33
|
+
System.String
|
|
34
|
+
#>
|
|
35
|
+
[CmdletBinding()]
|
|
36
|
+
[OutputType([string])]
|
|
37
|
+
param()
|
|
38
|
+
|
|
39
|
+
return $script:PromotionMcpOnlyBlockedReason
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function Test-PromotionBypassToken {
|
|
43
|
+
<#
|
|
44
|
+
.SYNOPSIS
|
|
45
|
+
Return $true when a Bash command contains a forbidden promotion token.
|
|
46
|
+
.PARAMETER CommandText
|
|
47
|
+
The Bash command text extracted from CLAUDE_TOOL_INPUT.
|
|
48
|
+
.OUTPUTS
|
|
49
|
+
System.Boolean
|
|
50
|
+
#>
|
|
51
|
+
[CmdletBinding()]
|
|
52
|
+
[OutputType([bool])]
|
|
53
|
+
param(
|
|
54
|
+
[Parameter(Mandatory)]
|
|
55
|
+
[string] $CommandText
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Inspect only the command text so the hook remains a narrow, non-mutating
|
|
59
|
+
# policy gate for direct promotion-script bypass attempts.
|
|
60
|
+
$forbiddenTokens = @(
|
|
61
|
+
'new-potential-entry.ps1',
|
|
62
|
+
'new_potential_bug_entry',
|
|
63
|
+
'potential_to_issue',
|
|
64
|
+
'new_active_feature_folder'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
foreach ($token in $forbiddenTokens) {
|
|
68
|
+
if ($CommandText.IndexOf($token, [System.StringComparison]::OrdinalIgnoreCase) -ge 0) {
|
|
69
|
+
return $true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return $false
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function Get-PromotionMcpOnlyBlockDecision {
|
|
77
|
+
<#
|
|
78
|
+
.SYNOPSIS
|
|
79
|
+
Construct the structured block decision for a forbidden Bash command.
|
|
80
|
+
.OUTPUTS
|
|
81
|
+
System.Collections.Specialized.OrderedDictionary
|
|
82
|
+
#>
|
|
83
|
+
[CmdletBinding()]
|
|
84
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
85
|
+
param()
|
|
86
|
+
|
|
87
|
+
return [ordered]@{
|
|
88
|
+
decision = 'block'
|
|
89
|
+
reason = (Get-PromotionMcpOnlyBlockedReason)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function Invoke-PromotionMcpOnlyDecision {
|
|
94
|
+
<#
|
|
95
|
+
.SYNOPSIS
|
|
96
|
+
Parse CLAUDE_TOOL_INPUT and return an allow-or-block decision.
|
|
97
|
+
.PARAMETER ToolInputRaw
|
|
98
|
+
The raw JSON tool payload supplied by Claude Code.
|
|
99
|
+
.OUTPUTS
|
|
100
|
+
System.Collections.Specialized.OrderedDictionary
|
|
101
|
+
.NOTES
|
|
102
|
+
Missing tool input or missing command text is treated as allow because
|
|
103
|
+
non-Bash invocations or empty Bash requests cannot bypass promotion flow.
|
|
104
|
+
#>
|
|
105
|
+
[CmdletBinding()]
|
|
106
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
107
|
+
param(
|
|
108
|
+
[string] $ToolInputRaw
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if (-not $ToolInputRaw) {
|
|
112
|
+
return [ordered]@{ decision = 'allow' }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
117
|
+
} catch {
|
|
118
|
+
throw "enforce-promotion-mcp-only hook received malformed JSON in CLAUDE_TOOL_INPUT: $_"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
$commandText = $toolInput.command
|
|
122
|
+
if (-not $commandText) {
|
|
123
|
+
return [ordered]@{ decision = 'allow' }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (Test-PromotionBypassToken -CommandText $commandText) {
|
|
127
|
+
return Get-PromotionMcpOnlyBlockDecision
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return [ordered]@{ decision = 'allow' }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# Allow dot-sourcing in tests without executing the entrypoint.
|
|
134
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
$decision = Invoke-PromotionMcpOnlyDecision -ToolInputRaw $env:CLAUDE_TOOL_INPUT
|
|
140
|
+
} catch {
|
|
141
|
+
Write-Error $_
|
|
142
|
+
exit 1
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
$decision | ConvertTo-Json -Compress | Write-Output
|
|
146
|
+
|
|
147
|
+
exit 0
|