# Behavior traces — garrytan/gstack

> Canonical page: https://codevetter.com/unpack/gstack/behavior-traces

# Behavior traces — garrytan/gstack

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

Four flows were traced end-to-end. Install: ./setup checks bun, compiles binaries, regenerates host skill docs, and links skills into the host's skill dir. Browse command: CLI → state file → health probe → daemon spawn → authenticated POST → scope check → Playwright → sanitized untrusted-wrapped output. Local render: gstack-render → pickEngine → loopback static serve → aside repl single script (or daemon command sequence) → artifact copy-out. Paid-eval CI: planner emits a slice manifest from diff selection, six executors run shards, and a fail-closed reconcile job + token-isolated comment job close the lane.
- Install trace: ./setup (bash, set -e, umask 077) → short-circuit --help → require bun on PATH → resolve SOURCE_GSTACK_DIR + per-host skill dirs (CODEX_SKILLS, FACTORY_SKILLS, OPENCODE_SKILLS, CURSOR_SKILLS, KIRO_SKILLS) → scripts/build.sh compiles binaries → gen-skill-docs renders host output → _link_or_copy symlinks skills → prune retired renders (ownership-gated). — [setup#L1-85](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/setup#L1-L85) [scripts/build.sh](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/build.sh)
- Browse command trace (e.g. `$B snapshot -i`): cli.ts readState() reads .gstack/browse.json → isProcessAlive + isServerHealthy GET /health → on missing/dead daemon spawn server.ts detached (15s/30s-CI start budget via resolveStartTimeout, BROWSE_START_TIMEOUT override) → version-mismatch auto-restart → POST /command Bearer → server.ts buildFetchHandler → canonicalizeCommand → validateScopedToken/checkScope → handleSnapshot → wrap/sanitize → stdout. — [browse/src/cli.ts#L29-53](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/cli.ts#L29-L53) [browse/src/cli.ts#L141-160](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/cli.ts#L141-L160) [browse/src/server.ts#L16-55](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/server.ts#L16-L55) [browse/src/commands.ts#L215-218](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/commands.ts#L215-L218)
- Snapshot→act trace: `snapshot` calls page.accessibility.snapshot(), assigns @e1..@eN refs stored as Map<string, RefEntry> of Playwright Locators on BrowserManager; a later `click @e3` resolves the ref with an async count() staleness check before locator.click(); navigation clears the map via framenavigated. — [ARCHITECTURE.md#L245-283](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L245-L283) [browse/src/snapshot.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/snapshot.ts) [browse/src/browser-manager.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/browser-manager.ts)
- Aside drive trace: a skill's BROWSER SETUP runs the generated probe (command -v aside + `aside repl 'console.log("ASIDE_READY " + pwd)'` with gtimeout/timeout/perl fallbacks) → READY | NEEDS_ASIDE | ASIDE_NOT_RUNNING → on READY the skill runs one self-contained `aside repl` script per flow ending in console.log("GSTACK_STEP_OK") and copies artifacts out of the printed ASIDE_DIR. — [scripts/resolvers/aside.ts#L71-105](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/resolvers/aside.ts#L71-L105) [ARCHITECTURE.md#L11-25](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L11-L25)
- Render trace: gstack-render.ts parses flags into RenderSpec → pickEngine/probeAside → Bun.serve binds 127.0.0.1 ephemeral port serving only the file's dir (per-render secret first path segment, realpath containment, no dir listing) → Aside path runs one repl script with goto+wait+pdf/screenshot/eval steps via raw CDP Page.printToPDF → copies artifacts from ASIDE_DIR → prints ENGINE= + OK lines; fallback runs the same spec as daemon calls newtab --json → goto → js-poll → pdf --from-file / screenshot → closetab in a finally. — [bin/gstack-render.ts#L1-46](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/bin/gstack-render.ts#L1-L46) [lib/aside-render.ts#L1-42](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/lib/aside-render.ts#L1-L42) [ARCHITECTURE.md#L106-115](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L106-L115)
- Paid-eval CI trace: evals.yml build-image (hash-keyed ghcr image) → plan-slices runs test-paid-shards.ts --emit-plan (EVALS_TIER=gate, 6 slices) → eval-slices matrix executes each slice inside the container with seeded claude config + registered skills → slices-report re-runs the runner with --report to reconcile artifacts vs manifest FAIL-CLOSED (PIPESTATUS pinned) → slices-comment posts the PR comment from a separate job holding the write token and zero repo code. — [.github/workflows/evals.yml#L87-155](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/.github/workflows/evals.yml#L87-L155) [.github/workflows/evals.yml#L230-307](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/.github/workflows/evals.yml#L230-L307) [scripts/test-paid-shards.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/test-paid-shards.ts)
- Free-test trace: `bun run test` → scripts/test-free-shards.ts enumerates TEST_ROOTS (browse/test, test/, make-pdf/test, design/test) excluding paid files via isPaidTestFile → stable-hash shard assignment → N concurrent `bun test` children → BunTestOutputClassifier strict classification (a shard without bun's terminal summary FAILS; wall-timeout SIGKILL = distinct timed-out) → optional GSTACK_FREE_RETRY_FLAKY attribution-gated retry writing the flake ledger. — [scripts/test-free-shards.ts#L1-75](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/test-free-shards.ts#L1-L75) [scripts/test-strict-output.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/test-strict-output.ts) [test/helpers/paid-test-set.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/test/helpers/paid-test-set.ts)
- pair-agent tunnel trace: POST /pair (root-only, local listener) mints a setup key → remote agent POSTs /connect on the tunnel listener (rate-limited, unauth) → exchangeSetupKey yields a scoped token (DEFAULT_PAIR_SCOPES = read+write+admin+meta) → tunnel listener serves only /connect + /command with a browser-driving command allowlist; root token on the tunnel = 403; denials are logged to ~/.gstack/security/attempts.jsonl. — [ARCHITECTURE.md#L135-166](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L135-L166) [browse/src/token-registry.ts#L90-98](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/token-registry.ts#L90-L98) [browse/src/tunnel-denial-log.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/browse/src/tunnel-denial-log.ts)
- Ship trace: /ship template runs {{PREAMBLE}} (gstack-skill-start) → {{THIRD_PARTY_ACTIONS}} → {{BASE_BRANCH_DETECT}} → {{GBRAIN_CONTEXT_LOAD}} → enumerated gates (on-base-branch abort, conflict stop, test triage, review ASK items, MINOR/MAJOR bump asks) → auto-commit/push/PR. — [ship/SKILL.md.tmpl#L29-60](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ship/SKILL.md.tmpl#L29-L60) [scripts/resolvers/index.ts#L71](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/scripts/resolvers/index.ts#L71)
- Skill invocation runtime trace: generated SKILL.md opens with {{PREAMBLE}} → bin/gstack-skill-start runs update check + session tracking (~/.gstack/sessions/<parent-pid>, 2h prune) → emits STATUS lines → skill executes → bin/gstack-skill-end records telemetry. — [ARCHITECTURE.md#L357-362](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ARCHITECTURE.md#L357-L362) [bin/gstack-skill-start](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/bin/gstack-skill-start) [bin/gstack-skill-end](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/bin/gstack-skill-end)
- iOS QA trace (inferred from layout): gstack-ios-qa-daemon (ios-qa/daemon/src/index.ts) brokers devicectl over a CoreDevice tunnel; auth-mint/session-tokens manage the tailnet allowlist; Swift templates under ios-qa/templates/ (DebugBridgeManager, StateServer, DebugBridgeTouch) are injected into the target app by gstack-ios-qa-regen. (inferred) — [ios-qa/daemon/src/index.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ios-qa/daemon/src/index.ts) [ios-qa/daemon/src/devicectl.ts](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ios-qa/daemon/src/devicectl.ts) [ios-qa/templates/DebugBridgeManager.swift.template](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/ios-qa/templates/DebugBridgeManager.swift.template) [AGENTS.md](https://github.com/garrytan/gstack/blob/35dd014c580037d1c009776d8b0584587c1bd42c/AGENTS.md)

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)
