diff --git a/browse/src/find-browse.ts b/browse/src/find-browse.ts index 9a8ed157a..ab9f6a54d 100644 --- a/browse/src/find-browse.ts +++ b/browse/src/find-browse.ts @@ -65,6 +65,16 @@ export function locateBinary(): string | null { const found = findExecutable(local); if (found) return found; } + + // Source-checkout fallback (no installed skill layout — the binary + // lives directly at /browse/dist/browse[.exe]). Hit by: + // - gstack repo dev workflow before `./setup` runs + // - the windows-setup-e2e.yml CI workflow which builds binaries + // in place but never installs them under a marker dir + // - make-pdf consumers running from a sibling source checkout + const sourceCheckout = join(root, 'browse', 'dist', 'browse'); + const sourceFound = findExecutable(sourceCheckout); + if (sourceFound) return sourceFound; } // Global fallback diff --git a/browse/test/find-browse.test.ts b/browse/test/find-browse.test.ts index 2f1cdc0e2..333e09acd 100644 --- a/browse/test/find-browse.test.ts +++ b/browse/test/find-browse.test.ts @@ -47,4 +47,15 @@ describe('locateBinary', () => { expect(typeof locateBinary).toBe('function'); expect(locateBinary.length).toBe(0); }); + + test('source-checkout fallback resolves /browse/dist/browse[.exe]', () => { + // The windows-setup-e2e.yml workflow builds binaries directly under + // browse/dist/ (no .claude/skills/gstack/ install layout). find-browse + // must resolve those — otherwise every fresh build that hasn't run + // ./setup yet looks broken. Static pin so a future refactor that + // drops the source-checkout branch trips this test. + const src = require('fs').readFileSync(require('path').join(__dirname, '../src/find-browse.ts'), 'utf-8'); + expect(src).toContain('Source-checkout fallback'); + expect(src).toContain("join(root, 'browse', 'dist', 'browse')"); + }); });