@danmoisan/drm-copilot-mcp 1.1.17 → 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 +1405 -684
- package/package.json +6 -4
- 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 +16 -5
- package/resources/claude-customizations/.claude/agents/orchestrator.md +21 -7
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +37 -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-lane-assertion.sh +4 -2
- 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/OrchestratorState.psm1 +6 -13
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +396 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
- 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 +153 -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 +9 -1
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +7 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
- 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 +171 -5
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +6 -15
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +45 -11
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +7 -4
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +42 -16
- 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 +97 -19
- 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 +7 -3
- package/resources/claude-customizations/pack-manifests/core.json +25 -0
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +9 -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 +13 -3
- 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 +13 -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 +30 -6
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +16 -6
- 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 +43 -11
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +19 -4
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
- package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +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/feature-reviewer-c1.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +3 -3
- 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 +9 -1
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- 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 -315
package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1
CHANGED
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
#>
|
|
33
33
|
[CmdletBinding()]
|
|
34
34
|
param()
|
|
35
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
35
36
|
|
|
36
37
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
37
38
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
38
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
39
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
39
40
|
|
|
40
41
|
function Get-PowerShellTestPurityBlockDecision {
|
|
41
42
|
[CmdletBinding()]
|
|
@@ -72,6 +73,8 @@ function Invoke-PowerShellTestPurityDecision {
|
|
|
72
73
|
param(
|
|
73
74
|
[string] $ToolInputRaw
|
|
74
75
|
)
|
|
76
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-powershell-test-purity:'
|
|
77
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
75
78
|
|
|
76
79
|
if (-not $ToolInputRaw) {
|
|
77
80
|
return $null
|
|
@@ -145,6 +148,9 @@ function Invoke-PowerShellTestPurityDecision {
|
|
|
145
148
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
146
149
|
return
|
|
147
150
|
}
|
|
151
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('check-powershell-test-purity: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
152
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-powershell-test-purity:'
|
|
153
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
148
154
|
|
|
149
155
|
try {
|
|
150
156
|
# Transport and mapping come from the shared module. A well-formed payload
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
#>
|
|
30
30
|
[CmdletBinding()]
|
|
31
31
|
param()
|
|
32
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
32
33
|
|
|
33
34
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
34
35
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
35
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
36
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
36
37
|
|
|
37
38
|
function Get-PythonTestPurityBlockDecision {
|
|
38
39
|
[CmdletBinding()]
|
|
@@ -69,6 +70,8 @@ function Invoke-PythonTestPurityDecision {
|
|
|
69
70
|
param(
|
|
70
71
|
[string] $ToolInputRaw
|
|
71
72
|
)
|
|
73
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-python-test-purity:'
|
|
74
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
72
75
|
|
|
73
76
|
if (-not $ToolInputRaw) {
|
|
74
77
|
return $null
|
|
@@ -145,6 +148,9 @@ function Invoke-PythonTestPurityDecision {
|
|
|
145
148
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
146
149
|
return
|
|
147
150
|
}
|
|
151
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('check-python-test-purity: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
152
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'check-python-test-purity:'
|
|
153
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
148
154
|
|
|
149
155
|
try {
|
|
150
156
|
# Transport and mapping come from the shared module. A well-formed payload
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
$contractPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'scripts/epic-child-launch-contract.ps1'
|
|
4
4
|
if (Test-Path -LiteralPath $contractPath -PathType Leaf) {
|
|
5
|
-
. $contractPath
|
|
5
|
+
try { . $contractPath } catch { Add-HookDependencyFailure -Name 'epic-child-launch-contract.ps1' -ErrorRecord $_ }
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
$script:CodexEpicChildContexts = @('epic_preparation_child', 'epic_execution_child')
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1
CHANGED
|
@@ -43,10 +43,11 @@
|
|
|
43
43
|
#>
|
|
44
44
|
[CmdletBinding()]
|
|
45
45
|
param()
|
|
46
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
46
47
|
|
|
47
48
|
# Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
|
|
48
49
|
# mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
|
|
49
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
50
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
50
51
|
|
|
51
52
|
# The only path this hook governs. On-disk reconstruction of an apply_patch
|
|
52
53
|
# Update is requested for this path alone, so a patch that merely happens to
|
|
@@ -214,6 +215,8 @@ function Invoke-CheckpointMonotonicDecision {
|
|
|
214
215
|
param(
|
|
215
216
|
[string] $ToolInputRaw
|
|
216
217
|
)
|
|
218
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'CHECKPOINT_ORDER_BLOCKED:'
|
|
219
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
217
220
|
|
|
218
221
|
if (-not $ToolInputRaw) {
|
|
219
222
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
@@ -312,6 +315,9 @@ function Invoke-CheckpointMonotonicDecision {
|
|
|
312
315
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
313
316
|
return
|
|
314
317
|
}
|
|
318
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('CHECKPOINT_ORDER_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
319
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'CHECKPOINT_ORDER_BLOCKED:'
|
|
320
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
315
321
|
|
|
316
322
|
try {
|
|
317
323
|
# Transport and mapping come from the shared module. Update reconstruction is
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
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
|
-
. (Join-Path $PSScriptRoot 'codex-authority-store.ps1')
|
|
9
|
-
. (Join-Path $PSScriptRoot 'codex-agent-profile-attestation.ps1')
|
|
9
|
+
try { . (Join-Path $PSScriptRoot 'codex-authority-store.ps1') } catch { Add-HookDependencyFailure -Name 'codex-authority-store.ps1' -ErrorRecord $_ }
|
|
10
|
+
try { . (Join-Path $PSScriptRoot 'codex-agent-profile-attestation.ps1') } catch { Add-HookDependencyFailure -Name 'codex-agent-profile-attestation.ps1' -ErrorRecord $_ }
|
|
10
11
|
|
|
11
12
|
$script:CodexModelGateRepositoryRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
|
|
12
13
|
|
|
@@ -91,6 +92,8 @@ function Invoke-CodexModelRoutingDecision {
|
|
|
91
92
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
92
93
|
[AllowNull()][AllowEmptyString()][string] $AttestationRaw
|
|
93
94
|
)
|
|
95
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MODEL_ROUTING_ATTESTATION_BLOCKED:'
|
|
96
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
94
97
|
|
|
95
98
|
$payload = ConvertFrom-CodexModelGateJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
96
99
|
if ([string]::IsNullOrWhiteSpace($AttestationRaw)) {
|
|
@@ -150,6 +153,9 @@ function Get-CodexModelGateDenyDecision {
|
|
|
150
153
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
151
154
|
return
|
|
152
155
|
}
|
|
156
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('MODEL_ROUTING_ATTESTATION_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
157
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'MODEL_ROUTING_ATTESTATION_BLOCKED:'
|
|
158
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
153
159
|
|
|
154
160
|
try {
|
|
155
161
|
$payloadRaw = [Console]::In.ReadToEnd()
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1
CHANGED
|
@@ -29,32 +29,37 @@
|
|
|
29
29
|
completion is not asserted, the write is allowed via
|
|
30
30
|
hookSpecificOutput.permissionDecision='allow' (backward compatibility).
|
|
31
31
|
|
|
32
|
-
Edit tool calls supply only old_string/new_string (a partial patch)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
Edit tool calls supply only old_string/new_string (a partial patch). An Edit
|
|
33
|
+
call is validated by reading the checkpoint at the Edit's targeted file_path
|
|
34
|
+
through the injectable CheckpointReader seam and applying the old_string ->
|
|
35
|
+
new_string replacement in memory; the resulting content is then evaluated
|
|
36
|
+
like a Write. One occurrence of old_string is replaced unless replace_all is
|
|
37
|
+
true. The hook fails closed: a missing, empty, or unreadable targeted
|
|
38
|
+
checkpoint, an absent or empty old_string, zero or ambiguous occurrences of
|
|
39
|
+
old_string, and a Write with empty content all deny, and the deny reason
|
|
40
|
+
names the cause. Write content or patched content that is not valid JSON is
|
|
41
|
+
also denied, because the canonical checkpoint is required to stay valid JSON.
|
|
37
42
|
|
|
38
43
|
.NOTES
|
|
39
44
|
Compatible with PowerShell 7+. Read-only validation gate.
|
|
40
45
|
#>
|
|
41
46
|
[CmdletBinding()]
|
|
42
47
|
param()
|
|
48
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
43
49
|
|
|
44
50
|
# Reuse the adjacent hook's shared checkpoint policy logic. This dot-source is by
|
|
45
51
|
# design, not a copy-paste defect, so the hook is not renamed.
|
|
46
|
-
. (Join-Path $PSScriptRoot 'enforce-checkpoint-monotonic.ps1')
|
|
52
|
+
try { . (Join-Path $PSScriptRoot 'enforce-checkpoint-monotonic.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-checkpoint-monotonic.ps1' -ErrorRecord $_ }
|
|
47
53
|
|
|
48
54
|
# Shared Codex PreToolUse transport. Dot-sourced explicitly rather than relying on
|
|
49
55
|
# the transitive load above, so this hook's transport does not depend on its
|
|
50
56
|
# neighbour's internals. Every transport error it raises names this hook, because
|
|
51
57
|
# the shared parser is called with -HookName 'enforce-completion-consistency'.
|
|
52
|
-
. (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1')
|
|
58
|
+
try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
|
|
53
59
|
|
|
54
60
|
# Dot-source the shared validation helpers. Guarded so a missing file produces a
|
|
55
61
|
# clear error and so dot-sourcing this hook in tests loads the helpers too.
|
|
56
|
-
|
|
57
|
-
. $script:CompletionHelpersPath
|
|
62
|
+
try { . (Join-Path $PSScriptRoot 'enforce-completion-helpers.ps1') } catch { Add-HookDependencyFailure -Name 'enforce-completion-helpers.ps1' -ErrorRecord $_ }
|
|
58
63
|
|
|
59
64
|
function ConvertFrom-CheckpointJson {
|
|
60
65
|
<#
|
|
@@ -76,9 +81,10 @@ function Get-CheckpointFileContent {
|
|
|
76
81
|
Reads the on-disk checkpoint content for the read-then-validate Edit path.
|
|
77
82
|
.DESCRIPTION
|
|
78
83
|
Returns the full file text when the path resolves to a file on disk, or
|
|
79
|
-
$null when the file does not exist.
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
$null when the file does not exist. An existing empty file yields an
|
|
85
|
+
empty string, never $null, so a missing checkpoint and an empty
|
|
86
|
+
checkpoint stay distinct. Tests inject a CheckpointReader scriptblock
|
|
87
|
+
instead of mocking this function so no temporary files are required.
|
|
82
88
|
#>
|
|
83
89
|
[CmdletBinding()]
|
|
84
90
|
[OutputType([string])]
|
|
@@ -90,7 +96,9 @@ function Get-CheckpointFileContent {
|
|
|
90
96
|
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
|
91
97
|
return $null
|
|
92
98
|
}
|
|
93
|
-
|
|
99
|
+
$text = Get-Content -LiteralPath $Path -Raw -ErrorAction Stop
|
|
100
|
+
if ($null -eq $text) { return '' }
|
|
101
|
+
return [string]$text
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
function Test-IsCheckpointPath {
|
|
@@ -270,26 +278,34 @@ function Get-MissingCompletionEvidence {
|
|
|
270
278
|
function Resolve-EditedCheckpointContent {
|
|
271
279
|
<#
|
|
272
280
|
.SYNOPSIS
|
|
273
|
-
Returns
|
|
274
|
-
|
|
281
|
+
Returns an object with Content and Failure for an Edit-tool call: the
|
|
282
|
+
patched checkpoint content on success, or a failure cause when the patch
|
|
283
|
+
cannot be applied against the targeted checkpoint.
|
|
275
284
|
.DESCRIPTION
|
|
276
|
-
Implements the read-then-validate Edit path.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
replacement is applied in memory (no
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
285
|
+
Implements the read-then-validate Edit path. The checkpoint at the
|
|
286
|
+
caller-supplied CheckpointPath (the Edit's targeted file_path, passed to
|
|
287
|
+
the reader unchanged) is read through the injectable CheckpointReader seam
|
|
288
|
+
and the old_string -> new_string replacement is applied in memory (no
|
|
289
|
+
on-disk mutation). One occurrence of old_string is replaced unless
|
|
290
|
+
replace_all is true. Failure is one of no-old_string (absent or empty
|
|
291
|
+
old_string), checkpoint-unreadable (the reader threw), checkpoint-missing
|
|
292
|
+
(the reader returned $null), checkpoint-empty (the reader returned an
|
|
293
|
+
empty string), old_string-not-found, or old_string-ambiguous. Content is
|
|
294
|
+
$null on failure and Failure is $null on success. The caller denies on
|
|
295
|
+
any Failure.
|
|
283
296
|
#>
|
|
284
297
|
[CmdletBinding()]
|
|
285
|
-
[OutputType([
|
|
298
|
+
[OutputType([pscustomobject])]
|
|
286
299
|
param(
|
|
287
300
|
[Parameter(Mandatory)]
|
|
288
301
|
[AllowNull()]
|
|
289
302
|
$ToolInput,
|
|
290
303
|
|
|
291
304
|
[Parameter(Mandatory)]
|
|
292
|
-
[scriptblock] $CheckpointReader
|
|
305
|
+
[scriptblock] $CheckpointReader,
|
|
306
|
+
|
|
307
|
+
[Parameter(Mandatory)]
|
|
308
|
+
[string] $CheckpointPath
|
|
293
309
|
)
|
|
294
310
|
|
|
295
311
|
$oldString = $null
|
|
@@ -297,7 +313,7 @@ function Resolve-EditedCheckpointContent {
|
|
|
297
313
|
$oldString = [string]$ToolInput.old_string
|
|
298
314
|
}
|
|
299
315
|
if ([string]::IsNullOrEmpty($oldString)) {
|
|
300
|
-
return $null
|
|
316
|
+
return [pscustomobject]@{ Content = $null; Failure = 'no-old_string' }
|
|
301
317
|
}
|
|
302
318
|
|
|
303
319
|
$newString = ''
|
|
@@ -305,20 +321,46 @@ function Resolve-EditedCheckpointContent {
|
|
|
305
321
|
$newString = [string]$ToolInput.new_string
|
|
306
322
|
}
|
|
307
323
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
324
|
+
try {
|
|
325
|
+
$onDisk = & $CheckpointReader $CheckpointPath
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
# A reader exception must not escape the gate; report it as a failure cause.
|
|
329
|
+
return [pscustomobject]@{ Content = $null; Failure = 'checkpoint-unreadable' }
|
|
330
|
+
}
|
|
331
|
+
if ($null -eq $onDisk) {
|
|
332
|
+
return [pscustomobject]@{ Content = $null; Failure = 'checkpoint-missing' }
|
|
312
333
|
}
|
|
313
334
|
|
|
314
335
|
$onDiskText = [string]$onDisk
|
|
315
|
-
if (
|
|
316
|
-
|
|
317
|
-
return $null
|
|
336
|
+
if ($onDiskText.Length -eq 0) {
|
|
337
|
+
return [pscustomobject]@{ Content = $null; Failure = 'checkpoint-empty' }
|
|
318
338
|
}
|
|
319
339
|
|
|
320
|
-
# Apply the patch in memory
|
|
321
|
-
|
|
340
|
+
# Apply the patch in memory; one occurrence unless replace_all is true.
|
|
341
|
+
$replaceAll = Get-EditReplaceAllFlag -ToolInput $ToolInput
|
|
342
|
+
return Invoke-SingleOccurrenceEdit -Text $onDiskText -OldString $oldString -NewString $newString -ReplaceAll $replaceAll
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function ConvertTo-CompletionDenyDecision {
|
|
346
|
+
<#
|
|
347
|
+
.SYNOPSIS
|
|
348
|
+
Builds the PreToolUse deny decision for the given reason.
|
|
349
|
+
#>
|
|
350
|
+
[CmdletBinding()]
|
|
351
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
352
|
+
param(
|
|
353
|
+
[Parameter(Mandatory)]
|
|
354
|
+
[string] $Reason
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return [ordered]@{
|
|
358
|
+
hookSpecificOutput = [ordered]@{
|
|
359
|
+
hookEventName = 'PreToolUse'
|
|
360
|
+
permissionDecision = 'deny'
|
|
361
|
+
permissionDecisionReason = $Reason
|
|
362
|
+
}
|
|
363
|
+
}
|
|
322
364
|
}
|
|
323
365
|
|
|
324
366
|
function Invoke-CompletionConsistencyDecision {
|
|
@@ -341,6 +383,8 @@ function Invoke-CompletionConsistencyDecision {
|
|
|
341
383
|
[Parameter(Mandatory = $false)]
|
|
342
384
|
[scriptblock] $RoutingMatrixReader
|
|
343
385
|
)
|
|
386
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'COMPLETION_CONSISTENCY_BLOCKED:'
|
|
387
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
344
388
|
|
|
345
389
|
if (-not $ToolInputRaw) {
|
|
346
390
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
@@ -363,19 +407,25 @@ function Invoke-CompletionConsistencyDecision {
|
|
|
363
407
|
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
364
408
|
}
|
|
365
409
|
|
|
366
|
-
# Write tool:
|
|
367
|
-
#
|
|
368
|
-
#
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
410
|
+
# Write tool: a present content property is validated directly, and empty
|
|
411
|
+
# content is denied. Edit tool: no content property is supplied, so read the
|
|
412
|
+
# targeted checkpoint through the injectable seam and apply the old_string ->
|
|
413
|
+
# new_string patch in memory (read-then-validate). Any failure cause denies.
|
|
414
|
+
$cause = $null
|
|
415
|
+
if ($toolInput.PSObject.Properties.Name -contains 'content') {
|
|
416
|
+
$content = $toolInput.content
|
|
372
417
|
if (-not $content) {
|
|
373
|
-
|
|
374
|
-
hookEventName = 'PreToolUse'; permissionDecision = 'deny'
|
|
375
|
-
permissionDecisionReason = 'COMPLETION_CONSISTENCY_BLOCKED: the canonical checkpoint cannot be deleted, emptied, or replaced through an unresolved patch.'
|
|
376
|
-
} }
|
|
418
|
+
$cause = 'write-content-empty'
|
|
377
419
|
}
|
|
378
420
|
}
|
|
421
|
+
else {
|
|
422
|
+
$edit = Resolve-EditedCheckpointContent -ToolInput $toolInput -CheckpointReader $CheckpointReader -CheckpointPath $filePath
|
|
423
|
+
$content = $edit.Content
|
|
424
|
+
$cause = $edit.Failure
|
|
425
|
+
}
|
|
426
|
+
if ($cause) {
|
|
427
|
+
return ConvertTo-CompletionDenyDecision -Reason "COMPLETION_CONSISTENCY_BLOCKED: the canonical checkpoint cannot be deleted, emptied, or replaced through an unresolved patch ($cause)."
|
|
428
|
+
}
|
|
379
429
|
|
|
380
430
|
try {
|
|
381
431
|
$payload = ConvertFrom-CheckpointJson -Json $content
|
|
@@ -414,6 +464,9 @@ function Invoke-CompletionConsistencyDecision {
|
|
|
414
464
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
415
465
|
return
|
|
416
466
|
}
|
|
467
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('COMPLETION_CONSISTENCY_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
468
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'COMPLETION_CONSISTENCY_BLOCKED:'
|
|
469
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
417
470
|
|
|
418
471
|
try {
|
|
419
472
|
# -HookName makes every transport error name this hook rather than the
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1
CHANGED
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
- Test-IsValidFeatureFolder: rejects sentinel/placeholder feature folders
|
|
12
12
|
and folders not anchored under docs/features/active/<segment>; optionally
|
|
13
13
|
verifies on-disk existence through an injectable scriptblock seam.
|
|
14
|
+
- Get-EditReplaceAllFlag: returns the boolean value of the replace_all
|
|
15
|
+
property of an Edit tool input; the string 'true' is honoured and the
|
|
16
|
+
string 'false' is not.
|
|
17
|
+
- Invoke-SingleOccurrenceEdit: pure single-occurrence patch of a text;
|
|
18
|
+
reports a failure cause instead of replacing when old_string is empty,
|
|
19
|
+
absent, or ambiguous.
|
|
14
20
|
|
|
15
21
|
This script is dot-sourced by enforce-completion-consistency.ps1. It contains
|
|
16
22
|
no entrypoint logic, so dot-sourcing it in tests has no side effects.
|
|
@@ -161,3 +167,102 @@ function Test-RouteRequiresPrGate {
|
|
|
161
167
|
}
|
|
162
168
|
return ([bool]$route.requires_pr_gate -eq $true)
|
|
163
169
|
}
|
|
170
|
+
|
|
171
|
+
function Get-EditReplaceAllFlag {
|
|
172
|
+
<#
|
|
173
|
+
.SYNOPSIS
|
|
174
|
+
Returns the boolean value of the replace_all property of an Edit tool input.
|
|
175
|
+
.DESCRIPTION
|
|
176
|
+
Returns $false when the tool input is null or has no replace_all property.
|
|
177
|
+
Returns the value when it is already a boolean. Returns $true for a string
|
|
178
|
+
whose trimmed, case-insensitive value is 'true'. Returns $false for every
|
|
179
|
+
other value. No [bool] cast is used because [bool]'false' is $true in
|
|
180
|
+
PowerShell.
|
|
181
|
+
#>
|
|
182
|
+
[CmdletBinding()]
|
|
183
|
+
[OutputType([bool])]
|
|
184
|
+
param(
|
|
185
|
+
[Parameter(Mandatory)]
|
|
186
|
+
[AllowNull()]
|
|
187
|
+
$ToolInput
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if ($null -eq $ToolInput -or -not ($ToolInput.PSObject.Properties.Name -contains 'replace_all')) {
|
|
191
|
+
return $false
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
$value = $ToolInput.replace_all
|
|
195
|
+
if ($value -is [bool]) {
|
|
196
|
+
return $value
|
|
197
|
+
}
|
|
198
|
+
if ($value -is [string]) {
|
|
199
|
+
return $value.Trim() -ieq 'true'
|
|
200
|
+
}
|
|
201
|
+
return $false
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function Invoke-SingleOccurrenceEdit {
|
|
205
|
+
<#
|
|
206
|
+
.SYNOPSIS
|
|
207
|
+
Applies an old_string to new_string patch to a text in memory and reports
|
|
208
|
+
a failure cause when the patch cannot be applied unambiguously.
|
|
209
|
+
.DESCRIPTION
|
|
210
|
+
Pure function with no I/O. Normalizes CRLF to LF in all three strings. An
|
|
211
|
+
empty OldString yields Failure 'no-old_string'. Zero ordinal occurrences
|
|
212
|
+
yield Failure 'old_string-not-found'. When ReplaceAll is true every
|
|
213
|
+
occurrence is replaced by ordinal String.Replace. Otherwise a second
|
|
214
|
+
ordinal search that starts after the end of the first match yields Failure
|
|
215
|
+
'old_string-ambiguous' when it finds a match (overlapping candidates are
|
|
216
|
+
counted once), and no match yields a single splice by Substring. No regular
|
|
217
|
+
expression is used, so a '$' in NewString stays literal. Returns an object
|
|
218
|
+
with Content and Failure; Content is $null on failure and Failure is $null
|
|
219
|
+
on success.
|
|
220
|
+
#>
|
|
221
|
+
[CmdletBinding()]
|
|
222
|
+
[OutputType([pscustomobject])]
|
|
223
|
+
param(
|
|
224
|
+
[Parameter(Mandatory)]
|
|
225
|
+
[AllowNull()]
|
|
226
|
+
[AllowEmptyString()]
|
|
227
|
+
[string] $Text,
|
|
228
|
+
|
|
229
|
+
[Parameter(Mandatory)]
|
|
230
|
+
[AllowNull()]
|
|
231
|
+
[AllowEmptyString()]
|
|
232
|
+
[string] $OldString,
|
|
233
|
+
|
|
234
|
+
[Parameter(Mandatory)]
|
|
235
|
+
[AllowNull()]
|
|
236
|
+
[AllowEmptyString()]
|
|
237
|
+
[string] $NewString,
|
|
238
|
+
|
|
239
|
+
[Parameter(Mandatory = $false)]
|
|
240
|
+
[bool] $ReplaceAll = $false
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
$normalizedText = $Text.Replace("`r`n", "`n")
|
|
244
|
+
$normalizedOld = $OldString.Replace("`r`n", "`n")
|
|
245
|
+
$normalizedNew = $NewString.Replace("`r`n", "`n")
|
|
246
|
+
|
|
247
|
+
if ($normalizedOld.Length -eq 0) {
|
|
248
|
+
return [pscustomobject]@{ Content = $null; Failure = 'no-old_string' }
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
$comparison = [System.StringComparison]::Ordinal
|
|
252
|
+
$firstIndex = $normalizedText.IndexOf($normalizedOld, $comparison)
|
|
253
|
+
if ($firstIndex -lt 0) {
|
|
254
|
+
return [pscustomobject]@{ Content = $null; Failure = 'old_string-not-found' }
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if ($ReplaceAll) {
|
|
258
|
+
return [pscustomobject]@{ Content = $normalizedText.Replace($normalizedOld, $normalizedNew); Failure = $null }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
$afterFirst = $firstIndex + $normalizedOld.Length
|
|
262
|
+
if ($normalizedText.IndexOf($normalizedOld, $afterFirst, $comparison) -ge 0) {
|
|
263
|
+
return [pscustomobject]@{ Content = $null; Failure = 'old_string-ambiguous' }
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
$spliced = $normalizedText.Substring(0, $firstIndex) + $normalizedNew + $normalizedText.Substring($afterFirst)
|
|
267
|
+
return [pscustomobject]@{ Content = $spliced; Failure = $null }
|
|
268
|
+
}
|
|
@@ -10,10 +10,11 @@
|
|
|
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
15
|
$contractPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'scripts/epic-child-launch-contract.ps1'
|
|
15
16
|
if (Test-Path -LiteralPath $contractPath -PathType Leaf) {
|
|
16
|
-
. $contractPath
|
|
17
|
+
try { . $contractPath } catch { Add-HookDependencyFailure -Name 'epic-child-launch-contract.ps1' -ErrorRecord $_ }
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
function ConvertFrom-CodexChildGuardJson {
|
|
@@ -218,6 +219,8 @@ function Invoke-CodexEpicChildGuardDecision {
|
|
|
218
219
|
[Parameter(Mandatory)][AllowEmptyString()][string] $ActualSpecSha256,
|
|
219
220
|
[Parameter(Mandatory)][AllowEmptyString()][string] $ActualProfileSha256
|
|
220
221
|
)
|
|
222
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_BINDING_BLOCKED:'
|
|
223
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
221
224
|
|
|
222
225
|
$payload = ConvertFrom-CodexChildGuardJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
223
226
|
if ([string]::IsNullOrWhiteSpace([string]$Attestation.launch_id)) {
|
|
@@ -282,6 +285,9 @@ function Get-CodexChildGuardLiveBranch {
|
|
|
282
285
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
283
286
|
return
|
|
284
287
|
}
|
|
288
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_WORKTREE_BINDING_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
289
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_WORKTREE_BINDING_BLOCKED:'
|
|
290
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
285
291
|
|
|
286
292
|
try {
|
|
287
293
|
$payloadRaw = [Console]::In.ReadToEnd()
|
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
<#
|
|
2
2
|
.SYNOPSIS
|
|
3
3
|
Gates epic child and integration PR merges behind checkpointed green state.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Docs-only branch (issue #927): after the standalone branch denies an explicit PR number,
|
|
7
|
+
and only when no checkpoint is present at the repository root (both checkpoint texts are
|
|
8
|
+
blank; operator decision OD-1, stricter than the Claude per-PR rule), the gate calls
|
|
9
|
+
Get-DocsOnlyMergeExemption from hook-docs-only-diff.ps1 with the repository root. That
|
|
10
|
+
function runs gh pr view and git there and allows the merge when its conditions M1-M9
|
|
11
|
+
hold; otherwise the deny gains " (docs-only exemption not applied: <Reason>)", where the
|
|
12
|
+
reason may be DOCS_ONLY_EXEMPTION_PR_UNRESOLVED. A blank RepositoryRoot denies at M2
|
|
13
|
+
before any process starts. The hook never fetches; --match-head-commit, when present,
|
|
14
|
+
must equal headRefOid (OD-2). Residual limits: an ambient GH_REPO or GH_HOST is not
|
|
15
|
+
visible in the command text; gh and git run in the repository root, so a cd made by an
|
|
16
|
+
earlier shell call is not visible either; a push after the lookup can change the head
|
|
17
|
+
unless --match-head-commit is passed; and the control is policy-level, not cryptographic.
|
|
4
18
|
#>
|
|
5
19
|
[CmdletBinding()]
|
|
6
20
|
param()
|
|
21
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
7
22
|
|
|
8
23
|
# Shared command-line parser (issue #545). The scope filter and the PR-number resolver below
|
|
9
24
|
# both run against the segment that structurally invokes `gh pr merge`, which is what keeps
|
|
10
25
|
# 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')
|
|
26
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
|
|
27
|
+
try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
|
|
28
|
+
# Shared docs-only diff classification and the merge-side docs-only exemption (issue #927).
|
|
29
|
+
try { . (Join-Path $PSScriptRoot 'hook-docs-only-diff.ps1') } catch { Add-HookDependencyFailure -Name 'hook-docs-only-diff.ps1' -ErrorRecord $_ }
|
|
13
30
|
|
|
14
31
|
# Reason codes for the standalone-merge authorization branch (issue #670), spelled
|
|
15
32
|
# byte-identically to the Claude helpers file. Each of the four assignments below is the only
|
|
@@ -125,8 +142,11 @@ function Invoke-CodexEpicMergeDecision {
|
|
|
125
142
|
param(
|
|
126
143
|
[Parameter(Mandatory)][string] $PayloadRaw,
|
|
127
144
|
[AllowNull()][AllowEmptyString()][string] $ChildCheckpointRaw,
|
|
128
|
-
[AllowNull()][AllowEmptyString()][string] $EpicCheckpointRaw
|
|
145
|
+
[AllowNull()][AllowEmptyString()][string] $EpicCheckpointRaw,
|
|
146
|
+
[AllowNull()][AllowEmptyString()][string] $RepositoryRoot
|
|
129
147
|
)
|
|
148
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_MERGE_GATE_BLOCKED:'
|
|
149
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
130
150
|
|
|
131
151
|
$payload = ConvertFrom-CodexMergeJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
132
152
|
if ([string]$payload.tool_name -ne 'Bash') {
|
|
@@ -172,11 +192,20 @@ function Invoke-CodexEpicMergeDecision {
|
|
|
172
192
|
if ($verdict.Allowed) {
|
|
173
193
|
return $null
|
|
174
194
|
}
|
|
195
|
+
# Docs-only branch (issue #927, OD-1): only when no checkpoint is present at the root.
|
|
196
|
+
$docsOnlySuffix = ''
|
|
197
|
+
if ([string]::IsNullOrWhiteSpace($ChildCheckpointRaw) -and [string]::IsNullOrWhiteSpace($EpicCheckpointRaw)) {
|
|
198
|
+
$docsOnly = Get-DocsOnlyMergeExemption -CommandText $command -PrNumber $prNumber -WorktreeRoot $RepositoryRoot
|
|
199
|
+
if ($docsOnly.Exempt) {
|
|
200
|
+
return $null
|
|
201
|
+
}
|
|
202
|
+
$docsOnlySuffix = ' (docs-only exemption not applied: ' + $docsOnly.Reason + ')'
|
|
203
|
+
}
|
|
175
204
|
return [ordered]@{
|
|
176
205
|
hookSpecificOutput = [ordered]@{
|
|
177
206
|
hookEventName = 'PreToolUse'
|
|
178
207
|
permissionDecision = 'deny'
|
|
179
|
-
permissionDecisionReason = 'EPIC_MERGE_GATE_BLOCKED: ' + $verdict.ReasonCode + ': ' + $verdict.Message
|
|
208
|
+
permissionDecisionReason = 'EPIC_MERGE_GATE_BLOCKED: ' + $verdict.ReasonCode + ': ' + $verdict.Message + $docsOnlySuffix
|
|
180
209
|
}
|
|
181
210
|
}
|
|
182
211
|
}
|
|
@@ -360,6 +389,9 @@ function Test-CodexStandaloneMergeAuthorization {
|
|
|
360
389
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
361
390
|
return
|
|
362
391
|
}
|
|
392
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_MERGE_GATE_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
393
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_MERGE_GATE_BLOCKED:'
|
|
394
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
363
395
|
|
|
364
396
|
try {
|
|
365
397
|
$payloadRaw = [Console]::In.ReadToEnd()
|
|
@@ -368,7 +400,7 @@ try {
|
|
|
368
400
|
$epicPath = Join-Path $repositoryRoot 'artifacts/orchestration/epic-orchestrator-state.json'
|
|
369
401
|
$childRaw = if (Test-Path -LiteralPath $childPath -PathType Leaf) { Get-Content -Raw -LiteralPath $childPath } else { '' }
|
|
370
402
|
$epicRaw = if (Test-Path -LiteralPath $epicPath -PathType Leaf) { Get-Content -Raw -LiteralPath $epicPath } else { '' }
|
|
371
|
-
$decision = Invoke-CodexEpicMergeDecision -PayloadRaw $payloadRaw -ChildCheckpointRaw $childRaw -EpicCheckpointRaw $epicRaw
|
|
403
|
+
$decision = Invoke-CodexEpicMergeDecision -PayloadRaw $payloadRaw -ChildCheckpointRaw $childRaw -EpicCheckpointRaw $epicRaw -RepositoryRoot $repositoryRoot
|
|
372
404
|
if ($null -ne $decision) {
|
|
373
405
|
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
374
406
|
}
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#>
|
|
10
10
|
[CmdletBinding()]
|
|
11
11
|
param()
|
|
12
|
+
$script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
|
|
12
13
|
|
|
13
14
|
$script:AllowedPreparationMcpTools = @(
|
|
14
15
|
'mcp__drm-copilot__new_potential_entry',
|
|
@@ -209,6 +210,8 @@ function Invoke-EpicPlanningOnlyDecision {
|
|
|
209
210
|
[AllowNull()][AllowEmptyString()][string] $CurrentBranch,
|
|
210
211
|
[string] $RegistryPath = (Join-Path $script:EpicPlanningRepositoryRoot 'config/orchestration-handoff-registry.json')
|
|
211
212
|
)
|
|
213
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_PLANNING_ONLY_BLOCKED:'
|
|
214
|
+
if ($null -ne $dependencyDecision) { return $dependencyDecision }
|
|
212
215
|
|
|
213
216
|
$payload = ConvertFrom-EpicPlanningJson -Raw $PayloadRaw -Name 'PreToolUse input'
|
|
214
217
|
$attestedPreparation = $EpicExecutionContext -eq 'epic_preparation_child'
|
|
@@ -325,6 +328,9 @@ function Get-EpicPlanningCurrentBranch {
|
|
|
325
328
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
326
329
|
return
|
|
327
330
|
}
|
|
331
|
+
if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('EPIC_PLANNING_ONLY_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
|
|
332
|
+
$dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'EPIC_PLANNING_ONLY_BLOCKED:'
|
|
333
|
+
if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
|
|
328
334
|
|
|
329
335
|
try {
|
|
330
336
|
$payloadRaw = [Console]::In.ReadToEnd()
|