@danmoisan/drm-copilot-mcp 1.1.22 → 1.1.24
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 +18758 -12030
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/MEMORY.md +1 -1
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_test_files_count_against_500_cap.md +4 -4
- package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +1 -1
- package/resources/claude-customizations/.claude/agents/discovery-capability-sentinel.md +34 -0
- package/resources/claude-customizations/.claude/agents/feature-review.md +8 -0
- package/resources/claude-customizations/.claude/agents/legacy-parity-analyst.md +101 -43
- package/resources/claude-customizations/.claude/agents/migration-coverage-reviewer.md +107 -43
- package/resources/claude-customizations/.claude/agents/orchestrator.md +1 -1
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +60 -6
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +21 -1
- package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +1 -1
- package/resources/claude-customizations/.claude/agents/pr-author.md +48 -7
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +1 -1
- package/resources/claude-customizations/.claude/agents/requirements-reconciler.md +117 -42
- package/resources/claude-customizations/.claude/agents/runtime-characterization-analyst.md +103 -43
- package/resources/claude-customizations/.claude/hooks/discovery-capability-probe.ps1 +102 -0
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +69 -194
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-planning-gate.ps1 +87 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-green-ci.ps1 +325 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +29 -7
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +23 -10
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +29 -21
- package/resources/claude-customizations/.claude/hooks/enforce-file-size-limit.ps1 +244 -0
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +51 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +168 -48
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +1 -1
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +22 -11
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +59 -20
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +51 -4
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +72 -11
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.current-branch.ps1 +149 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +4 -2
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +59 -20
- package/resources/claude-customizations/.claude/hooks/record-discovery-agent-start.ps1 +132 -0
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +56 -212
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-feature-folder.ps1 +146 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-rejection.ps1 +172 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +34 -4
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +9 -3
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusAggregate.psm1 +154 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusCombination.psm1 +228 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +1 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusNormalization.psm1 +4 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +63 -16
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +56 -1
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +4 -1
- package/resources/claude-customizations/.claude/lib/cleanup-manifest/CleanupWorktreeManifest.psm1 +33 -6
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +5 -1
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +25 -2
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +188 -341
- package/resources/claude-customizations/.claude/lib/file-size-policy/FileSizePolicy.psm1 +434 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateFeatureFolderRecord.psm1 +166 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +8 -3
- package/resources/claude-customizations/.claude/lib/worktree-resolution/HookTargetWorktree.psm1 +391 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunRecordPath.psm1 +185 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +11 -21
- package/resources/claude-customizations/.claude/rules/general-code-change.md +4 -1
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +29 -5
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +152 -20
- package/resources/claude-customizations/.claude/rules/powershell.md +1 -1
- package/resources/claude-customizations/.claude/rules/shell.md +1 -1
- package/resources/claude-customizations/.claude/settings.json +36 -3
- package/resources/claude-customizations/.claude/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/claude-customizations/.claude/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +2 -2
- package/resources/claude-customizations/.claude/skills/discovery-behavior-reconciliation/SKILL.md +28 -47
- package/resources/claude-customizations/.claude/skills/discovery-coverage-ledger/SKILL.md +32 -48
- package/resources/claude-customizations/.claude/skills/discovery-parity-matrix/SKILL.md +28 -45
- package/resources/claude-customizations/.claude/skills/discovery-repo-inventory/SKILL.md +28 -62
- package/resources/claude-customizations/.claude/skills/discovery-runtime-characterization/SKILL.md +28 -45
- package/resources/claude-customizations/.claude/skills/discovery-validate-artifacts/SKILL.md +28 -61
- package/resources/claude-customizations/.claude/skills/discovery-workflow/SKILL.md +55 -139
- package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +25 -10
- package/resources/claude-customizations/.claude/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +1 -0
- package/resources/claude-customizations/.claude/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/claude-customizations/.claude/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +15 -7
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +25 -2
- package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +11 -1
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +124 -14
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +72 -7
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/parallel-run/SKILL.md +6 -0
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +56 -9
- package/resources/claude-customizations/.claude/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/claude-customizations/.claude/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/claude-customizations/.claude/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/claude-customizations/.claude-variants/csharp-legacy/agents/csharp-typed-engineer.md +1 -1
- package/resources/claude-customizations/config/blast-radius.json +6 -5
- package/resources/claude-customizations/config/orchestration-routing.json +61 -1
- package/resources/claude-customizations/pack-manifests/core.json +40 -1
- package/resources/codex-and-agents-customizations/.agents/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +7 -0
- package/resources/codex-and-agents-customizations/.agents/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-coverage-ledger/SKILL.md +50 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-parity-matrix/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-repo-inventory/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-runtime-characterization/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-validate-artifacts/SKILL.md +46 -0
- package/resources/codex-and-agents-customizations/.agents/skills/discovery-workflow/SKILL.md +62 -0
- package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +25 -10
- package/resources/codex-and-agents-customizations/.agents/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +4 -1
- package/resources/codex-and-agents-customizations/.agents/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/codex-and-agents-customizations/.agents/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/codex-and-agents-customizations/.agents/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/discovery-capability-sentinel.toml +51 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +8 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c1.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c2.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3-elevated.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c4.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst.toml +148 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c1.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c2.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3-elevated.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c4.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer.toml +154 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c1.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c2.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3-elevated.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c4.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler.toml +164 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c1.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c2.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3-elevated.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c4.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst.toml +150 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +39 -3
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-agent-profile-attestation.ps1 +22 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/discovery-capability-probe.ps1 +97 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/discovery-start-attestation.ps1 +171 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +4 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-artifact-gate.ps1 +187 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-planning-gate.ps1 +149 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-file-size-limit.ps1 +282 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +239 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +6 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +54 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +54 -15
- package/resources/codex-and-agents-customizations/.codex/hooks/file-size-policy.ps1 +421 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-target-worktree.ps1 +369 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/record-subagent-routing-attestation.ps1 +8 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +22 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-discovery-agent-output.ps1 +178 -0
- package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +11 -1
- package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +1 -1
- package/resources/codex-and-agents-customizations/AGENTS.md +4 -1
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +65 -1
- package/resources/config/orchestration-routing.json +61 -1
- package/resources/customizations/.github/agents/commentary-remediation.agent.md +1 -1
- package/resources/customizations/.github/agents/discovery-capability-sentinel.agent.md +34 -0
- package/resources/customizations/.github/agents/legacy-parity-analyst.agent.md +122 -0
- package/resources/customizations/.github/agents/migration-coverage-reviewer.agent.md +128 -0
- package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +1 -1
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +1 -1
- package/resources/customizations/.github/agents/requirements-reconciler.agent.md +138 -0
- package/resources/customizations/.github/agents/runtime-characterization-analyst.agent.md +124 -0
- package/resources/customizations/.github/hooks/discovery-agent-start.ps1 +139 -0
- package/resources/customizations/.github/hooks/discovery-agent-stop.ps1 +123 -0
- package/resources/customizations/.github/hooks/discovery-capability-probe.ps1 +98 -0
- package/resources/customizations/.github/hooks/discovery-planning.ps1 +91 -0
- package/resources/customizations/.github/hooks/discovery-pre-tool.ps1 +123 -0
- package/resources/customizations/.github/hooks/discovery.json +35 -0
- package/resources/customizations/.github/instructions/general-code-change.instructions.md +5 -2
- package/resources/customizations/.github/instructions/mermaid.instructions.md +85 -0
- package/resources/customizations/.github/instructions/powershell-code-change.instructions.md +1 -1
- package/resources/customizations/.github/prompts/execute-hard-lock.prompt.md +105 -0
- package/resources/customizations/.github/prompts/remediate-comments.prompt.md +1 -1
- package/resources/customizations/.github/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
- package/resources/customizations/.github/skills/characterize-runtime-behavior/SKILL.md +134 -0
- package/resources/customizations/.github/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-coverage-ledger/SKILL.md +50 -0
- package/resources/customizations/.github/skills/discovery-parity-matrix/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-repo-inventory/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-runtime-characterization/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-validate-artifacts/SKILL.md +46 -0
- package/resources/customizations/.github/skills/discovery-workflow/SKILL.md +62 -0
- package/resources/customizations/.github/skills/execution-environment/SKILL.md +25 -10
- package/resources/customizations/.github/skills/extract-feature-contract/SKILL.md +133 -0
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +8 -0
- package/resources/customizations/.github/skills/generate-acceptance-scenarios/SKILL.md +132 -0
- package/resources/customizations/.github/skills/initialize-discovery-workspace/SKILL.md +131 -0
- package/resources/customizations/.github/skills/inventory-legacy-system/SKILL.md +131 -0
- package/resources/customizations/.github/skills/reconcile-parity-matrix/SKILL.md +131 -0
- package/resources/customizations/.github/skills/review-discovery-coverage/SKILL.md +129 -0
- package/resources/customizations/.github/skills/validate-discovery-artifacts/SKILL.md +127 -0
- package/resources/lib/codex-routing/CodexDeployment.psm1 +5 -1
- package/resources/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
- package/resources/lib/codex-routing/CodexTopology.psm1 +25 -2
- package/resources/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
- package/resources/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
- package/resources/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
- package/resources/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
- package/resources/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
- package/resources/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
- package/resources/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
- package/resources/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
- package/resources/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
- package/resources/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
- package/resources/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
- package/resources/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
- package/resources/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
- package/resources/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
- package/resources/powershell/PoshQC/PoshQC.Parallel.psm1 +452 -0
- package/resources/powershell/PoshQC/PoshQC.Shard.psm1 +106 -8
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +12 -0
- package/resources/powershell/PoshQC/PoshQC.psd1 +6 -1
- package/resources/powershell/PoshQC/PoshQC.psm1 +7 -1
- package/resources/powershell/PoshQC/README.md +20 -1
- package/resources/templates/policy_audit/code-review.yyyy-MM-ddTHH-mm.md +4 -4
- package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +4 -4
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Pre-tool-use hook that blocks a Write or Edit leaving a covered file above 800 lines.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
This script is invoked by the Claude Code PreToolUse hook before any Write or Edit
|
|
7
|
+
operation. It enforces the hard tier of the tiered file-size policy: 500 lines is
|
|
8
|
+
guidance, 700 lines is advisory, and above 800 lines a split is enforced regardless
|
|
9
|
+
of logical separability. The policy functions live in the shared module
|
|
10
|
+
../lib/file-size-policy/FileSizePolicy.psm1.
|
|
11
|
+
|
|
12
|
+
Decision order:
|
|
13
|
+
1. A dependency-load failure denies (fail closed).
|
|
14
|
+
2. An unreadable envelope denies.
|
|
15
|
+
3. A path that is not covered (outside the extension allowlist, under an excluded
|
|
16
|
+
directory, or outside the repository root) allows with no file read.
|
|
17
|
+
4. Write: the resulting size is the logical line count of content. The pre-write
|
|
18
|
+
file is read only when that size is above 800.
|
|
19
|
+
Edit: the pre-edit file is read through the ReadFileContent seam and the
|
|
20
|
+
old_string to new_string replacement is applied in memory. An unreadable or
|
|
21
|
+
missing file, or an edit that cannot be resolved, denies.
|
|
22
|
+
5. The baseline-free pre-edit-size ratchet decides: a result above 800 lines is
|
|
23
|
+
denied unless the file already existed and does not grow.
|
|
24
|
+
|
|
25
|
+
The hook does not read config/file-size-baseline.json, because it ships to
|
|
26
|
+
repositories that have no baseline; the repository's CI gate is the
|
|
27
|
+
baseline-aware check. The deny shape is hookSpecificOutput.permissionDecision =
|
|
28
|
+
'deny' with permissionDecisionReason, exit 0.
|
|
29
|
+
|
|
30
|
+
.NOTES
|
|
31
|
+
Compatible with PowerShell 7+.
|
|
32
|
+
This script must not modify any state; it is a read-only validation gate.
|
|
33
|
+
#>
|
|
34
|
+
[CmdletBinding()]
|
|
35
|
+
param()
|
|
36
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
37
|
+
|
|
38
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/hook-payload/HookPayload.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookPayload.psm1' -ErrorRecord $_ }
|
|
39
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/file-size-policy/FileSizePolicy.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'FileSizePolicy.psm1' -ErrorRecord $_ }
|
|
40
|
+
|
|
41
|
+
function Get-FileSizeLimitBlockDecision {
|
|
42
|
+
<#
|
|
43
|
+
.SYNOPSIS
|
|
44
|
+
Constructs a deny-decision ordered dictionary carrying the supplied reason.
|
|
45
|
+
.PARAMETER Reason
|
|
46
|
+
The deny reason; it starts with FILE_SIZE_LIMIT_BLOCKED:.
|
|
47
|
+
#>
|
|
48
|
+
[CmdletBinding()]
|
|
49
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
50
|
+
param(
|
|
51
|
+
[Parameter(Mandatory)]
|
|
52
|
+
[string] $Reason
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return [ordered]@{
|
|
56
|
+
hookSpecificOutput = [ordered]@{
|
|
57
|
+
hookEventName = 'PreToolUse'
|
|
58
|
+
permissionDecision = 'deny'
|
|
59
|
+
permissionDecisionReason = $Reason
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Get-FileSizeLimitAllowDecision {
|
|
65
|
+
<#
|
|
66
|
+
.SYNOPSIS
|
|
67
|
+
Constructs the allow-decision ordered dictionary.
|
|
68
|
+
#>
|
|
69
|
+
[CmdletBinding()]
|
|
70
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
71
|
+
param()
|
|
72
|
+
|
|
73
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function Get-FileSizeLimitReplaceAllFlag {
|
|
77
|
+
<#
|
|
78
|
+
.SYNOPSIS
|
|
79
|
+
Returns the boolean value of the replace_all property of an Edit tool input.
|
|
80
|
+
.DESCRIPTION
|
|
81
|
+
A boolean is returned as is; a string is true only when its trimmed value is
|
|
82
|
+
'true' (case-insensitive); every other value, and an absent property, is false.
|
|
83
|
+
No [bool] cast is used because [bool]'false' is $true in PowerShell.
|
|
84
|
+
.PARAMETER ToolInput
|
|
85
|
+
The tool_input object.
|
|
86
|
+
#>
|
|
87
|
+
[CmdletBinding()]
|
|
88
|
+
[OutputType([bool])]
|
|
89
|
+
param(
|
|
90
|
+
[AllowNull()]
|
|
91
|
+
[object] $ToolInput
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
$value = Get-ClaudeHookEnvelopeValue -Envelope $ToolInput -Name 'replace_all'
|
|
95
|
+
if ($value -is [bool]) {
|
|
96
|
+
return $value
|
|
97
|
+
}
|
|
98
|
+
if ($value -is [string]) {
|
|
99
|
+
return ($value.Trim() -ieq 'true')
|
|
100
|
+
}
|
|
101
|
+
return $false
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function Invoke-FileSizeLimitDecision {
|
|
105
|
+
<#
|
|
106
|
+
.SYNOPSIS
|
|
107
|
+
Parses the PreToolUse envelope and returns an allow-or-deny decision.
|
|
108
|
+
.PARAMETER ToolInputRaw
|
|
109
|
+
The raw JSON hook payload acquired by Read-ClaudeHookRawPayload.
|
|
110
|
+
.PARAMETER RepositoryRoot
|
|
111
|
+
The repository root used to resolve relative paths. Defaults to the current
|
|
112
|
+
location, which is the project root when Claude Code runs the hook.
|
|
113
|
+
.PARAMETER ReadFileContent
|
|
114
|
+
Seam that returns the text of a file, $null when the file does not exist, and
|
|
115
|
+
throws when it cannot be read. Tests supply in-memory content.
|
|
116
|
+
#>
|
|
117
|
+
[CmdletBinding()]
|
|
118
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
119
|
+
param(
|
|
120
|
+
[AllowNull()]
|
|
121
|
+
[AllowEmptyString()]
|
|
122
|
+
[string] $ToolInputRaw,
|
|
123
|
+
|
|
124
|
+
[string] $RepositoryRoot = (Get-Location).ProviderPath,
|
|
125
|
+
|
|
126
|
+
[scriptblock] $ReadFileContent = {
|
|
127
|
+
param([string] $Path)
|
|
128
|
+
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return $null }
|
|
129
|
+
return [System.IO.File]::ReadAllText($Path)
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FILE_SIZE_LIMIT_BLOCKED:'
|
|
133
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
134
|
+
|
|
135
|
+
$payload = Resolve-ClaudeHookToolInput -Raw $ToolInputRaw
|
|
136
|
+
if (-not $payload.IsValid) {
|
|
137
|
+
return Get-FileSizeLimitBlockDecision -Reason ('FILE_SIZE_LIMIT_BLOCKED: payload anomaly - ' +
|
|
138
|
+
(Get-ClaudeHookPayloadAnomalyReason -Anomaly $payload.Anomaly) +
|
|
139
|
+
'. The gate fails closed on an envelope it cannot read.')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
$toolInput = $payload.Value
|
|
143
|
+
$filePath = Get-ClaudeHookToolInputString -ToolInput $toolInput -Name 'file_path'
|
|
144
|
+
$relativePath = ConvertTo-FileSizeRelativePath -Path $filePath -RepositoryRoot $RepositoryRoot
|
|
145
|
+
if (-not (Test-FileSizeCoveredPath -RelativePath $relativePath)) {
|
|
146
|
+
return Get-FileSizeLimitAllowDecision
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
$isRooted = ($filePath -match '^[\\/]') -or ($filePath -match '^[A-Za-z]:[\\/]')
|
|
150
|
+
$readPath = if ($isRooted) { $filePath } else { Join-Path $RepositoryRoot $relativePath }
|
|
151
|
+
$toolName = Get-ClaudeHookToolInputString -ToolInput $payload.Envelope -Name 'tool_name'
|
|
152
|
+
$isEdit = ($toolName -eq 'Edit')
|
|
153
|
+
|
|
154
|
+
$resultCount = 0
|
|
155
|
+
if (-not $isEdit) {
|
|
156
|
+
$resultCount = Get-FileSizeLogicalLineCount -Content (Get-ClaudeHookToolInputString -ToolInput $toolInput -Name 'content')
|
|
157
|
+
if ($resultCount -le (Get-FileSizePolicyLimit).HardLimit) {
|
|
158
|
+
return Get-FileSizeLimitAllowDecision
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
$preEditContent = & $ReadFileContent $readPath
|
|
164
|
+
} catch {
|
|
165
|
+
return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: '$relativePath' could not be read to measure its size ($($_.Exception.Message)). The gate fails closed for a covered file."
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
$preEditCount = $null
|
|
169
|
+
if ($null -ne $preEditContent) {
|
|
170
|
+
$preEditCount = Get-FileSizeLogicalLineCount -Content ([string]$preEditContent)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if ($isEdit) {
|
|
174
|
+
if ($null -eq $preEditContent) {
|
|
175
|
+
return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: '$relativePath' does not exist, so the Edit cannot be measured. The gate fails closed for a covered file."
|
|
176
|
+
}
|
|
177
|
+
$edit = Resolve-FileSizeEditContent -Content ([string]$preEditContent) `
|
|
178
|
+
-OldString (Get-ClaudeHookToolInputString -ToolInput $toolInput -Name 'old_string') `
|
|
179
|
+
-NewString (Get-ClaudeHookToolInputString -ToolInput $toolInput -Name 'new_string') `
|
|
180
|
+
-ReplaceAll (Get-FileSizeLimitReplaceAllFlag -ToolInput $toolInput)
|
|
181
|
+
if ($null -ne $edit.Failure) {
|
|
182
|
+
return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: the Edit to '$relativePath' could not be resolved in memory ($($edit.Failure)). The gate fails closed for a covered file."
|
|
183
|
+
}
|
|
184
|
+
$resultCount = Get-FileSizeLogicalLineCount -Content $edit.Content
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
$decision = Get-FileSizeHookDecision -RelativePath $relativePath -ResultLineCount $resultCount -PreEditLineCount $preEditCount
|
|
188
|
+
if ($decision.Allowed) {
|
|
189
|
+
return Get-FileSizeLimitAllowDecision
|
|
190
|
+
}
|
|
191
|
+
return Get-FileSizeLimitBlockDecision -Reason $decision.Reason
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function Invoke-FileSizeLimitEntryPoint {
|
|
195
|
+
<#
|
|
196
|
+
.SYNOPSIS
|
|
197
|
+
Runs the file-size decision and returns the process exit code.
|
|
198
|
+
.DESCRIPTION
|
|
199
|
+
Acquires the payload through the shared reader unless the caller supplies one,
|
|
200
|
+
writes the compact JSON decision to the output stream, and returns 0. It never
|
|
201
|
+
returns 1: exit 1 is non-blocking for PreToolUse, so every anomaly is already a
|
|
202
|
+
deny decision by the time control reaches here.
|
|
203
|
+
.PARAMETER ToolInputRaw
|
|
204
|
+
Optional pre-acquired payload text. When omitted the ReadPayload seam runs.
|
|
205
|
+
.PARAMETER ReadPayload
|
|
206
|
+
Seam for payload acquisition.
|
|
207
|
+
#>
|
|
208
|
+
[CmdletBinding()]
|
|
209
|
+
[OutputType([int])]
|
|
210
|
+
param(
|
|
211
|
+
[AllowNull()]
|
|
212
|
+
[AllowEmptyString()]
|
|
213
|
+
[string] $ToolInputRaw,
|
|
214
|
+
|
|
215
|
+
[scriptblock] $ReadPayload = { Read-ClaudeHookRawPayload }
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if (-not $PSBoundParameters.ContainsKey('ToolInputRaw')) {
|
|
219
|
+
$ToolInputRaw = [string](& $ReadPayload)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
$decision = Invoke-FileSizeLimitDecision -ToolInputRaw $ToolInputRaw
|
|
223
|
+
|
|
224
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
225
|
+
|
|
226
|
+
return 0
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
# Guard allows dot-sourcing in tests without executing the entrypoint.
|
|
230
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('FILE_SIZE_LIMIT_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
234
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FILE_SIZE_LIMIT_BLOCKED:'
|
|
235
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
236
|
+
|
|
237
|
+
# The entry point returns its [int] exit code as the last pipeline element and the
|
|
238
|
+
# decision JSON before it, so the decision is written explicitly here first.
|
|
239
|
+
$entryPointResult = @(Invoke-FileSizeLimitEntryPoint)
|
|
240
|
+
if ($entryPointResult.Count -gt 1) {
|
|
241
|
+
$entryPointResult[0..($entryPointResult.Count - 2)] | Write-Output
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
exit ([int]$entryPointResult[-1])
|
|
@@ -40,6 +40,14 @@
|
|
|
40
40
|
delegation prompt to a receipt-gated subagent type carries the canonical issue
|
|
41
41
|
number line and a `branch:` label naming the item's branch.
|
|
42
42
|
|
|
43
|
+
Author-asserted autoclose line (issue #989): for subagent `pr-author` only, once the
|
|
44
|
+
per-feature receipt is confirmed, a checkpoint that records an `issue-num` and whose
|
|
45
|
+
`epic_mode` is not true requires the prompt line
|
|
46
|
+
`Author-asserted autoclose issues: #<issue-num>` at the start of a line. Its absence denies
|
|
47
|
+
with the AUTHOR_ASSERTED_AUTOCLOSE_MISSING sub-code (Get-ModelRoutingAuthorAssertedReason).
|
|
48
|
+
The epic-scope path is not subject to this rule. Only the JSON boolean true waives the line;
|
|
49
|
+
a string or number such as "true" or 1 does not (issue #1001).
|
|
50
|
+
|
|
43
51
|
.NOTES
|
|
44
52
|
Compatible with PowerShell 7+. Read-only presence-gating deterrent.
|
|
45
53
|
#>
|
|
@@ -198,6 +206,44 @@ function Get-ModelRoutingTargetCheckpointResolution {
|
|
|
198
206
|
}
|
|
199
207
|
}
|
|
200
208
|
|
|
209
|
+
function Get-ModelRoutingAuthorAssertedReason {
|
|
210
|
+
<#
|
|
211
|
+
.SYNOPSIS
|
|
212
|
+
Return the deny reason for a pr-author delegation that omits the author-asserted line, or $null.
|
|
213
|
+
.DESCRIPTION
|
|
214
|
+
Returns $null when the checkpoint records no usable issue-num, when it carries an
|
|
215
|
+
epic_mode property whose value is true (an epic child whose integration PR owns the
|
|
216
|
+
closing keyword), or when a prompt line starts with 'Author-asserted autoclose issues:'
|
|
217
|
+
and names '#<issue-num>' later on that line with no digit after the number. Property
|
|
218
|
+
presence is tested first because strict mode throws on a missing property. Only the
|
|
219
|
+
JSON boolean true waives the line: a string or number such as "true" or 1 does not
|
|
220
|
+
(issue #1001).
|
|
221
|
+
.PARAMETER Checkpoint
|
|
222
|
+
The resolved per-feature checkpoint object.
|
|
223
|
+
.PARAMETER PromptText
|
|
224
|
+
The delegation prompt.
|
|
225
|
+
.OUTPUTS
|
|
226
|
+
System.String or $null
|
|
227
|
+
#>
|
|
228
|
+
[CmdletBinding()]
|
|
229
|
+
[OutputType([string])]
|
|
230
|
+
param(
|
|
231
|
+
[Parameter(Mandatory)][AllowNull()] $Checkpoint,
|
|
232
|
+
[Parameter(Mandatory)][AllowEmptyString()][string] $PromptText
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
$names = @($Checkpoint.PSObject.Properties.Name)
|
|
236
|
+
$issue = if ($names -contains 'issue-num') { ConvertTo-WorktreeItemIssueNumber -Value $Checkpoint.'issue-num' } else { $null }
|
|
237
|
+
if ($null -eq $issue -or ($names -contains 'epic_mode' -and ($Checkpoint.epic_mode -is [bool]) -and $Checkpoint.epic_mode)) {
|
|
238
|
+
return $null
|
|
239
|
+
}
|
|
240
|
+
$line = "Author-asserted autoclose issues: #$issue"
|
|
241
|
+
if ([regex]::IsMatch($PromptText, '(?m)^Author-asserted autoclose issues:[^\r\n]*#' + $issue + '(?!\d)')) {
|
|
242
|
+
return $null
|
|
243
|
+
}
|
|
244
|
+
return "MODEL_ROUTING_RECEIPT_BLOCKED: AUTHOR_ASSERTED_AUTOCLOSE_MISSING: the checkpoint records issue-num $issue, so the Agent(pr-author) delegation prompt must carry the line '$line' so the PR body emits '- Closes #$issue'. Add that line on its own line, or omit it only for an epic child (epic_mode true)."
|
|
245
|
+
}
|
|
246
|
+
|
|
201
247
|
function Invoke-ModelRoutingReceiptDecision {
|
|
202
248
|
<#
|
|
203
249
|
.SYNOPSIS
|
|
@@ -274,6 +320,11 @@ function Invoke-ModelRoutingReceiptDecision {
|
|
|
274
320
|
|
|
275
321
|
$checkpoint = Get-ModelRoutingCheckpoint -CheckpointPath $resolution.CheckpointPath
|
|
276
322
|
if (Test-ModelRoutingReceiptPresent -Checkpoint $checkpoint -Subagent $subagent) {
|
|
323
|
+
# Issue #989: the pr-author delegation names the item's issue as author-asserted.
|
|
324
|
+
$authorAssertedReason = if ($subagent -eq 'pr-author') { Get-ModelRoutingAuthorAssertedReason -Checkpoint $checkpoint -PromptText $prompt } else { $null }
|
|
325
|
+
if ($authorAssertedReason) {
|
|
326
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'deny'; permissionDecisionReason = $authorAssertedReason } }
|
|
327
|
+
}
|
|
277
328
|
return $allow
|
|
278
329
|
}
|
|
279
330
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Epic-scope legs, checkpoint read seams, and target resolution of the preimplementation gate.
|
|
4
4
|
|
|
5
5
|
.DESCRIPTION
|
|
6
|
-
Dot-sourced by enforce-orchestration-preimplementation-gate.ps1. Holds
|
|
6
|
+
Dot-sourced by enforce-orchestration-preimplementation-gate.ps1. Holds five groups of
|
|
7
7
|
functions:
|
|
8
8
|
|
|
9
9
|
- The import guards for the worktree-resolution modules (issue #690). A failed import
|
|
@@ -15,13 +15,20 @@
|
|
|
15
15
|
read binds to the calling process's directory. Get-CheckpointContent and
|
|
16
16
|
Get-OrchestrationModeDenyReason were relocated here from the gate file by issue #690
|
|
17
17
|
to keep the gate inside the 500-line cap.
|
|
18
|
+
- The target-resolution building blocks of issue #1010: the worktree-list wrapper
|
|
19
|
+
Get-OrchestrationGateWorktreeList (the only listing seam), the recording invoker
|
|
20
|
+
Invoke-OrchestrationGateWorktreeList, which records a failed or empty listing in
|
|
21
|
+
$script:OrchestrationGateWorktreeListFailed, and the command-operand parser
|
|
22
|
+
Get-OrchestrationGateCommandOperandPath for git add and git commit.
|
|
18
23
|
- The target resolution of issue #690. Resolve-OrchestrationGateTarget selects the
|
|
19
24
|
worktree whose checkpoint governs the call from portable identity only: the
|
|
20
25
|
integration_branch: value for an epic delegation, the parallel_slug: value for a
|
|
21
|
-
parallel delegation, the
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
parallel delegation, and the canonical issue-number line and branch: label for a
|
|
27
|
+
single-feature delegation. The path and command legs resolve through
|
|
28
|
+
Resolve-HookTargetWorktree (issue #1010) from the file_path or from every git add
|
|
29
|
+
and git commit selector and absolute operand. Read-OrchestrationGateCheckpoint reads
|
|
30
|
+
the checkpoint beneath the resolved root, or returns the deny for an unresolved
|
|
31
|
+
target.
|
|
25
32
|
- The epic-scope decision for the command and path legs (issue #663). A staging
|
|
26
33
|
command or a Write/Edit call is epic scope when the effective worktree's HEAD equals
|
|
27
34
|
the integration branch of the epic checkpoint that Resolve-EpicScopeCheckpoint
|
|
@@ -30,21 +37,24 @@
|
|
|
30
37
|
|
|
31
38
|
.NOTES
|
|
32
39
|
PowerShell 7+. Depends on functions the gate defines or dot-sources before any call:
|
|
33
|
-
Split-OrchestrationCommandLine and ConvertTo-OrchestrationCommandToken (helpers file),
|
|
34
40
|
Get-OrchestrationDelegationCheckpointPath (modes file), the gate's allow and block
|
|
35
|
-
decision constructors, and,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
decision constructors, and Read-CommandLineSegment, Get-CommandLineGlobalOption, and
|
|
42
|
+
Get-CommandLineInvocation (loaded by the gate's dot-source of
|
|
43
|
+
hook-command-invocation.ps1), which the targets file this file dot-sources (issue #738)
|
|
44
|
+
and Get-OrchestrationGateCommandOperandPath call. Imports
|
|
45
|
+
WorktreeResolution.psm1 (the reason-code accessors), then WorktreeItemResolution.psm1
|
|
46
|
+
and WorktreeRunResolution.psm1 before EpicScopeResolution.psm1, so the nested import
|
|
47
|
+
inside EpicScopeResolution reuses the same module instance, and HookTargetWorktree.psm1
|
|
48
|
+
(Resolve-HookTargetWorktree, issue #1009) last. Mirrored byte-identically under
|
|
41
49
|
extensions/drm-copilot/resources/claude-customizations/.
|
|
42
50
|
#>
|
|
43
51
|
|
|
52
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeResolution.psm1' -ErrorRecord $_ }
|
|
44
53
|
try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeItemResolution.psm1' -ErrorRecord $_ }
|
|
45
54
|
try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeRunResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeRunResolution.psm1' -ErrorRecord $_ }
|
|
46
55
|
try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'EpicScopeResolution.psm1' -ErrorRecord $_ }
|
|
47
56
|
try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/EpicScopeReadiness.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'EpicScopeReadiness.psm1' -ErrorRecord $_ }
|
|
57
|
+
try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/HookTargetWorktree.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'HookTargetWorktree.psm1' -ErrorRecord $_ }
|
|
48
58
|
# Per-segment target resolution for the epic-scope decision (issue #738).
|
|
49
59
|
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-targets.ps1')
|
|
50
60
|
|
|
@@ -102,15 +112,137 @@ function Get-OrchestrationModeDenyReason {
|
|
|
102
112
|
'require that checkpoint to satisfy every readiness predicate before implementation begins.')
|
|
103
113
|
}
|
|
104
114
|
|
|
115
|
+
function Get-OrchestrationGateWorktreeList {
|
|
116
|
+
<#
|
|
117
|
+
.SYNOPSIS
|
|
118
|
+
Returns the porcelain worktree listing for the session root (issue #1010 seam).
|
|
119
|
+
.DESCRIPTION
|
|
120
|
+
Runs the listing exactly as the default WorktreeListInvoker of
|
|
121
|
+
Resolve-HookTargetWorktree does and returns an empty string on a non-zero exit. It
|
|
122
|
+
is the only test seam for the listing.
|
|
123
|
+
.OUTPUTS
|
|
124
|
+
System.String
|
|
125
|
+
#>
|
|
126
|
+
[CmdletBinding()]
|
|
127
|
+
[OutputType([string])]
|
|
128
|
+
param([Parameter(Mandatory)][string] $SessionRoot)
|
|
129
|
+
|
|
130
|
+
$porcelain = & git -C $SessionRoot worktree list --porcelain 2>$null
|
|
131
|
+
if ($LASTEXITCODE -ne 0) { return '' }
|
|
132
|
+
return ($porcelain -join "`n")
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function Invoke-OrchestrationGateWorktreeList {
|
|
136
|
+
<#
|
|
137
|
+
.SYNOPSIS
|
|
138
|
+
Recording WorktreeListInvoker: returns the listing and records a listing failure.
|
|
139
|
+
.DESCRIPTION
|
|
140
|
+
Sets $script:OrchestrationGateWorktreeListFailed when the wrapper throws (and then
|
|
141
|
+
rethrows) or when its text holds no worktree entry, so the gate denies instead of
|
|
142
|
+
accepting the resolver's session-root fallback (issue #1010, spec E1).
|
|
143
|
+
.OUTPUTS
|
|
144
|
+
System.String
|
|
145
|
+
#>
|
|
146
|
+
[CmdletBinding()]
|
|
147
|
+
[OutputType([string])]
|
|
148
|
+
param([Parameter(Mandatory)][string] $SessionRoot)
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
$text = [string](Get-OrchestrationGateWorktreeList -SessionRoot $SessionRoot)
|
|
152
|
+
} catch {
|
|
153
|
+
$script:OrchestrationGateWorktreeListFailed = $true
|
|
154
|
+
throw
|
|
155
|
+
}
|
|
156
|
+
if (@(ConvertFrom-HookTargetWorktreePorcelain -Text $text).Count -eq 0) {
|
|
157
|
+
$script:OrchestrationGateWorktreeListFailed = $true
|
|
158
|
+
}
|
|
159
|
+
return $text
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function Get-OrchestrationGateCommandOperandPath {
|
|
163
|
+
<#
|
|
164
|
+
.SYNOPSIS
|
|
165
|
+
Returns the worktree-selecting paths of every git add and git commit invocation.
|
|
166
|
+
.DESCRIPTION
|
|
167
|
+
Scans every Structural match of git add and git commit (every command segment and
|
|
168
|
+
wrapper payload). Each -C value in any git global-option position and each absolute
|
|
169
|
+
operand is returned, distinct and in first-seen order. Relative operands, a -C on a
|
|
170
|
+
git segment invoking neither add nor commit, and Indeterminate matches are ignored.
|
|
171
|
+
For a match whose record is not argument-injected, a subcommand-aware walk (issue
|
|
172
|
+
#1010, F2) also reads the tokens after the subcommand with a per-subcommand option
|
|
173
|
+
model, compared case-sensitively: a value option consumes the next token unless its
|
|
174
|
+
value is inline (--name=value) or attached (-mvalue); a standalone flag consumes
|
|
175
|
+
itself; '--' makes every later token an operand; a redirection and its target are
|
|
176
|
+
skipped; any other dash token, such as the cluster -am, stops the walk. Its literal
|
|
177
|
+
absolute tokens are returned, and a token the walk reads as an option value is not
|
|
178
|
+
returned as an operand.
|
|
179
|
+
.PARAMETER Command
|
|
180
|
+
The full command line.
|
|
181
|
+
.OUTPUTS
|
|
182
|
+
System.String[]
|
|
183
|
+
#>
|
|
184
|
+
[CmdletBinding()]
|
|
185
|
+
[OutputType([string[]])]
|
|
186
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Command)
|
|
187
|
+
|
|
188
|
+
$valueOptions = @{
|
|
189
|
+
commit = @('-m', '--message', '-F', '--file', '--author', '--date', '-C', '--reuse-message', '-c', '--reedit-message', '-t', '--template', '--fixup', '--squash', '--trailer', '--pathspec-from-file')
|
|
190
|
+
add = @('--pathspec-from-file', '--chmod')
|
|
191
|
+
}
|
|
192
|
+
$flagOptions = @{
|
|
193
|
+
commit = @('-a', '--all', '--amend', '--no-edit', '--no-verify', '-n', '-s', '--signoff', '-q', '--quiet', '-v', '--verbose', '--allow-empty', '-o', '--only', '-i', '--include', '--pathspec-file-nul')
|
|
194
|
+
add = @('-A', '--all', '-u', '--update', '-f', '--force', '-N', '--intent-to-add', '-n', '--dry-run', '-v', '--verbose', '--pathspec-file-nul')
|
|
195
|
+
}
|
|
196
|
+
$absolutePattern = '^([A-Za-z]:[\\/]|/)'
|
|
197
|
+
$paths = [System.Collections.Generic.List[string]]::new()
|
|
198
|
+
foreach ($subcommand in @('add', 'commit')) {
|
|
199
|
+
foreach ($match in @(Get-CommandLineInvocation -CommandText $Command -CommandWord 'git' -SubcommandPath @($subcommand))) {
|
|
200
|
+
if ($match.Status -ne 'Structural') { continue }
|
|
201
|
+
$walked = [System.Collections.Generic.List[string]]::new()
|
|
202
|
+
$optionValues = [System.Collections.Generic.List[string]]::new()
|
|
203
|
+
$tokens = if ($match.Segment.ArgumentInjected) { [string[]]@() } else { [string[]]@($match.Segment.Tokens) }
|
|
204
|
+
$afterSeparator = $false
|
|
205
|
+
for ($index = [int]$match.OperandIndex; $index -lt $tokens.Count; $index++) {
|
|
206
|
+
$token = $tokens[$index]
|
|
207
|
+
if (-not $afterSeparator -and $token -match '^(<|>|\d*>|&>)') {
|
|
208
|
+
if ($token -match '^(\d*[<>]{1,2}&?|&>{1,2})$') { $index++ }
|
|
209
|
+
continue
|
|
210
|
+
}
|
|
211
|
+
if ($afterSeparator -or -not $token.StartsWith('-')) { $walked.Add($token); continue }
|
|
212
|
+
if ($token -ceq '--') { $afterSeparator = $true; continue }
|
|
213
|
+
$name = if ($token.IndexOf('=') -gt 0) { $token.Substring(0, $token.IndexOf('=')) } else { $token }
|
|
214
|
+
if ($valueOptions[$subcommand] -ccontains $name) {
|
|
215
|
+
if ($name -ceq $token -and $index + 1 -lt $tokens.Count) { $index++; $optionValues.Add($tokens[$index]) }
|
|
216
|
+
continue
|
|
217
|
+
}
|
|
218
|
+
if ($token -match '^-[^-].' -and $valueOptions[$subcommand] -ccontains $token.Substring(0, 2)) { continue }
|
|
219
|
+
if ($flagOptions[$subcommand] -ccontains $token) { continue }
|
|
220
|
+
break
|
|
221
|
+
}
|
|
222
|
+
$candidates = @(@($match.GlobalOptions) | Where-Object { $_.Name -ceq '-C' -and $_.Value } | ForEach-Object { [string]$_.Value })
|
|
223
|
+
$candidates += @(@($match.Operands) | Where-Object { $_ -match $absolutePattern -and $optionValues -cnotcontains $_ })
|
|
224
|
+
$candidates += @($walked | Where-Object { $_ -match $absolutePattern -and (Test-CommandLineTokenLiteral -Token $_) })
|
|
225
|
+
foreach ($candidate in $candidates) {
|
|
226
|
+
if ($paths -notcontains $candidate) { $paths.Add($candidate) }
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return [string[]]$paths.ToArray()
|
|
231
|
+
}
|
|
232
|
+
|
|
105
233
|
function Resolve-OrchestrationGateTarget {
|
|
106
234
|
<#
|
|
107
235
|
.SYNOPSIS
|
|
108
236
|
Resolves the worktree whose checkpoint governs a gated call (issue #690 seam).
|
|
109
237
|
.DESCRIPTION
|
|
110
238
|
An epic delegation is keyed on integration_branch: (with epic_feature_folder: as a
|
|
111
|
-
cross-check), a parallel delegation on parallel_slug:, a
|
|
112
|
-
|
|
113
|
-
|
|
239
|
+
cross-check), a parallel delegation on parallel_slug:, and a single-feature
|
|
240
|
+
delegation on its canonical issue-number line and branch: label. The path and
|
|
241
|
+
command legs use Resolve-HookTargetWorktree (issue #1010): a path leg passes its
|
|
242
|
+
file_path, a command leg the Get-OrchestrationGateCommandOperandPath result, and the
|
|
243
|
+
recording invoker supplies the worktree listing. A failed or empty listing denies as
|
|
244
|
+
not derivable instead of falling back to the session root; an ambiguous result
|
|
245
|
+
denies as ambiguous; a null root denies as not derivable.
|
|
114
246
|
.OUTPUTS
|
|
115
247
|
System.Management.Automation.PSCustomObject (the worktree-resolution target result).
|
|
116
248
|
#>
|
|
@@ -131,13 +263,29 @@ function Resolve-OrchestrationGateTarget {
|
|
|
131
263
|
}
|
|
132
264
|
return Resolve-WorktreeParallelTarget -ParallelSlug $signal.ParallelSlug -SessionRoot $sessionRoot
|
|
133
265
|
}
|
|
134
|
-
if ($FilePath) {
|
|
135
|
-
return Resolve-
|
|
266
|
+
if (-not $FilePath -and -not $Command) {
|
|
267
|
+
return Resolve-WorktreeItemTarget -Text $Prompt -SessionRoot $sessionRoot
|
|
268
|
+
}
|
|
269
|
+
$script:OrchestrationGateWorktreeListFailed = $false
|
|
270
|
+
$invoker = { param($SessionRoot) Invoke-OrchestrationGateWorktreeList -SessionRoot $SessionRoot }
|
|
271
|
+
$resolved = if ($FilePath) {
|
|
272
|
+
Resolve-HookTargetWorktree -SessionRoot $sessionRoot -FilePath @($FilePath) -WorktreeListInvoker $invoker
|
|
273
|
+
} else {
|
|
274
|
+
Resolve-HookTargetWorktree -SessionRoot $sessionRoot -CommandOperandPath @(Get-OrchestrationGateCommandOperandPath -Command $Command) -WorktreeListInvoker $invoker
|
|
275
|
+
}
|
|
276
|
+
$detail = "resolver source $($resolved.Source): $($resolved.Detail)"
|
|
277
|
+
if ($script:OrchestrationGateWorktreeListFailed) {
|
|
278
|
+
return [pscustomobject]@{ Status = 'NoTarget'; WorktreeRoot = $null; ReasonCode = (Get-WorktreeResolutionNoTargetReasonCode); Detail = "the worktree listing failed or named no worktree; $detail" }
|
|
136
279
|
}
|
|
137
|
-
if ($
|
|
138
|
-
return
|
|
280
|
+
if ($resolved.Ambiguous) {
|
|
281
|
+
return [pscustomobject]@{ Status = 'Ambiguous'; WorktreeRoot = $null; ReasonCode = (Get-WorktreeResolutionAmbiguityReasonCode); Detail = $detail }
|
|
139
282
|
}
|
|
140
|
-
|
|
283
|
+
if ([string]::IsNullOrEmpty([string]$resolved.WorktreeRoot)) {
|
|
284
|
+
return [pscustomobject]@{ Status = 'NoTarget'; WorktreeRoot = $null; ReasonCode = (Get-WorktreeResolutionNoTargetReasonCode); Detail = $detail }
|
|
285
|
+
}
|
|
286
|
+
$isSession = [string]::Equals([string]$resolved.WorktreeRoot, (ConvertTo-HookTargetWorktreeNormalizedPath -Path $sessionRoot), [System.StringComparison]::OrdinalIgnoreCase)
|
|
287
|
+
$status = if ($isSession) { 'SessionRoot' } else { 'OtherWorktree' }
|
|
288
|
+
return [pscustomobject]@{ Status = $status; WorktreeRoot = [string]$resolved.WorktreeRoot; ReasonCode = $null; Detail = $detail }
|
|
141
289
|
}
|
|
142
290
|
|
|
143
291
|
function Read-OrchestrationGateCheckpoint {
|
|
@@ -187,34 +335,6 @@ function Read-OrchestrationGateCheckpoint {
|
|
|
187
335
|
}
|
|
188
336
|
}
|
|
189
337
|
|
|
190
|
-
function Get-OrchestrationEpicScopeSelector {
|
|
191
|
-
<#
|
|
192
|
-
.SYNOPSIS
|
|
193
|
-
Returns the value of a leading `git -C <value>` selector, or $null.
|
|
194
|
-
.DESCRIPTION
|
|
195
|
-
Pure. Reads only the first segment of the command line, split and tokenized with
|
|
196
|
-
the helpers-file parser so quoting is handled exactly as the staging exemption
|
|
197
|
-
handles it. An unbalanced command line has no decidable selector and returns $null.
|
|
198
|
-
.PARAMETER Command
|
|
199
|
-
The full command line.
|
|
200
|
-
.OUTPUTS
|
|
201
|
-
System.String
|
|
202
|
-
#>
|
|
203
|
-
[CmdletBinding()]
|
|
204
|
-
[OutputType([string])]
|
|
205
|
-
param([Parameter(Mandatory)][AllowEmptyString()][string] $Command)
|
|
206
|
-
|
|
207
|
-
$split = Split-OrchestrationCommandLine -CommandText $Command
|
|
208
|
-
if (-not $split.Balanced -or @($split.Segments).Count -eq 0) {
|
|
209
|
-
return $null
|
|
210
|
-
}
|
|
211
|
-
$token = @(ConvertTo-OrchestrationCommandToken -Segment ([string]@($split.Segments)[0]).Trim())
|
|
212
|
-
if ($token.Count -ge 3 -and $token[0] -ceq 'git' -and $token[1] -ceq '-C' -and $token[2]) {
|
|
213
|
-
return $token[2]
|
|
214
|
-
}
|
|
215
|
-
return $null
|
|
216
|
-
}
|
|
217
|
-
|
|
218
338
|
function Get-OrchestrationEpicScopeDecision {
|
|
219
339
|
<#
|
|
220
340
|
.SYNOPSIS
|
|
@@ -239,7 +239,7 @@ function Test-OrchestrationReady {
|
|
|
239
239
|
}
|
|
240
240
|
$lifecycleReady = $false
|
|
241
241
|
if ($Payload.PSObject.Properties.Name -contains 'lifecycle_ready') {
|
|
242
|
-
$lifecycleReady = [bool]$Payload.lifecycle_ready
|
|
242
|
+
$lifecycleReady = ($Payload.lifecycle_ready -is [bool]) -and $Payload.lifecycle_ready
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
if (-not $issueNum -or -not $featureFolder -or -not $routeId -or -not $lifecycleReady) {
|