fix: PowerShell hooks audit, script hardening, and workflow fixes - #20
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.
) * 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.
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.
…acts 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.
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.
[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.
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.
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.
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>
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>
Co-Authored-By: Claude Fable 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.
This pull request merges the
hotfix/ps-hooks-auditbranch intomain.Summary of Changes
install.sh/install.ps1with strict modes, prefix guards, and proper quoting.prompt-router.sh.jqkeyword output.Notes
Includes
REVIEW-TODO.mdoutlining outstanding findings to review or address pre/post-merge.