@danmoisan/drm-copilot-mcp 1.1.18 → 1.1.19
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 +989 -662
- package/package.json +3 -2
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +11 -0
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -0
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +12 -4
- package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
- package/resources/claude-customizations/.claude/agents/feature-review.md +6 -4
- package/resources/claude-customizations/.claude/agents/orchestrator.md +5 -4
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +31 -13
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +9 -6
- package/resources/claude-customizations/.claude/agents/pr-author.md +15 -2
- package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -1
- package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
- package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
- package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +55 -23
- package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
- package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
- package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
- package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
- package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
- package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
- package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
- package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
- package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
- package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
- package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
- package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
- package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +493 -0
- package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
- package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
- package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +66 -38
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
- package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +64 -32
- package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
- package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
- package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
- package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +31 -34
- package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
- package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
- package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +24 -3
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
- package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
- package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
- package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +37 -4
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +47 -8
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
- package/resources/claude-customizations/.claude/rules/shell.md +10 -8
- package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
- package/resources/claude-customizations/.claude/settings.json +3 -4
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +5 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +2 -0
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +2 -0
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +33 -6
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +4 -3
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +14 -6
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
- package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +79 -16
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
- package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +2 -2
- package/resources/claude-customizations/pack-manifests/core.json +23 -0
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +11 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +10 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
- package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +13 -5
- package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +15 -6
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
- package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +10 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +2 -1
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +37 -5
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +493 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +9 -0
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +2 -2
- package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
- package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +1 -1
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
- package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +25 -28
- package/resources/powershell/PoshQC/PoshQC.psm1 +1 -0
- package/resources/powershell/PoshQC/README.md +8 -2
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -319
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
#>
|
|
9
9
|
[CmdletBinding()]
|
|
10
10
|
param()
|
|
11
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
11
12
|
|
|
12
|
-
. (Join-Path $PSScriptRoot 'codex-authority-store.ps1')
|
|
13
|
+
try { . (Join-Path $PSScriptRoot 'codex-authority-store.ps1') } catch { Add-HookDependencyFailure -Name 'codex-authority-store.ps1' -ErrorRecord $_ }
|
|
13
14
|
|
|
14
15
|
function ConvertFrom-EpicRootGatePayload {
|
|
15
16
|
[CmdletBinding()]
|
|
@@ -54,6 +55,8 @@ function Invoke-EpicRootInvocationDecision {
|
|
|
54
55
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
55
56
|
[AllowNull()][AllowEmptyString()][string] $AttestationRaw
|
|
56
57
|
)
|
|
58
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_INVOCATION_ORIGIN_BLOCKED:'
|
|
59
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
57
60
|
|
|
58
61
|
$payload = ConvertFrom-EpicRootGatePayload -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
59
62
|
if ([string]::IsNullOrWhiteSpace($AttestationRaw)) {
|
|
@@ -87,6 +90,9 @@ function Invoke-EpicRootInvocationDecision {
|
|
|
87
90
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
88
91
|
return
|
|
89
92
|
}
|
|
93
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_INVOCATION_ORIGIN_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
94
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_INVOCATION_ORIGIN_BLOCKED:'
|
|
95
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
90
96
|
|
|
91
97
|
try {
|
|
92
98
|
$payloadRaw = [Console]::In.ReadToEnd()
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
#>
|
|
11
11
|
[CmdletBinding()]
|
|
12
12
|
param()
|
|
13
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
13
14
|
|
|
14
|
-
. (Join-Path $PSScriptRoot 'codex-epic-child-launch-attestation.ps1')
|
|
15
|
+
try { . (Join-Path $PSScriptRoot 'codex-epic-child-launch-attestation.ps1') } catch { Add-HookDependencyFailure -Name 'codex-epic-child-launch-attestation.ps1' -ErrorRecord $_ }
|
|
15
16
|
|
|
16
17
|
$script:AllowedDependencyStatuses = @('merged', 'worktree_removed')
|
|
17
18
|
|
|
@@ -178,6 +179,8 @@ function Invoke-CodexEpicWaveDecision {
|
|
|
178
179
|
[AllowEmptyString()][string] $RepositoryRoot = '',
|
|
179
180
|
[datetimeoffset] $Now = [datetimeoffset]::UtcNow
|
|
180
181
|
)
|
|
182
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WAVE_BARRIER_BLOCKED:'
|
|
183
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
181
184
|
|
|
182
185
|
$payload = ConvertFrom-CodexWaveJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
183
186
|
if (-not (Test-CodexWaveMutation -Payload $payload)) {
|
|
@@ -252,6 +255,9 @@ function Get-CodexPrimaryWorktreeRoot {
|
|
|
252
255
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
253
256
|
return
|
|
254
257
|
}
|
|
258
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_WAVE_BARRIER_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
259
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WAVE_BARRIER_BLOCKED:'
|
|
260
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
255
261
|
|
|
256
262
|
try {
|
|
257
263
|
$payloadRaw = [Console]::In.ReadToEnd()
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
#>
|
|
5
5
|
[CmdletBinding()]
|
|
6
6
|
param()
|
|
7
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
7
8
|
|
|
8
9
|
# Shared command-line parser (issue #545). The scope filter and the operand extractor below
|
|
9
10
|
# both run against the segment that structurally invokes `git worktree remove`, which is what
|
|
10
11
|
# keeps the two runtimes on one implementation of the same concern.
|
|
11
|
-
. (Join-Path $PSScriptRoot 'hook-command-scanner.ps1')
|
|
12
|
-
. (Join-Path $PSScriptRoot 'hook-command-invocation.ps1')
|
|
12
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
13
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
13
14
|
|
|
14
15
|
$script:SafeWorktreeStatuses = @('merged', 'worktree_removed')
|
|
15
16
|
|
|
@@ -33,40 +34,6 @@ function ConvertFrom-CodexWorktreeJson {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
function Get-CodexWorktreeRemovalPath {
|
|
37
|
-
<#
|
|
38
|
-
.SYNOPSIS
|
|
39
|
-
Extract the target worktree path from a git worktree remove command.
|
|
40
|
-
.DESCRIPTION
|
|
41
|
-
The operand comes from the segment that structurally invokes git worktree remove, so
|
|
42
|
-
a chained 'cd <path> &&' segment contributes nothing and a quoted mention of the
|
|
43
|
-
phrase resolves to no operand. The tokenizer strips balanced double and single
|
|
44
|
-
quotes, which is what the previous pattern's `double` and `single` alternatives did.
|
|
45
|
-
|
|
46
|
-
The previous pattern accepted '--force' only immediately after 'remove'. That
|
|
47
|
-
spelling is preserved and the trailing spelling now works too, because '--force' is a
|
|
48
|
-
zero-argument flag that never contributes an operand wherever it is written. Its
|
|
49
|
-
presence is read structurally through Test-CommandLineFlag rather than by a raw-text
|
|
50
|
-
search. The empty-string-on-miss contract is unchanged: callers test `if ($target)`.
|
|
51
|
-
.OUTPUTS
|
|
52
|
-
System.String
|
|
53
|
-
#>
|
|
54
|
-
[CmdletBinding()]
|
|
55
|
-
[OutputType([string])]
|
|
56
|
-
param([Parameter(Mandatory)][AllowEmptyString()][string] $Command)
|
|
57
|
-
|
|
58
|
-
$hasForce = Test-CommandLineFlag -CommandText $Command -CommandWord 'git' -SubcommandPath @('worktree', 'remove') -FlagName '--force'
|
|
59
|
-
$operands = @(Get-CommandLineOperand -CommandText $Command -CommandWord 'git' -SubcommandPath @('worktree', 'remove'))
|
|
60
|
-
|
|
61
|
-
if ($operands.Count -gt 0) {
|
|
62
|
-
return [string]$operands[0]
|
|
63
|
-
}
|
|
64
|
-
if ($hasForce) {
|
|
65
|
-
return '--force'
|
|
66
|
-
}
|
|
67
|
-
return ''
|
|
68
|
-
}
|
|
69
|
-
|
|
70
37
|
function Get-NormalizedCodexWorktreePath {
|
|
71
38
|
[CmdletBinding()]
|
|
72
39
|
[OutputType([string])]
|
|
@@ -114,6 +81,8 @@ function Invoke-CodexWorktreeRemovalDecision {
|
|
|
114
81
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
115
82
|
[AllowNull()][AllowEmptyString()][string] $EpicCheckpointRaw
|
|
116
83
|
)
|
|
84
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_REMOVAL_BLOCKED:'
|
|
85
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
117
86
|
|
|
118
87
|
$payload = ConvertFrom-CodexWorktreeJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
119
88
|
if ([string]$payload.tool_name -ne 'Bash') {
|
|
@@ -126,18 +95,59 @@ function Invoke-CodexWorktreeRemovalDecision {
|
|
|
126
95
|
if (-not (Test-CommandLineInvocation -CommandText $command -CommandWord 'git' -SubcommandPath @('worktree', 'remove'))) {
|
|
127
96
|
return $null
|
|
128
97
|
}
|
|
129
|
-
|
|
98
|
+
# Issue #824: the removal targets are derived structurally from every invocation. A
|
|
99
|
+
# target that cannot be derived denies before the checkpoint is read, and every derived
|
|
100
|
+
# target must be authorized on its own.
|
|
101
|
+
$resolution = Resolve-CommandLineInvocationTarget -CommandText $command -CommandWord 'git' -SubcommandPath @('worktree', 'remove')
|
|
102
|
+
if ($resolution.Status -eq 'NoMatch') {
|
|
103
|
+
return $null
|
|
104
|
+
}
|
|
105
|
+
if ($resolution.Status -ne 'Targets') {
|
|
106
|
+
return [ordered]@{
|
|
107
|
+
hookSpecificOutput = [ordered]@{
|
|
108
|
+
hookEventName = 'PreToolUse'
|
|
109
|
+
permissionDecision = 'deny'
|
|
110
|
+
permissionDecisionReason = 'EPIC_WORKTREE_REMOVAL_BLOCKED: TARGET_WORKTREE_NOT_DERIVABLE: the git worktree remove target cannot be derived from the command text. No checkpoint can authorize this removal.'
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
130
114
|
$checkpoint = ConvertFrom-CodexWorktreeJson -Raw $EpicCheckpointRaw -Name 'epic checkpoint' -Optional
|
|
131
115
|
$workingDirectory = if ([string]::IsNullOrWhiteSpace([string]$payload.cwd)) {
|
|
132
116
|
(Get-Location).Path
|
|
133
117
|
} else {
|
|
134
118
|
[string]$payload.cwd
|
|
135
119
|
}
|
|
136
|
-
$
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
120
|
+
foreach ($target in @($resolution.Targets)) {
|
|
121
|
+
$denial = Get-CodexWorktreeRemovalTargetDenial -Target $target -Checkpoint $checkpoint -WorkingDirectory $workingDirectory
|
|
122
|
+
if ($null -ne $denial) {
|
|
123
|
+
return $denial
|
|
124
|
+
}
|
|
140
125
|
}
|
|
126
|
+
return $null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function Get-CodexWorktreeRemovalTargetDenial {
|
|
130
|
+
<#
|
|
131
|
+
.SYNOPSIS
|
|
132
|
+
Evaluate one derived removal target and return its deny decision, or $null when authorized.
|
|
133
|
+
.PARAMETER Target
|
|
134
|
+
One removal target derived by Resolve-CommandLineInvocationTarget.
|
|
135
|
+
.PARAMETER Checkpoint
|
|
136
|
+
The parsed epic checkpoint, or $null when absent or unreadable.
|
|
137
|
+
.PARAMETER WorkingDirectory
|
|
138
|
+
The directory a relative target resolves against.
|
|
139
|
+
.OUTPUTS
|
|
140
|
+
System.Collections.Specialized.OrderedDictionary or $null
|
|
141
|
+
#>
|
|
142
|
+
[CmdletBinding()]
|
|
143
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
144
|
+
param(
|
|
145
|
+
[Parameter(Mandatory)][string] $Target,
|
|
146
|
+
[AllowNull()] $Checkpoint,
|
|
147
|
+
[Parameter(Mandatory)][string] $WorkingDirectory
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
$feature = Find-CodexWorktreeFeature -Checkpoint $Checkpoint -TargetPath $Target -WorkingDirectory $WorkingDirectory
|
|
141
151
|
if ($null -ne $feature -and
|
|
142
152
|
@($feature.PSObject.Properties.Name) -contains 'merge_status' -and
|
|
143
153
|
$script:SafeWorktreeStatuses -contains [string]$feature.merge_status) {
|
|
@@ -156,6 +166,9 @@ function Invoke-CodexWorktreeRemovalDecision {
|
|
|
156
166
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
157
167
|
return
|
|
158
168
|
}
|
|
169
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_WORKTREE_REMOVAL_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
170
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_REMOVAL_BLOCKED:'
|
|
171
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
159
172
|
|
|
160
173
|
try {
|
|
161
174
|
$payloadRaw = [Console]::In.ReadToEnd()
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1
CHANGED
|
@@ -40,10 +40,11 @@
|
|
|
40
40
|
#>
|
|
41
41
|
[CmdletBinding()]
|
|
42
42
|
param()
|
|
43
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
43
44
|
|
|
44
45
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
45
46
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
46
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
47
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
47
48
|
|
|
48
49
|
function Test-EvidenceLocationForbidden {
|
|
49
50
|
<#
|
|
@@ -122,6 +123,8 @@ function Invoke-EvidenceLocationDecision {
|
|
|
122
123
|
param(
|
|
123
124
|
[string] $ToolInputRaw
|
|
124
125
|
)
|
|
126
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EVIDENCE_LOCATION_BLOCKED:'
|
|
127
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
125
128
|
|
|
126
129
|
if (-not $ToolInputRaw) {
|
|
127
130
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
@@ -192,5 +195,8 @@ function Invoke-EvidenceLocationEntryPoint {
|
|
|
192
195
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
193
196
|
return
|
|
194
197
|
}
|
|
198
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EVIDENCE_LOCATION_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
199
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EVIDENCE_LOCATION_BLOCKED:'
|
|
200
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
195
201
|
|
|
196
202
|
exit (Invoke-EvidenceLocationEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()))
|
|
@@ -26,12 +26,16 @@
|
|
|
26
26
|
Get-OrchestrationDelegationCheckpointPath (modes file), and the gate's allow and block
|
|
27
27
|
decision constructors Get-OrchestrationPreimplementationGateAllowDecision and
|
|
28
28
|
Get-OrchestrationPreimplementationGateBlockDecision. The resolver and its seams come
|
|
29
|
-
from the resolution sibling dot-sourced below.
|
|
29
|
+
from the resolution sibling dot-sourced below. The per-segment target resolver comes
|
|
30
|
+
from the targets file dot-sourced below (issue #738), which calls
|
|
31
|
+
Read-CommandLineSegment, Get-CommandLineGlobalOption, and Get-CommandLineInvocation,
|
|
32
|
+
loaded by the gate's dot-source of hook-command-invocation.ps1.
|
|
30
33
|
Mirrored byte-identically under extensions/drm-copilot/resources/codex-and-agents-customizations/.
|
|
31
34
|
AUTHORITY: PowerShell-authoritative. The epic readiness predicate has no reference implementation in another language, and this hook starts no interpreter process (issue #707, D15).
|
|
32
35
|
#>
|
|
33
36
|
|
|
34
37
|
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-epic-resolution.ps1')
|
|
38
|
+
. (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-targets.ps1')
|
|
35
39
|
|
|
36
40
|
# An epic manifest lives under the epics tree; the pattern is tested after backslash
|
|
37
41
|
# normalisation so either separator spelling is accepted.
|
|
@@ -152,11 +156,14 @@ function Get-OrchestrationEpicScopeDecision {
|
|
|
152
156
|
.SYNOPSIS
|
|
153
157
|
Returns the epic-scope decision for an implementation-classified command or path, or $null.
|
|
154
158
|
.DESCRIPTION
|
|
155
|
-
Resolves
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
Resolves the target of every command segment, apply_patch file marker, and path
|
|
160
|
+
(issue #738), then the epic scope of the session root and of each target. A command
|
|
161
|
+
whose text is an apply_patch body is decided as a path leg over its marker paths.
|
|
162
|
+
When neither is epic scope, returns $null so the caller's single-feature path runs
|
|
163
|
+
unchanged. In epic scope, denies an unresolvable, ambiguous, or out-of-scope target,
|
|
164
|
+
and otherwise evaluates the epic command-leg readiness predicate against every
|
|
165
|
+
target: the first failure denies (the session-root wording is unchanged), and no
|
|
166
|
+
failure allows.
|
|
160
167
|
.PARAMETER Command
|
|
161
168
|
The command line of a command or apply_patch leg; empty for a path leg.
|
|
162
169
|
.PARAMETER FilePath
|
|
@@ -175,15 +182,29 @@ function Get-OrchestrationEpicScopeDecision {
|
|
|
175
182
|
if (-not $Command -and -not $FilePath) {
|
|
176
183
|
return $null
|
|
177
184
|
}
|
|
178
|
-
$
|
|
179
|
-
$
|
|
180
|
-
|
|
185
|
+
$epicScopeSessionRoot = (Get-Location).Path
|
|
186
|
+
$legCommand = [string]$Command
|
|
187
|
+
$legPaths = @($FilePath)
|
|
188
|
+
$markerPaths = @(Get-OrchestrationPatchMarkerPath -PatchText $legCommand)
|
|
189
|
+
if ($markerPaths.Count -gt 0) {
|
|
190
|
+
$legCommand = ''
|
|
191
|
+
$legPaths = $markerPaths
|
|
192
|
+
}
|
|
193
|
+
$targetResult = Get-OrchestrationCommandTarget -Command $legCommand -FilePath $legPaths -SessionRoot $epicScopeSessionRoot
|
|
194
|
+
$scopeResolver = {
|
|
195
|
+
param([string] $Selector)
|
|
196
|
+
Resolve-EpicScopeCheckpoint -SessionRoot $epicScopeSessionRoot -WorktreeSelector $Selector
|
|
197
|
+
}
|
|
198
|
+
$verdict = Resolve-OrchestrationEpicTargetVerdict -SessionRoot $epicScopeSessionRoot -TargetResult $targetResult -ScopeResolver $scopeResolver
|
|
199
|
+
$outcome = Resolve-OrchestrationEpicTargetOutcome -Verdict $verdict -ReadinessFailure {
|
|
200
|
+
param($Scope)
|
|
201
|
+
Get-EpicCommandLegReadinessFailure -Checkpoint $Scope.Checkpoint -MergeInProgress $Scope.MergeInProgress
|
|
202
|
+
}
|
|
203
|
+
if ($outcome.Outcome -eq 'none') {
|
|
181
204
|
return $null
|
|
182
205
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (-not $failure) {
|
|
186
|
-
return Get-OrchestrationPreimplementationGateAllowDecision
|
|
206
|
+
if ($outcome.Outcome -eq 'deny') {
|
|
207
|
+
return Get-OrchestrationPreimplementationGateBlockDecision -Reason $outcome.Reason
|
|
187
208
|
}
|
|
188
|
-
return Get-
|
|
209
|
+
return Get-OrchestrationPreimplementationGateAllowDecision
|
|
189
210
|
}
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
tree? Every parse ambiguity answers false, so the caller's pre-change deny is the
|
|
10
10
|
fallback for every unmodeled form.
|
|
11
11
|
|
|
12
|
+
Shell-agnostic parsing (issue #735): the shell that executes a hooked command is
|
|
13
|
+
undetermined per command, so every shape whose meaning differs between a POSIX shell
|
|
14
|
+
and PowerShell denies - a backslash anywhere, and { } , ( ) @ outside quotes. Evidence:
|
|
15
|
+
research/research.2026-10-08T14-00.md (Q1) in the issue #732 feature folder.
|
|
16
|
+
|
|
12
17
|
The normative contract is the D4 fail-closed rule table in
|
|
13
18
|
docs/features/active/2026-08-24-preimplementation-gate-blocks-planner-integration-commits-539/spec.md.
|
|
14
19
|
Rule-table row numbers are cited inline against the code that realizes them.
|
|
@@ -28,15 +33,15 @@ $script:OrchestrationBookkeepingTrees = @(
|
|
|
28
33
|
)
|
|
29
34
|
|
|
30
35
|
# Characters that make a command line statically unresolvable (D4 row 12, as narrowed by
|
|
31
|
-
# issues #663 and #
|
|
32
|
-
# characters (`<`, `>`,
|
|
33
|
-
# quotes (U+2018 to U+201E) anywhere
|
|
36
|
+
# issues #663, #713, #732, and #735): interpolation characters outside single quotes;
|
|
37
|
+
# outside-quote characters (`<`, `>`, the `#` comment introducer, and the shell-divergent
|
|
38
|
+
# `{ } , ( ) @`) outside any quote; and typographic quotes (U+2018 to U+201E) anywhere.
|
|
34
39
|
$script:InterpolationCommandCharacters = [char[]]@('$', '`')
|
|
35
|
-
$script:OutsideQuoteCommandCharacters = [char[]]@('>', '<', '#')
|
|
40
|
+
$script:OutsideQuoteCommandCharacters = [char[]]@('>', '<', '#', '{', '}', ',', '(', ')', '@')
|
|
36
41
|
$script:TypographicQuoteCharacters = [char[]]@(0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E)
|
|
37
42
|
|
|
38
|
-
# Wildcards
|
|
39
|
-
#
|
|
43
|
+
# Wildcards a selector value may not carry (LACS L6). An operand carrying one fails the
|
|
44
|
+
# operand allowlist (issue #732).
|
|
40
45
|
$script:PathspecWildcardCharacters = [char[]]@('*', '?', '[')
|
|
41
46
|
|
|
42
47
|
# The single repository selector modelled between the command name and the subcommand: D4
|
|
@@ -112,12 +117,12 @@ function Test-OrchestrationCommandTextUnresolvable {
|
|
|
112
117
|
.SYNOPSIS
|
|
113
118
|
Reports whether a command line carries a statically unresolvable character.
|
|
114
119
|
.DESCRIPTION
|
|
115
|
-
Realizes D4 row 12 as narrowed by issues #663 and #
|
|
116
|
-
Split-OrchestrationCommandLine. `$` or backtick answers true outside
|
|
117
|
-
double quotes (single quotes keep it literal); `<`, `>`,
|
|
118
|
-
only outside a quoted span. A typographic quote (U+2018 to
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
Realizes D4 row 12 as narrowed by issues #663, #713, #732, and #735, with quote state
|
|
121
|
+
tracked as in Split-OrchestrationCommandLine. `$` or backtick answers true outside
|
|
122
|
+
quotes or inside double quotes (single quotes keep it literal); `<`, `>`, `#`, and
|
|
123
|
+
`{ } , ( ) @` answer true only outside a quoted span. A typographic quote (U+2018 to
|
|
124
|
+
U+201E) or a backslash answers true anywhere, because POSIX shells and PowerShell read
|
|
125
|
+
them differently and the executing shell is undetermined (fail closed).
|
|
121
126
|
.PARAMETER CommandText
|
|
122
127
|
The full command line as the shell would receive it.
|
|
123
128
|
.OUTPUTS
|
|
@@ -127,8 +132,8 @@ function Test-OrchestrationCommandTextUnresolvable {
|
|
|
127
132
|
[OutputType([bool])]
|
|
128
133
|
param([Parameter(Mandatory)][AllowEmptyString()][string] $CommandText)
|
|
129
134
|
|
|
130
|
-
#
|
|
131
|
-
if ($CommandText.Contains('\
|
|
135
|
+
# A backslash or typographic quote is read differently by POSIX shells and PowerShell (#735).
|
|
136
|
+
if ($CommandText.Contains('\') -or $CommandText.IndexOfAny($script:TypographicQuoteCharacters) -ge 0) {
|
|
132
137
|
return $true
|
|
133
138
|
}
|
|
134
139
|
|
|
@@ -141,13 +146,9 @@ function Test-OrchestrationCommandTextUnresolvable {
|
|
|
141
146
|
return $true
|
|
142
147
|
}
|
|
143
148
|
|
|
144
|
-
# Decide by quote state: inside a span only the closing quote matters
|
|
145
|
-
#
|
|
146
|
-
# quote opens one and a redirection character is unresolvable.
|
|
149
|
+
# Decide by quote state: inside a span only the closing quote matters; outside a
|
|
150
|
+
# span a quote opens one and an outside-quote character is unresolvable.
|
|
147
151
|
if ($openQuote -ne [char]0) {
|
|
148
|
-
if ($openQuote -eq '"' -and $character -eq '\') {
|
|
149
|
-
return $true
|
|
150
|
-
}
|
|
151
152
|
if ($character -eq $openQuote) {
|
|
152
153
|
$openQuote = [char]0
|
|
153
154
|
}
|
|
@@ -222,9 +223,10 @@ function Test-ExemptOrchestrationOperand {
|
|
|
222
223
|
.SYNOPSIS
|
|
223
224
|
Tests one pathspec operand against the five exempt orchestration trees.
|
|
224
225
|
.DESCRIPTION
|
|
225
|
-
Realizes D4 rows 3, 9, 15, 16, 17
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
Realizes D4 rows 3, 9, 15, 16, and 17 as narrowed by issues #732 and #735. An operand
|
|
227
|
+
is exempt only when it matches the plain ASCII allowlist A-Z a-z 0-9 . _ / - (which
|
|
228
|
+
excludes pathspec magic, drive letters, backslashes, globs, braces, and non-ASCII
|
|
229
|
+
look-alikes), is not rooted, carries no '..' segment, and starts with an exempt tree.
|
|
228
230
|
.OUTPUTS
|
|
229
231
|
System.Boolean
|
|
230
232
|
#>
|
|
@@ -232,43 +234,14 @@ function Test-ExemptOrchestrationOperand {
|
|
|
232
234
|
[OutputType([bool])]
|
|
233
235
|
param([Parameter(Mandatory)][AllowEmptyString()][string] $Operand)
|
|
234
236
|
|
|
235
|
-
if (-
|
|
236
|
-
return $false
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
# Row 3b and row 9: any leading colon is pathspec magic, which can escape or invert the
|
|
240
|
-
# tree scope, so no colon-led operand is ever resolvable by a prefix test.
|
|
241
|
-
if ($Operand.StartsWith(':')) {
|
|
237
|
+
if ($Operand -cnotmatch '^[A-Za-z0-9._/-]+$' -or $Operand.StartsWith('/')) {
|
|
242
238
|
return $false
|
|
243
239
|
}
|
|
244
|
-
|
|
245
|
-
# Row 18: separator normalization precedes every prefix comparison below.
|
|
246
|
-
$normalized = $Operand -replace '\\', '/'
|
|
247
|
-
|
|
248
|
-
# Row 16: rooted, drive-lettered, and UNC spellings all deny; the exempt prefixes stay
|
|
249
|
-
# repo-relative (this is the posture issue #516 later composes with).
|
|
250
|
-
if ($normalized.StartsWith('/')) {
|
|
240
|
+
if (($Operand -split '/') -contains '..') {
|
|
251
241
|
return $false
|
|
252
242
|
}
|
|
253
|
-
if ($normalized -match '^[A-Za-z]:') {
|
|
254
|
-
return $false
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
# Rows 15c and 17: any parent-directory component escapes the prefix.
|
|
258
|
-
if (($normalized -split '/') -contains '..') {
|
|
259
|
-
return $false
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
# Row 15: only the literal prefix before the first wildcard is prefix-tested, so a glob
|
|
263
|
-
# whose wildcard occupies or truncates an ancestor segment cannot pass.
|
|
264
|
-
$literalPrefix = $normalized
|
|
265
|
-
$wildcardIndex = $normalized.IndexOfAny($script:PathspecWildcardCharacters)
|
|
266
|
-
if ($wildcardIndex -ge 0) {
|
|
267
|
-
$literalPrefix = $normalized.Substring(0, $wildcardIndex)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
243
|
foreach ($tree in $script:OrchestrationBookkeepingTrees) {
|
|
271
|
-
if ($
|
|
244
|
+
if ($Operand.StartsWith($tree)) {
|
|
272
245
|
return $true
|
|
273
246
|
}
|
|
274
247
|
}
|
|
@@ -444,7 +417,7 @@ function Test-ExemptOrchestrationStagingCommand {
|
|
|
444
417
|
command line splits cleanly into segments and EVERY segment parses as a complete,
|
|
445
418
|
recognized staging or integration invocation carrying at least one pathspec operand,
|
|
446
419
|
with every operand resolving inside one of the five exempt orchestration-bookkeeping
|
|
447
|
-
trees after balanced-quote stripping
|
|
420
|
+
trees after balanced-quote stripping.
|
|
448
421
|
|
|
449
422
|
The all-segments reading is deliberate and fail-closed: a chained line denies unless
|
|
450
423
|
each of its segments is independently a recognized all-exempt invocation, so a
|
|
@@ -464,8 +437,8 @@ function Test-ExemptOrchestrationStagingCommand {
|
|
|
464
437
|
return $false
|
|
465
438
|
}
|
|
466
439
|
|
|
467
|
-
# Row 12: `$` or backtick outside single quotes,
|
|
468
|
-
# typographic quote
|
|
440
|
+
# Row 12: `$` or backtick outside single quotes, `< > # { } , ( ) @` outside quotes, and
|
|
441
|
+
# any typographic quote or backslash make the operand list untrustworthy (#732, #735).
|
|
469
442
|
if (Test-OrchestrationCommandTextUnresolvable -CommandText $CommandText) {
|
|
470
443
|
return $false
|
|
471
444
|
}
|