diff --git a/CHANGELOG.md b/CHANGELOG.md index a4a95832f..e56e3277e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [1.91.37.0] - 2026-10-07 +## [1.91.39.0] - 2026-10-07 ### Added - Choose separate model tiers for planning and implementation. Independent plan reviews default to Fable 5.1 or GPT-6 Astra; implementation handoffs recommend Opus 5.5 or GPT-6.1 Sol without switching your session. Explicit model choices still win, and `plan_review_tier smart` or `host` provides an alternative to the frontier default. diff --git a/VERSION b/VERSION index b866b816f..a93bd3efa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.91.37.0 +1.91.39.0 diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md index dc887b150..277279533 100644 --- a/agents-digest/gstack-AGENTS.md +++ b/agents-digest/gstack-AGENTS.md @@ -1,4 +1,4 @@ -# gstack digest v1.91.37.0 — regenerate/re-copy after upgrading gstack +# gstack digest v1.91.39.0 — regenerate/re-copy after upgrading gstack Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed for agent hosts without a full skill install. The full skills add workflows, diff --git a/package.json b/package.json index e730c6b91..94e32ab88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.91.37", + "version": "1.91.39", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module", diff --git a/test/pty-output-wake.test.ts b/test/pty-output-wake.test.ts index a5f1e7c94..17675a21e 100644 --- a/test/pty-output-wake.test.ts +++ b/test/pty-output-wake.test.ts @@ -58,17 +58,29 @@ process.stdout.write('TERMINAL_READY'); `, { mode: 0o755 }); const originalBinary = process.env.BROWSE_TERMINAL_BINARY; let session: ClaudePtySession | undefined; + let terminal: Bun.Terminal | undefined; + const spawn = Bun.spawn; + const spawnSpy = spyOn(Bun, 'spawn').mockImplementation(((...args: any[]) => { + const child = (spawn as any)(...args); + if (args[1]?.cwd === dir && args[1]?.terminal) terminal = child.terminal; + return child; + }) as typeof Bun.spawn); try { process.env.BROWSE_TERMINAL_BINARY = fake; session = await launchClaudePty({ cwd: dir, model: 'fixture', timeoutMs: 5000, sessionLedger: false }); await session.waitFor('TERMINAL_READY', { timeoutMs: 3000 }); + expect(terminal?.closed).toBe(false); expect(descriptors().length).toBeGreaterThan(before.length); await session.close(); expect(session.exited()).toBe(true); + expect(terminal?.closed).toBe(true); + const settledBy = performance.now() + 1000; + while (JSON.stringify(descriptors()) !== JSON.stringify(before) && performance.now() < settledBy) await Bun.sleep(10); expect(descriptors()).toEqual(before); } finally { try { await session?.close(); } finally { + spawnSpy.mockRestore(); if (originalBinary === undefined) delete process.env.BROWSE_TERMINAL_BINARY; else process.env.BROWSE_TERMINAL_BINARY = originalBinary; fs.rmSync(dir, { recursive: true, force: true });