@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
|
@@ -17,14 +17,19 @@
|
|
|
17
17
|
|
|
18
18
|
Both helpers read the script-scoped configuration the parent hook declares and call the
|
|
19
19
|
parent hook's injectable read seams, so this file is only ever dot-sourced from that hook
|
|
20
|
-
and never invoked on its own. $script:PrContextArtifactPath is
|
|
21
|
-
|
|
20
|
+
and never invoked on its own. $script:PrContextArtifactPath is the repository-relative
|
|
21
|
+
literal used in messages and as the composition input; every artifact read is composed
|
|
22
|
+
beneath the root Resolve-PrAuthorArtifactRoot selects (issue #850).
|
|
23
|
+
$script:OrchestratorStateCheckpointPath is different after
|
|
22
24
|
issue #673: the parent declares it null, and Get-PrAuthorBypassReason assigns it the
|
|
23
25
|
absolute checkpoint path of the worktree identity resolution selected, so every later
|
|
24
26
|
reader receives one resolved path rather than deriving its own.
|
|
25
27
|
|
|
26
28
|
.NOTES
|
|
27
|
-
Compatible with PowerShell 7+.
|
|
29
|
+
Compatible with PowerShell 7+. Dependencies are in-repository only: the command parsers
|
|
30
|
+
and worktree-resolution modules loaded below, and the artifact-root and docs-only siblings.
|
|
31
|
+
No PowerShell Gallery module is required.
|
|
32
|
+
The docs-only sibling runs the git executable at call time (issue #901).
|
|
28
33
|
#>
|
|
29
34
|
[CmdletBinding()]
|
|
30
35
|
param()
|
|
@@ -47,6 +52,10 @@ Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemR
|
|
|
47
52
|
# Epic scope (issue #663): the epic integration pull request is gated against the epic checkpoint.
|
|
48
53
|
Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeResolution.psm1') -Force -ErrorAction Stop
|
|
49
54
|
Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeReadiness.psm1') -Force -ErrorAction Stop
|
|
55
|
+
# Artifact-root resolution and the Check 1 body-path binding (issue #850).
|
|
56
|
+
. (Join-Path $PSScriptRoot 'enforce-pr-author-skill.artifact-root.ps1')
|
|
57
|
+
# Docs-only exemption from the orchestrator-state preflight (issue #901).
|
|
58
|
+
. (Join-Path $PSScriptRoot 'enforce-pr-author-skill.docs-only.ps1')
|
|
50
59
|
|
|
51
60
|
function Resolve-PrAuthorWorktreeTarget {
|
|
52
61
|
<#
|
|
@@ -98,7 +107,9 @@ function Get-PrAuthorTargetCheckpointResolution {
|
|
|
98
107
|
refuses to answer rather than answering from unrelated state. Neither reason-code
|
|
99
108
|
literal appears in this file; both come from the accessors named above.
|
|
100
109
|
.OUTPUTS
|
|
101
|
-
System.Collections.Specialized.OrderedDictionary with CheckpointPath
|
|
110
|
+
System.Collections.Specialized.OrderedDictionary with CheckpointPath, Reason,
|
|
111
|
+
WorktreeRoot (the resolved root, or $null when unresolved), and Status (the target's
|
|
112
|
+
status), so the artifact root is taken from the same resolution (issue #850).
|
|
102
113
|
#>
|
|
103
114
|
[CmdletBinding()]
|
|
104
115
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
@@ -111,15 +122,51 @@ function Get-PrAuthorTargetCheckpointResolution {
|
|
|
111
122
|
|
|
112
123
|
switch ($target.Status) {
|
|
113
124
|
{ $_ -in @('SessionRoot', 'OtherWorktree') } {
|
|
114
|
-
return [ordered]@{ CheckpointPath = (Get-WorktreeItemCheckpointPath -WorktreeRoot $target.WorktreeRoot); Reason = $null }
|
|
125
|
+
return [ordered]@{ CheckpointPath = (Get-WorktreeItemCheckpointPath -WorktreeRoot $target.WorktreeRoot); Reason = $null; WorktreeRoot = $target.WorktreeRoot; Status = $target.Status }
|
|
115
126
|
}
|
|
116
127
|
default {
|
|
117
128
|
$reason = "$($target.ReasonCode): $($target.Detail) The pr-author gate will not validate this call against the session root's checkpoint, because that checkpoint may belong to a different item. Pass --head <branch> on the gh pr create command so the call names its own target."
|
|
118
|
-
return [ordered]@{ CheckpointPath = $null; Reason = $reason }
|
|
129
|
+
return [ordered]@{ CheckpointPath = $null; Reason = $reason; WorktreeRoot = $null; Status = $target.Status }
|
|
119
130
|
}
|
|
120
131
|
}
|
|
121
132
|
}
|
|
122
133
|
|
|
134
|
+
function Get-PrAuthorBodyFileValue {
|
|
135
|
+
<#
|
|
136
|
+
.SYNOPSIS
|
|
137
|
+
Return the normalized --body-file value of the matched gh pr create or gh pr edit, or $null.
|
|
138
|
+
.DESCRIPTION
|
|
139
|
+
Reads the flag value from the first Structural gh pr create match, else gh pr edit.
|
|
140
|
+
Backslashes become forward slashes and one leading './' is removed (issue #824). A
|
|
141
|
+
rooted value is returned as written, with separators normalized, and is bound to the
|
|
142
|
+
resolved worktree by Get-PrAuthorBodyPathBindingReason (issue #850).
|
|
143
|
+
.PARAMETER CommandText
|
|
144
|
+
The Bash command text under evaluation.
|
|
145
|
+
.OUTPUTS
|
|
146
|
+
System.String or $null
|
|
147
|
+
#>
|
|
148
|
+
[CmdletBinding()]
|
|
149
|
+
[OutputType([string])]
|
|
150
|
+
param(
|
|
151
|
+
[Parameter(Mandatory)]
|
|
152
|
+
[string] $CommandText
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
$subcommandPath = @('pr', 'edit')
|
|
156
|
+
if (Test-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath @('pr', 'create')) {
|
|
157
|
+
$subcommandPath = @('pr', 'create')
|
|
158
|
+
}
|
|
159
|
+
$value = Get-CommandLineFlagValue -CommandText $CommandText -CommandWord 'gh' -SubcommandPath $subcommandPath -FlagName '--body-file'
|
|
160
|
+
if ($null -eq $value) {
|
|
161
|
+
return $null
|
|
162
|
+
}
|
|
163
|
+
$value = $value.Replace('\', '/')
|
|
164
|
+
if ($value.StartsWith('./')) {
|
|
165
|
+
$value = $value.Substring(2)
|
|
166
|
+
}
|
|
167
|
+
return $value
|
|
168
|
+
}
|
|
169
|
+
|
|
123
170
|
function Test-PrAuthorReceiptVerification {
|
|
124
171
|
<#
|
|
125
172
|
.SYNOPSIS
|
|
@@ -127,8 +174,9 @@ function Test-PrAuthorReceiptVerification {
|
|
|
127
174
|
.DESCRIPTION
|
|
128
175
|
Runs the six ordered receipt checks on the --body-file-with-context path. Each check is its
|
|
129
176
|
own short-circuiting branch; the first failure returns its reason code:
|
|
130
|
-
1. PR_BODY_PATH_NONCANONICAL - --body-file path
|
|
131
|
-
artifacts/pr_body_<N>.md
|
|
177
|
+
1. PR_BODY_PATH_NONCANONICAL - --body-file path is not the canonical
|
|
178
|
+
artifacts/pr_body_<N>.md beneath the artifact
|
|
179
|
+
root (relative only for the session worktree).
|
|
132
180
|
2. PR_AUTHOR_RECEIPT_MISSING - sibling artifacts/pr_body_<N>.receipt.json absent.
|
|
133
181
|
3. PR_AUTHOR_RECEIPT_NUMBER_MISMATCH- receipt.number (integer) != <N> from the path.
|
|
134
182
|
4. PR_AUTHOR_RECEIPT_HASH_MISMATCH - inline SHA-256 (lowercase hex) of the body bytes
|
|
@@ -139,9 +187,10 @@ function Test-PrAuthorReceiptVerification {
|
|
|
139
187
|
matching --base <epic_context.integration_branch>.
|
|
140
188
|
Returns $null when all six checks pass (allow). All disk access flows through the four
|
|
141
189
|
injectable seams (Get-PrBodyFileBytes, Get-PrAuthorReceiptContent,
|
|
142
|
-
Get-PrContextSummaryLastWriteUtc, Get-PrAuthorCheckpointContent)
|
|
143
|
-
|
|
144
|
-
|
|
190
|
+
Get-PrContextSummaryLastWriteUtc, Get-PrAuthorCheckpointContent), each given an absolute
|
|
191
|
+
path beneath the artifact root (issue #850); SHA-256 is computed inline. This is a
|
|
192
|
+
policy-level integrity check, not a cryptographic control: any actor with Write access
|
|
193
|
+
to artifacts/ can replace the body file and the receipt together.
|
|
145
194
|
.PARAMETER CommandText
|
|
146
195
|
The Bash command text containing the --body-file argument.
|
|
147
196
|
.PARAMETER CheckpointPath
|
|
@@ -150,6 +199,10 @@ function Test-PrAuthorReceiptVerification {
|
|
|
150
199
|
.PARAMETER EpicScope
|
|
151
200
|
Optional. The epic-scope result Get-PrAuthorBypassReason resolved (issue #663), passed
|
|
152
201
|
through to check 6 so the call is resolved once; $null outside epic scope.
|
|
202
|
+
.PARAMETER ArtifactRoot
|
|
203
|
+
The resolved worktree root the body, receipt, and summary are read beneath.
|
|
204
|
+
.PARAMETER RelativeBodyAllowed
|
|
205
|
+
Whether a relative --body-file is read from the resolved worktree (the session worktree).
|
|
153
206
|
.OUTPUTS
|
|
154
207
|
System.String or $null
|
|
155
208
|
#>
|
|
@@ -163,18 +216,25 @@ function Test-PrAuthorReceiptVerification {
|
|
|
163
216
|
[string] $CheckpointPath,
|
|
164
217
|
|
|
165
218
|
[AllowNull()]
|
|
166
|
-
[object] $EpicScope
|
|
219
|
+
[object] $EpicScope,
|
|
220
|
+
|
|
221
|
+
[Parameter(Mandatory)]
|
|
222
|
+
[string] $ArtifactRoot,
|
|
223
|
+
|
|
224
|
+
[bool] $RelativeBodyAllowed
|
|
167
225
|
)
|
|
168
226
|
|
|
169
|
-
# Check 1: the --body-file
|
|
170
|
-
#
|
|
171
|
-
|
|
172
|
-
|
|
227
|
+
# Check 1: the --body-file value must be the canonical artifacts/pr_body_<N>.md beneath the
|
|
228
|
+
# artifact root (issue #850); C1a's structural read and spelling normalization are reused.
|
|
229
|
+
$binding = Get-PrAuthorBodyPathBindingReason -CommandText $CommandText -ArtifactRoot $ArtifactRoot -RelativeBodyAllowed $RelativeBodyAllowed
|
|
230
|
+
if ($binding.Reason) {
|
|
231
|
+
return $binding.Reason
|
|
173
232
|
}
|
|
174
233
|
|
|
175
|
-
$bodyNumber =
|
|
176
|
-
$bodyFilePath = "artifacts/pr_body_$bodyNumber.md"
|
|
177
|
-
$receiptFilePath = "artifacts/pr_body_$bodyNumber.receipt.json"
|
|
234
|
+
$bodyNumber = $binding.BodyNumber
|
|
235
|
+
$bodyFilePath = Join-WorktreeResolutionPath -WorktreeRoot $ArtifactRoot -RepoRelativePath "artifacts/pr_body_$bodyNumber.md"
|
|
236
|
+
$receiptFilePath = Join-WorktreeResolutionPath -WorktreeRoot $ArtifactRoot -RepoRelativePath "artifacts/pr_body_$bodyNumber.receipt.json"
|
|
237
|
+
$summaryPath = Join-WorktreeResolutionPath -WorktreeRoot $ArtifactRoot -RepoRelativePath $script:PrContextArtifactPath
|
|
178
238
|
|
|
179
239
|
# Check 2: the sibling receipt file must exist (read via the injectable seam).
|
|
180
240
|
$receiptRaw = Get-PrAuthorReceiptContent -ReceiptFilePath $receiptFilePath
|
|
@@ -228,7 +288,7 @@ function Test-PrAuthorReceiptVerification {
|
|
|
228
288
|
return "PR_AUTHOR_RECEIPT_STALE: ``$receiptFilePath`` has a missing or unparseable ``created_at``. The pr-author agent must record a UTC ISO-8601 ``created_at`` strictly newer than ``$script:PrContextArtifactPath``."
|
|
229
289
|
}
|
|
230
290
|
|
|
231
|
-
$contextLastWrite = Get-PrContextSummaryLastWriteUtc
|
|
291
|
+
$contextLastWrite = Get-PrContextSummaryLastWriteUtc -Path $summaryPath
|
|
232
292
|
if (($null -eq $contextLastWrite) -or ($createdAt -le $contextLastWrite)) {
|
|
233
293
|
return "PR_AUTHOR_RECEIPT_STALE: ``$receiptFilePath`` ``created_at`` is not strictly newer than the last-write time of ``$script:PrContextArtifactPath``. The pr-author agent must regenerate the body and receipt after refreshing the PR context."
|
|
234
294
|
}
|
|
@@ -248,17 +308,16 @@ function Get-PrAuthorBypassReason {
|
|
|
248
308
|
Inspect the command text and return a block reason string, or $null when the command is allowed.
|
|
249
309
|
.DESCRIPTION
|
|
250
310
|
Returns PR_AUTHOR_SKILL_BLOCKED when gh pr create or gh pr edit is run with --body (inline,
|
|
251
|
-
no --body-file), or when gh pr create is run with no body flag at all
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
311
|
+
no --body-file), or when gh pr create is run with no body flag at all; these cases and the
|
|
312
|
+
gh pr edit no-body allow perform no resolution. For a --body-file command the artifact root
|
|
313
|
+
is resolved once (issue #850), and the deny precedence is: the resolution reason
|
|
314
|
+
(no-target or ambiguity code, or an underivable epic worktree), PR_CONTEXT_MISSING when the
|
|
315
|
+
context summary is absent beneath the resolved worktree, ORCHESTRATOR_STATE_PREFLIGHT_FAILED
|
|
316
|
+
unless Get-PrAuthorDocsOnlyExemption exempts a docs-only gh pr create (issue #901), then
|
|
317
|
+
receipt checks 1-6 via Test-PrAuthorReceiptVerification. Returns $null for all allowed
|
|
318
|
+
patterns.
|
|
258
319
|
.PARAMETER CommandText
|
|
259
320
|
The Bash command text extracted from the envelope's tool_input.
|
|
260
|
-
.PARAMETER ContextExists
|
|
261
|
-
Whether artifacts/pr_context.summary.txt currently exists on disk.
|
|
262
321
|
.OUTPUTS
|
|
263
322
|
System.String or $null
|
|
264
323
|
#>
|
|
@@ -266,10 +325,7 @@ function Get-PrAuthorBypassReason {
|
|
|
266
325
|
[OutputType([string])]
|
|
267
326
|
param(
|
|
268
327
|
[Parameter(Mandatory)]
|
|
269
|
-
[string] $CommandText
|
|
270
|
-
|
|
271
|
-
[Parameter(Mandatory)]
|
|
272
|
-
[bool] $ContextExists
|
|
328
|
+
[string] $CommandText
|
|
273
329
|
)
|
|
274
330
|
|
|
275
331
|
# Only act on gh pr create or gh pr edit subcommands. The test is structural: a segment
|
|
@@ -290,22 +346,21 @@ function Get-PrAuthorBypassReason {
|
|
|
290
346
|
$hasBodyFile = Test-CommandLineFlag -CommandText $CommandText -CommandWord 'gh' -SubcommandPath $subcommandPath -FlagName '--body-file'
|
|
291
347
|
$hasInlineBody = Test-CommandLineFlag -CommandText $CommandText -CommandWord 'gh' -SubcommandPath $subcommandPath -FlagName '--body'
|
|
292
348
|
|
|
293
|
-
# Raw-scan fallback
|
|
294
|
-
#
|
|
295
|
-
#
|
|
296
|
-
#
|
|
297
|
-
#
|
|
298
|
-
# whole-text --body-file match set $hasBodyFile for exactly this input.
|
|
349
|
+
# Raw-scan fallback (issue #824). Wrapper payloads are now read structurally, so the flags
|
|
350
|
+
# above already come from a payload's own tokens. The raw text is scanned only when the
|
|
351
|
+
# invocation could not be read structurally at all: no Structural match exists for the
|
|
352
|
+
# subcommand path and at least one Indeterminate match does. The --body-file test runs
|
|
353
|
+
# first and wins, so a --body-file is never misread as an inline body.
|
|
299
354
|
if (-not $hasBodyFile -and -not $hasInlineBody) {
|
|
300
|
-
$
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
$
|
|
307
|
-
|
|
308
|
-
|
|
355
|
+
$matchList = @(Get-CommandLineInvocation -CommandText $CommandText -CommandWord 'gh' -SubcommandPath $subcommandPath)
|
|
356
|
+
if (@($matchList | Where-Object { $_.Status -eq 'Structural' }).Count -eq 0) {
|
|
357
|
+
$comparison = [System.StringComparison]::OrdinalIgnoreCase
|
|
358
|
+
foreach ($match in @($matchList | Where-Object { $_.Status -eq 'Indeterminate' })) {
|
|
359
|
+
if ($match.Segment.RawText.IndexOf('--body-file', $comparison) -ge 0) {
|
|
360
|
+
$hasBodyFile = $true
|
|
361
|
+
} elseif ($match.Segment.RawText.IndexOf('--body', $comparison) -ge 0) {
|
|
362
|
+
$hasInlineBody = $true
|
|
363
|
+
}
|
|
309
364
|
}
|
|
310
365
|
}
|
|
311
366
|
}
|
|
@@ -330,36 +385,34 @@ function Get-PrAuthorBypassReason {
|
|
|
330
385
|
}
|
|
331
386
|
}
|
|
332
387
|
|
|
333
|
-
#
|
|
334
|
-
|
|
335
|
-
|
|
388
|
+
# Issue #850: the worktree whose artifacts are read is resolved once, before Case C. Epic
|
|
389
|
+
# scope (issue #663) selects the epic checkpoint's worktree and reads no per-feature
|
|
390
|
+
# checkpoint; otherwise identity resolution selects the item worktree, and an unresolved
|
|
391
|
+
# target denies here, ahead of PR_CONTEXT_MISSING.
|
|
392
|
+
$artifact = Resolve-PrAuthorArtifactRoot -CommandText $CommandText
|
|
393
|
+
if ($artifact.Reason) {
|
|
394
|
+
return $artifact.Reason
|
|
336
395
|
}
|
|
337
396
|
|
|
338
|
-
#
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
$epicScope = $null
|
|
343
|
-
if ($hasBodyFile -and $ContextExists) {
|
|
344
|
-
$epicScope = Resolve-EpicScopeCheckpoint -Text $CommandText -SessionRoot (Get-Location).Path
|
|
397
|
+
# Case C: --body-file present but the context artifact is absent beneath the resolved worktree.
|
|
398
|
+
$summaryPath = Join-WorktreeResolutionPath -WorktreeRoot $artifact.ArtifactRoot -RepoRelativePath $script:PrContextArtifactPath
|
|
399
|
+
if (-not (Get-PrContextArtifactExistence -Path $summaryPath)) {
|
|
400
|
+
return "PR_CONTEXT_MISSING: '$script:PrContextArtifactPath' in worktree '$($artifact.ArtifactRoot)' is absent. Run ``mcp__drm-copilot__collect_pr_context`` in that worktree before creating or editing the PR body."
|
|
345
401
|
}
|
|
346
402
|
|
|
347
403
|
# Orchestrator-state preflight: runs inside this same PreToolUse hook (so it cannot be
|
|
348
|
-
# bypassed by invoking gh pr create/edit directly) before receipt verification.
|
|
349
|
-
|
|
404
|
+
# bypassed by invoking gh pr create/edit directly) before receipt verification. The
|
|
405
|
+
# checkpoint path is assigned once here and read by every later consumer, so the
|
|
406
|
+
# preflight, the receipt verifier, and the epic base-branch check gate one item.
|
|
407
|
+
if ($null -ne $artifact.EpicScope) {
|
|
408
|
+
$epicScope = $artifact.EpicScope
|
|
350
409
|
$failure = Get-EpicPrCreationReadinessFailure -Checkpoint $epicScope.Checkpoint -HeadBranch $epicScope.Branch
|
|
351
410
|
if ($failure) {
|
|
352
411
|
return "ORCHESTRATOR_STATE_PREFLIGHT_FAILED: this epic-scope pull request was evaluated against $($epicScope.CheckpointPath), and the failed readiness predicate is '$failure'."
|
|
353
412
|
}
|
|
354
|
-
$script:OrchestratorStateCheckpointPath = $
|
|
355
|
-
}
|
|
356
|
-
$
|
|
357
|
-
if ($resolution.Reason) {
|
|
358
|
-
return $resolution.Reason
|
|
359
|
-
}
|
|
360
|
-
# Assigned once here and read by every later consumer, so the preflight, the receipt
|
|
361
|
-
# verifier, and the epic base-branch check cannot disagree about which item is gated.
|
|
362
|
-
$script:OrchestratorStateCheckpointPath = $resolution.CheckpointPath
|
|
413
|
+
$script:OrchestratorStateCheckpointPath = $artifact.CheckpointPath
|
|
414
|
+
} else {
|
|
415
|
+
$script:OrchestratorStateCheckpointPath = $artifact.CheckpointPath
|
|
363
416
|
$checkpointPath = $script:OrchestratorStateCheckpointPath
|
|
364
417
|
$preflightResult = Invoke-OrchestratorStatePreflight -CheckpointPath $checkpointPath
|
|
365
418
|
if ($preflightResult.HasErrors) {
|
|
@@ -368,16 +421,17 @@ function Get-PrAuthorBypassReason {
|
|
|
368
421
|
} else {
|
|
369
422
|
$preflightResult.ErrorText
|
|
370
423
|
}
|
|
371
|
-
|
|
424
|
+
$exemption = Get-PrAuthorDocsOnlyExemption -CommandText $CommandText -WorktreeRoot $artifact.ArtifactRoot -CheckpointPath $checkpointPath
|
|
425
|
+
if (-not $exemption.Exempt) {
|
|
426
|
+
return "ORCHESTRATOR_STATE_PREFLIGHT_FAILED: $preflightSummary (docs-only exemption not applied: $($exemption.Reason))"
|
|
427
|
+
}
|
|
372
428
|
}
|
|
373
429
|
}
|
|
374
430
|
|
|
375
431
|
# Receipt verification: extends, and does not replace, the previously-allowed path.
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
return $receiptReason
|
|
380
|
-
}
|
|
432
|
+
$receiptReason = Test-PrAuthorReceiptVerification -CommandText $CommandText -CheckpointPath $script:OrchestratorStateCheckpointPath -EpicScope $artifact.EpicScope -ArtifactRoot $artifact.ArtifactRoot -RelativeBodyAllowed $artifact.RelativeBodyAllowed
|
|
433
|
+
if ($receiptReason) {
|
|
434
|
+
return $receiptReason
|
|
381
435
|
}
|
|
382
436
|
|
|
383
437
|
return $null
|
package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Artifact-root resolution and the Check 1 body-path binding for enforce-pr-author-skill.ps1 (issue #850).
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Dot-sourced by enforce-pr-author-skill-helpers.ps1 after its module imports. Holds:
|
|
7
|
+
|
|
8
|
+
- Resolve-PrAuthorArtifactRoot, which resolves once per call the worktree whose
|
|
9
|
+
artifacts/ tree the gate reads: the epic checkpoint's worktree under epic scope, or
|
|
10
|
+
the item worktree identity resolution selects. The PR context summary, the body, and
|
|
11
|
+
the receipt are composed beneath that root, so a gate running in the session worktree
|
|
12
|
+
no longer reads another item's artifacts from its own process directory.
|
|
13
|
+
- Get-PrAuthorBodyPathBindingReason, the Check 1 binding: a relative canonical
|
|
14
|
+
--body-file value is accepted only when the resolved worktree is the session worktree,
|
|
15
|
+
because gh reads a relative path from its own process directory; an absolute value is
|
|
16
|
+
accepted only when it equals the canonical path beneath the resolved root.
|
|
17
|
+
- Test-PrAuthorBodyPathEqual and Get-PrAuthorEpicArtifactRoot, the pure path helpers.
|
|
18
|
+
- ConvertTo-PrAuthorBodyNumber, the strict body-number parse (issue #901, #850 note L19).
|
|
19
|
+
|
|
20
|
+
.NOTES
|
|
21
|
+
PowerShell 7+. Depends, at call time, on Get-PrAuthorBodyFileValue and
|
|
22
|
+
Get-PrAuthorTargetCheckpointResolution from the helpers file and on the worktree-resolution
|
|
23
|
+
modules it imports. It reads no file. Mirrored byte-identically under
|
|
24
|
+
extensions/drm-copilot/resources/claude-customizations/.
|
|
25
|
+
#>
|
|
26
|
+
[CmdletBinding()]
|
|
27
|
+
param()
|
|
28
|
+
|
|
29
|
+
function Test-PrAuthorBodyPathEqual {
|
|
30
|
+
<#
|
|
31
|
+
.SYNOPSIS
|
|
32
|
+
Compare two paths: case-insensitive for drive-letter and UNC paths, case-sensitive otherwise.
|
|
33
|
+
.PARAMETER Left
|
|
34
|
+
The first path, in either separator style.
|
|
35
|
+
.PARAMETER Right
|
|
36
|
+
The second path, in either separator style.
|
|
37
|
+
.OUTPUTS
|
|
38
|
+
System.Boolean
|
|
39
|
+
#>
|
|
40
|
+
[CmdletBinding()]
|
|
41
|
+
[OutputType([bool])]
|
|
42
|
+
param(
|
|
43
|
+
[AllowNull()][AllowEmptyString()][string] $Left,
|
|
44
|
+
[AllowNull()][AllowEmptyString()][string] $Right
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
$a = ConvertTo-WorktreeResolutionNormalizedPath -Path $Left
|
|
48
|
+
$b = ConvertTo-WorktreeResolutionNormalizedPath -Path $Right
|
|
49
|
+
if ($null -eq $a -or $null -eq $b) {
|
|
50
|
+
return $false
|
|
51
|
+
}
|
|
52
|
+
$comparison = if ($a -match '^([A-Za-z]:|//)' -or $b -match '^([A-Za-z]:|//)') {
|
|
53
|
+
[System.StringComparison]::OrdinalIgnoreCase
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
[System.StringComparison]::Ordinal
|
|
57
|
+
}
|
|
58
|
+
return [string]::Equals($a, $b, $comparison)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Get-PrAuthorEpicArtifactRoot {
|
|
62
|
+
<#
|
|
63
|
+
.SYNOPSIS
|
|
64
|
+
Return the worktree root that holds an epic checkpoint path, or $null.
|
|
65
|
+
.PARAMETER CheckpointPath
|
|
66
|
+
The absolute epic checkpoint path the epic-scope resolver composed.
|
|
67
|
+
.OUTPUTS
|
|
68
|
+
System.String or $null
|
|
69
|
+
#>
|
|
70
|
+
[CmdletBinding()]
|
|
71
|
+
[OutputType([string])]
|
|
72
|
+
param(
|
|
73
|
+
[AllowNull()][AllowEmptyString()][string] $CheckpointPath
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
$normalized = ConvertTo-WorktreeResolutionNormalizedPath -Path $CheckpointPath
|
|
77
|
+
$suffix = '/' + (Get-EpicScopeCheckpointRelativePath)
|
|
78
|
+
if ($null -eq $normalized -or -not $normalized.EndsWith($suffix, [System.StringComparison]::Ordinal)) {
|
|
79
|
+
return $null
|
|
80
|
+
}
|
|
81
|
+
$root = $normalized.Substring(0, $normalized.Length - $suffix.Length)
|
|
82
|
+
if ($root.Length -eq 0) {
|
|
83
|
+
return $null
|
|
84
|
+
}
|
|
85
|
+
return $root
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function Resolve-PrAuthorArtifactRoot {
|
|
89
|
+
<#
|
|
90
|
+
.SYNOPSIS
|
|
91
|
+
Resolve, once per call, the worktree whose artifacts the gate reads (issue #850).
|
|
92
|
+
.DESCRIPTION
|
|
93
|
+
Epic scope: the root is the worktree holding the epic checkpoint, and a relative body
|
|
94
|
+
path is allowed only when that root is the session worktree. Otherwise the item target
|
|
95
|
+
is resolved by identity; an unresolved target returns its resolution reason unchanged,
|
|
96
|
+
and a relative body path is allowed only for a SessionRoot target.
|
|
97
|
+
.PARAMETER CommandText
|
|
98
|
+
The Bash command text under evaluation.
|
|
99
|
+
.OUTPUTS
|
|
100
|
+
System.Collections.Specialized.OrderedDictionary with Reason, ArtifactRoot,
|
|
101
|
+
CheckpointPath, EpicScope, Status, and RelativeBodyAllowed.
|
|
102
|
+
#>
|
|
103
|
+
[CmdletBinding()]
|
|
104
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
105
|
+
param(
|
|
106
|
+
[Parameter(Mandatory)]
|
|
107
|
+
[string] $CommandText
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
$epicScope = Resolve-EpicScopeCheckpoint -Text $CommandText -SessionRoot (Get-Location).Path
|
|
111
|
+
if ($null -ne $epicScope -and $epicScope.IsEpicScope) {
|
|
112
|
+
$root = Get-PrAuthorEpicArtifactRoot -CheckpointPath $epicScope.CheckpointPath
|
|
113
|
+
$reason = $null
|
|
114
|
+
$relativeAllowed = $false
|
|
115
|
+
if ($null -eq $root) {
|
|
116
|
+
$reason = "ORCHESTRATOR_STATE_PREFLIGHT_FAILED: the epic checkpoint path '$($epicScope.CheckpointPath)' does not end with '$(Get-EpicScopeCheckpointRelativePath)', so the worktree that holds it cannot be derived."
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
$relativeAllowed = Test-PrAuthorBodyPathEqual -Left $root -Right $epicScope.WorktreeRoot
|
|
120
|
+
}
|
|
121
|
+
return [ordered]@{
|
|
122
|
+
Reason = $reason
|
|
123
|
+
ArtifactRoot = $root
|
|
124
|
+
CheckpointPath = $epicScope.CheckpointPath
|
|
125
|
+
EpicScope = $epicScope
|
|
126
|
+
Status = 'Epic'
|
|
127
|
+
RelativeBodyAllowed = $relativeAllowed
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
$resolution = Get-PrAuthorTargetCheckpointResolution -CommandText $CommandText
|
|
132
|
+
$resolved = -not $resolution.Reason
|
|
133
|
+
return [ordered]@{
|
|
134
|
+
Reason = $resolution.Reason
|
|
135
|
+
ArtifactRoot = if ($resolved) { ConvertTo-WorktreeResolutionNormalizedPath -Path $resolution.WorktreeRoot } else { $null }
|
|
136
|
+
CheckpointPath = $resolution.CheckpointPath
|
|
137
|
+
EpicScope = $null
|
|
138
|
+
Status = $resolution.Status
|
|
139
|
+
RelativeBodyAllowed = ($resolved -and $resolution.Status -eq 'SessionRoot')
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function ConvertTo-PrAuthorBodyNumber {
|
|
144
|
+
<#
|
|
145
|
+
.SYNOPSIS
|
|
146
|
+
Parse the <N> of artifacts/pr_body_<N>.md, or return $null.
|
|
147
|
+
.DESCRIPTION
|
|
148
|
+
Accepts only ASCII digits that parse as an Int32 and whose canonical invariant spelling
|
|
149
|
+
equals the input, so a value above Int32.MaxValue, a leading zero, and a non-ASCII
|
|
150
|
+
decimal digit all return $null instead of throwing or naming a different file.
|
|
151
|
+
.PARAMETER Digits
|
|
152
|
+
The digit run captured from the body-file name.
|
|
153
|
+
.OUTPUTS
|
|
154
|
+
System.Int32 or $null
|
|
155
|
+
#>
|
|
156
|
+
[CmdletBinding()]
|
|
157
|
+
[OutputType([int])]
|
|
158
|
+
param(
|
|
159
|
+
[AllowNull()][AllowEmptyString()][string] $Digits
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
$number = 0
|
|
163
|
+
$parsed = [int]::TryParse($Digits, [System.Globalization.NumberStyles]::None, [System.Globalization.CultureInfo]::InvariantCulture, [ref] $number)
|
|
164
|
+
if (-not $parsed -or $number.ToString([System.Globalization.CultureInfo]::InvariantCulture) -cne $Digits) {
|
|
165
|
+
return $null
|
|
166
|
+
}
|
|
167
|
+
return $number
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function Get-PrAuthorBodyPathBindingReason {
|
|
171
|
+
<#
|
|
172
|
+
.SYNOPSIS
|
|
173
|
+
Check 1: bind the --body-file value to the canonical body path beneath the artifact root.
|
|
174
|
+
.DESCRIPTION
|
|
175
|
+
Reads the value once through Get-PrAuthorBodyFileValue. A relative
|
|
176
|
+
artifacts/pr_body_<N>.md (case-sensitive) is accepted only when RelativeBodyAllowed is
|
|
177
|
+
true; otherwise the deny names the absolute canonical path to pass instead. An absolute
|
|
178
|
+
value is accepted only when it equals that canonical path under Test-PrAuthorBodyPathEqual.
|
|
179
|
+
Any other value, including no readable value, denies with the generic text.
|
|
180
|
+
.PARAMETER CommandText
|
|
181
|
+
The Bash command text under evaluation.
|
|
182
|
+
.PARAMETER ArtifactRoot
|
|
183
|
+
The resolved worktree root the artifacts are read beneath.
|
|
184
|
+
.PARAMETER RelativeBodyAllowed
|
|
185
|
+
Whether a relative body path is read from the resolved worktree.
|
|
186
|
+
.OUTPUTS
|
|
187
|
+
System.Collections.Specialized.OrderedDictionary with Reason and BodyNumber.
|
|
188
|
+
#>
|
|
189
|
+
[CmdletBinding()]
|
|
190
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
191
|
+
param(
|
|
192
|
+
[Parameter(Mandatory)]
|
|
193
|
+
[string] $CommandText,
|
|
194
|
+
|
|
195
|
+
[Parameter(Mandatory)]
|
|
196
|
+
[string] $ArtifactRoot,
|
|
197
|
+
|
|
198
|
+
[bool] $RelativeBodyAllowed
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
$generic = "PR_BODY_PATH_NONCANONICAL: ``--body-file`` must reference the canonical ``artifacts/pr_body_<N>.md`` file produced by the pr-author skill beneath the target worktree '$ArtifactRoot' (relative only when that worktree is the session worktree). The path supplied does not match."
|
|
202
|
+
$value = ConvertTo-WorktreeResolutionNormalizedPath -Path (Get-PrAuthorBodyFileValue -CommandText $CommandText)
|
|
203
|
+
if ($null -eq $value) {
|
|
204
|
+
return [ordered]@{ Reason = $generic; BodyNumber = $null }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if ($value -cmatch '^artifacts/pr_body_(\d+)\.md$') {
|
|
208
|
+
$number = ConvertTo-PrAuthorBodyNumber -Digits $Matches[1]
|
|
209
|
+
if ($null -eq $number) {
|
|
210
|
+
return [ordered]@{ Reason = $generic; BodyNumber = $null }
|
|
211
|
+
}
|
|
212
|
+
if (-not $RelativeBodyAllowed) {
|
|
213
|
+
$canonical = Join-WorktreeResolutionPath -WorktreeRoot $ArtifactRoot -RepoRelativePath "artifacts/pr_body_$number.md"
|
|
214
|
+
return [ordered]@{
|
|
215
|
+
Reason = "PR_BODY_PATH_NONCANONICAL: the target worktree '$ArtifactRoot' is not the session worktree, so gh would read a relative --body-file from the session worktree. Pass the absolute canonical path '$canonical'."
|
|
216
|
+
BodyNumber = $null
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return [ordered]@{ Reason = $null; BodyNumber = $number }
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if ($value -match '/artifacts/pr_body_(\d+)\.md$') {
|
|
223
|
+
$number = ConvertTo-PrAuthorBodyNumber -Digits $Matches[1]
|
|
224
|
+
if ($null -ne $number) {
|
|
225
|
+
$canonical = Join-WorktreeResolutionPath -WorktreeRoot $ArtifactRoot -RepoRelativePath "artifacts/pr_body_$number.md"
|
|
226
|
+
if (Test-PrAuthorBodyPathEqual -Left $value -Right $canonical) {
|
|
227
|
+
return [ordered]@{ Reason = $null; BodyNumber = $number }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return [ordered]@{ Reason = $generic; BodyNumber = $null }
|
|
233
|
+
}
|