diff --git a/CHANGELOG.md b/CHANGELOG.md index adcc97a..3ae6812 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 non-existent `~/.claude/hooks/ck/` directory after the `ck` -> `specwright` rename. - `/sd:setup` Phase 7 (and Phase 1.5) now verify every hook `command` path in `.claude/settings.json` resolves to a file on disk, warning loudly when a hook is not firing. +- `hooks/powershell/subagent-retro.ps1`, `prompt-router.ps1`, and `spec-gate.ps1` no longer assign + parsed hook JSON to `$input` - PowerShell's reserved automatic pipeline variable. Assigning to it + threw a non-terminating `ParameterBindingException` on every real (piped/redirected) stdin + invocation, leaving it unbound and causing every PowerShell hook to exit silently before reading + any input. Renamed to `$hookInput` in all three files. --- diff --git a/hooks/powershell/prompt-router.ps1 b/hooks/powershell/prompt-router.ps1 index 8103e80..de3bf48 100644 --- a/hooks/powershell/prompt-router.ps1 +++ b/hooks/powershell/prompt-router.ps1 @@ -173,11 +173,11 @@ function Get-InProgressSpecs { # ---- main ---- -$input = Read-StdinJson -if ($null -eq $input) { exit 0 } +$hookInput = Read-StdinJson +if ($null -eq $hookInput) { exit 0 } -$prompt = $input.prompt -$cwd = $input.cwd +$prompt = $hookInput.prompt +$cwd = $hookInput.cwd if ([string]::IsNullOrWhiteSpace($prompt) -or [string]::IsNullOrWhiteSpace($cwd)) { exit 0 } if (-not (Test-Path -LiteralPath $cwd)) { exit 0 } diff --git a/hooks/powershell/spec-gate.ps1 b/hooks/powershell/spec-gate.ps1 index 3ba4e72..97fcd41 100644 --- a/hooks/powershell/spec-gate.ps1 +++ b/hooks/powershell/spec-gate.ps1 @@ -166,13 +166,13 @@ function Write-BlockDecision { # ---- main ---- -$input = Read-StdinJson -if ($null -eq $input) { exit 0 } +$hookInput = Read-StdinJson +if ($null -eq $hookInput) { exit 0 } -$toolName = $input.tool_name +$toolName = $hookInput.tool_name if ($toolName -ne 'Edit' -and $toolName -ne 'Write' -and $toolName -ne 'MultiEdit') { exit 0 } -$cwd = $input.cwd +$cwd = $hookInput.cwd if ([string]::IsNullOrWhiteSpace($cwd)) { $cwd = (Get-Location).Path } $config = Get-ProjectConfig -Cwd $cwd @@ -188,7 +188,7 @@ $mode = 'warn' try { if ($config.hooks.specGate.mode) { $mode = [string]$config.hooks.specGate.mode } } catch { } if ($mode -eq 'off') { exit 0 } -$filePath = $input.tool_input.file_path +$filePath = $hookInput.tool_input.file_path if ([string]::IsNullOrWhiteSpace($filePath)) { exit 0 } $rel = ConvertTo-RelativePath -Cwd $cwd -FilePath $filePath diff --git a/hooks/powershell/subagent-retro.ps1 b/hooks/powershell/subagent-retro.ps1 index 229d0ae..c9f9c35 100644 --- a/hooks/powershell/subagent-retro.ps1 +++ b/hooks/powershell/subagent-retro.ps1 @@ -156,14 +156,14 @@ function Remove-StaleStateFiles { # ---- main ---- -$input = Read-StdinJson -if ($null -eq $input) { exit 0 } +$hookInput = Read-StdinJson +if ($null -eq $hookInput) { exit 0 } -$cwd = $input.cwd +$cwd = $hookInput.cwd if ([string]::IsNullOrWhiteSpace($cwd)) { $cwd = (Get-Location).Path } if (-not (Test-Path -LiteralPath $cwd)) { exit 0 } -$sessionId = $input.session_id +$sessionId = $hookInput.session_id if ([string]::IsNullOrWhiteSpace($sessionId)) { $sessionId = 'no-session' } $config = Get-ProjectConfig -Cwd $cwd