@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,282 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Pre-tool-use hook that blocks a Write, Edit, or apply_patch leaving a covered file above 800 lines.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
This script is invoked by the Codex PreToolUse hook under the ^(apply_patch|Edit|Write)$
|
|
7
|
+
matcher. 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 of
|
|
9
|
+
logical separability. The policy functions are the dot-sourced Codex twin
|
|
10
|
+
file-size-policy.ps1, which is held text-identical to the Claude module.
|
|
11
|
+
|
|
12
|
+
The stdin payload is parsed by ConvertFrom-CodexPreToolUsePayload and mapped to
|
|
13
|
+
file-edit records by ConvertTo-CodexFileEditInput. Per record:
|
|
14
|
+
- A path that is not covered, and a Delete, allow with no file read.
|
|
15
|
+
- Write and apply_patch Add use the record content.
|
|
16
|
+
- Edit resolves old_string to new_string in memory against the pre-edit file read
|
|
17
|
+
through the ReadFileContent seam; a missing or unreadable file, or an edit that
|
|
18
|
+
cannot be resolved, denies.
|
|
19
|
+
- apply_patch Update is reconstructed by a second ConvertTo-CodexFileEditInput call
|
|
20
|
+
with -ResolveUpdateContent and -GovernedPath set to the patched path; empty
|
|
21
|
+
reconstructed content denies.
|
|
22
|
+
- A rename evaluates the destination, and the source supplies the pre-edit size.
|
|
23
|
+
A result above 800 lines is denied unless the file already existed and does not grow.
|
|
24
|
+
|
|
25
|
+
Allowed payloads produce NO stdout and exit 0. A deny writes the PreToolUse JSON
|
|
26
|
+
envelope to stdout and exits 0. Empty, malformed, or tool_input-less stdin writes the
|
|
27
|
+
reason to stderr and exits 2.
|
|
28
|
+
|
|
29
|
+
.NOTES
|
|
30
|
+
Compatible with PowerShell 7+.
|
|
31
|
+
This script must not modify any state; it is a read-only validation gate.
|
|
32
|
+
#>
|
|
33
|
+
[CmdletBinding()]
|
|
34
|
+
param()
|
|
35
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
36
|
+
|
|
37
|
+
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
38
|
+
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
39
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
40
|
+
try { . (Join-Path $PSScriptRoot 'file-size-policy.ps1') } catch { Add-HookDependencyFailure -Name 'file-size-policy.ps1' -ErrorRecord $_ }
|
|
41
|
+
|
|
42
|
+
function Get-FileSizeLimitBlockDecision {
|
|
43
|
+
<#
|
|
44
|
+
.SYNOPSIS
|
|
45
|
+
Constructs a deny-decision ordered dictionary carrying the supplied reason.
|
|
46
|
+
.PARAMETER Reason
|
|
47
|
+
The deny reason; it starts with FILE_SIZE_LIMIT_BLOCKED:.
|
|
48
|
+
#>
|
|
49
|
+
[CmdletBinding()]
|
|
50
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
51
|
+
param(
|
|
52
|
+
[Parameter(Mandatory)]
|
|
53
|
+
[string] $Reason
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return [ordered]@{
|
|
57
|
+
hookSpecificOutput = [ordered]@{
|
|
58
|
+
hookEventName = 'PreToolUse'
|
|
59
|
+
permissionDecision = 'deny'
|
|
60
|
+
permissionDecisionReason = $Reason
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function Get-CodexFileSizeRecordValue {
|
|
66
|
+
<#
|
|
67
|
+
.SYNOPSIS
|
|
68
|
+
Returns a named property of a file-edit record, or $null when it is absent.
|
|
69
|
+
#>
|
|
70
|
+
[CmdletBinding()]
|
|
71
|
+
[OutputType([object])]
|
|
72
|
+
param(
|
|
73
|
+
[Parameter(Mandatory)]
|
|
74
|
+
[AllowNull()]
|
|
75
|
+
$Record,
|
|
76
|
+
|
|
77
|
+
[Parameter(Mandatory)]
|
|
78
|
+
[string] $Name
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if ($null -eq $Record -or $Record.PSObject.Properties.Name -notcontains $Name) {
|
|
82
|
+
return $null
|
|
83
|
+
}
|
|
84
|
+
return $Record.$Name
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function Get-CodexFileSizeReplaceAllFlag {
|
|
88
|
+
<#
|
|
89
|
+
.SYNOPSIS
|
|
90
|
+
Returns the boolean value of a record's replace_all property.
|
|
91
|
+
.DESCRIPTION
|
|
92
|
+
A boolean is returned as is; a string is true only when its trimmed value is
|
|
93
|
+
'true' (case-insensitive); every other value is false.
|
|
94
|
+
#>
|
|
95
|
+
[CmdletBinding()]
|
|
96
|
+
[OutputType([bool])]
|
|
97
|
+
param(
|
|
98
|
+
[Parameter(Mandatory)]
|
|
99
|
+
[AllowNull()]
|
|
100
|
+
$Record
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
$value = Get-CodexFileSizeRecordValue -Record $Record -Name 'replace_all'
|
|
104
|
+
if ($value -is [bool]) {
|
|
105
|
+
return $value
|
|
106
|
+
}
|
|
107
|
+
if ($value -is [string]) {
|
|
108
|
+
return ($value.Trim() -ieq 'true')
|
|
109
|
+
}
|
|
110
|
+
return $false
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function Get-CodexFileSizeUpdatedContent {
|
|
114
|
+
<#
|
|
115
|
+
.SYNOPSIS
|
|
116
|
+
Reconstructs the post-patch content of an apply_patch Update for one patched path.
|
|
117
|
+
.OUTPUTS
|
|
118
|
+
The reconstructed content, or an empty string when it cannot be reconstructed.
|
|
119
|
+
#>
|
|
120
|
+
[CmdletBinding()]
|
|
121
|
+
[OutputType([string])]
|
|
122
|
+
param(
|
|
123
|
+
[Parameter(Mandatory)]
|
|
124
|
+
$Payload,
|
|
125
|
+
|
|
126
|
+
[Parameter(Mandatory)]
|
|
127
|
+
[string] $SourcePath
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
$resolved = @(
|
|
131
|
+
ConvertTo-CodexFileEditInput -Payload $Payload -ResolveUpdateContent -GovernedPath $SourcePath |
|
|
132
|
+
Where-Object { $_.operation -eq 'Update' -and $_.source_path -eq $SourcePath }
|
|
133
|
+
)
|
|
134
|
+
if ($resolved.Count -eq 0) {
|
|
135
|
+
return ''
|
|
136
|
+
}
|
|
137
|
+
return [string]$resolved[0].content
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function Invoke-CodexFileSizeLimitDecision {
|
|
141
|
+
<#
|
|
142
|
+
.SYNOPSIS
|
|
143
|
+
Returns the deny decision for one file-edit record, or $null when it is allowed.
|
|
144
|
+
.PARAMETER Record
|
|
145
|
+
One record from ConvertTo-CodexFileEditInput.
|
|
146
|
+
.PARAMETER Payload
|
|
147
|
+
The parsed payload, used to reconstruct an apply_patch Update.
|
|
148
|
+
.PARAMETER RepositoryRoot
|
|
149
|
+
The repository root used to resolve relative paths. Defaults to the current location.
|
|
150
|
+
.PARAMETER ReadFileContent
|
|
151
|
+
Seam that returns the text of a file, $null when the file does not exist, and
|
|
152
|
+
throws when it cannot be read. Tests supply in-memory content.
|
|
153
|
+
#>
|
|
154
|
+
[CmdletBinding()]
|
|
155
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
156
|
+
param(
|
|
157
|
+
[Parameter(Mandatory)]
|
|
158
|
+
$Record,
|
|
159
|
+
|
|
160
|
+
[Parameter(Mandatory)]
|
|
161
|
+
$Payload,
|
|
162
|
+
|
|
163
|
+
[string] $RepositoryRoot = (Get-Location).ProviderPath,
|
|
164
|
+
|
|
165
|
+
[scriptblock] $ReadFileContent = {
|
|
166
|
+
param([string] $Path)
|
|
167
|
+
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return $null }
|
|
168
|
+
return [System.IO.File]::ReadAllText($Path)
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FILE_SIZE_LIMIT_BLOCKED:'
|
|
172
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
173
|
+
|
|
174
|
+
$operation = [string](Get-CodexFileSizeRecordValue -Record $Record -Name 'operation')
|
|
175
|
+
$sourcePath = [string](Get-CodexFileSizeRecordValue -Record $Record -Name 'source_path')
|
|
176
|
+
$relativePath = ConvertTo-FileSizeRelativePath -Path ([string]$Record.file_path) -RepositoryRoot $RepositoryRoot
|
|
177
|
+
if ($operation -eq 'Delete' -or -not (Test-FileSizeCoveredPath -RelativePath $relativePath)) {
|
|
178
|
+
return $null
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# The pre-edit size comes from the source path, which differs from the target only for a rename.
|
|
182
|
+
$sourceRelative = ConvertTo-FileSizeRelativePath -Path $sourcePath -RepositoryRoot $RepositoryRoot
|
|
183
|
+
$isRooted = ($sourcePath -match '^[\\/]') -or ($sourcePath -match '^[A-Za-z]:[\\/]')
|
|
184
|
+
$readPath = if ($isRooted -or $null -eq $sourceRelative) { $sourcePath } else { Join-Path $RepositoryRoot $sourceRelative }
|
|
185
|
+
$hardLimit = (Get-FileSizePolicyLimit).HardLimit
|
|
186
|
+
|
|
187
|
+
$resultCount = 0
|
|
188
|
+
if ($operation -eq 'Update') {
|
|
189
|
+
$updated = Get-CodexFileSizeUpdatedContent -Payload $Payload -SourcePath $sourcePath
|
|
190
|
+
if ([string]::IsNullOrEmpty($updated)) {
|
|
191
|
+
return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: the apply_patch Update to '$relativePath' could not be reconstructed to measure its size. The gate fails closed for a covered file."
|
|
192
|
+
}
|
|
193
|
+
$resultCount = Get-FileSizeLogicalLineCount -Content $updated
|
|
194
|
+
} elseif ($operation -ne 'Edit') {
|
|
195
|
+
$resultCount = Get-FileSizeLogicalLineCount -Content ([string](Get-CodexFileSizeRecordValue -Record $Record -Name 'content'))
|
|
196
|
+
}
|
|
197
|
+
if ($operation -ne 'Edit' -and $resultCount -le $hardLimit) {
|
|
198
|
+
return $null
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
$preEditContent = & $ReadFileContent $readPath
|
|
203
|
+
} catch {
|
|
204
|
+
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."
|
|
205
|
+
}
|
|
206
|
+
$preEditCount = $null
|
|
207
|
+
if ($null -ne $preEditContent) {
|
|
208
|
+
$preEditCount = Get-FileSizeLogicalLineCount -Content ([string]$preEditContent)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if ($operation -eq 'Edit') {
|
|
212
|
+
if ($null -eq $preEditContent) {
|
|
213
|
+
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."
|
|
214
|
+
}
|
|
215
|
+
$edit = Resolve-FileSizeEditContent -Content ([string]$preEditContent) `
|
|
216
|
+
-OldString ([string](Get-CodexFileSizeRecordValue -Record $Record -Name 'old_string')) `
|
|
217
|
+
-NewString ([string](Get-CodexFileSizeRecordValue -Record $Record -Name 'new_string')) `
|
|
218
|
+
-ReplaceAll (Get-CodexFileSizeReplaceAllFlag -Record $Record)
|
|
219
|
+
if ($null -ne $edit.Failure) {
|
|
220
|
+
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."
|
|
221
|
+
}
|
|
222
|
+
$resultCount = Get-FileSizeLogicalLineCount -Content $edit.Content
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
$decision = Get-FileSizeHookDecision -RelativePath $relativePath -ResultLineCount $resultCount -PreEditLineCount $preEditCount
|
|
226
|
+
if ($decision.Allowed) {
|
|
227
|
+
return $null
|
|
228
|
+
}
|
|
229
|
+
return Get-FileSizeLimitBlockDecision -Reason $decision.Reason
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function Invoke-CodexFileSizeLimitEntryPoint {
|
|
233
|
+
<#
|
|
234
|
+
.SYNOPSIS
|
|
235
|
+
Reads one Codex PreToolUse payload and returns the process exit code.
|
|
236
|
+
.PARAMETER PayloadRaw
|
|
237
|
+
The raw stdin text. AllowEmptyString is required so empty input reaches the shared
|
|
238
|
+
parser and fails closed with exit 2.
|
|
239
|
+
.PARAMETER RepositoryRoot
|
|
240
|
+
The repository root passed to the per-record decision.
|
|
241
|
+
.PARAMETER ReadFileContent
|
|
242
|
+
Optional file-reader seam passed to the per-record decision.
|
|
243
|
+
#>
|
|
244
|
+
[CmdletBinding()]
|
|
245
|
+
[OutputType([int])]
|
|
246
|
+
param(
|
|
247
|
+
[Parameter(Mandatory)]
|
|
248
|
+
[AllowEmptyString()]
|
|
249
|
+
[string] $PayloadRaw,
|
|
250
|
+
|
|
251
|
+
[string] $RepositoryRoot = (Get-Location).ProviderPath,
|
|
252
|
+
|
|
253
|
+
[scriptblock] $ReadFileContent
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
try {
|
|
257
|
+
$payload = ConvertFrom-CodexPreToolUsePayload -PayloadRaw $PayloadRaw -HookName 'enforce-file-size-limit'
|
|
258
|
+
foreach ($record in @(ConvertTo-CodexFileEditInput -Payload $payload)) {
|
|
259
|
+
$decisionArgs = @{ Record = $record; Payload = $payload; RepositoryRoot = $RepositoryRoot }
|
|
260
|
+
if ($PSBoundParameters.ContainsKey('ReadFileContent')) { $decisionArgs['ReadFileContent'] = $ReadFileContent }
|
|
261
|
+
$decision = Invoke-CodexFileSizeLimitDecision @decisionArgs
|
|
262
|
+
if ($null -ne $decision) {
|
|
263
|
+
[Console]::Out.WriteLine(($decision | ConvertTo-Json -Compress -Depth 5))
|
|
264
|
+
return 0
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return 0
|
|
268
|
+
} catch {
|
|
269
|
+
[Console]::Error.WriteLine([string]$_)
|
|
270
|
+
return 2
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# Guard allows dot-sourcing in tests without executing the entrypoint.
|
|
275
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('FILE_SIZE_LIMIT_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
279
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FILE_SIZE_LIMIT_BLOCKED:'
|
|
280
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
281
|
+
|
|
282
|
+
exit (Invoke-CodexFileSizeLimitEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()))
|
|
@@ -4,12 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
.DESCRIPTION
|
|
6
6
|
Dot-sourced by enforce-orchestration-preimplementation-gate.ps1. The Codex counterpart
|
|
7
|
-
of the issue #663 Claude sibling, holding
|
|
7
|
+
of the issue #663 Claude sibling, holding three groups of functions:
|
|
8
8
|
|
|
9
9
|
- The two per-mode read seams of issue #554 (Get-EpicCheckpointContent and
|
|
10
10
|
Get-ParallelCheckpointContent), relocated verbatim from the gate file so the gate
|
|
11
11
|
stays inside the 500-line cap. Their names and behaviour are unchanged, so tests
|
|
12
12
|
that mock or shadow them by name are unaffected.
|
|
13
|
+
- The target-resolution building blocks of issue #1010, byte-identical to the Claude
|
|
14
|
+
sibling: the worktree-list wrapper Get-OrchestrationGateWorktreeList (the only
|
|
15
|
+
listing seam), the recording invoker Invoke-OrchestrationGateWorktreeList, and the
|
|
16
|
+
command-operand parser Get-OrchestrationGateCommandOperandPath, plus the reason-code
|
|
17
|
+
pair restated from WorktreeResolution.psm1. They feed Resolve-OrchestrationGateTarget
|
|
18
|
+
and Read-OrchestrationGateCheckpoint, which read the single-feature checkpoint through
|
|
19
|
+
the Get-CheckpointContent seam (mandatory absolute Path, moved here from the gate)
|
|
20
|
+
beneath the worktree the file path, apply_patch markers, or command operands name.
|
|
13
21
|
- The epic-scope decision for the command, apply_patch, and path legs. A call is epic
|
|
14
22
|
scope when the effective worktree's HEAD (the -C selector worktree when present,
|
|
15
23
|
otherwise the session root) equals the integration_branch of
|
|
@@ -29,13 +37,23 @@
|
|
|
29
37
|
from the resolution sibling dot-sourced below. The per-segment target resolver comes
|
|
30
38
|
from the targets file dot-sourced below (issue #738), which calls
|
|
31
39
|
Read-CommandLineSegment, Get-CommandLineGlobalOption, and Get-CommandLineInvocation,
|
|
32
|
-
loaded by the gate's dot-source of hook-command-invocation.ps1.
|
|
40
|
+
loaded by the gate's dot-source of hook-command-invocation.ps1. Resolve-HookTargetWorktree
|
|
41
|
+
and ConvertFrom-HookTargetWorktreePorcelain come from the guarded dot-source of the
|
|
42
|
+
resolver twin hook-target-worktree.ps1 (issue #1009).
|
|
33
43
|
Mirrored byte-identically under extensions/drm-copilot/resources/codex-and-agents-customizations/.
|
|
34
44
|
AUTHORITY: PowerShell-authoritative. The epic readiness predicate has no reference implementation in another language, and this hook starts no interpreter process (issue #707, D15).
|
|
35
45
|
#>
|
|
36
46
|
|
|
37
47
|
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-epic-resolution.ps1')
|
|
38
48
|
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-targets.ps1')
|
|
49
|
+
try { . (Join-Path $PSScriptRoot 'hook-target-worktree.ps1') } catch { Add-HookDependencyFailure -Name 'hook-target-worktree.ps1' -ErrorRecord $_ }
|
|
50
|
+
|
|
51
|
+
# The target-resolution reason codes (issue #1010). Their source is
|
|
52
|
+
# Get-WorktreeResolutionAmbiguityReasonCode and Get-WorktreeResolutionNoTargetReasonCode
|
|
53
|
+
# in .claude/lib/worktree-resolution/WorktreeResolution.psm1; Codex hooks cannot import
|
|
54
|
+
# .claude/lib, so the two literals are restated once here and pinned equal by a test.
|
|
55
|
+
$script:OrchestrationGateAmbiguousReasonCode = 'TARGET_WORKTREE_AMBIGUOUS'
|
|
56
|
+
$script:OrchestrationGateNotDerivableReasonCode = 'TARGET_WORKTREE_NOT_DERIVABLE'
|
|
39
57
|
|
|
40
58
|
# An epic manifest lives under the epics tree; the pattern is tested after backslash
|
|
41
59
|
# normalisation so either separator spelling is accepted.
|
|
@@ -68,6 +86,225 @@ function Get-ParallelCheckpointContent {
|
|
|
68
86
|
return Get-Content -Raw -LiteralPath $path
|
|
69
87
|
}
|
|
70
88
|
|
|
89
|
+
# The single-feature read seam (issue #1010, moved from the gate file). It takes the
|
|
90
|
+
# absolute path composed beneath the resolved worktree root, so no read binds to the
|
|
91
|
+
# calling process's directory; an absent file returns an empty string.
|
|
92
|
+
function Get-CheckpointContent {
|
|
93
|
+
[CmdletBinding()]
|
|
94
|
+
[OutputType([string])]
|
|
95
|
+
param([Parameter(Mandatory)][ValidatePattern('^([A-Za-z]:[\\/]|/)')][string] $Path)
|
|
96
|
+
|
|
97
|
+
if (-not (Test-Path -LiteralPath $Path)) {
|
|
98
|
+
return ''
|
|
99
|
+
}
|
|
100
|
+
return Get-Content -Raw -LiteralPath $Path
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function Get-OrchestrationGateWorktreeList {
|
|
104
|
+
<#
|
|
105
|
+
.SYNOPSIS
|
|
106
|
+
Returns the porcelain worktree listing for the session root (issue #1010 seam).
|
|
107
|
+
.DESCRIPTION
|
|
108
|
+
Runs the listing exactly as the default WorktreeListInvoker of
|
|
109
|
+
Resolve-HookTargetWorktree does and returns an empty string on a non-zero exit. It
|
|
110
|
+
is the only test seam for the listing.
|
|
111
|
+
.OUTPUTS
|
|
112
|
+
System.String
|
|
113
|
+
#>
|
|
114
|
+
[CmdletBinding()]
|
|
115
|
+
[OutputType([string])]
|
|
116
|
+
param([Parameter(Mandatory)][string] $SessionRoot)
|
|
117
|
+
|
|
118
|
+
$porcelain = & git -C $SessionRoot worktree list --porcelain 2>$null
|
|
119
|
+
if ($LASTEXITCODE -ne 0) { return '' }
|
|
120
|
+
return ($porcelain -join "`n")
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function Invoke-OrchestrationGateWorktreeList {
|
|
124
|
+
<#
|
|
125
|
+
.SYNOPSIS
|
|
126
|
+
Recording WorktreeListInvoker: returns the listing and records a listing failure.
|
|
127
|
+
.DESCRIPTION
|
|
128
|
+
Sets $script:OrchestrationGateWorktreeListFailed when the wrapper throws (and then
|
|
129
|
+
rethrows) or when its text holds no worktree entry, so the gate denies instead of
|
|
130
|
+
accepting the resolver's session-root fallback (issue #1010, spec E1).
|
|
131
|
+
.OUTPUTS
|
|
132
|
+
System.String
|
|
133
|
+
#>
|
|
134
|
+
[CmdletBinding()]
|
|
135
|
+
[OutputType([string])]
|
|
136
|
+
param([Parameter(Mandatory)][string] $SessionRoot)
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
$text = [string](Get-OrchestrationGateWorktreeList -SessionRoot $SessionRoot)
|
|
140
|
+
} catch {
|
|
141
|
+
$script:OrchestrationGateWorktreeListFailed = $true
|
|
142
|
+
throw
|
|
143
|
+
}
|
|
144
|
+
if (@(ConvertFrom-HookTargetWorktreePorcelain -Text $text).Count -eq 0) {
|
|
145
|
+
$script:OrchestrationGateWorktreeListFailed = $true
|
|
146
|
+
}
|
|
147
|
+
return $text
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function Get-OrchestrationGateCommandOperandPath {
|
|
151
|
+
<#
|
|
152
|
+
.SYNOPSIS
|
|
153
|
+
Returns the worktree-selecting paths of every git add and git commit invocation.
|
|
154
|
+
.DESCRIPTION
|
|
155
|
+
Scans every Structural match of git add and git commit (every command segment and
|
|
156
|
+
wrapper payload). Each -C value in any git global-option position and each absolute
|
|
157
|
+
operand is returned, distinct and in first-seen order. Relative operands, a -C on a
|
|
158
|
+
git segment invoking neither add nor commit, and Indeterminate matches are ignored.
|
|
159
|
+
For a match whose record is not argument-injected, a subcommand-aware walk (issue
|
|
160
|
+
#1010, F2) also reads the tokens after the subcommand with a per-subcommand option
|
|
161
|
+
model, compared case-sensitively: a value option consumes the next token unless its
|
|
162
|
+
value is inline (--name=value) or attached (-mvalue); a standalone flag consumes
|
|
163
|
+
itself; '--' makes every later token an operand; a redirection and its target are
|
|
164
|
+
skipped; any other dash token, such as the cluster -am, stops the walk. Its literal
|
|
165
|
+
absolute tokens are returned, and a token the walk reads as an option value is not
|
|
166
|
+
returned as an operand.
|
|
167
|
+
.PARAMETER Command
|
|
168
|
+
The full command line.
|
|
169
|
+
.OUTPUTS
|
|
170
|
+
System.String[]
|
|
171
|
+
#>
|
|
172
|
+
[CmdletBinding()]
|
|
173
|
+
[OutputType([string[]])]
|
|
174
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Command)
|
|
175
|
+
|
|
176
|
+
$valueOptions = @{
|
|
177
|
+
commit = @('-m', '--message', '-F', '--file', '--author', '--date', '-C', '--reuse-message', '-c', '--reedit-message', '-t', '--template', '--fixup', '--squash', '--trailer', '--pathspec-from-file')
|
|
178
|
+
add = @('--pathspec-from-file', '--chmod')
|
|
179
|
+
}
|
|
180
|
+
$flagOptions = @{
|
|
181
|
+
commit = @('-a', '--all', '--amend', '--no-edit', '--no-verify', '-n', '-s', '--signoff', '-q', '--quiet', '-v', '--verbose', '--allow-empty', '-o', '--only', '-i', '--include', '--pathspec-file-nul')
|
|
182
|
+
add = @('-A', '--all', '-u', '--update', '-f', '--force', '-N', '--intent-to-add', '-n', '--dry-run', '-v', '--verbose', '--pathspec-file-nul')
|
|
183
|
+
}
|
|
184
|
+
$absolutePattern = '^([A-Za-z]:[\\/]|/)'
|
|
185
|
+
$paths = [System.Collections.Generic.List[string]]::new()
|
|
186
|
+
foreach ($subcommand in @('add', 'commit')) {
|
|
187
|
+
foreach ($match in @(Get-CommandLineInvocation -CommandText $Command -CommandWord 'git' -SubcommandPath @($subcommand))) {
|
|
188
|
+
if ($match.Status -ne 'Structural') { continue }
|
|
189
|
+
$walked = [System.Collections.Generic.List[string]]::new()
|
|
190
|
+
$optionValues = [System.Collections.Generic.List[string]]::new()
|
|
191
|
+
$tokens = if ($match.Segment.ArgumentInjected) { [string[]]@() } else { [string[]]@($match.Segment.Tokens) }
|
|
192
|
+
$afterSeparator = $false
|
|
193
|
+
for ($index = [int]$match.OperandIndex; $index -lt $tokens.Count; $index++) {
|
|
194
|
+
$token = $tokens[$index]
|
|
195
|
+
if (-not $afterSeparator -and $token -match '^(<|>|\d*>|&>)') {
|
|
196
|
+
if ($token -match '^(\d*[<>]{1,2}&?|&>{1,2})$') { $index++ }
|
|
197
|
+
continue
|
|
198
|
+
}
|
|
199
|
+
if ($afterSeparator -or -not $token.StartsWith('-')) { $walked.Add($token); continue }
|
|
200
|
+
if ($token -ceq '--') { $afterSeparator = $true; continue }
|
|
201
|
+
$name = if ($token.IndexOf('=') -gt 0) { $token.Substring(0, $token.IndexOf('=')) } else { $token }
|
|
202
|
+
if ($valueOptions[$subcommand] -ccontains $name) {
|
|
203
|
+
if ($name -ceq $token -and $index + 1 -lt $tokens.Count) { $index++; $optionValues.Add($tokens[$index]) }
|
|
204
|
+
continue
|
|
205
|
+
}
|
|
206
|
+
if ($token -match '^-[^-].' -and $valueOptions[$subcommand] -ccontains $token.Substring(0, 2)) { continue }
|
|
207
|
+
if ($flagOptions[$subcommand] -ccontains $token) { continue }
|
|
208
|
+
break
|
|
209
|
+
}
|
|
210
|
+
$candidates = @(@($match.GlobalOptions) | Where-Object { $_.Name -ceq '-C' -and $_.Value } | ForEach-Object { [string]$_.Value })
|
|
211
|
+
$candidates += @(@($match.Operands) | Where-Object { $_ -match $absolutePattern -and $optionValues -cnotcontains $_ })
|
|
212
|
+
$candidates += @($walked | Where-Object { $_ -match $absolutePattern -and (Test-CommandLineTokenLiteral -Token $_) })
|
|
213
|
+
foreach ($candidate in $candidates) {
|
|
214
|
+
if ($paths -notcontains $candidate) { $paths.Add($candidate) }
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return [string[]]$paths.ToArray()
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function Resolve-OrchestrationGateTarget {
|
|
222
|
+
<#
|
|
223
|
+
.SYNOPSIS
|
|
224
|
+
Resolves the worktree whose checkpoint governs a single-feature path or command leg (issue #1010).
|
|
225
|
+
.DESCRIPTION
|
|
226
|
+
Calls Resolve-HookTargetWorktree with the recording invoker: a file path is passed as
|
|
227
|
+
-FilePath, the marker paths of an apply_patch body as -FilePath (markers in two
|
|
228
|
+
worktrees resolve as ambiguous), and any other command's
|
|
229
|
+
Get-OrchestrationGateCommandOperandPath result as -CommandOperandPath. A failed or
|
|
230
|
+
empty listing gives NoTarget instead of the session-root fallback; Ambiguous gives
|
|
231
|
+
Ambiguous; a null root gives NoTarget; otherwise SessionRoot or OtherWorktree.
|
|
232
|
+
.OUTPUTS
|
|
233
|
+
System.Management.Automation.PSCustomObject with Status, WorktreeRoot, ReasonCode, and Detail.
|
|
234
|
+
#>
|
|
235
|
+
[CmdletBinding()]
|
|
236
|
+
[OutputType([pscustomobject])]
|
|
237
|
+
param(
|
|
238
|
+
[AllowNull()][AllowEmptyString()][string] $FilePath = '',
|
|
239
|
+
[AllowNull()][AllowEmptyString()][string] $Command = ''
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
$sessionRoot = (Get-Location).Path
|
|
243
|
+
$script:OrchestrationGateWorktreeListFailed = $false
|
|
244
|
+
$invoker = { param($SessionRoot) Invoke-OrchestrationGateWorktreeList -SessionRoot $SessionRoot }
|
|
245
|
+
$markerPaths = if ($FilePath) { @() } else { @(Get-OrchestrationPatchMarkerPath -PatchText ([string]$Command)) }
|
|
246
|
+
$resolved = if ($FilePath) {
|
|
247
|
+
Resolve-HookTargetWorktree -SessionRoot $sessionRoot -FilePath @($FilePath) -WorktreeListInvoker $invoker
|
|
248
|
+
} elseif ($markerPaths.Count -gt 0) {
|
|
249
|
+
Resolve-HookTargetWorktree -SessionRoot $sessionRoot -FilePath $markerPaths -WorktreeListInvoker $invoker
|
|
250
|
+
} else {
|
|
251
|
+
Resolve-HookTargetWorktree -SessionRoot $sessionRoot -CommandOperandPath @(Get-OrchestrationGateCommandOperandPath -Command ([string]$Command)) -WorktreeListInvoker $invoker
|
|
252
|
+
}
|
|
253
|
+
$detail = "resolver source $($resolved.Source): $($resolved.Detail)"
|
|
254
|
+
if ($script:OrchestrationGateWorktreeListFailed) {
|
|
255
|
+
return [pscustomobject]@{ Status = 'NoTarget'; WorktreeRoot = $null; ReasonCode = $script:OrchestrationGateNotDerivableReasonCode; Detail = "the worktree listing failed or named no worktree; $detail" }
|
|
256
|
+
}
|
|
257
|
+
if ($resolved.Ambiguous) {
|
|
258
|
+
return [pscustomobject]@{ Status = 'Ambiguous'; WorktreeRoot = $null; ReasonCode = $script:OrchestrationGateAmbiguousReasonCode; Detail = $detail }
|
|
259
|
+
}
|
|
260
|
+
if ([string]::IsNullOrEmpty([string]$resolved.WorktreeRoot)) {
|
|
261
|
+
return [pscustomobject]@{ Status = 'NoTarget'; WorktreeRoot = $null; ReasonCode = $script:OrchestrationGateNotDerivableReasonCode; Detail = $detail }
|
|
262
|
+
}
|
|
263
|
+
$isSession = [string]::Equals([string]$resolved.WorktreeRoot, (ConvertTo-HookTargetWorktreeNormalizedPath -Path $sessionRoot), [System.StringComparison]::OrdinalIgnoreCase)
|
|
264
|
+
$status = if ($isSession) { 'SessionRoot' } else { 'OtherWorktree' }
|
|
265
|
+
return [pscustomobject]@{ Status = $status; WorktreeRoot = [string]$resolved.WorktreeRoot; ReasonCode = $null; Detail = $detail }
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function Read-OrchestrationGateCheckpoint {
|
|
269
|
+
<#
|
|
270
|
+
.SYNOPSIS
|
|
271
|
+
Reads the checkpoint beneath the resolved target worktree, or returns the deny reason.
|
|
272
|
+
.DESCRIPTION
|
|
273
|
+
Resolved is $false, with DenyReason set, when the target is NoTarget or Ambiguous.
|
|
274
|
+
Otherwise Raw holds the checkpoint text (empty when absent) and Path its absolute
|
|
275
|
+
path, composed beneath the resolved root with a forward slash.
|
|
276
|
+
.OUTPUTS
|
|
277
|
+
System.Management.Automation.PSCustomObject
|
|
278
|
+
#>
|
|
279
|
+
[CmdletBinding()]
|
|
280
|
+
[OutputType([pscustomobject])]
|
|
281
|
+
param(
|
|
282
|
+
[Parameter(Mandatory)][string] $Mode,
|
|
283
|
+
[AllowNull()][AllowEmptyString()][string] $FilePath = '',
|
|
284
|
+
[AllowNull()][AllowEmptyString()][string] $Command = ''
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
$target = Resolve-OrchestrationGateTarget -FilePath $FilePath -Command $Command
|
|
288
|
+
if ($target.Status -eq 'NoTarget' -or $target.Status -eq 'Ambiguous') {
|
|
289
|
+
return [pscustomobject]@{
|
|
290
|
+
Resolved = $false
|
|
291
|
+
Raw = ''
|
|
292
|
+
Path = $null
|
|
293
|
+
DenyReason = ("PREIMPLEMENTATION_GATE_BLOCKED: $($target.ReasonCode): the target worktree of this $Mode call " +
|
|
294
|
+
"could not be resolved: $($target.Detail). Implementation operations require an identifiable target " +
|
|
295
|
+
'worktree whose checkpoint is ready.')
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
$path = ([string]$target.WorktreeRoot).TrimEnd('/') + '/artifacts/orchestration/orchestrator-state.json'
|
|
300
|
+
return [pscustomobject]@{
|
|
301
|
+
Resolved = $true
|
|
302
|
+
Raw = [string](Get-CheckpointContent -Path $path)
|
|
303
|
+
Path = $path
|
|
304
|
+
DenyReason = $null
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
71
308
|
function Get-OrchestrationEpicScopeSelector {
|
|
72
309
|
<#
|
|
73
310
|
.SYNOPSIS
|
|
@@ -33,8 +33,6 @@ try { . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-e
|
|
|
33
33
|
# Shared command-line parser (issue #545): per-segment scan text and structural matching.
|
|
34
34
|
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
35
35
|
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
36
|
-
# The readiness checkpoint this gate reads and names in its block message.
|
|
37
|
-
$script:CheckpointPath = 'artifacts/orchestration/orchestrator-state.json'
|
|
38
36
|
|
|
39
37
|
# Every orchestration checkpoint a planner or orchestrator surface writes. Writing one
|
|
40
38
|
# of these is orchestration bookkeeping, not implementation, so the gate must not
|
|
@@ -270,7 +268,7 @@ function Test-OrchestrationReady {
|
|
|
270
268
|
}
|
|
271
269
|
$lifecycleReady = $false
|
|
272
270
|
if ($Payload.PSObject.Properties.Name -contains 'lifecycle_ready') {
|
|
273
|
-
$lifecycleReady = [bool]$Payload.lifecycle_ready
|
|
271
|
+
$lifecycleReady = ($Payload.lifecycle_ready -is [bool]) -and $Payload.lifecycle_ready
|
|
274
272
|
}
|
|
275
273
|
|
|
276
274
|
if (-not $issueNum -or -not $featureFolder -or -not $routeId -or -not $lifecycleReady) {
|
|
@@ -284,17 +282,6 @@ function Test-OrchestrationReady {
|
|
|
284
282
|
)
|
|
285
283
|
}
|
|
286
284
|
|
|
287
|
-
function Get-CheckpointContent {
|
|
288
|
-
[CmdletBinding()]
|
|
289
|
-
[OutputType([string])]
|
|
290
|
-
param()
|
|
291
|
-
|
|
292
|
-
if (-not (Test-Path -LiteralPath $script:CheckpointPath)) {
|
|
293
|
-
return ''
|
|
294
|
-
}
|
|
295
|
-
return Get-Content -Raw -LiteralPath $script:CheckpointPath
|
|
296
|
-
}
|
|
297
|
-
|
|
298
285
|
function Get-OrchestrationPreimplementationGateAllowDecision {
|
|
299
286
|
[CmdletBinding()]
|
|
300
287
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
@@ -445,8 +432,12 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
445
432
|
Get-OrchestrationModeDenyReason -Mode $mode -Failure $failure)
|
|
446
433
|
}
|
|
447
434
|
|
|
435
|
+
# Truthiness fall-through is kept: an empty -CheckpointRaw resolves like an unbound one.
|
|
436
|
+
# The checkpoint is read beneath the worktree the call targets (issue #1010).
|
|
448
437
|
if (-not $CheckpointRaw) {
|
|
449
|
-
$
|
|
438
|
+
$read = Read-OrchestrationGateCheckpoint -Mode 'single-feature' -FilePath $filePath -Command $command
|
|
439
|
+
if (-not $read.Resolved) { return Get-OrchestrationPreimplementationGateBlockDecision -Reason $read.DenyReason }
|
|
440
|
+
$CheckpointRaw = $read.Raw
|
|
450
441
|
}
|
|
451
442
|
try {
|
|
452
443
|
$checkpoint = ConvertFrom-CheckpointJson -Json $CheckpointRaw
|