Merge origin/main into garrytan/slim-gstack-skills

VERSION → 1.15.0.0 (MINOR bump on top of main's v1.14.0.0). Branch's
v1.13.1.0 work (preamble compression + real-PTY harness + 5 plan-mode
tests passing) consolidated with v1.15.0.0 work (6 new E2E tests on the
harness + parseNumberedOptions + budget regression utils) into a single
release entry — v1.13.1.0 never landed on main, so its content rolls
into the final shippable version per the never-orphan rule in
CLAUDE.md.

Conflicts resolved:
- VERSION: 1.13.1.0 (HEAD) + 1.14.0.0 (main) → 1.15.0.0
- package.json: matching 1.15.0.0
- CHANGELOG.md: replaced HEAD's 1.13.1.0 entry with a consolidated
  1.15.0.0 entry above main's untouched 1.14.0.0 entry. Itemized
  changes split per-version (no shared header).

CLAUDE.md adds "Scale-aware bumps — use common sense" guidance under
CHANGELOG + VERSION style. Big diffs (>2K LOC, new capability) bump
MINOR; PATCH is for fixes/small adds; MAJOR for breaking changes.
Codified after a v1.14.1.0 PATCH attempt got correctly pushed back on
for a ~10K-line additions / -24K-line removals release.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-04-26 04:53:23 -07:00
35 changed files with 3049 additions and 5120 deletions
+5 -27
View File
@@ -1677,30 +1677,8 @@ describe('no compiled binaries in git', () => {
});
});
describe('sidebar agent (#584)', () => {
// #584 — Sidebar Write: sidebar-agent.ts allowedTools includes Write
test('sidebar-agent.ts allowedTools includes Write', () => {
const content = fs.readFileSync(path.join(ROOT, 'browse', 'src', 'sidebar-agent.ts'), 'utf-8');
// Find the allowedTools line in the askClaude function
const match = content.match(/--allowedTools['"]\s*,\s*['"]([^'"]+)['"]/);
expect(match).not.toBeNull();
expect(match![1]).toContain('Write');
});
// #584 — Server Write: server.ts allowedTools includes Write (DRY parity)
test('server.ts allowedTools excludes Write (agent is read-only + Bash)', () => {
const content = fs.readFileSync(path.join(ROOT, 'browse', 'src', 'server.ts'), 'utf-8');
// Find the sidebar allowedTools in the headed-mode path
const match = content.match(/--allowedTools['"]\s*,\s*['"]([^'"]+)['"]/);
expect(match).not.toBeNull();
expect(match![1]).toContain('Bash');
expect(match![1]).not.toContain('Write');
});
// #584 — Sidebar stderr: stderr handler is not empty
test('sidebar-agent.ts stderr handler is not empty', () => {
const content = fs.readFileSync(path.join(ROOT, 'browse', 'src', 'sidebar-agent.ts'), 'utf-8');
// The stderr handler should NOT be an empty arrow function
expect(content).not.toContain("proc.stderr.on('data', () => {})");
});
});
// `sidebar agent (#584)` describe block was here. sidebar-agent.ts and
// the entire chat-queue path were ripped in favor of the interactive
// claude PTY (terminal-agent.ts); these assertions had no target file.
// Terminal-pane invariants are covered by browse/test/sidebar-tabs.test.ts
// and browse/test/terminal-agent.test.ts.