Summary
./setup is structured so that the riskiest step (Playwright Chromium
download) runs before several lower-risk steps (skill linking, hook
installation, version migrations). When the riskiest step fails, the
script exits 1 mid-run and the lower-risk steps never get a chance to
complete.
This means a user on a flaky network, a corporate machine with a
locked-down bunx, or hitting the Bun-on-Windows pipe bug
(oven-sh/bun#4253) ends up with a half-installed gstack: bun may be
copied, the browse binary may be built, but the actual user-facing
artifacts (skills, hooks, plan-tune machinery, gbrain regen) are
missing. A re-run of ./setup does the same thing — dies at the same
step — and the user has no easy path to a working install minus
browser features.
Failure modes observed
The current setup order interleaves trivial filesystem ops, expensive
compute, settings.json mutations, and external network/sudo steps:
- Build browse binary (network:
bun install)
- Install Playwright Chromium (network, sudo, package manager) — may exit 1
- Ensure
~/.gstack/projects/ exists (trivial filesystem)
- Install for Claude (filesystem)
5-6. Install for Codex / Kiro / Factory / OpenCode (filesystem)
- .agents/ sidecar symlinks (filesystem)
- Run version migrations (filesystem)
- First-time welcome + legacy cleanup (filesystem)
- Team mode hook install in
settings.json (mutation)
- Plan-tune hook install in
settings.json (mutation)
Concrete user-facing breakage when step 2 fails:
| Step |
What's missing on re-run failure |
User impact |
| 4-6 |
Skills not symlinked into ~/.claude/skills/ |
/qa, /ship, /review etc. don't exist |
| 7 |
.agents/ sidecar symlinks not created |
Codex skills broken |
| 8 |
Version migrations not run |
Stale config from prior gstack version |
| 9 |
Welcome message + /tmp/gstack-latest-version cleanup never happens |
Cosmetic, but the legacy /tmp file accumulates |
| 10 |
Team-mode SessionStart hook not registered in settings.json |
Team auto-sync silently disabled |
| 11 |
Plan-tune PostToolUse + PreToolUse hooks not registered |
/plan-tune AUQ capture silently disabled |
Even the trivial mkdir -p "$HOME/.gstack/projects" happens AFTER the
Playwright step, so a brand-new user without ~/.gstack/ ends up
without it.
Proposal
Reorder setup so steps run in increasing order of failure probability:
- Phase A — pure filesystem (
~/.gstack/, welcome, GBrain detection
file scan). Cannot fail in practice.
- Phase B — local compute: bun build, skill linking, version
migrations, GBrain SKILL.md regen. Fails only on bun bugs, fully
reproducible locally.
- Phase C —
settings.json mutation: team-mode and plan-tune hooks.
Fails only if settings.json is malformed, fully reversible.
- Phase D — external network / sudo / package managers: coreutils
on macOS, emoji font on Linux, Playwright Chromium. Highest fail risk.
With this order, a Phase D failure leaves the user with a working gstack
install minus browser-driven features (/qa, /design-review,
make-pdf, sidebar, /pair-agent). Re-running ./setup retries only
the failed phase since A-C are idempotent.
A separate (smaller) follow-up — already in flight as #1900, coordinated
with #1838 — converts the Playwright exit 1 paths to best-effort warns
so even a re-run failure is non-fatal.
Related
Summary
./setupis structured so that the riskiest step (Playwright Chromiumdownload) runs before several lower-risk steps (skill linking, hook
installation, version migrations). When the riskiest step fails, the
script exits 1 mid-run and the lower-risk steps never get a chance to
complete.
This means a user on a flaky network, a corporate machine with a
locked-down
bunx, or hitting the Bun-on-Windows pipe bug(oven-sh/bun#4253) ends up with a half-installed gstack: bun may be
copied, the browse binary may be built, but the actual user-facing
artifacts (skills, hooks, plan-tune machinery, gbrain regen) are
missing. A re-run of
./setupdoes the same thing — dies at the samestep — and the user has no easy path to a working install minus
browser features.
Failure modes observed
The current
setuporder interleaves trivial filesystem ops, expensivecompute, settings.json mutations, and external network/sudo steps:
bun install)~/.gstack/projects/exists (trivial filesystem)5-6. Install for Codex / Kiro / Factory / OpenCode (filesystem)
settings.json(mutation)settings.json(mutation)Concrete user-facing breakage when step 2 fails:
~/.claude/skills//qa,/ship,/reviewetc. don't exist.agents/sidecar symlinks not created/tmp/gstack-latest-versioncleanup never happens/tmpfile accumulatesSessionStarthook not registered insettings.jsonPostToolUse+PreToolUsehooks not registered/plan-tuneAUQ capture silently disabledEven the trivial
mkdir -p "$HOME/.gstack/projects"happens AFTER thePlaywright step, so a brand-new user without
~/.gstack/ends upwithout it.
Proposal
Reorder
setupso steps run in increasing order of failure probability:~/.gstack/, welcome, GBrain detectionfile scan). Cannot fail in practice.
migrations, GBrain SKILL.md regen. Fails only on bun bugs, fully
reproducible locally.
settings.jsonmutation: team-mode and plan-tune hooks.Fails only if
settings.jsonis malformed, fully reversible.on macOS, emoji font on Linux, Playwright Chromium. Highest fail risk.
With this order, a Phase D failure leaves the user with a working gstack
install minus browser-driven features (
/qa,/design-review,make-pdf, sidebar,/pair-agent). Re-running./setupretries onlythe failed phase since A-C are idempotent.
A separate (smaller) follow-up — already in flight as #1900, coordinated
with #1838 — converts the Playwright
exit 1paths to best-effort warnsso even a re-run failure is non-fatal.
Related
unrelated bug fixes and a Playwright behavior change. Per review
request, that PR is being split into three:
bun_cmdrouting +tail -3pipe)exit 1→ best-effort warn (coordinates with fix(setup): pin Playwright browser install to bundled version so headed browse connect works (#1829) #1838)same Playwright block).
ChildProcess.stdiofromchild_process.spawn({ stdio: ["pipe"] })has onlynullvalues oven-sh/bun#4253 — Bun-on-Windows pipe bug that Phase D needs totolerate, not abort over.