fix(setup-windows): auto-reexec under pwsh when running on Windows PowerShell 5.1 (BUG-005)#58
Merged
Merged
Conversation
…werShell 5.1 (BUG-005) SDD-002 (PR #51) introduced Merge-ClaudeSettings which uses `ConvertFrom-Json -AsHashtable` -- a parameter added in PowerShell 7.0 that does NOT exist in Windows PowerShell 5.1. The natural Windows command `PowerShell -ExecutionPolicy Bypass -File .\setup-windows.ps1` resolves `PowerShell` to 5.1 on a stock Windows machine, the Merge function's wide try/catch swallows the ParameterBindingException as if it were a JSON parse error ("not valid JSON after placeholder substitution: A parameter cannot be found that matches parameter name 'AsHashtable'"), and the per-key merge from ai/claude/settings.json is silently skipped. Existing ~/.claude/settings.json survives untouched, so the bug is invisible until a fresh-machine bootstrap depends on the template merge. Implementation: preamble block after param() and before CONFIGURATION header detects $PSVersionTable.PSVersion.Major < 7. If `Get-Command pwsh` resolves to PowerShell 7+, re-exec under it with `-NoProfile -ExecutionPolicy Bypass -File $PSCommandPath @args` and exit with the child's exit code. Otherwise, print an actionable [ERROR] line pointing at `winget install Microsoft.PowerShell` and exit 1 (fail-loud, no silent skip). Verification: - Smoke under Windows PowerShell 5.1.22621.6931: first output line is `[INFO] Windows PowerShell 5.1.22621.6931 detected; re-executing under pwsh (...) for full feature compatibility (BUG-005)`. Setup proceeds under pwsh, settings.json merged correctly (1687 bytes, 14 plugins + preserved user customizations), zero AsHashtable warnings. - Smoke under pwsh 7.6.1 direct: preamble no-op, no `[INFO] ... detected` lines, existing behavior preserved (verified during BUG-004 smoke same day). - pwsh-missing branch: not directly testable (pwsh installed on dev machine); structurally locked by bats grep asserting `winget install Microsoft.PowerShell` literal + `exit 1`. - 5 new bats asserts in tests/setup-windows.bats; RED -> GREEN via grep-by-grep emulation. - PSScriptAnalyzer: 4 new Write-Host warnings, style-consistent with existing Write-Info/Success/Warn/Err wrappers (those wrappers are themselves Write-Host calls; preamble cannot use them because the wrappers are defined below the preamble's runtime position). Zero Errors. Zero new rule classes. Linux side (setup-linux.sh) is immune by construction (bash + jq, no shell-version coupling); zero changes there. Negative-parity bats assert locks this in. Spec: specs/BUG-005-setup-ps7-reexec/ Vault: 10_projects/dotfiles/11-tasks.md (entry added in same session) Sibling: PR #57 (BUG-004 claude-mem-truncate-guard) Upstream: https://learn.microsoft.com/powershell/scripting/whats-new/what-s-new-in-powershell-70 Co-Authored-By: Claude Opus 4.7 <[email protected]>
0d69424 to
d711db0
Compare
4 tasks
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
Merge-ClaudeSettingstemplate merge introduced by SDD-002 (PR feat(setup): track ai/claude/settings.json template + per-key merge (SDD-002) #51). The function usesConvertFrom-Json -AsHashtable, a PS 7+ only parameter; on PS 5.1 the widetry/catchmisclassifies theParameterBindingExceptionas a JSON parse error and returns early.setup-windows.ps1(right afterparam()) that detects$PSVersionTable.PSVersion.Major -lt 7. Ifpwsh(7+) is on PATH, re-execs the script under pwsh with$PSCommandPath @argsand exits with the child's exit code. Otherwise fails loud withwinget install Microsoft.PowerShellhint +exit 1.setup-linux.shuses bash + jq, no shell-version coupling — verified untouched (negative-parity bats assert locks this in).Root cause
PowerShell -ExecutionPolicy Bypass -File .\setup-windows.ps1resolvesPowerShellto Windows PowerShell 5.1 on a stock Windows machine.Merge-ClaudeSettingsthen callsConvertFrom-Json -AsHashtablewhich fails withParameterBindingException. The function'stry { ... } catch { Write-Warn "...not valid JSON..."; return }catches everything and prints the misleading "not valid JSON after placeholder substitution: A parameter cannot be found that matches parameter name 'AsHashtable'" warning. Empirically observed 2026-05-19 in setup output on a Windows 11 22631.6931 admin machine.Test plan
tests/setup-windows.bats(PSVersion detection, pwsh re-exec branch, fail-loud branch +exit 1, BUG-005 cite in inline comment, negative parity onsetup-linux.sh)[INFO] Windows PowerShell 5.1.22621.6931 detected; re-executing under pwsh (...) for full feature compatibility (BUG-005). Setup proceeds under pwsh;settings.jsonmerged (1687 bytes, 14 plugins + preserved user customizations); zeroAsHashtablewarnings.[INFO] ... detectedline appeared)PSAvoidUsingWriteHostwarnings, style-consistent with existing wrappers; zero new rule classes; zero Errors)git diff main..HEAD --stat -- setup-linux.shempty (Linux untouched)Design decisions (in
verification.md)Merge-ClaudeSettingscould have been rewritten to convertPSCustomObjectto hashtable recursively for PS 5.1 compat (~30 lines of subtle recursion vs ~15 lines of preamble). Chose re-exec because Microsoft is sunsetting Windows PowerShell 5.1 and locking the script to pwsh at the front door lets downstream code freely use modern PS features (ternary, null-conditional, etc.) without future-bug risk.@argsinstead of$PSBoundParameters— currentparam()is empty; positional@argssuffices. Inline comment specifies$PSBoundParametersis the correct forwarding mechanism if named params are added later.References
specs/BUG-005-setup-ps7-reexec/Merge-ClaudeSettingswith-AsHashtabledependencyConvertFrom-Json -AsHashtableadded10_projects/dotfiles/11-tasks.md"BUG-005-setup-ps7-reexec"