@danmoisan/drm-copilot-mcp 1.0.13 → 1.0.15
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 +24 -0
- package/resources/claude-customizations/.claude/agents/epic-planner.md +121 -0
- package/resources/claude-customizations/.claude/agents/orchestrator.md +2 -2
- package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +246 -0
- package/resources/claude-customizations/.claude/settings.json +9 -2
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +7 -0
- package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +189 -0
- package/resources/claude-customizations/.claude/skills/epic-run/SKILL.md +38 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +21 -2
- package/resources/claude-customizations/pack-manifests/core.json +4 -0
- 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 +167 -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
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
|
|
1
2
|
<#
|
|
2
3
|
.SYNOPSIS
|
|
3
|
-
Blocks implementation
|
|
4
|
+
Blocks implementation operations before orchestration readiness exists.
|
|
4
5
|
#>
|
|
5
6
|
[CmdletBinding()]
|
|
6
7
|
param()
|
|
7
8
|
|
|
8
9
|
$script:CheckpointPath = 'artifacts/orchestration/orchestrator-state.json'
|
|
9
|
-
$script:Issue232FeatureFolder = 'docs/features/active/2026-06-24-harden-orchestrate-skill-232'
|
|
10
10
|
|
|
11
11
|
function ConvertFrom-CheckpointJson {
|
|
12
12
|
[CmdletBinding()]
|
|
@@ -29,12 +29,12 @@ function Get-StringProperty {
|
|
|
29
29
|
return ([string]$Value.$Name).Trim()
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function Test-
|
|
32
|
+
function Test-FeatureDocumentationOrEvidencePath {
|
|
33
33
|
[CmdletBinding()]
|
|
34
34
|
[OutputType([bool])]
|
|
35
35
|
param([Parameter(Mandatory)][string] $NormalizedPath)
|
|
36
36
|
|
|
37
|
-
return $NormalizedPath.StartsWith(
|
|
37
|
+
return $NormalizedPath.StartsWith('docs/features/active/')
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function Test-ImplementationPath {
|
|
@@ -42,7 +42,7 @@ function Test-ImplementationPath {
|
|
|
42
42
|
[OutputType([bool])]
|
|
43
43
|
param([Parameter(Mandatory)][string] $NormalizedPath)
|
|
44
44
|
|
|
45
|
-
if (Test-
|
|
45
|
+
if (Test-FeatureDocumentationOrEvidencePath -NormalizedPath $NormalizedPath) {
|
|
46
46
|
return $false
|
|
47
47
|
}
|
|
48
48
|
if ($NormalizedPath -eq $script:CheckpointPath) {
|
|
@@ -51,7 +51,59 @@ function Test-ImplementationPath {
|
|
|
51
51
|
return $NormalizedPath -match '\.(py|ps1|psm1|ts|tsx|js|jsx|cs|json|yml|yaml)$'
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
function Test-
|
|
54
|
+
function Test-ImplementationCommand {
|
|
55
|
+
[CmdletBinding()]
|
|
56
|
+
[OutputType([bool])]
|
|
57
|
+
param([Parameter(Mandatory)][string] $Command)
|
|
58
|
+
|
|
59
|
+
$normalizedCommand = $Command.Trim()
|
|
60
|
+
if (-not $normalizedCommand) {
|
|
61
|
+
return $false
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
foreach ($match in [regex]::Matches($normalizedCommand, '(?m)^\*\*\* (?:Add|Update|Delete) File:\s*(?<path>.+?)\s*$')) {
|
|
65
|
+
$path = (([string]$match.Groups['path'].Value).Trim()) -replace '\\', '/'
|
|
66
|
+
if (Test-ImplementationPath -NormalizedPath $path) {
|
|
67
|
+
return $true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
foreach ($match in [regex]::Matches($normalizedCommand, '(?m)^\*\*\* Move to:\s*(?<path>.+?)\s*$')) {
|
|
71
|
+
$path = (([string]$match.Groups['path'].Value).Trim()) -replace '\\', '/'
|
|
72
|
+
if (Test-ImplementationPath -NormalizedPath $path) {
|
|
73
|
+
return $true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
$implementationCommandPatterns = @(
|
|
78
|
+
'(^|\s)git\s+(add|commit)\b',
|
|
79
|
+
'(^|\s)(poetry\s+run\s+)?(black|ruff|pyright|pytest)\b',
|
|
80
|
+
'(^|\s)npm\s+.*\s+(prettier|lint|typecheck|test:unit)\b',
|
|
81
|
+
'(^|\s)npx\s+(prettier|eslint|tsc|jest)\b',
|
|
82
|
+
'(^|\s)pwsh\s+.*(Invoke-Pester|tests/scripts/)'
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
foreach ($pattern in $implementationCommandPatterns) {
|
|
86
|
+
if ($normalizedCommand -match $pattern) {
|
|
87
|
+
return $true
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return $false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function Test-ImplementationDelegation {
|
|
94
|
+
[CmdletBinding()]
|
|
95
|
+
[OutputType([bool])]
|
|
96
|
+
param([Parameter(Mandatory)][AllowNull()] $ToolInput)
|
|
97
|
+
|
|
98
|
+
if ($null -eq $ToolInput) {
|
|
99
|
+
return $false
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
$payloadText = ($ToolInput | ConvertTo-Json -Depth 20 -Compress)
|
|
103
|
+
return $payloadText -match '(python-typed-engineer|powershell-typed-engineer|typescript-engineer|csharp-typed-engineer|atomic-executor|implementation|execute)'
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function Test-OrchestrationReady {
|
|
55
107
|
[CmdletBinding()]
|
|
56
108
|
[OutputType([bool])]
|
|
57
109
|
param([Parameter(Mandatory)][AllowNull()] $Payload)
|
|
@@ -70,9 +122,12 @@ function Test-Issue232OrchestrationReady {
|
|
|
70
122
|
$lifecycleReady = [bool]$Payload.lifecycle_ready
|
|
71
123
|
}
|
|
72
124
|
|
|
125
|
+
if (-not $issueNum -or -not $featureFolder -or -not $routeId -or -not $lifecycleReady) {
|
|
126
|
+
return $false
|
|
127
|
+
}
|
|
128
|
+
|
|
73
129
|
return (
|
|
74
|
-
$
|
|
75
|
-
$featureFolder -eq $script:Issue232FeatureFolder -and
|
|
130
|
+
$featureFolder.StartsWith('docs/features/active/') -and
|
|
76
131
|
$routeId -and
|
|
77
132
|
$lifecycleReady
|
|
78
133
|
)
|
|
@@ -89,6 +144,36 @@ function Get-CheckpointContent {
|
|
|
89
144
|
return Get-Content -Raw -LiteralPath $script:CheckpointPath
|
|
90
145
|
}
|
|
91
146
|
|
|
147
|
+
function Get-OrchestrationPreimplementationGateAllowDecision {
|
|
148
|
+
[CmdletBinding()]
|
|
149
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
150
|
+
param()
|
|
151
|
+
|
|
152
|
+
return [ordered]@{
|
|
153
|
+
hookSpecificOutput = [ordered]@{
|
|
154
|
+
hookEventName = 'PreToolUse'
|
|
155
|
+
permissionDecision = 'allow'
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function Get-OrchestrationPreimplementationGateBlockDecision {
|
|
161
|
+
[CmdletBinding()]
|
|
162
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
163
|
+
param(
|
|
164
|
+
[Parameter(Mandatory)]
|
|
165
|
+
[string] $Reason
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return [ordered]@{
|
|
169
|
+
hookSpecificOutput = [ordered]@{
|
|
170
|
+
hookEventName = 'PreToolUse'
|
|
171
|
+
permissionDecision = 'deny'
|
|
172
|
+
permissionDecisionReason = $Reason
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
92
177
|
function Invoke-OrchestrationPreimplementationGateDecision {
|
|
93
178
|
[CmdletBinding()]
|
|
94
179
|
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
@@ -98,21 +183,30 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
98
183
|
)
|
|
99
184
|
|
|
100
185
|
if (-not $ToolInputRaw) {
|
|
101
|
-
return
|
|
186
|
+
return Get-OrchestrationPreimplementationGateAllowDecision
|
|
102
187
|
}
|
|
103
188
|
try {
|
|
104
189
|
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
105
190
|
} catch {
|
|
106
|
-
throw "enforce-orchestration-preimplementation-gate
|
|
191
|
+
throw "enforce-orchestration-preimplementation-gate received malformed mapped tool_input JSON: $_"
|
|
107
192
|
}
|
|
108
193
|
|
|
109
|
-
$
|
|
110
|
-
|
|
111
|
-
|
|
194
|
+
$requiresReadyCheckpoint = $false
|
|
195
|
+
$filePath = Get-StringProperty -Value $toolInput -Name 'file_path'
|
|
196
|
+
if ($filePath) {
|
|
197
|
+
$normalized = ([string]$filePath) -replace '\\', '/'
|
|
198
|
+
$requiresReadyCheckpoint = Test-ImplementationPath -NormalizedPath $normalized
|
|
199
|
+
} else {
|
|
200
|
+
$command = Get-StringProperty -Value $toolInput -Name 'command'
|
|
201
|
+
if ($command) {
|
|
202
|
+
$requiresReadyCheckpoint = Test-ImplementationCommand -Command $command
|
|
203
|
+
} else {
|
|
204
|
+
$requiresReadyCheckpoint = Test-ImplementationDelegation -ToolInput $toolInput
|
|
205
|
+
}
|
|
112
206
|
}
|
|
113
|
-
|
|
114
|
-
if (-not
|
|
115
|
-
return
|
|
207
|
+
|
|
208
|
+
if (-not $requiresReadyCheckpoint) {
|
|
209
|
+
return Get-OrchestrationPreimplementationGateAllowDecision
|
|
116
210
|
}
|
|
117
211
|
|
|
118
212
|
if (-not $CheckpointRaw) {
|
|
@@ -124,13 +218,32 @@ function Invoke-OrchestrationPreimplementationGateDecision {
|
|
|
124
218
|
$checkpoint = $null
|
|
125
219
|
}
|
|
126
220
|
|
|
127
|
-
if (Test-
|
|
128
|
-
return
|
|
221
|
+
if (Test-OrchestrationReady -Payload $checkpoint) {
|
|
222
|
+
return Get-OrchestrationPreimplementationGateAllowDecision
|
|
129
223
|
}
|
|
130
|
-
return
|
|
131
|
-
|
|
132
|
-
|
|
224
|
+
return Get-OrchestrationPreimplementationGateBlockDecision -Reason 'PREIMPLEMENTATION_GATE_BLOCKED: Implementation operations require artifacts/orchestration/orchestrator-state.json to contain issue number, feature folder, route metadata, lifecycle readiness, and checkpoint state before implementation begins.'
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function ConvertFrom-CodexPreimplementationHookPayload {
|
|
228
|
+
[CmdletBinding()]
|
|
229
|
+
param([Parameter(Mandatory)][string] $PayloadRaw)
|
|
230
|
+
|
|
231
|
+
if ([string]::IsNullOrWhiteSpace($PayloadRaw)) {
|
|
232
|
+
throw 'enforce-orchestration-preimplementation-gate hook input is empty.'
|
|
133
233
|
}
|
|
234
|
+
try {
|
|
235
|
+
$payload = $PayloadRaw | ConvertFrom-Json -ErrorAction Stop
|
|
236
|
+
} catch {
|
|
237
|
+
throw "enforce-orchestration-preimplementation-gate hook input is malformed JSON: $_"
|
|
238
|
+
}
|
|
239
|
+
if ($payload.PSObject.Properties.Name -notcontains 'tool_input' -or $null -eq $payload.tool_input) {
|
|
240
|
+
throw 'enforce-orchestration-preimplementation-gate hook input is missing tool_input.'
|
|
241
|
+
}
|
|
242
|
+
if ([string]$payload.hook_event_name -ne 'PreToolUse' -or
|
|
243
|
+
@('Bash', 'apply_patch') -notcontains [string]$payload.tool_name) {
|
|
244
|
+
throw 'enforce-orchestration-preimplementation-gate requires a supported PreToolUse payload.'
|
|
245
|
+
}
|
|
246
|
+
return $payload
|
|
134
247
|
}
|
|
135
248
|
|
|
136
249
|
if ($MyInvocation.InvocationName -eq '.') {
|
|
@@ -138,11 +251,14 @@ if ($MyInvocation.InvocationName -eq '.') {
|
|
|
138
251
|
}
|
|
139
252
|
|
|
140
253
|
try {
|
|
141
|
-
$
|
|
254
|
+
$payload = ConvertFrom-CodexPreimplementationHookPayload -PayloadRaw ([Console]::In.ReadToEnd())
|
|
255
|
+
$toolInputRaw = $payload.tool_input | ConvertTo-Json -Compress -Depth 20
|
|
256
|
+
$decision = Invoke-OrchestrationPreimplementationGateDecision -ToolInputRaw $toolInputRaw
|
|
257
|
+
if ($decision.hookSpecificOutput.permissionDecision -eq 'deny') {
|
|
258
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
259
|
+
}
|
|
260
|
+
exit 0
|
|
142
261
|
} catch {
|
|
143
|
-
|
|
144
|
-
exit
|
|
262
|
+
[Console]::Error.WriteLine([string]$_)
|
|
263
|
+
exit 2
|
|
145
264
|
}
|
|
146
|
-
|
|
147
|
-
$decision | ConvertTo-Json -Compress | Write-Output
|
|
148
|
-
exit 0
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
# Converted hook
|
|
2
|
-
# Review the generated hook behavior before enabling it.
|
|
3
1
|
|
|
4
2
|
<#
|
|
5
3
|
.SYNOPSIS
|
|
6
4
|
Pre-tool-use hook that enforces the PowerShell per-batch change budget.
|
|
7
5
|
|
|
8
6
|
.DESCRIPTION
|
|
9
|
-
This script is invoked by the
|
|
7
|
+
This script is invoked by the Codex PreToolUse hook before any Write or Edit
|
|
10
8
|
operation. When the target file is a PowerShell source file (.ps1, .psm1, .psd1),
|
|
11
9
|
it classifies the file as either production or test and checks the running count
|
|
12
10
|
against the per-batch cap:
|
|
13
11
|
- 3 production PowerShell files per batch
|
|
14
12
|
- 3 test PowerShell files per batch
|
|
15
13
|
|
|
16
|
-
A "batch" is scoped to the current
|
|
17
|
-
persisted under .
|
|
14
|
+
A "batch" is scoped to the current Codex session. The running count is
|
|
15
|
+
persisted under .codex/state/powershell-batch-budget.<session_id>.json. Only
|
|
18
16
|
distinct file paths are counted; repeated edits to the same file consume one slot.
|
|
19
17
|
|
|
20
18
|
Test files are those matching:
|
|
@@ -24,15 +22,13 @@
|
|
|
24
22
|
All other .ps1/.psm1/.psd1 files are treated as production files. Non-PowerShell
|
|
25
23
|
paths pass through.
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
before the session starts, or by writing {"prodCap": N, "testCap": M} into the
|
|
30
|
-
state file.
|
|
25
|
+
An approved per-session override is recorded by writing
|
|
26
|
+
{"prodCap": N, "testCap": M} into the Codex state file.
|
|
31
27
|
|
|
32
|
-
When the cap would be exceeded by a new file, the script emits a JSON
|
|
33
|
-
|
|
34
|
-
deleting the state file before starting a new
|
|
35
|
-
always allowed through.
|
|
28
|
+
When the cap would be exceeded by a new file, the script emits a PreToolUse JSON
|
|
29
|
+
response with hookSpecificOutput.permissionDecision = 'deny' and exits 0. The session
|
|
30
|
+
must explicitly reset the counter by deleting the state file before starting a new
|
|
31
|
+
batch. Files already counted are always allowed through.
|
|
36
32
|
|
|
37
33
|
.NOTES
|
|
38
34
|
Compatible with PowerShell 7+.
|
|
@@ -93,8 +89,11 @@ function Get-PowerShellBatchBudgetBlockDecision {
|
|
|
93
89
|
)
|
|
94
90
|
|
|
95
91
|
$decision = [ordered]@{
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
hookSpecificOutput = [ordered]@{
|
|
93
|
+
hookEventName = 'PreToolUse'
|
|
94
|
+
permissionDecision = 'deny'
|
|
95
|
+
permissionDecisionReason = $Reason
|
|
96
|
+
}
|
|
98
97
|
}
|
|
99
98
|
if ($State) {
|
|
100
99
|
$decision.state = $State
|
|
@@ -119,7 +118,7 @@ function Invoke-PowerShellBatchBudgetDecision {
|
|
|
119
118
|
|
|
120
119
|
$normalized = $FilePath -replace '\\', '/'
|
|
121
120
|
if ($normalized -notmatch '\.(ps1|psm1|psd1)$') {
|
|
122
|
-
return [ordered]@{
|
|
121
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $false }
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
$isTestFile = ($normalized -match '(^|/)tests/.*\.ps1$') -or ($normalized -match '\.Tests\.ps1$')
|
|
@@ -128,13 +127,12 @@ function Invoke-PowerShellBatchBudgetDecision {
|
|
|
128
127
|
$kind = if ($isTestFile) { 'test' } else { 'production' }
|
|
129
128
|
|
|
130
129
|
if ($targetList -contains $normalized) {
|
|
131
|
-
return [ordered]@{
|
|
130
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $false }
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
if ($targetList.Count -ge $cap) {
|
|
135
134
|
$currentFiles = ($targetList -join ', ')
|
|
136
|
-
$
|
|
137
|
-
$reason = "PowerShell per-batch budget exceeded: $kind file cap is $cap and is already full ($currentFiles). Requested new file: $normalized. Split the work into a new batch, raise the cap via CLAUDE_POWERSHELL_BUDGET_$kindUpper environment variable with approved scope, or reset the batch by deleting $StateFile."
|
|
135
|
+
$reason = "PowerShell per-batch budget exceeded: $kind file cap is $cap and is already full ($currentFiles). Requested new file: $normalized. Split the work into a new batch, record an approved cap in $StateFile, or reset the batch by deleting that state file."
|
|
138
136
|
return Get-PowerShellBatchBudgetBlockDecision -Reason $reason -State $State
|
|
139
137
|
}
|
|
140
138
|
|
|
@@ -144,7 +142,7 @@ function Invoke-PowerShellBatchBudgetDecision {
|
|
|
144
142
|
$State.prodFiles = @($State.prodFiles) + @($normalized)
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
return [ordered]@{
|
|
145
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' }; state = $State; shouldWriteState = $true }
|
|
148
146
|
}
|
|
149
147
|
|
|
150
148
|
function Invoke-PowerShellBatchBudgetHook {
|
|
@@ -166,26 +164,26 @@ function Invoke-PowerShellBatchBudgetHook {
|
|
|
166
164
|
)
|
|
167
165
|
|
|
168
166
|
if (-not $ToolInputRaw) {
|
|
169
|
-
return [ordered]@{
|
|
167
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
170
168
|
}
|
|
171
169
|
|
|
172
170
|
try {
|
|
173
171
|
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
174
172
|
} catch {
|
|
175
|
-
return Get-PowerShellBatchBudgetBlockDecision -Reason 'PowerShell batch-budget hook received malformed JSON in
|
|
173
|
+
return Get-PowerShellBatchBudgetBlockDecision -Reason 'PowerShell batch-budget hook received malformed JSON in Codex tool_input.'
|
|
176
174
|
}
|
|
177
175
|
|
|
178
176
|
$filePath = $toolInput.file_path
|
|
179
177
|
if (-not $filePath) {
|
|
180
|
-
return [ordered]@{
|
|
178
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
181
179
|
}
|
|
182
180
|
|
|
183
181
|
$normalized = $filePath -replace '\\', '/'
|
|
184
182
|
if ($normalized -notmatch '\.(ps1|psm1|psd1)$') {
|
|
185
|
-
return [ordered]@{
|
|
183
|
+
return [ordered]@{ hookSpecificOutput = [ordered]@{ hookEventName = 'PreToolUse'; permissionDecision = 'allow' } }
|
|
186
184
|
}
|
|
187
185
|
|
|
188
|
-
$stateDir = Join-Path -Path $Root -ChildPath '.
|
|
186
|
+
$stateDir = Join-Path -Path $Root -ChildPath '.codex/state'
|
|
189
187
|
if (-not (& $TestPathExists $stateDir)) {
|
|
190
188
|
& $EnsureDirectory $stateDir
|
|
191
189
|
}
|
|
@@ -214,28 +212,75 @@ function Invoke-PowerShellBatchBudgetHook {
|
|
|
214
212
|
return $decision
|
|
215
213
|
}
|
|
216
214
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
215
|
+
function ConvertFrom-CodexPowerShellBudgetPayload {
|
|
216
|
+
[CmdletBinding()]
|
|
217
|
+
param([Parameter(Mandatory)][string] $PayloadRaw)
|
|
220
218
|
|
|
221
|
-
$
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
if ([string]::IsNullOrWhiteSpace($PayloadRaw)) {
|
|
220
|
+
throw 'enforce-powershell-batch-budget hook input is empty.'
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
$payload = $PayloadRaw | ConvertFrom-Json -ErrorAction Stop
|
|
224
|
+
} catch {
|
|
225
|
+
throw "enforce-powershell-batch-budget hook input is malformed JSON: $_"
|
|
226
|
+
}
|
|
227
|
+
if ($payload.PSObject.Properties.Name -notcontains 'tool_input' -or $null -eq $payload.tool_input) {
|
|
228
|
+
throw 'enforce-powershell-batch-budget hook input is missing tool_input.'
|
|
229
|
+
}
|
|
230
|
+
if ([string]$payload.hook_event_name -ne 'PreToolUse' -or [string]$payload.tool_name -ne 'apply_patch') {
|
|
231
|
+
throw 'enforce-powershell-batch-budget requires a PreToolUse apply_patch payload.'
|
|
232
|
+
}
|
|
233
|
+
if ([string]::IsNullOrWhiteSpace([string]$payload.session_id)) {
|
|
234
|
+
throw 'enforce-powershell-batch-budget hook input is missing session_id.'
|
|
235
|
+
}
|
|
236
|
+
return $payload
|
|
224
237
|
}
|
|
225
238
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if ($
|
|
232
|
-
|
|
239
|
+
function Get-CodexPowerShellBudgetPath {
|
|
240
|
+
[CmdletBinding()]
|
|
241
|
+
[OutputType([string])]
|
|
242
|
+
param([Parameter(Mandatory)] $Payload)
|
|
243
|
+
|
|
244
|
+
if ($Payload.tool_input.PSObject.Properties.Name -contains 'file_path') {
|
|
245
|
+
return [string]$Payload.tool_input.file_path
|
|
246
|
+
}
|
|
247
|
+
$command = [string]$Payload.tool_input.command
|
|
248
|
+
if ([string]::IsNullOrWhiteSpace($command)) {
|
|
249
|
+
throw 'enforce-powershell-batch-budget cannot map tool_input to a file edit.'
|
|
250
|
+
}
|
|
251
|
+
[string[]] $paths = @(
|
|
252
|
+
[regex]::Matches($command, '(?m)^\*\*\* (?:(?:Add|Update|Delete) File|Move to):\s*(?<path>.+?)\s*$') |
|
|
253
|
+
ForEach-Object { ([string]$_.Groups['path'].Value).Trim() }
|
|
254
|
+
)
|
|
255
|
+
$paths = @($paths | Select-Object -Unique)
|
|
256
|
+
if ($paths.Count -eq 0) {
|
|
257
|
+
throw 'enforce-powershell-batch-budget received an unrecognized apply_patch command.'
|
|
258
|
+
}
|
|
259
|
+
return $paths
|
|
233
260
|
}
|
|
234
261
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
$decision.Remove('state')
|
|
238
|
-
$decision | ConvertTo-Json -Compress | Write-Output
|
|
262
|
+
if ($MyInvocation.InvocationName -eq '.') {
|
|
263
|
+
return
|
|
239
264
|
}
|
|
240
265
|
|
|
241
|
-
|
|
266
|
+
try {
|
|
267
|
+
$payload = ConvertFrom-CodexPowerShellBudgetPayload -PayloadRaw ([Console]::In.ReadToEnd())
|
|
268
|
+
$sessionId = ([string]$payload.session_id) -replace '[^A-Za-z0-9._-]', '_'
|
|
269
|
+
$repositoryRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
|
|
270
|
+
$prodCap = 3
|
|
271
|
+
$testCap = 3
|
|
272
|
+
|
|
273
|
+
foreach ($path in @(Get-CodexPowerShellBudgetPath -Payload $payload)) {
|
|
274
|
+
$toolInputRaw = @{ file_path = $path } | ConvertTo-Json -Compress
|
|
275
|
+
$decision = Invoke-PowerShellBatchBudgetHook -ToolInputRaw $toolInputRaw -SessionId $sessionId -Root $repositoryRoot -ProdCap $prodCap -TestCap $testCap
|
|
276
|
+
if ($decision.hookSpecificOutput.permissionDecision -eq 'deny') {
|
|
277
|
+
$decision.Remove('state')
|
|
278
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
279
|
+
exit 0
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
exit 0
|
|
283
|
+
} catch {
|
|
284
|
+
[Console]::Error.WriteLine([string]$_)
|
|
285
|
+
exit 2
|
|
286
|
+
}
|
package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
|
|
1
2
|
<#
|
|
2
3
|
.SYNOPSIS
|
|
3
4
|
Pre-tool-use hook that blocks Bash promotion-script bypass attempts.
|
|
4
5
|
|
|
5
6
|
.DESCRIPTION
|
|
6
|
-
This script is invoked by the
|
|
7
|
-
|
|
8
|
-
variable, inspects the attempted command text, and blocks direct promotion
|
|
7
|
+
This script is invoked by the Codex PreToolUse hook before a shell command runs.
|
|
8
|
+
It reads one Codex JSON object from stdin, inspects tool_input.command, and blocks direct promotion
|
|
9
9
|
script execution that would bypass the repository's MCP-only promotion path.
|
|
10
10
|
|
|
11
11
|
Forbidden command tokens (legacy promotion-script bypass):
|
|
@@ -70,7 +70,7 @@ function Get-PromotionBypassReason {
|
|
|
70
70
|
Returns the gh-CLI issue creation reason when a forbidden gh pattern is matched.
|
|
71
71
|
Returns $null when the command is allowed.
|
|
72
72
|
.PARAMETER CommandText
|
|
73
|
-
The
|
|
73
|
+
The shell command text extracted from the Codex tool_input object.
|
|
74
74
|
.OUTPUTS
|
|
75
75
|
System.String or $null.
|
|
76
76
|
#>
|
|
@@ -118,7 +118,7 @@ function Test-PromotionBypassToken {
|
|
|
118
118
|
.SYNOPSIS
|
|
119
119
|
Return $true when a Bash command contains a forbidden promotion bypass pattern.
|
|
120
120
|
.PARAMETER CommandText
|
|
121
|
-
The
|
|
121
|
+
The shell command text extracted from the Codex tool_input object.
|
|
122
122
|
.OUTPUTS
|
|
123
123
|
System.Boolean
|
|
124
124
|
#>
|
|
@@ -153,17 +153,39 @@ function Get-PromotionMcpOnlyBlockDecision {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
return [ordered]@{
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
hookSpecificOutput = [ordered]@{
|
|
157
|
+
hookEventName = 'PreToolUse'
|
|
158
|
+
permissionDecision = 'deny'
|
|
159
|
+
permissionDecisionReason = $Reason
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function Get-PromotionMcpOnlyAllowDecision {
|
|
165
|
+
<#
|
|
166
|
+
.SYNOPSIS
|
|
167
|
+
Construct the structured allow decision for a permitted Bash command.
|
|
168
|
+
.OUTPUTS
|
|
169
|
+
System.Collections.Specialized.OrderedDictionary
|
|
170
|
+
#>
|
|
171
|
+
[CmdletBinding()]
|
|
172
|
+
[OutputType([System.Collections.Specialized.OrderedDictionary])]
|
|
173
|
+
param()
|
|
174
|
+
|
|
175
|
+
return [ordered]@{
|
|
176
|
+
hookSpecificOutput = [ordered]@{
|
|
177
|
+
hookEventName = 'PreToolUse'
|
|
178
|
+
permissionDecision = 'allow'
|
|
179
|
+
}
|
|
158
180
|
}
|
|
159
181
|
}
|
|
160
182
|
|
|
161
183
|
function Invoke-PromotionMcpOnlyDecision {
|
|
162
184
|
<#
|
|
163
185
|
.SYNOPSIS
|
|
164
|
-
Parse
|
|
186
|
+
Parse the mapped Codex tool_input JSON and return an allow-or-deny decision.
|
|
165
187
|
.PARAMETER ToolInputRaw
|
|
166
|
-
The
|
|
188
|
+
The mapped tool_input JSON supplied by Codex.
|
|
167
189
|
.OUTPUTS
|
|
168
190
|
System.Collections.Specialized.OrderedDictionary
|
|
169
191
|
.NOTES
|
|
@@ -177,18 +199,18 @@ function Invoke-PromotionMcpOnlyDecision {
|
|
|
177
199
|
)
|
|
178
200
|
|
|
179
201
|
if (-not $ToolInputRaw) {
|
|
180
|
-
return
|
|
202
|
+
return Get-PromotionMcpOnlyAllowDecision
|
|
181
203
|
}
|
|
182
204
|
|
|
183
205
|
try {
|
|
184
206
|
$toolInput = $ToolInputRaw | ConvertFrom-Json -ErrorAction Stop
|
|
185
207
|
} catch {
|
|
186
|
-
throw "enforce-promotion-mcp-only
|
|
208
|
+
throw "enforce-promotion-mcp-only received malformed mapped tool_input JSON: $_"
|
|
187
209
|
}
|
|
188
210
|
|
|
189
211
|
$commandText = $toolInput.command
|
|
190
212
|
if (-not $commandText) {
|
|
191
|
-
return
|
|
213
|
+
return Get-PromotionMcpOnlyAllowDecision
|
|
192
214
|
}
|
|
193
215
|
|
|
194
216
|
$reason = Get-PromotionBypassReason -CommandText $commandText
|
|
@@ -196,7 +218,28 @@ function Invoke-PromotionMcpOnlyDecision {
|
|
|
196
218
|
return Get-PromotionMcpOnlyBlockDecision -Reason $reason
|
|
197
219
|
}
|
|
198
220
|
|
|
199
|
-
return
|
|
221
|
+
return Get-PromotionMcpOnlyAllowDecision
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function ConvertFrom-CodexPromotionHookPayload {
|
|
225
|
+
[CmdletBinding()]
|
|
226
|
+
param([Parameter(Mandatory)][string] $PayloadRaw)
|
|
227
|
+
|
|
228
|
+
if ([string]::IsNullOrWhiteSpace($PayloadRaw)) {
|
|
229
|
+
throw 'enforce-promotion-mcp-only hook input is empty.'
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
$payload = $PayloadRaw | ConvertFrom-Json -ErrorAction Stop
|
|
233
|
+
} catch {
|
|
234
|
+
throw "enforce-promotion-mcp-only hook input is malformed JSON: $_"
|
|
235
|
+
}
|
|
236
|
+
if ($payload.PSObject.Properties.Name -notcontains 'tool_input' -or $null -eq $payload.tool_input) {
|
|
237
|
+
throw 'enforce-promotion-mcp-only hook input is missing tool_input.'
|
|
238
|
+
}
|
|
239
|
+
if ([string]$payload.hook_event_name -ne 'PreToolUse' -or [string]$payload.tool_name -ne 'Bash') {
|
|
240
|
+
throw 'enforce-promotion-mcp-only requires a PreToolUse Bash payload.'
|
|
241
|
+
}
|
|
242
|
+
return $payload
|
|
200
243
|
}
|
|
201
244
|
|
|
202
245
|
# Allow dot-sourcing in tests without executing the entrypoint.
|
|
@@ -205,12 +248,14 @@ if ($MyInvocation.InvocationName -eq '.') {
|
|
|
205
248
|
}
|
|
206
249
|
|
|
207
250
|
try {
|
|
208
|
-
$
|
|
251
|
+
$payload = ConvertFrom-CodexPromotionHookPayload -PayloadRaw ([Console]::In.ReadToEnd())
|
|
252
|
+
$toolInputRaw = $payload.tool_input | ConvertTo-Json -Compress -Depth 20
|
|
253
|
+
$decision = Invoke-PromotionMcpOnlyDecision -ToolInputRaw $toolInputRaw
|
|
254
|
+
if ($decision.hookSpecificOutput.permissionDecision -eq 'deny') {
|
|
255
|
+
$decision | ConvertTo-Json -Compress -Depth 5 | Write-Output
|
|
256
|
+
}
|
|
257
|
+
exit 0
|
|
209
258
|
} catch {
|
|
210
|
-
|
|
211
|
-
exit
|
|
259
|
+
[Console]::Error.WriteLine([string]$_)
|
|
260
|
+
exit 2
|
|
212
261
|
}
|
|
213
|
-
|
|
214
|
-
$decision | ConvertTo-Json -Compress | Write-Output
|
|
215
|
-
|
|
216
|
-
exit 0
|