@danmoisan/drm-copilot-mcp 1.0.14 → 1.0.16
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 +3160 -458
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +13 -4
- package/resources/claude-customizations/.claude/skills/epic-run/SKILL.md +22 -4
- package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +100 -0
- package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/agents/openai.yaml +4 -0
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +170 -0
- package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +230 -0
- package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +39 -0
- package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +89 -9
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +39 -4
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/tonality/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +153 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +153 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +153 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +153 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +153 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +95 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +95 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +95 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +95 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +95 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c1.toml +99 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c2.toml +99 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3-elevated.toml +99 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3.toml +99 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c4.toml +99 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +96 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-planner.toml +97 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +62 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +62 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +62 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +62 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +62 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +200 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +200 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +200 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +200 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +200 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +53 -3
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c1.toml +110 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c2.toml +110 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3-elevated.toml +110 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3.toml +110 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c4.toml +110 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c1.toml +28 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c2.toml +28 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c3-elevated.toml +28 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c3.toml +28 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author-c4.toml +28 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c1.toml +55 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c2.toml +55 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c3-elevated.toml +55 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c3.toml +55 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature-c4.toml +55 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +102 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +102 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +102 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +102 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +102 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c1.toml +105 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c2.toml +105 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c3-elevated.toml +105 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c3.toml +105 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher-c4.toml +105 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c1.toml +50 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c2.toml +50 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c3-elevated.toml +50 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c3.toml +50 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer-c4.toml +50 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer.toml +2 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +202 -37
- package/resources/codex-and-agents-customizations/.codex/hooks/authorize-root-epic-invocation.ps1 +236 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +178 -69
- package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +92 -19
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-agent-profile-attestation.ps1 +199 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-authority-store.ps1 +182 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +129 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +148 -31
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +198 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +28 -19
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +325 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +140 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +292 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +135 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +295 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +151 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +99 -34
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +143 -27
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +88 -43
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +65 -20
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +88 -42
- package/resources/codex-and-agents-customizations/.codex/hooks/record-subagent-routing-attestation.ps1 +414 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +164 -51
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +154 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +58 -23
- package/resources/codex-and-agents-customizations/AGENTS.md +27 -0
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +66 -1
- package/resources/codex-and-agents-customizations/pack-manifests/csharp-legacy.json +6 -1
- package/resources/codex-and-agents-customizations/pack-manifests/csharp-modern.json +6 -1
- package/resources/codex-and-agents-customizations/pack-manifests/powershell.json +6 -1
- package/resources/codex-and-agents-customizations/pack-manifests/python.json +6 -1
- package/resources/codex-and-agents-customizations/pack-manifests/typescript.json +6 -1
- package/resources/config/orchestration-routing.json +146 -0
- package/resources/powershell/PoshQC/PoshQC.Analyzer.psm1 +1 -1
- package/resources/powershell/PoshQC/PoshQC.ScanConfig.psm1 +125 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +14 -2
- package/resources/powershell/PoshQC/PoshQC.psd1 +0 -4
- package/resources/powershell/PoshQC/PoshQC.psm1 +26 -6
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +34 -18
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Resolves the non-workspace authority store used by Codex provenance hooks.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Epic-entry receipts and routed-subagent attestations must not be writable by
|
|
7
|
+
workspace-scoped agents. These helpers derive a repository- and session-bound
|
|
8
|
+
directory under CODEX_HOME and exact receipt/attestation paths within it.
|
|
9
|
+
#>
|
|
10
|
+
[CmdletBinding()]
|
|
11
|
+
param()
|
|
12
|
+
|
|
13
|
+
function Get-CodexAuthoritySha256 {
|
|
14
|
+
[CmdletBinding()]
|
|
15
|
+
[OutputType([string])]
|
|
16
|
+
param([Parameter(Mandatory)][AllowEmptyString()][string] $Text)
|
|
17
|
+
|
|
18
|
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($Text)
|
|
19
|
+
return [Convert]::ToHexString(
|
|
20
|
+
[System.Security.Cryptography.SHA256]::HashData($bytes)
|
|
21
|
+
).ToLowerInvariant()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function Get-CodexCanonicalAuthorityPath {
|
|
25
|
+
[CmdletBinding()]
|
|
26
|
+
[OutputType([string])]
|
|
27
|
+
param([Parameter(Mandatory)][string] $Path)
|
|
28
|
+
|
|
29
|
+
$fullPath = [System.IO.Path]::GetFullPath($Path).TrimEnd(
|
|
30
|
+
[System.IO.Path]::DirectorySeparatorChar,
|
|
31
|
+
[System.IO.Path]::AltDirectorySeparatorChar
|
|
32
|
+
)
|
|
33
|
+
if ($IsWindows) {
|
|
34
|
+
return $fullPath.ToLowerInvariant()
|
|
35
|
+
}
|
|
36
|
+
return $fullPath
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function Get-CodexAuthorityRepositoryKey {
|
|
40
|
+
[CmdletBinding()]
|
|
41
|
+
[OutputType([string])]
|
|
42
|
+
param([Parameter(Mandatory)][string] $RepositoryRoot)
|
|
43
|
+
|
|
44
|
+
return Get-CodexAuthoritySha256 -Text (
|
|
45
|
+
Get-CodexCanonicalAuthorityPath -Path $RepositoryRoot
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function Get-CodexResolvedAuthorityPath {
|
|
50
|
+
[CmdletBinding()]
|
|
51
|
+
[OutputType([string])]
|
|
52
|
+
param([Parameter(Mandatory)][string] $Path)
|
|
53
|
+
|
|
54
|
+
$candidate = [System.IO.Path]::GetFullPath($Path)
|
|
55
|
+
$suffix = [System.Collections.Generic.Stack[string]]::new()
|
|
56
|
+
while (-not (Test-Path -LiteralPath $candidate)) {
|
|
57
|
+
$leaf = Split-Path $candidate -Leaf
|
|
58
|
+
if ([string]::IsNullOrWhiteSpace($leaf)) {
|
|
59
|
+
break
|
|
60
|
+
}
|
|
61
|
+
$suffix.Push($leaf)
|
|
62
|
+
$candidate = Split-Path $candidate -Parent
|
|
63
|
+
}
|
|
64
|
+
if (-not (Test-Path -LiteralPath $candidate)) {
|
|
65
|
+
return Get-CodexCanonicalAuthorityPath -Path $Path
|
|
66
|
+
}
|
|
67
|
+
$item = Get-Item -Force -LiteralPath $candidate
|
|
68
|
+
$resolved = if ($null -ne $item.LinkTarget) {
|
|
69
|
+
$target = [string]$item.LinkTarget
|
|
70
|
+
if (-not [System.IO.Path]::IsPathFullyQualified($target)) {
|
|
71
|
+
$target = Join-Path (Split-Path $candidate -Parent) $target
|
|
72
|
+
}
|
|
73
|
+
[System.IO.Path]::GetFullPath($target)
|
|
74
|
+
} else {
|
|
75
|
+
[string](Resolve-Path -LiteralPath $candidate).ProviderPath
|
|
76
|
+
}
|
|
77
|
+
while ($suffix.Count -gt 0) {
|
|
78
|
+
$resolved = Join-Path $resolved $suffix.Pop()
|
|
79
|
+
}
|
|
80
|
+
return Get-CodexCanonicalAuthorityPath -Path $resolved
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function Assert-CodexAuthorityOutsideRepository {
|
|
84
|
+
[CmdletBinding()]
|
|
85
|
+
param(
|
|
86
|
+
[Parameter(Mandatory)][string] $AuthorityPath,
|
|
87
|
+
[Parameter(Mandatory)][string] $RepositoryRoot
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
$authority = Get-CodexResolvedAuthorityPath -Path $AuthorityPath
|
|
91
|
+
$repository = Get-CodexResolvedAuthorityPath -Path $RepositoryRoot
|
|
92
|
+
$prefix = $repository + [System.IO.Path]::DirectorySeparatorChar
|
|
93
|
+
$comparison = if ($IsWindows) {
|
|
94
|
+
[System.StringComparison]::OrdinalIgnoreCase
|
|
95
|
+
} else {
|
|
96
|
+
[System.StringComparison]::Ordinal
|
|
97
|
+
}
|
|
98
|
+
if ($authority.Equals($repository, $comparison) -or $authority.StartsWith($prefix, $comparison)) {
|
|
99
|
+
throw 'EPIC_INVOCATION_ORIGIN_BLOCKED: the Codex authority store must be outside the repository workspace.'
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function Get-CodexAuthorityHome {
|
|
104
|
+
[CmdletBinding()]
|
|
105
|
+
[OutputType([string])]
|
|
106
|
+
param()
|
|
107
|
+
|
|
108
|
+
if (-not [string]::IsNullOrWhiteSpace($env:CODEX_HOME)) {
|
|
109
|
+
return [System.IO.Path]::GetFullPath($env:CODEX_HOME)
|
|
110
|
+
}
|
|
111
|
+
$profileRoot = [Environment]::GetFolderPath(
|
|
112
|
+
[Environment+SpecialFolder]::UserProfile
|
|
113
|
+
)
|
|
114
|
+
if ([string]::IsNullOrWhiteSpace($profileRoot)) {
|
|
115
|
+
throw 'EPIC_INVOCATION_ORIGIN_BLOCKED: CODEX_HOME and the user profile are unavailable.'
|
|
116
|
+
}
|
|
117
|
+
return Join-Path $profileRoot '.codex'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function ConvertTo-CodexAuthorityPathSegment {
|
|
121
|
+
[CmdletBinding()]
|
|
122
|
+
[OutputType([string])]
|
|
123
|
+
param([Parameter(Mandatory)][string] $Value)
|
|
124
|
+
|
|
125
|
+
if ([string]::IsNullOrWhiteSpace($Value)) {
|
|
126
|
+
throw 'EPIC_INVOCATION_ORIGIN_BLOCKED: authority path identity is empty.'
|
|
127
|
+
}
|
|
128
|
+
return $Value -replace '[^A-Za-z0-9._-]', '_'
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function Get-CodexAuthorityStateRoot {
|
|
132
|
+
[CmdletBinding()]
|
|
133
|
+
[OutputType([string])]
|
|
134
|
+
param(
|
|
135
|
+
[Parameter(Mandatory)][string] $RepositoryRoot,
|
|
136
|
+
[Parameter(Mandatory)][string] $SessionId
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
$repositoryKey = Get-CodexAuthorityRepositoryKey -RepositoryRoot $RepositoryRoot
|
|
140
|
+
$safeSession = ConvertTo-CodexAuthorityPathSegment -Value $SessionId
|
|
141
|
+
$stateRoot = Join-Path (
|
|
142
|
+
Join-Path (Join-Path (Get-CodexAuthorityHome) 'authority/epic-entry') $repositoryKey
|
|
143
|
+
) $safeSession
|
|
144
|
+
Assert-CodexAuthorityOutsideRepository -AuthorityPath $stateRoot -RepositoryRoot $RepositoryRoot
|
|
145
|
+
return $stateRoot
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function Get-CodexAuthorityReceiptPath {
|
|
149
|
+
[CmdletBinding()]
|
|
150
|
+
[OutputType([string])]
|
|
151
|
+
param(
|
|
152
|
+
[Parameter(Mandatory)][string] $RepositoryRoot,
|
|
153
|
+
[Parameter(Mandatory)][string] $SessionId,
|
|
154
|
+
[Parameter(Mandatory)][string] $TurnId
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
$stateRoot = Get-CodexAuthorityStateRoot `
|
|
158
|
+
-RepositoryRoot $RepositoryRoot `
|
|
159
|
+
-SessionId $SessionId
|
|
160
|
+
$safeTurn = ConvertTo-CodexAuthorityPathSegment -Value $TurnId
|
|
161
|
+
return Join-Path $stateRoot "epic-root-invocation.$safeTurn.json"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function Get-CodexAuthorityAttestationPath {
|
|
165
|
+
[CmdletBinding()]
|
|
166
|
+
[OutputType([string])]
|
|
167
|
+
param(
|
|
168
|
+
[Parameter(Mandatory)][string] $RepositoryRoot,
|
|
169
|
+
[Parameter(Mandatory)][string] $SessionId,
|
|
170
|
+
[Parameter(Mandatory)][string] $AttestationKey
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
$stateRoot = Get-CodexAuthorityStateRoot `
|
|
174
|
+
-RepositoryRoot $RepositoryRoot `
|
|
175
|
+
-SessionId $SessionId
|
|
176
|
+
$safeKey = ConvertTo-CodexAuthorityPathSegment -Value $AttestationKey
|
|
177
|
+
return Join-Path $stateRoot "codex-routing-attestation.$safeKey.json"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if ($MyInvocation.InvocationName -ne '.') {
|
|
181
|
+
throw 'codex-authority-store.ps1 is a helper and must be dot-sourced.'
|
|
182
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Validate inherited external-launch authority for routed epic child subagents.
|
|
2
|
+
|
|
3
|
+
$contractPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'scripts/epic-child-launch-contract.ps1'
|
|
4
|
+
if (Test-Path -LiteralPath $contractPath -PathType Leaf) {
|
|
5
|
+
. $contractPath
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
$script:CodexEpicChildContexts = @('epic_preparation_child', 'epic_execution_child')
|
|
9
|
+
|
|
10
|
+
function Get-CodexEpicChildLaunchEnvironment {
|
|
11
|
+
[CmdletBinding()]
|
|
12
|
+
[OutputType([pscustomobject])]
|
|
13
|
+
param()
|
|
14
|
+
|
|
15
|
+
return [pscustomobject]@{
|
|
16
|
+
launch_id = [string]$env:CODEX_EPIC_CHILD_LAUNCH_ID
|
|
17
|
+
receipt_path = [string]$env:CODEX_EPIC_CHILD_LAUNCH_RECEIPT
|
|
18
|
+
spec_path = [string]$env:CODEX_EPIC_CHILD_LAUNCH_SPEC
|
|
19
|
+
worktree_path = [string]$env:CODEX_EPIC_CHILD_EXPECTED_WORKTREE
|
|
20
|
+
delegation_id = [string]$env:CODEX_EPIC_CHILD_DELEGATION_ID
|
|
21
|
+
execution_context = [string]$env:CODEX_EPIC_CHILD_EXECUTION_CONTEXT
|
|
22
|
+
deployment_agent = [string]$env:CODEX_EPIC_CHILD_AGENT
|
|
23
|
+
model = [string]$env:CODEX_EPIC_CHILD_MODEL
|
|
24
|
+
reasoning_effort = [string]$env:CODEX_EPIC_CHILD_REASONING_EFFORT
|
|
25
|
+
profile_sha256 = [string]$env:CODEX_EPIC_CHILD_PROFILE_SHA256
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function Get-CodexEpicChildCanonicalPath {
|
|
30
|
+
[CmdletBinding()]
|
|
31
|
+
[OutputType([string])]
|
|
32
|
+
param([Parameter(Mandatory)][string] $Path, [Parameter(Mandatory)][string] $BasePath)
|
|
33
|
+
|
|
34
|
+
$candidate = if ([System.IO.Path]::IsPathFullyQualified($Path)) {
|
|
35
|
+
$Path
|
|
36
|
+
} else {
|
|
37
|
+
Join-Path $BasePath $Path
|
|
38
|
+
}
|
|
39
|
+
return [System.IO.Path]::GetFullPath($candidate).TrimEnd(
|
|
40
|
+
[System.IO.Path]::DirectorySeparatorChar,
|
|
41
|
+
[System.IO.Path]::AltDirectorySeparatorChar
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function Test-CodexEpicChildRoutingLaunchAuthority {
|
|
46
|
+
[CmdletBinding()]
|
|
47
|
+
[OutputType([bool])]
|
|
48
|
+
param(
|
|
49
|
+
[AllowNull()] $RoutingReceipt,
|
|
50
|
+
[Parameter(Mandatory)] $Payload,
|
|
51
|
+
[Parameter(Mandatory)][string] $RepositoryRoot,
|
|
52
|
+
[AllowNull()] $LaunchEnvironment,
|
|
53
|
+
[AllowNull()][AllowEmptyString()][string] $LaunchReceiptRaw,
|
|
54
|
+
[datetimeoffset] $Now = [datetimeoffset]::UtcNow
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
$context = if ($null -eq $RoutingReceipt) { '' } else {
|
|
58
|
+
[string]$RoutingReceipt.execution_context
|
|
59
|
+
}
|
|
60
|
+
if ($script:CodexEpicChildContexts -cnotcontains $context) {
|
|
61
|
+
return $true
|
|
62
|
+
}
|
|
63
|
+
$environment = if ($null -eq $LaunchEnvironment) {
|
|
64
|
+
Get-CodexEpicChildLaunchEnvironment
|
|
65
|
+
} else {
|
|
66
|
+
$LaunchEnvironment
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
$receiptPath = Get-CodexEpicChildCanonicalPath -Path ([string]$environment.receipt_path) -BasePath $RepositoryRoot
|
|
70
|
+
$raw = if ($PSBoundParameters.ContainsKey('LaunchReceiptRaw')) {
|
|
71
|
+
$LaunchReceiptRaw
|
|
72
|
+
} else {
|
|
73
|
+
Get-Content -Raw -LiteralPath $receiptPath -ErrorAction Stop
|
|
74
|
+
}
|
|
75
|
+
$receipt = $raw | ConvertFrom-Json -Depth 32 -ErrorAction Stop
|
|
76
|
+
if ((Get-CodexChildActiveReceiptErrorList -Receipt $receipt -ExpectedSessionId ([string]$Payload.session_id) -Now $Now).Count -gt 0) {
|
|
77
|
+
return $false
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
$comparison = if ($IsWindows) {
|
|
81
|
+
[System.StringComparison]::OrdinalIgnoreCase
|
|
82
|
+
} else {
|
|
83
|
+
[System.StringComparison]::Ordinal
|
|
84
|
+
}
|
|
85
|
+
$worktree = Get-CodexEpicChildCanonicalPath -Path ([string]$receipt.worktree_path) -BasePath $RepositoryRoot
|
|
86
|
+
$trustedRoot = Get-CodexEpicChildCanonicalPath -Path ([string]$receipt.trusted_repository_root) -BasePath $RepositoryRoot
|
|
87
|
+
$launchRoot = Join-Path $trustedRoot 'artifacts/orchestration/epic-child-launches'
|
|
88
|
+
$specPath = Get-CodexEpicChildCanonicalPath -Path ([string]$receipt.spec_path) -BasePath $trustedRoot
|
|
89
|
+
$checkpointName = if ($context -ceq 'epic_preparation_child') {
|
|
90
|
+
'epic-planner-state.json'
|
|
91
|
+
} else {
|
|
92
|
+
'epic-orchestrator-state.json'
|
|
93
|
+
}
|
|
94
|
+
$expectedCheckpoint = Join-Path $trustedRoot "artifacts/orchestration/$checkpointName"
|
|
95
|
+
$pathPairs = @(
|
|
96
|
+
@($receiptPath, (Get-CodexEpicChildCanonicalPath -Path ([string]$receipt.receipt_path) -BasePath $trustedRoot)),
|
|
97
|
+
@((Get-CodexEpicChildCanonicalPath -Path ([string]$environment.spec_path) -BasePath $trustedRoot), $specPath),
|
|
98
|
+
@((Get-CodexEpicChildCanonicalPath -Path ([string]$environment.worktree_path) -BasePath $RepositoryRoot), $worktree)
|
|
99
|
+
)
|
|
100
|
+
foreach ($pair in $pathPairs) {
|
|
101
|
+
if (-not ([string]$pair[0]).Equals([string]$pair[1], $comparison)) {
|
|
102
|
+
return $false
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
$identityPairs = @(
|
|
106
|
+
@([string]$environment.launch_id, [string]$receipt.launch_id),
|
|
107
|
+
@([string]$environment.delegation_id, [string]$receipt.delegation_id),
|
|
108
|
+
@([string]$environment.execution_context, [string]$receipt.execution_context),
|
|
109
|
+
@([string]$environment.deployment_agent, [string]$receipt.deployment_agent),
|
|
110
|
+
@([string]$environment.model, [string]$receipt.model),
|
|
111
|
+
@([string]$environment.reasoning_effort, [string]$receipt.model_reasoning_effort),
|
|
112
|
+
@([string]$environment.profile_sha256, [string]$receipt.profile_sha256)
|
|
113
|
+
)
|
|
114
|
+
foreach ($pair in $identityPairs) {
|
|
115
|
+
if (-not ([string]$pair[0]).Equals([string]$pair[1], [System.StringComparison]::Ordinal)) {
|
|
116
|
+
return $false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
$repository = Get-CodexEpicChildCanonicalPath -Path $RepositoryRoot -BasePath $RepositoryRoot
|
|
120
|
+
$checkpoint = Get-CodexEpicChildCanonicalPath -Path ([string]$receipt.checkpoint_path) -BasePath $trustedRoot
|
|
121
|
+
return $repository.Equals($worktree, $comparison) -and
|
|
122
|
+
$context -ceq [string]$receipt.execution_context -and
|
|
123
|
+
$checkpoint.Equals($expectedCheckpoint, $comparison) -and
|
|
124
|
+
$receiptPath.StartsWith($launchRoot + [System.IO.Path]::DirectorySeparatorChar, $comparison) -and
|
|
125
|
+
$specPath.StartsWith($launchRoot + [System.IO.Path]::DirectorySeparatorChar, $comparison)
|
|
126
|
+
} catch {
|
|
127
|
+
return $false
|
|
128
|
+
}
|
|
129
|
+
}
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
|
|
1
2
|
<#
|
|
2
3
|
.SYNOPSIS
|
|
3
4
|
Pre-tool-use hook that blocks Write operations on the orchestrator checkpoint
|
|
4
5
|
file when completed_steps appear out of declared canonical order.
|
|
5
6
|
|
|
6
7
|
.DESCRIPTION
|
|
7
|
-
Invoked by the
|
|
8
|
+
Invoked by the Codex PreToolUse hook on Write or Edit operations. The
|
|
8
9
|
hook activates only when the target file_path is
|
|
9
10
|
artifacts/orchestration/orchestrator-state.json.
|
|
10
11
|
|
|
@@ -27,9 +28,11 @@
|
|
|
27
28
|
|
|
28
29
|
Entries that do not match any canonical prefix are treated as informational
|
|
29
30
|
and ignored. If any pair (i, j) with i < j has a higher canonical index at
|
|
30
|
-
position i than at position j, the script
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
position i than at position j, the script denies via a PreToolUse JSON
|
|
32
|
+
response with hookSpecificOutput.permissionDecision='deny' and a reason
|
|
33
|
+
listing the offending pair. A non-empty rollback_history array suppresses
|
|
34
|
+
this check because rollbacks legitimately reorder steps. All allow paths
|
|
35
|
+
emit hookSpecificOutput.permissionDecision='allow'.
|
|
33
36
|
|
|
34
37
|
Edit tool calls supply only old_string/new_string (a partial patch) and
|
|
35
38
|
cannot be reliably validated without the full target file content, so they
|
|
@@ -195,7 +198,7 @@ function Test-IsCheckpointPath {
|
|
|
195
198
|
function Invoke-CheckpointMonotonicDecision {
|
|
196
199
|
<#
|
|
197
200
|
.SYNOPSIS
|
|
198
|
-
Parses
|
|
201
|
+
Parses Codex tool_input and returns an allow-or-block decision.
|
|
199
202
|
#>
|
|
200
203
|
[CmdletBinding()]
|
|
201
204
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
@@ -204,44 +207,49 @@ function Invoke-CheckpointMonotonicDecision {
|
|
|
204
207
|
)
|
|
205
208
|
|
|
206
209
|
if (-not $ToolInputRaw) {
|
|
207
|
-
return [ordered]@{
|
|
210
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
208
211
|
}
|
|
209
212
|
|
|
210
213
|
try {
|
|
211
214
|
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
212
215
|
}
|
|
213
216
|
catch {
|
|
214
|
-
throw "enforce-checkpoint-monotonic hook received malformed JSON in
|
|
217
|
+
throw "enforce-checkpoint-monotonic hook received malformed JSON in Codex tool_input: $_"
|
|
215
218
|
}
|
|
216
219
|
|
|
217
220
|
$filePath = $toolInput.file_path
|
|
218
221
|
if (-not $filePath) {
|
|
219
|
-
return [ordered]@{
|
|
222
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
220
223
|
}
|
|
221
224
|
|
|
222
225
|
$normalized = $filePath -replace '\\', '/'
|
|
223
226
|
if (-not (Test-IsCheckpointPath -NormalizedPath $normalized)) {
|
|
224
|
-
return [ordered]@{
|
|
227
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
225
228
|
}
|
|
226
229
|
|
|
227
|
-
#
|
|
228
|
-
#
|
|
230
|
+
# The adapter supplies complete post-patch content for every recognized
|
|
231
|
+
# operation. Empty content therefore represents deletion and must fail
|
|
232
|
+
# closed for the canonical checkpoint.
|
|
229
233
|
$content = $toolInput.content
|
|
230
234
|
if (-not $content) {
|
|
231
|
-
return [ordered]@{
|
|
235
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{
|
|
236
|
+
hookEventName = 'PreToolUse'; permissionDecision = 'deny'
|
|
237
|
+
permissionDecisionReason = 'CHECKPOINT_ORDER_BLOCKED: the canonical checkpoint cannot be deleted or replaced with empty content.'
|
|
238
|
+
} }
|
|
232
239
|
}
|
|
233
240
|
|
|
234
241
|
try {
|
|
235
242
|
$payload = ConvertFrom-CheckpointJson -Json $content
|
|
236
243
|
}
|
|
237
244
|
catch {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
245
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{
|
|
246
|
+
hookEventName = 'PreToolUse'; permissionDecision = 'deny'
|
|
247
|
+
permissionDecisionReason = 'CHECKPOINT_ORDER_BLOCKED: the canonical checkpoint must remain valid JSON.'
|
|
248
|
+
} }
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
if (-not $payload.PSObject.Properties.Name -contains 'completed_steps') {
|
|
244
|
-
return [ordered]@{
|
|
252
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
245
253
|
}
|
|
246
254
|
|
|
247
255
|
$steps = @()
|
|
@@ -256,14 +264,17 @@ function Invoke-CheckpointMonotonicDecision {
|
|
|
256
264
|
$rollbackHistory = $payload.rollback_history
|
|
257
265
|
}
|
|
258
266
|
if ($rollbackHistory -and @($rollbackHistory).Count -gt 0) {
|
|
259
|
-
return [ordered]@{
|
|
267
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
260
268
|
}
|
|
261
269
|
|
|
262
270
|
$pair = if ($steps.Count -ge 2) { Get-OutOfOrderPair -CompletedSteps $steps } else { $null }
|
|
263
271
|
if ($null -ne $pair) {
|
|
264
272
|
return [ordered]@{
|
|
265
|
-
|
|
266
|
-
|
|
273
|
+
hookSpecificOutput = [ordered]@{
|
|
274
|
+
hookEventName = 'PreToolUse'
|
|
275
|
+
permissionDecision = 'deny'
|
|
276
|
+
permissionDecisionReason = "CHECKPOINT_ORDER_BLOCKED: completed_steps lists '$($pair.EarlierEntry)' at position $($pair.EarlierPos) before '$($pair.LaterEntry)' at position $($pair.LaterPos), but the canonical orchestrator workflow requires the later step to follow the earlier one. Reorder completed_steps or, if a rollback occurred, record it in rollback_history."
|
|
277
|
+
}
|
|
267
278
|
}
|
|
268
279
|
}
|
|
269
280
|
|
|
@@ -277,27 +288,133 @@ function Invoke-CheckpointMonotonicDecision {
|
|
|
277
288
|
$missing += 'S4_atomic_planning'
|
|
278
289
|
}
|
|
279
290
|
return [ordered]@{
|
|
280
|
-
|
|
281
|
-
|
|
291
|
+
hookSpecificOutput = [ordered]@{
|
|
292
|
+
hookEventName = 'PreToolUse'
|
|
293
|
+
permissionDecision = 'deny'
|
|
294
|
+
permissionDecisionReason = "CHECKPOINT_ORDER_BLOCKED: completed_steps lists '$($missingPrerequisite.Step)' before required prerequisite step(s): $($missing -join ', '). Record promotion and planning completion before implementation, review, PR, CI, or DONE steps."
|
|
295
|
+
}
|
|
282
296
|
}
|
|
283
297
|
}
|
|
284
298
|
|
|
285
|
-
return [ordered]@{
|
|
299
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
286
300
|
}
|
|
287
301
|
|
|
288
302
|
# Guard allows dot-sourcing in tests without executing the entrypoint.
|
|
303
|
+
function ConvertFrom-CodexCheckpointHookPayload {
|
|
304
|
+
[CmdletBinding()]
|
|
305
|
+
param([Parameter(Mandatory)][string] $PayloadRaw)
|
|
306
|
+
|
|
307
|
+
if ([string]::IsNullOrWhiteSpace($PayloadRaw)) {
|
|
308
|
+
throw 'enforce-checkpoint-monotonic hook input is empty.'
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
$payload = $PayloadRaw | ConvertFrom-Json -ErrorAction Stop
|
|
312
|
+
} catch {
|
|
313
|
+
throw "enforce-checkpoint-monotonic hook input is malformed JSON: $_"
|
|
314
|
+
}
|
|
315
|
+
if ($payload.PSObject.Properties.Name -notcontains 'tool_input' -or $null -eq $payload.tool_input) {
|
|
316
|
+
throw 'enforce-checkpoint-monotonic hook input is missing tool_input.'
|
|
317
|
+
}
|
|
318
|
+
if ([string]$payload.hook_event_name -ne 'PreToolUse' -or [string]$payload.tool_name -ne 'apply_patch') {
|
|
319
|
+
throw 'enforce-checkpoint-monotonic requires a PreToolUse apply_patch payload.'
|
|
320
|
+
}
|
|
321
|
+
return $payload
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function ConvertTo-CodexApplyPatchCheckpointInput {
|
|
325
|
+
[CmdletBinding()]
|
|
326
|
+
[OutputType([object[]])]
|
|
327
|
+
param([Parameter(Mandatory)] $Payload)
|
|
328
|
+
|
|
329
|
+
if ($Payload.tool_input.PSObject.Properties.Name -contains 'file_path') {
|
|
330
|
+
return , $Payload.tool_input
|
|
331
|
+
}
|
|
332
|
+
$command = [string]$Payload.tool_input.command
|
|
333
|
+
if ([string]::IsNullOrWhiteSpace($command)) {
|
|
334
|
+
throw 'enforce-checkpoint-monotonic cannot map tool_input to a file edit.'
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
$fileMatches = [regex]::Matches(
|
|
338
|
+
$command,
|
|
339
|
+
'(?ms)^\*\*\* (?<operation>Add|Update|Delete) File:\s*(?<path>.+?)\r?\n(?<body>.*?)(?=^\*\*\* (?:(?:Add|Update|Delete) File:|End Patch)\s*|\z)'
|
|
340
|
+
)
|
|
341
|
+
if ($fileMatches.Count -eq 0) {
|
|
342
|
+
throw 'enforce-checkpoint-monotonic received an unrecognized apply_patch command.'
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
$inputs = [System.Collections.Generic.List[object]]::new()
|
|
346
|
+
foreach ($match in $fileMatches) {
|
|
347
|
+
$sourcePath = ([string]$match.Groups['path'].Value).Trim()
|
|
348
|
+
$path = $sourcePath
|
|
349
|
+
$operation = [string]$match.Groups['operation'].Value
|
|
350
|
+
$body = ([string]$match.Groups['body'].Value) -replace '\r\n', "`n"
|
|
351
|
+
$moveMatch = [regex]::Match($body, '(?m)^\*\*\* Move to:\s*(?<path>.+?)\s*$')
|
|
352
|
+
if ($moveMatch.Success) {
|
|
353
|
+
$path = ([string]$moveMatch.Groups['path'].Value).Trim()
|
|
354
|
+
}
|
|
355
|
+
if ($operation -eq 'Delete') {
|
|
356
|
+
$content = ''
|
|
357
|
+
} elseif ($operation -eq 'Add') {
|
|
358
|
+
$content = (($body -split "`n") | ForEach-Object {
|
|
359
|
+
if ($_.StartsWith('+') -and -not $_.StartsWith('+++')) {
|
|
360
|
+
$_.Substring(1)
|
|
361
|
+
}
|
|
362
|
+
}) -join "`n"
|
|
363
|
+
} else {
|
|
364
|
+
if (-not (Test-Path -LiteralPath $sourcePath -PathType Leaf)) {
|
|
365
|
+
throw "enforce-checkpoint-monotonic cannot read update source '$sourcePath'."
|
|
366
|
+
}
|
|
367
|
+
$content = (Get-Content -Raw -LiteralPath $sourcePath) -replace '\r\n', "`n"
|
|
368
|
+
$hunks = @([regex]::Split($body, '(?m)^@@[^\r\n]*\r?\n') | Where-Object { $_ -match '\S' })
|
|
369
|
+
foreach ($hunk in $hunks) {
|
|
370
|
+
$oldLines = [System.Collections.Generic.List[string]]::new()
|
|
371
|
+
$newLines = [System.Collections.Generic.List[string]]::new()
|
|
372
|
+
foreach ($line in ($hunk -split "`n")) {
|
|
373
|
+
if ($line -match '^\*\*\* (?:Move to|End of File)') {
|
|
374
|
+
continue
|
|
375
|
+
}
|
|
376
|
+
if ($line.StartsWith('+') -and -not $line.StartsWith('+++')) {
|
|
377
|
+
$newLines.Add($line.Substring(1))
|
|
378
|
+
} elseif ($line.StartsWith('-') -and -not $line.StartsWith('---')) {
|
|
379
|
+
$oldLines.Add($line.Substring(1))
|
|
380
|
+
} elseif ($line.StartsWith(' ')) {
|
|
381
|
+
$oldLines.Add($line.Substring(1))
|
|
382
|
+
$newLines.Add($line.Substring(1))
|
|
383
|
+
} else {
|
|
384
|
+
$oldLines.Add($line)
|
|
385
|
+
$newLines.Add($line)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
$oldText = $oldLines -join "`n"
|
|
389
|
+
$newText = $newLines -join "`n"
|
|
390
|
+
$index = $content.IndexOf($oldText, [System.StringComparison]::Ordinal)
|
|
391
|
+
if ($index -lt 0) {
|
|
392
|
+
throw "enforce-checkpoint-monotonic could not apply an in-memory patch hunk for '$path'."
|
|
393
|
+
}
|
|
394
|
+
$content = $content.Substring(0, $index) + $newText + $content.Substring($index + $oldText.Length)
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
$inputs.Add([pscustomobject]@{ file_path = $path; content = $content })
|
|
398
|
+
}
|
|
399
|
+
return $inputs.ToArray()
|
|
400
|
+
}
|
|
401
|
+
|
|
289
402
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
290
403
|
return
|
|
291
404
|
}
|
|
292
405
|
|
|
293
406
|
try {
|
|
294
|
-
$
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
407
|
+
$payload = ConvertFrom-CodexCheckpointHookPayload -PayloadRaw ([Console]::In.ReadToEnd())
|
|
408
|
+
foreach ($toolInput in @(ConvertTo-CodexApplyPatchCheckpointInput -Payload $payload)) {
|
|
409
|
+
$toolInputRaw = $toolInput | ConvertTo-Json -Compress -Depth 20
|
|
410
|
+
$decision = Invoke-CheckpointMonotonicDecision -ToolInputRaw $toolInputRaw
|
|
411
|
+
if ($decision.hookSpecificOutput.permissionDecision -eq 'deny') {
|
|
412
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
413
|
+
exit 0
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
exit 0
|
|
417
|
+
} catch {
|
|
418
|
+
[Console]::Error.WriteLine([string]$_)
|
|
419
|
+
exit 2
|
|
299
420
|
}
|
|
300
|
-
|
|
301
|
-
$decision | ConvertTo-Json -Compress | Write-Output
|
|
302
|
-
|
|
303
|
-
exit 0
|