diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..62b441689 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: A gstack skill, helper or setup step broke or did something unexpected +labels: bug +--- + +## What happened + + + +## Steps to reproduce + +1. +2. + +## Readiness report + +Paste the complete output of gstack's doctor. It starts no skill, makes no paid +call and prints no secrets or file contents. Run the line for your install: + +```bash +# Claude Code +~/.claude/skills/gstack/bin/gstack-doctor + +# Any other host: from your gstack checkout, ./setup --status ends with the +# absolute path of the doctor ("Readiness check: ..."). Run that path. +./setup --status + +# The state root (where installs.tsv lists every install) for the same checkout: +./bin/gstack-paths --get GSTACK_STATE_ROOT +``` + +```text +(doctor output here) +``` + +## Environment + +- Host (Claude Code, Codex, Cursor, ...) and its version: +- OS: diff --git a/README.md b/README.md index d35450885..0d2defa87 100644 --- a/README.md +++ b/README.md @@ -650,6 +650,16 @@ Data is stored in [Supabase](https://supabase.com) (open source Firebase alterna ## Troubleshooting +**Not sure what's wrong?** Run the doctor: `~/.claude/skills/gstack/bin/gstack-doctor` +(on other hosts, `./setup --status` in your gstack checkout ends with the +doctor's absolute path). Without starting a skill or spending anything, it +prints one row per check (install, state root, Bun, hooks, Codex and its cached +model probe, artifacts sync, the browse bundle, Claude Code, your largest +session journal and recent /autoplan guard codes), each `ok`, `warn`, +`not configured` or `fail` with the command that fixes it. It exits non-zero +only on `fail`. `--live` also runs the paid Codex model check (one short call). +Paste its output into bug reports. + **A message says `not run`, `unavailable` or names a fix?** Look it up in [docs/troubleshooting.md](docs/troubleshooting.md): every gate message gstack prints, what it means, what was kept, and the command that fixes it. diff --git a/scripts/lib/windows-curation.ts b/scripts/lib/windows-curation.ts index d9c9f06a2..1694a0f2a 100644 --- a/scripts/lib/windows-curation.ts +++ b/scripts/lib/windows-curation.ts @@ -240,6 +240,7 @@ export const KNOWN_WINDOWS_SAFE: Array<{ file: string; reason: string }> = [ { file: 'test/generator-eexist.test.ts', reason: 'E4: runs the generators through Bun argv with the Windows EEXIST emulation preload; no shebang execution' }, { file: 'test/gstack-config-gbrain-refresh.test.ts', reason: 'E6: runs bin/gstack-config through explicit bash; its gbrain/python3 shims are found by bash PATH lookup, never launched by CreateProcess' }, + { file: 'test/gstack-doctor.test.ts', reason: 'runs bin/gstack-doctor and setup --status through explicit bash argv in an os.tmpdir fixture; its bun/codex/claude/probe stubs are found by bash PATH lookup, and expected paths use bash spellings' }, { file: 'test/qa-evidence.test.ts', reason: 'invokes the production helper through Bun argv and exercises native Windows job cleanup, private file captures and backpressured receipt output', diff --git a/test/gstack-doctor.test.ts b/test/gstack-doctor.test.ts index db5dadc6e..cdfff7401 100644 --- a/test/gstack-doctor.test.ts +++ b/test/gstack-doctor.test.ts @@ -337,3 +337,23 @@ describe('./setup --status Codex row', () => { expect(fs.readdirSync(f.state).sort()).toEqual(before); }); }); + +describe('bug-report template and README (DX-2, DX-12)', () => { + const template = fs.readFileSync(path.join(REPO, '.github/ISSUE_TEMPLATE/bug_report.md'), 'utf8'); + + test('the template asks for the doctor output with the Claude Code path and a lookup for other hosts', () => { + expect(template).toContain('~/.claude/skills/gstack/bin/gstack-doctor'); + expect(template).toContain('./setup --status'); + expect(template).toContain('/bin/gstack-paths --get GSTACK_STATE_ROOT'); + }); + + test('the template names no bare gstack- command', () => { + for (const m of template.matchAll(/gstack-[a-z]/g)) expect(template.slice(0, m.index).endsWith('/bin/'), template.slice(m.index! - 40, m.index! + 20)).toBe(true); + }); + + test('README troubleshooting points at the doctor by absolute path', () => { + const readme = fs.readFileSync(path.join(REPO, 'README.md'), 'utf8'); + const section = readme.slice(readme.indexOf('## Troubleshooting')); + expect(section).toContain('`~/.claude/skills/gstack/bin/gstack-doctor`'); + }); +});