fix: rename reserved $input variable in PowerShell hooks - #17
Merged
developzoneio merged 1 commit intoJul 2, 2026
Merged
Conversation
Assigning parsed hook JSON to $input (PowerShell's automatic pipeline variable) throws a non-terminating ParameterBindingException whenever the hook receives real piped/redirected stdin - i.e. on every actual Claude Code invocation. The assignment silently fails, $input stays unbound, and the hook exits before reading any input. Renamed to $hookInput in subagent-retro.ps1, prompt-router.ps1, and spec-gate.ps1. Discovered while reproducing the 01-bug-subagent-retro-ps1-matches-clobber fixture; that bug was unreachable until this one was fixed.
6 tasks
developzoneio
added a commit
that referenced
this pull request
Jul 5, 2026
* fix: rename reserved $input variable in PowerShell hooks (#17) Assigning parsed hook JSON to $input (PowerShell's automatic pipeline variable) throws a non-terminating ParameterBindingException whenever the hook receives real piped/redirected stdin - i.e. on every actual Claude Code invocation. The assignment silently fails, $input stays unbound, and the hook exits before reading any input. Renamed to $hookInput in subagent-retro.ps1, prompt-router.ps1, and spec-gate.ps1. Discovered while reproducing the 01-bug-subagent-retro-ps1-matches-clobber fixture; that bug was unreachable until this one was fixed. * fix: stop $Matches clobber in subagent-retro.ps1 spec-ID extraction (#18) * fix: rename reserved $input variable in PowerShell hooks Assigning parsed hook JSON to $input (PowerShell's automatic pipeline variable) throws a non-terminating ParameterBindingException whenever the hook receives real piped/redirected stdin - i.e. on every actual Claude Code invocation. The assignment silently fails, $input stays unbound, and the hook exits before reading any input. Renamed to $hookInput in subagent-retro.ps1, prompt-router.ps1, and spec-gate.ps1. Discovered while reproducing the 01-bug-subagent-retro-ps1-matches-clobber fixture; that bug was unreachable until this one was fixed. * fix: stop $Matches clobber in subagent-retro.ps1 spec-ID extraction Get-IndexSpecs ran the spec-ID regex -match before the in-progress literal -match, so the second match overwrote $Matches and every in-progress spec was reported under the literal ID "in-progress" rather than its real ID. The retro-staleness check then looked for <specDir>/in-progress/05-retro.md, which never exists, so every in-progress spec was reported stale under the wrong ID. Swap the match order (in-progress first, ID regex last) to match the already-correct sister hooks prompt-router.ps1:167 and spec-gate.ps1:145. Verified against a fixture index (FEAT-123 in-progress, RCA-77 in-progress) - PowerShell now reports FEAT-123 and skips the RCA row, matching hooks/bash/subagent-retro.sh output exactly. * fix: same-line in-progress detection parity in spec-gate.sh bash used two independent file-wide greps for the in-progress marker and a spec ID, letting a legend/header line combine with an unrelated done row. spec-gate.ps1 and prompt-router.sh already require both on the same line; spec-gate.sh now matches. * fix: align feature.md and refactor.md subagent field names with contracts sd-spec-architect and sd-code-explorer read TASK/SPEC/IMPACT, not the TASK_TYPE/SPEC_REF/IMPACT_REF/TICKET_DATA names feature.md sent them. Both refine invocations were also missing the required SPEC path, and the TEMPLATE field was bare instead of the full template filename. refactor.md's characterization-test loop sent sd-implementer an unrecognized TASK_TYPE field instead of TASK_DETAILS/SPEC_REF/ WORKFLOW_TYPE. Reviewer invocations, which own TASK_TYPE/SPEC_REF as their own contract, are unchanged. * fix: make /sd:spec validate plan/tasks check type-aware The in-progress file-presence rule exempted only RCA from requiring 01-plan.md/02-tasks.md, but bug and perf workflows never produce those artifacts either (their artifact set is spec, decisions, artifacts, retro). Validate failed every correctly executed bug/perf spec. Narrowed the requirement to feature and refactor, and fixed the same overgeneralized claim in docs/usage.md's resume heuristic. * fix: parse debounce timestamp as UTC in subagent-retro.ps1 [datetime]::Parse of a "...Z" string returns Kind=Local, converted from UTC to local time. Subtracting that from a UTC now skewed $age by the machine's UTC offset -- wrongly suppressing reminders on UTC+N machines, never suppressing on UTC-N. Verified on a UTC+7 machine under Windows PowerShell 5.1 (the hooks' target runtime): old code showed a 420-minute skew immediately after save; fixed code shows ~0. * fix: apply per-workflow keyword defaults in prompt-router.ps1 PS only fell back to built-in defaults when project-config.json was absent or unparseable, then silently skipped any workflow whose keyword list was null once a config file existed. A valid config that omitted workflow.keywords (or one workflow's entry) lost keyword routing hints on Windows while bash kept emitting them from defaults, matching bash's per-workflow "// []" + empty-list fallback semantics. Verified against both a config missing workflow.keywords entirely and one overriding a single workflow, under Windows PowerShell 5.1. * fix: replace stale MCP tool names in agents, skills, and explore command * fix: remove hardcoded MSSQL/C#/TS stack references from agents and commands * fix: code-explorer impact-map returns analysis instead of self-appending * fix: walk full lifecycle state machine in bug/rca/perf workflows * fix: guard workflow Phase 0 against missing or malformed Layer-2 context * refactor: dedup rules copy-pasted from skills into agent/command bodies * docs: fix README/ROADMAP/usage drift after v1.3.0+ shipped * refactor: derive validate.sh/ps1 install counts from source tree * feat: add macOS to CI matrix and hook smoke tests Also fixes two PowerShell-7-only debounce bugs in subagent-retro.ps1 that the new smoke test caught: an unresolvable Split-Path parameter set, and re-Parse-ing an already-converted [datetime] as local time. * fix: harden install.sh - strict mode, prefix guard, quoting * fix: strip CRLF from jq keyword output in prompt-router.sh Some jq builds (observed with Windows jq.exe) emit CRLF for join("\n") output even from LF-only input, so every keyword but a workflow's last kept a trailing \r and never matched, silently dropping keyword-routing hints whenever project-config.json defined workflow.keywords. Fixture in scripts/smoke-hooks.sh/.ps1 now sets workflow.keywords so this path is actually exercised. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: make prompt-router.sh bash 3.2 compatible macOS runners execute hooks with system bash 3.2, which has no associative arrays: declare -A silently failed and every string subscript arithmetic-evaluated to 0, so the router emitted '- /sd:0' instead of '- /sd:bug' and the macOS smoke test failed. Replace the two associative arrays with parallel indexed arrays. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: add review findings TODO before merge Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
subagent-retro.ps1,prompt-router.ps1,spec-gate.ps1) assigned parsed hook JSON to$input, PowerShell's reserved automatic pipeline variable.ParameterBindingExceptionand leaves$inputunbound, so every PowerShell hook exits before reading any input at all.$hookInputin all three files. Reproduced and confirmed on both PowerShell 7 (pwsh) and Windows PowerShell 5.1.01-bug-subagent-retro-ps1-matches-clobber.mdaudit item - that bug was unreachable until this one was fixed, so it's split into its own PR ahead of it.Test plan
printf '{"cwd":"..."}' | pwsh -File hooks/powershell/subagent-retro.ps1now reads stdin and produces output instead of erroring silentlyprompt-router.ps1andspec-gate.ps1with representative JSON - both exit 0 and produce expected outputgrep -nP "[^\x00-\x7F]" hooks/powershell/*.ps1 install/*.ps1- no matches (pure ASCII preserved).\scripts\validate.ps1- all checks pass[Unreleased]entry added🤖 Generated with Claude Code