fix(windows): make the PowerShell scripts survive a real shell run - #22
fix(windows): make the PowerShell scripts survive a real shell run#22Firnschnee wants to merge 1 commit into
Conversation
Three bugs that pass PSScriptAnalyzer but break the first time the scripts run on a real Windows shell, found while verifying the beta on Windows 11 hardware. run-template-edge.ps1: the cmd /c redirect was quoted so that cmd.exe stripped the first and last quote of the command line (its documented behavior when the line contains a redirect), turning "node ..." > "log" 2>&1 into node ..." > "log 2>&1 a malformed line. cmd exited 1, no log was written, and the dev server never started, so the entire Edge fallback was a dead end. Wrap the whole pipeline in one /s /c "..." pair with the inner path quotes doubled. (This fixes server start only; the Edge window lifetime is tracked separately.) inspect.ps1: Search-Code did `if ($Dirs.Count -eq 0)`, but when none of src/services/app/lib exist the pipeline yields $null and $null.Count throws under StrictMode, breaking the FSA scan. Only the script's ErrorActionPreference = 'Continue' hid it. Use `if (-not $Dirs)`. desktop-quit.ps1: Invoke-PortSweep set $closed = $true whenever a parseable server.pid existed, so a stale pid (left by a crash or force-kill) made the run report "Stopped dev servers" when nothing was running. Only count it closed when the recorded process is actually alive.
Reviewer's guide (collapsed on small PRs)Reviewer's GuideFixes three Windows PowerShell script issues so they behave correctly when run in a real shell: the Edge dev-server fallback now starts and logs reliably via corrected cmd.exe quoting, the FSA scan in inspect.ps1 no longer throws under StrictMode when no search directories exist, and desktop-quit.ps1 only reports dev servers as stopped when it actually finds and kills a live process from server.pid. Sequence diagram for updated Invoke-PortSweep process handlingsequenceDiagram
actor User
participant DesktopQuitScript
participant InvokePortSweep
participant OSProcessManager
participant TargetProcess
User->>DesktopQuitScript: run desktop-quit.ps1
DesktopQuitScript->>InvokePortSweep: Invoke-PortSweep
InvokePortSweep->>InvokePortSweep: Get-Content server.pid
InvokePortSweep->>InvokePortSweep: [int]::TryParse(recorded, pidNum)
alt pid parsed
InvokePortSweep->>OSProcessManager: Get-Process -Id pidNum
alt process alive
OSProcessManager-->>InvokePortSweep: process info
InvokePortSweep->>TargetProcess: Stop-ProcessTree -ProcessId pidNum
InvokePortSweep->>InvokePortSweep: $closed = $true
else process not found (stale pid)
OSProcessManager-->>InvokePortSweep: $null
InvokePortSweep->>InvokePortSweep: $closed remains $false
end
else pid not parsed
InvokePortSweep->>InvokePortSweep: $closed remains $false
end
InvokePortSweep-->>DesktopQuitScript: return $closed
DesktopQuitScript-->>User: report dev servers stopped only if $closed
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In desktop-quit.ps1, when you detect a parseable but non-running PID (stale server.pid), consider removing or updating the PID file so future runs don't repeatedly encounter the same stale state.
- The cmd.exe quoting in run-template-edge.ps1 is now fairly intricate; it may be worth wrapping this in a small helper or adding a short example of the resulting command line in comments to reduce future maintenance mistakes around escaping.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In desktop-quit.ps1, when you detect a parseable but non-running PID (stale server.pid), consider removing or updating the PID file so future runs don't repeatedly encounter the same stale state.
- The cmd.exe quoting in run-template-edge.ps1 is now fairly intricate; it may be worth wrapping this in a small helper or adding a short example of the resulting command line in comments to reduce future maintenance mistakes around escaping.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Thanks. On the stale PID: it is already handled a level up, so I left |
Part of #21. Three bugs that pass PSScriptAnalyzer but break the first time the scripts run on a real Windows shell, found verifying the beta on Windows 11. - run-template-edge.ps1: the Edge fallback never started the dev server. cmd.exe stripped the outer quotes of a redirected command line; wrapped in one `/s /c "..."` pair with inner path quotes doubled. - inspect.ps1: StrictMode crash in the FSA scan — `$Dirs.Count` on $null. Changed to `if (-not $Dirs)`, which covers $null and @() alike. Cherry-picked from PR #22 (80a3623, by Firnschnee). The third fix in that PR (Invoke-PortSweep only counting a live recorded PID as "closed") is intentionally dropped here: the ownership-proof rewrite in 89aaad2 removed Invoke-PortSweep entirely, so a stale/dead recorded PID is already reported as stale rather than stopped. Identity-token writes from 89aaad2 and the cmd fix coexist in run-template-edge.ps1. Co-authored-by: Firnschnee <max.social@posteo.de> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Landed on `main` in 501da59 (cherry-picked with `-x`, your authorship preserved) — thank you, @Firnschnee. The Edge-fallback `cmd /s /c` quoting fix and the `inspect.ps1` StrictMode fix both shipped as-is. One note: the third hunk (`Invoke-PortSweep` only counting a live recorded PID as "closed") was intentionally dropped — a concurrent change (89aaad2) replaced the whole port-sweep cleanup with an ownership proof (a `server.identity` creation-time token, falling back to tree-owns-listener), so `Invoke-PortSweep`/`Get-PortOwner` no longer exist and a stale/dead recorded PID is already reported as stale rather than stopped. Your fix's intent is fully covered there. CHANGELOG updated. Closing since it's merged. |
Bump 0.1.0 -> 0.2.0 across marketplace.json (top-level + all three plugin entries) and all six plugin.json manifests. Move the entire CHANGELOG [Unreleased] block (static companion, doctor, verify, JSON output, fixed-port, hosted-URL wrappers, native bootstrap, ownership- safe cleanup, the Windows beta fixes) into a dated "## 0.2.0 - 2026-06-20" section; leave a fresh empty [Unreleased]. Reconcile the marketplace listing's Windows status line, the only outlier: it still said "untested on real hardware" while README and the CHANGELOG already reflect that real-hardware fixes (#8/#17/#18, #22/#23) have landed. Calibrate the listing text (marketplace.json + its two byte-identical app-it-windows plugin.json mirrors) to "Beta - first real-hardware fixes landed - maintainer wanted" — true, does not claim "tested", keeps the maintainer-wanted ask. The ~25 deliberate beta/maintainer-wanted placements in the deeper docs/ADR/ SKILL/contract files are left untouched by design. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Part of #21. Three bugs that pass PSScriptAnalyzer but break the first time the
scripts run on a real Windows shell, found while verifying the beta on Windows 11.
run-template-edge.ps1: the Edge fallback never started the dev server
The cmd /c command was quoted so that cmd.exe stripped the first and last quote of
a line containing a redirect (its documented behavior), turning
"node ..." > "log" 2>&1intonode ..." > "log 2>&1. cmd exited 1, no log waswritten, and the server never started, so the whole Edge fallback (the path for
users without the .NET SDK) was a dead end. Wrapped the pipeline in one
/s /c "..."pair with the inner path quotes doubled.Verified: the dev server now binds and serves (server.log shows the listen line,
the readiness probe gets a response). Scope note: this fixes server start only.
The Edge window lifetime (WaitForExit returns early because Chromium forks and
hands off) is a separate open item tracked in #21, not addressed here.
inspect.ps1: StrictMode crash in the FSA scan
Search-Codedidif ($Dirs.Count -eq 0), but when none of src/services/app/libexist the pipeline yields $null and
$null.Countthrows under StrictMode. Only thescript's
ErrorActionPreference = 'Continue'kept it limping. Changed toif (-not $Dirs), which covers $null and an empty result alike.desktop-quit.ps1: false "Stopped" report on a stale pid
Invoke-PortSweep set
$closed = $truewhenever a parseable server.pid existed, so astale pid (left by a crash or force-kill) made the run report "Stopped dev servers"
when nothing was running. Now it only counts as closed when the recorded process is
actually alive.
All three lint clean under the repo's PSScriptAnalyzerSettings.psd1 (Error +
Warning). Tested on Windows 11, .NET SDK 8.0.422, PowerShell 7.6.1.
Summary by Sourcery
Fix Windows PowerShell scripts so they behave correctly when run in a real shell instead of only passing static analysis.
Bug Fixes: