fix(windows): .gitignore glob for .exe + find-browse .exe resolution#1554
Open
Mike-E-Log wants to merge 2 commits into
Open
fix(windows): .gitignore glob for .exe + find-browse .exe resolution#1554Mike-E-Log wants to merge 2 commits into
Mike-E-Log wants to merge 2 commits into
Conversation
The current pattern `bin/gstack-global-discover` is exact-match and catches the Linux/macOS compile output. On Windows, `bun build --compile` appends `.exe`, producing `bin/gstack-global-discover.exe` which falls through the gitignore and shows as untracked after every build. Add the `*` glob suffix so the pattern catches both the no-extension form (Linux/macOS) and the `.exe` form (Windows). Precedent: the same .gitignore already uses `browse/dist/` (directory pattern) for the other compiled binaries, which works on Windows for the same reason. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`browse/src/find-browse.ts` uses Node's `fs.accessSync(p, X_OK)` with the hardcoded base name `browse` (no extension). On Windows, `bun build --compile` produces `browse.exe`. Node's `accessSync` is exact-match and on Windows degrades to a simple existence check (Windows has no true execute bit). So the compiled `find-browse.exe` always errors on Windows with `"ERROR: browse binary not found. Run: cd <skill-dir> && ./setup"` even when `browse.exe` is right next to it. Git Bash's `test -x` auto-resolves `.exe` on MSYS2, but Node's fs API does not. Add a local `isExecutable(p)` helper and a `findExecutable(base)` helper that probes the bare path then, on Windows, tries the `.exe / .cmd / .bat` extension fallback. Replace each callsite in `locateBinary()` to use the resolver. Daily impact is currently low because no SKILL.md uses find-browse (verified via grep across all `*/SKILL.md` files, top-level and nested) — the /browse skill's inline bash discovery uses `test -x` which Git Bash auto-resolves on Windows. But the compiled binary is shipped via setup and externally documented in BROWSER.md / CLAUDE.md as the canonical lookup path; any Node consumer that calls it would fail on Windows today. Exact mirror of the equivalent helpers in `make-pdf/src/browseClient.ts:89-98` (`findExecutable`) + `make-pdf/src/browseClient.ts:159-166` (`isExecutable`), and the same pair in `make-pdf/src/pdftotext.ts:52-61` + `:117-124`. Same signature, same `.exe / .cmd / .bat` ordering, same `win32` platform guard, same `accessSync(constants.X_OK)` probe. The gstack codebase has two existing copies of this pattern (`browse/src` referenced earlier, plus make-pdf twice); a third copy in find-browse keeps the module self-contained, per the comment in `make-pdf/src/pdftotext.ts:52` explicitly documenting the duplication-for-compile-isolation choice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shelman09
pushed a commit
to Namleh-Studios/gstack
that referenced
this pull request
May 19, 2026
…find-browse (garrytan#1554) bun build --compile on Windows appends .exe to the output filename, producing browse.exe instead of browse. find-browse's existsSync probe only checked the bare path and returned null on Windows even when the binary was correctly built. .gitignore similarly only excluded the bare bin/gstack-global-discover path, leaving the .exe variant tracked. This commit: - .gitignore: changes `bin/gstack-global-discover` → `bin/gstack-global-discover*` so the Windows .exe variant is ignored - browse/src/find-browse.ts: adds isExecutable + findExecutable helpers that fall back to .exe/.cmd/.bat probing on Windows, mirroring the same helper already in make-pdf/src/browseClient.ts and pdftotext.ts Contributed by @Mike-E-Log via garrytan#1554. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shelman09
pushed a commit
to Namleh-Studios/gstack
that referenced
this pull request
May 19, 2026
…ndows-latest Adds .github/workflows/windows-setup-e2e.yml as the gate that catches Bun shell-parser regressions in the build chain before they reach users. Triggers on PRs touching package.json, scripts/build.sh, scripts/write-version-files.sh, setup, browse cli/find-browse, or gstack-paths. What it verifies: 1. bun run build completes on Windows (the previously-broken path that garrytan#1538/garrytan#1537/garrytan#1530/garrytan#1457/garrytan#1561 reported) 2. All compiled binaries land on disk (browse.exe, find-browse.exe, design.exe, gstack-global-discover.exe) 3. find-browse resolves to the .exe variant on Windows (regression gate for garrytan#1554) 4. gstack-paths returns non-empty GSTACK_STATE_ROOT/PLAN_ROOT/TMP_ROOT on Windows (regression gate for garrytan#1570) Complements the existing windows-free-tests.yml (curated unit subset); this new workflow exercises the install path itself. Co-Authored-By: Claude Opus 4.7 (1M context) <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
Two small, narrow Windows-portability fixes that don't appear to be covered by any open PR:
.gitignore— match the.exesuffix onbin/gstack-global-discoverbrowse/src/find-browse.ts— resolve the.exesuffix on Windows, mirroring the helper already inmake-pdf/src/browseClient.ts:89andmake-pdf/src/pdftotext.ts:52Verified live on Windows 11 + Git Bash MSYS2 + bun 1.3.13. First-time contributor; please tell me if I've missed a convention.
Scoping note (deliberate omission)
I originally drafted this PR with a third fix for the bun-shell
(...) >redirect bug inpackage.json's build script. On checking the PR list before opening, I found that ground is already heavily covered:v1.39.2.0 fix: bun run build crashes on Windows from subshell-with-redirectionFix Bun Windows build script compatibilityFix Windows build artifact finalizationfix(build): bun-on-Windows compatibility for the package.json build scriptv1.33.3.0 fix: replace bash brace groups with subshells in build script for Windows compatibilityFive existing PRs is enough — adding a sixth would be noise rather than signal. I dropped that commit before opening this PR. The two fixes here are deliberately the ones that don't overlap with that crowd.
Why each fix exists
Fix 1:
.gitignore—bin/gstack-global-discover*One line:
Why: the pattern was exact-match. On Linux/macOS,
bun --compileproducesbin/gstack-global-discover(no extension) and the rule matches. On Windows, the output isbin/gstack-global-discover.exeand the rule misses it, sogit statusshows it as untracked after every build.Precedent:
browse/dist/(line 4) uses a directory pattern, which catches every extension under the directory. Same conceptual move — make the rule cover both Linux and Windows compile outputs — applies here. The*glob is the minimal change.Tighter alternatives (happy to switch if preferred): two explicit lines (
bin/gstack-global-discover+bin/gstack-global-discover.exe). The glob form would also match hypothetical future siblings like.mapor.dSYM; the tracked sourcebin/gstack-global-discover.tsis unaffected either way (it was added before the ignore pattern and remains tracked).Fix 2:
browse/src/find-browse.ts— Windows.exeresolution~30 lines: added two local helpers (
isExecutableandfindExecutable) and routed both candidate path lookups through them.Why:
find-browsewas usingexistsSync('.../browse')(exact-match, no extension). On Windows,bun --compileproducesbrowse.exe, and Node'sfs.existsSyncis strict (unlike Git Bash'stest -xwhich auto-resolves.exeon MSYS2). The compiledfind-browse.exetherefore always emitsERROR: browse binary not found. Run: cd <skill-dir> && ./setupon Windows, even whenbrowse.exeis right next to it.Precedent: exact mirror of the equivalent helpers in
make-pdf/src/browseClient.ts:89-98(findExecutable) +make-pdf/src/browseClient.ts:159-166(isExecutable), and the same pair inmake-pdf/src/pdftotext.ts:52-61+:117-124. Same signature, same.exe / .cmd / .batordering, samewin32platform guard, sameaccessSync(constants.X_OK)probe. The comment inmake-pdf/src/pdftotext.ts:52explicitly documents the "duplicated rather than shared because the two modules already duplicate isExecutable for compile-isolation" choice — this third copy in find-browse keeps the module self-contained for the same reason.Daily-impact note: no
SKILL.mdfile currently invokesfind-browse(verified via grep across allSKILL.mdfiles at any depth). The /browse skill's discovery uses bashtest -xwhich Git Bash auto-resolves to.exeon Windows. So this is a latent bug today: real defect, no current Windows consumer. Butbrowse/bin/find-browse(the bash shim) doesexecthe compiled binary as its primary path, andBROWSER.md/CLAUDE.mddocumentfind-browseas the canonical lookup. Any Node consumer that calls it would fail on Windows today.Test plan
bun test browse/test/find-browse.test.ts test/build-script-shell-compat.test.ts— 6 pass, 0 fail./browse/dist/find-browse.exeinvoked from various working directories on Windows — returns the absolute path tobrowse.exeinstead of erroringbun run buildon Windows,git statusno longer shows untrackedbin/gstack-global-discover.exefindExecutableonly takes the.exebranch onprocess.platform === 'win32'; the.gitignoreglob still matches the no-extension formOut of scope
(...) >bun-shell incompatibility — see PRs listed abovefindExecutablehelper (two existing copies inmake-pdf/; this third copy keeps the module self-contained, per the comment inpdftotext.ts:52)Notes