# Contributor handoff — garrytan/gstack

> Canonical page: https://codevetter.com/unpack/gstack/agent-handoff

# Contributor handoff — garrytan/gstack

Scanned commit 35dd014c580037d1c009776d8b0584587c1bd42c (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Read CLAUDE.md first — it is the operational manual (commands, generated-file rules, security invariants). The cardinal rules: edit .tmpl templates never generated SKILL.md; run `bun run test` (the strict shard runner) before commits and `bun run test:evals` before shipping; never run bare `bun test`; keep registry modules side-effect-free; wire egress receipts for any new off-machine send; and respect the token budgets enforced by catalog-budget/context-budget-ratchet tests. Safe edit boundaries: skill prose in .tmpl files, new commands via the commands.ts registry, new hosts via defineHost. Dangerous zones: browse/src/server.ts + extension/ + SSE/CDP paths (read docs/BROWSER_INTERNALS.md first), test/helpers (read docs/TESTING_INTERNALS.md), setup bash invariants.
- First reads for any agent: CLAUDE.md (commands + conventions + security invariants), docs/PROJECT_STRUCTURE.md (annotated tree), ARCHITECTURE.md (why), docs/BROWSER_INTERNALS.md before touching server.ts/extension/SSE/CDP, docs/TESTING_INTERNALS.md before writing E2E or passing env: to runners. — [CLAUDE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/CLAUDE.md) [docs/PROJECT_STRUCTURE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/docs/PROJECT_STRUCTURE.md) [docs/BROWSER_INTERNALS.md#L1-9](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/docs/BROWSER_INTERNALS.md#L1-L9) [docs/TESTING_INTERNALS.md#L1-5](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/docs/TESTING_INTERNALS.md#L1-L5)
- Generated-file rule: SKILL.md, review/design-checklist.md, lib/dom-dump.js, and agents-digest output are generated — edit the .tmpl or lib source, run `bun run gen:skill-docs`, commit both; never resolve SKILL.md merge conflicts by picking a side. — [CLAUDE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/CLAUDE.md) [ARCHITECTURE.md#L306-355](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L306-L355) [test/design-checklist-sync.test.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/design-checklist-sync.test.ts)
- Test discipline: `bun run test` (strict shard runner, ~90-100s, ~8,700 tests) before every commit; `bun run test:evals` (paid, diff-based) before shipping; bare `bun test` walks the whole repo including paid files and bypasses the strict classifier — explicitly forbidden. — [CLAUDE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/CLAUDE.md) [scripts/test-free-shards.ts#L14-20](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/test-free-shards.ts#L14-L20) [package.json#L26-36](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/package.json#L26-L36)
- Module convention: registry/data modules must have zero side effects on import (commands.ts, token-registry.ts, browser-skills.ts, touchfiles-data.ts are explicitly documented as such) because build scripts and tests import them; literal-only data files (touchfiles-data.ts) must stay importable by old git versions. — [browse/src/commands.ts#L1-11](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/commands.ts#L1-L11) [browse/src/token-registry.ts#L31](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/token-registry.ts#L31) [browse/src/browser-skills.ts#L20](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/browser-skills.ts#L20) [test/helpers/touchfiles.ts#L7-11](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/helpers/touchfiles.ts#L7-L11)
- lib/ vs scripts/ boundary: lib/design-catalog.ts documents that bin/ + lib/ travel to every host while scripts/ is never linked — runtime code may not import from scripts/; lib/egress-receipt.ts and browse/src/security.ts are constrained to Node builtins so the compiled binary can embed them. — [lib/design-catalog.ts#L4-6](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/lib/design-catalog.ts#L4-L6) [lib/egress-receipt.ts#L22-24](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/lib/egress-receipt.ts#L22-L24)
- New off-machine sends must write an egress receipt (writeReceipt or _receipted_curl/_receipted_git) BEFORE the send, or carry a reasoned SCANNER_EXEMPT entry — test/egress-receipt-wiring.test.ts fails CI on an unreceipted curl/git push/fetch to a non-loopback host. — [lib/egress-receipt.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/lib/egress-receipt.ts) [bin/gstack-egress-lib.sh](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/bin/gstack-egress-lib.sh) [CLAUDE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/CLAUDE.md) [test/egress-receipt-wiring.test.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/egress-receipt-wiring.test.ts)
- Token budgets are ratcheted: new skills must fit catalog-budget (1,150 token-equivalents of frontmatter name+description) and context-budget-ratchet ceilings; legitimate growth requires re-running test/helpers/capture-context-budget.ts and committing the fixture. — [test/catalog-budget.test.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/catalog-budget.test.ts) [test/context-budget-ratchet.test.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/context-budget-ratchet.test.ts) [CLAUDE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/CLAUDE.md)
- Skill-template conventions: each bash code block in a .tmpl runs in a separate shell (no variable persistence — carry state in prose), never hardcode branch names (use {{BASE_BRANCH_DETECT}}), express conditionals as numbered English steps, and never hardcode project-specific commands (read the target's CLAUDE.md / AskUserQuestion / persist). — [CLAUDE.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/CLAUDE.md) [SKILL.md.tmpl](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/SKILL.md.tmpl)
- The ONNX classifier can never move into the compiled binary (onnxruntime-node dlopen fails from bun's temp extract dir) — security-classifier.ts stays in security-sidecar-entry.ts; only pure-string pieces live in security.ts. — [ARCHITECTURE.md#L233](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L233)
- State paths must resolve through bin/gstack-paths (eval its output) rather than hardcoding ~/.gstack or ~/.claude — it handles GSTACK_HOME, CLAUDE_PLUGIN_DATA, CLAUDE_PLANS_DIR, and HOME-less containers; claude CLI binary resolution goes through lib/claude-bin.ts with GSTACK_CLAUDE_BIN override. — [bin/gstack-paths#L1-24](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/bin/gstack-paths#L1-L24) [lib/claude-bin.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/lib/claude-bin.ts) [AGENTS.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/AGENTS.md)
- Version bumps: VERSION file + package.json version are written by scripts/write-version-files.sh during /ship; detect-bump.ts classifies; the evals CI image deliberately excludes package.json from its hash so version bumps don't rebuild it. — [scripts/write-version-files.sh](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/write-version-files.sh) [scripts/detect-bump.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/detect-bump.ts) [.github/workflows/evals.yml#L38-44](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/.github/workflows/evals.yml#L38-L44)
- Known trap: on Windows the Bun-spawned server is broken — cli.ts hard-fails without browse/dist/server-node.mjs built by browse/scripts/build-node-server.sh; and `isProcessAlive` (signal-0, EPERM=alive) is the liveness check while GET /health is the responsiveness check — conflating them caused the busy-daemon bug class. — [browse/src/cli.ts#L89-119](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/cli.ts#L89-L119) [browse/src/cli.ts#L150-160](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/cli.ts#L150-L160) [browse/test/busy-daemon-iron-rule.test.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/test/busy-daemon-iron-rule.test.ts)
- PTY/E2E authoring trap: a PTY test typing a /skill slash command must pass seedSkills: true so the hermetic config dir links the LIVE working tree's SKILL.md files (the skills are the subject under test); per-test env: overrides merge last onto a complete hermetic env and are safe. — [docs/TESTING_INTERNALS.md#L19-37](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/docs/TESTING_INTERNALS.md#L19-L37) [test/helpers/hermetic-env.ts#L83-100](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/helpers/hermetic-env.ts#L83-L100)
- Agent-facing safety hooks (careful/freeze/guard) are themselves repo scripts (careful/bin/check-careful.sh, freeze/bin/check-freeze.sh, careful/bin/hook-extract.sh) — editing them changes enforcement semantics; check-freeze fails closed and sources the shared hook-extract helpers. — [careful/bin/check-careful.sh](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/careful/bin/check-careful.sh) [freeze/bin/check-freeze.sh](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/freeze/bin/check-freeze.sh) [docs/PROJECT_STRUCTURE.md#L62-64](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/docs/PROJECT_STRUCTURE.md#L62-L64)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
