mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-03 23:37:53 +01:00
* feat(loadouts): Opus 5.5 lite loadout with explicit model detection (GSTA-161)
modules/loadouts.json gains the lite loadout (eleven coaching preamble
pieces dropped; upgrade-check and brain-sync kept) and a models map that
sends only claude-opus-5-5 (and its dated snapshots) to it. Detection is
explicit: Capy passes --model to the installer, Claude Code opts in with
./setup --loadout lite; anything unmapped, invalid or unreadable serves full.
The checkout always stays the full render.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(loadouts): Opus 5.5 lite, detection order, Capy SKILL_ROOT, setup --loadout; troubleshooting anchors; changelog fragment (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(loadouts): claude_loadout read through CONFIG_BIN; capy skill context ceiling for the --model line (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (prune keeps a reused loadout folder, GSTACK_LOADOUT_SKILL_ROOT, claude_loadout guard test) (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (Capy skill passes the model as GSTACK_MODEL so an older installer ignores it) (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (prune only owned, unused folders; full root from the canonical Claude install; fallback reason and source) (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: loadout source example, install and resolve commands, Capy launch-file note (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(autoplan): --ceo-only runs the CEO review alone with zero questions (GST-537)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: classify autoplan-ceo-only in the Codex host metadata
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: select autoplan-ceo-only on the skills it runs; say it needs Claude Code
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: run autoplan-ceo-only in the marathon lane
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog entry for /autoplan --ceo-only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: count the autoplan-ceo-only paid file in the shard inventory
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat: gstack-autoplan next --ceo-only runs the CEO review alone and ends reviewed (GST-537)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: budget and close recover a budget-stopped CEO-only run; reviewed is at rest for checkpoints
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: CEO-only finish leaves owner-only cap items undecided, refuses marker phase flags and a plan at the report path, and replaces ceo-review.md atomically
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the CEO-only report-path guard compares real paths and refuses at the finish when the report file is the plan
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: CEO_ONLY_CONFLICT covers a plan linked to the report path
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(browse): failing-first device and touch tests (GSTA-227 F3, #3058)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the report-path guard keeps the lexical check, skips safe hard links and compares bigint file ids
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: per-session tabs for parallel agents; tab pins stop moving the shared active tab (#1961)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: keep the server.ts tab-pin anchor comment for source guards
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(browse): per-tab phone emulation and touch input ($B device, tap, swipe, pinch, touch; #3058, GSTA-227 F3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: copy lib/result-codes-autoplan.ts into the fixtures that copy the result-code tables, and keep it out of derived closures
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(qa, aside): touch pointer in /qa, Aside touch recipe verified on Aside 1.26, report Phones row (GSTA-227 F3, #3058)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: drop the sessions paragraph from /browse to stay inside the parity cap
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: F3 phone emulation and touch entry
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: hide the ps window in the session harness walk
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the decisions.jsonl status list names auto_kept
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(browse): session cap, LRU eviction, headed release and scoped auto-session rows
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: sessions keep tab <id> picks, sidebar claude stays on the user's tab, pinned rebuild and state load rebind the scope
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (touch cancel with no finger held is a no-op)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: Step 11 review fixes (headed tab adoption, pinned viewport reset, CLI retry keeps --session, rebuild id remap, --json notice, evicted-session reset, device kept after annotated captures, render opts out of sessions, session: client ids reserved)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: headed viewport auto keeps the user's active tab; render's closetab opts out of sessions
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: sessions, phone emulation and touch in BROWSER.md; session: client ids reserved; TODOS #1961/#3058 shipped
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: copy lib/result-codes-browse.ts into the fixtures that copy the result-code modules
lib/result-codes.ts imports ./result-codes-browse, so fixtures with an explicit
lib list failed with 'Cannot find module'. pr-dependencies lists it with the other
reason-code modules as selection data. GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat: gstack-clean reclaims per-repo .gstack scratch and logs, dry run by default (#2627)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: name the Aside touch recipe's coordinates <tap-x>/<tap-y> with a numeric grammar
The generated-bash lint (INV-3) rejected the free-text <x>/<y> placeholders. GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): leave hard-linked and unreadable logs alone; cut through a no-follow descriptor checked against the evaluated inode
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): tests that expect tmp removal see a quiet ps, so a codex elsewhere on the host cannot flake them
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): an unlistable tmp/ skips its group; liveness asked once per group on apply; BROWSER.md says which logs reset at daemon start
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): write output synchronously so --json reaches a pipe whole; test fixes for root, wrapper git and the ps stub
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): every change rechecks the verified folder and the measured file; full writes; EPIPE ends output quietly
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): the early-close test checks the bin's own exit status
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: list gstack-clean among the standalone CLIs
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): copied-install fixtures and the dependency list carry lib/result-codes-clean.ts
The remote pregate failed 11 cases in gstack-doctor, plan-tune-cathedral and
timeline-stop-hook-slug: each copies an explicit list of lib/result-codes-*.ts
files into a temp install, and lib/result-codes.ts now imports
./result-codes-clean. Same lists GSTA-168 extended for result-codes-eval.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: regenerate gstack-doctor-components.sh for the gstack-clean result codes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* qa: fold the touch pointer into the Phases sentence to fit the parity size cap after the main merge
qa's union was 95988 bytes (ratio 1.142 > maxSizeRatio 1.142, train 75). Now 95975 (1.1419). GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.10.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): classify gstack-tasks rows files (tasks-*) as kept, after main added the producer
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.20.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (restore the lib/result-codes-plan.ts ratchet row the base merge dropped)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): the producer scan ends a name at a colon, so prose after a path names the file (train 78)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.30.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* outside-voice-api: caller receipts, stop_reason, OpenAI max_completion_tokens
A caller can write its own egress receipt (sink, consent, payload class);
the default stays the outside-voice receipt, so existing callers send and
record the same bytes. The result carries the provider's stop reason, and
an OpenAI request gets max_completion_tokens only when the caller sets an
output limit (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan gate: item classes and the owner's answer provenance
Gate items carry item_class, ruleKept() names the keep-direction pick, and
answered decision rows record owner_mode, owner_named, rec_hash and
answered_role parsed from the owner's own words (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan: shadow-mode decider module, frozen prompt and spend accounting
The switch (off by default, fixed at init), the lease, one model call per
gate with a page retry and a truncation retry under one deadline, the
once-per-revision record with its journaled sha256, the 10% audit mark,
and shadow-labeled ledger rows that count against the cap, show as
shadow= on GATE_SPEND and stay out of the per-voice price (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* gstack-autoplan: shadow every published gate, the shadow export, config and docs
Every driver command that prints a gate records the shadow first and
checkpoints after it; answer waits for a live lease and records a dead
one retrospectively; gstack-autoplan shadow exports answered revisions
for taste-replay R2 (SHADOW_BEFORE_ANSWER otherwise); gstack-config
autoplan_shadow / autoplan_shadow_model; gstack-artifact validate checks
the record's hash (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: shadow mode for the CEO-only decider (GST-537 PR 3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan shadow: /ship review fixes
- register test/fixtures/shadow-fake-model.ts in FREE_FIXTURES (free-fixtures inventory failed)
- withRunLock: count dead-owner reclaims apart from waitMs iterations, so a long wait can still reclaim
- buildPage: fill the decider template in one pass, so slot names inside the plan stay plan text
- revise regate: the shared publish step prints the GATE and ESCALATE lines once
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan shadow: reply files never follow a link; the retry reserves against the current cap
- a model reply is written by temp file and rename, so a link at the reply path is replaced, not written through
- each shadow reservation reads the run's current spend cap, so a budget change during the call is not undone
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* outside-voice-api: write the egress receipt under the caller's env
callModel resolved the receipt's state root from process.env even when the caller passed env, so the shadow
tests wrote to the real ~/.gstack (the free-suite home-containment guard caught it). The receipt now uses
req.env; the shadow tests give the fake model a private HOME, GSTACK_HOME and GSTACK_STATE_ROOT, and the receipt
test no longer sets process.env to pass.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(autoplan): CEO-only runs leave main's open Critical/High finding items to the owner (no decision row)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(autoplan): shadow pages carry main's finding items; a finding item is never ceo_eligible
After merging #3767 (main 90a170c), open Critical/High findings are gate items
(item_class finding). The shadow records one row per gate item, so its pages now
include them. A CEO-only run leaves those items to the owner, so their rows are
ceo_eligible false (rule_pick was already null). The shadow fixtures follow
main's gate (items, counts, "Do it" tokens); the two merge adapters follow
main's doNext(out, rest, price) and its per-voice reservation (--estimate-usd).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.61.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(investigate): drop the five-phase step procedure (GST-938)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: GST-938 fragment wording
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(investigate): keep the web-search sanitize guard; update BROWSER.md and docs/skills.md (review pass 1)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: GST-938 wording
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(investigate): pin the web-search guard; changelog size (adversarial review)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): classify restamp-staging.json, the restamp producer main gained after #3779's base (wave browse)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (wave browse): scoped newtab keeps a concurrent tab switch; shadow validate catches a deleted record; a failed shadow publish is journaled
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: a failed shadow publish journals under the run lock and never throws (wave browse review pass 2)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(unattended): shadow publish failures and the missing-record validate check (wave browse docs audit)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: wave browse integrator fixes fragment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: shadow reader dedupes by run folder, so two runs started in the same second both count (wave browse CI free-suite 16)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: regenerate doctor result anchors in generator order (wave browse rebuild without #3818)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: name the wave fragment after the rebuilt wave
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
308 lines
12 KiB
Cheetah
308 lines
12 KiB
Cheetah
---
|
|
name: qa
|
|
preamble-tier: 4
|
|
version: 2.0.0
|
|
description: |
|
|
Test the site, API or CLI and fix the bugs it finds.
|
|
Covers browser/API/CLI/job/worker/webhook bugs and commits verified fixes atomically.
|
|
Use when asked to "qa", "QA", "qa test this", "test this site", "find bugs", "find bugs on site",
|
|
"test and fix", or "fix what's broken".
|
|
Proactively suggest when the user says a feature is ready for testing
|
|
or asks "does this work?". Three tiers: Quick (critical/high only),
|
|
Standard (+ medium), Exhaustive (+ cosmetic). Produces contract outcomes or browser health scores,
|
|
fix evidence, and a ship-readiness summary. For report-only mode, use /qa-only. (gstack)
|
|
codex_default_prompt: "Use $gstack-qa to test what changed (browser, API, CLI, jobs, workers, webhooks), reproduce each defect, fix it, and prove the fix with a regression test."
|
|
voice-triggers:
|
|
- "quality check"
|
|
- "test the app"
|
|
- "run QA"
|
|
allowed-tools:
|
|
- Bash
|
|
- Read
|
|
- Write
|
|
- Edit
|
|
- Glob
|
|
- Grep
|
|
- AskUserQuestion
|
|
- WebSearch
|
|
triggers:
|
|
- qa test this
|
|
- find bugs on site
|
|
- test the site
|
|
---
|
|
|
|
{{PREAMBLE}}
|
|
|
|
{{BASE_BRANCH_DETECT}}
|
|
|
|
{{GBRAIN_CONTEXT_LOAD}}
|
|
|
|
# /qa: Test → Fix → Verify
|
|
|
|
---
|
|
|
|
{{SECTION_INDEX:qa}}
|
|
|
|
---
|
|
|
|
## Setup
|
|
|
|
{{SECTION:scope}}
|
|
|
|
**Parse the user's request for these parameters:**
|
|
|
|
| Parameter | Default | Override example |
|
|
|-----------|---------|-----------------:|
|
|
| Target | (infer from request/repository or ask) | Browser URL, API route, CLI command, job, worker or webhook |
|
|
| Tier | Standard | `--quick`, `--exhaustive` |
|
|
| Mode | full | `--quick`, `--regression <previous-report-or-baseline>` |
|
|
| Output dir | `.gstack/qa-reports/` | `Output to /tmp/qa` |
|
|
| Scope | Selected target (or diff-scoped) | `Focus on duplicate webhook delivery` |
|
|
| Auth | Isolated synthetic identity for functional probes | Browser session handling lives in browser setup; never request credentials in chat |
|
|
|
|
**Tiers determine which issues get fixed:**
|
|
- **Quick:** Fix critical + high severity only
|
|
- **Standard:** + medium severity (default)
|
|
- **Exhaustive:** + low/cosmetic severity
|
|
|
|
`--quick` sets both the Quick fix tier and Quick exploration; `--exhaustive` changes only the fix tier.
|
|
Regression mode preserves the selected fix tier.
|
|
If both `--quick` and `--regression` are supplied, ask which exploration mode to use
|
|
before setup or probes. Keep the selected fix tier; this choice concerns exploration only.
|
|
|
|
**On a feature branch without an explicit scope:** Use diff-aware testing of changed
|
|
and adjacent behavior. Select the surface first; absence of a URL never forces a browser.
|
|
|
|
**Check for clean working tree:**
|
|
|
|
```bash
|
|
git status --porcelain
|
|
```
|
|
|
|
If dirty, **STOP** and use AskUserQuestion. Explain that a clean tree keeps QA fixes atomic:
|
|
- A) Commit all current changes with a descriptive message before QA (recommended).
|
|
- B) Stash changes, run QA, then pop the stash.
|
|
- C) Abort for manual cleanup.
|
|
|
|
Execute only the user's choice before continuing setup.
|
|
|
|
**Prepare report artifacts before browser setup.** Resolve any supplied prior report
|
|
and baseline paths before writing. Select the output override or `.gstack/qa-reports`.
|
|
Create that directory if absent. Use the directory as `REPORT_DIR`
|
|
only when it is empty; otherwise choose a fresh owned run subdirectory.
|
|
Use `run-YYYYMMDDTHHMMSSZ` in UTC, adding a suffix on collision. Keep all local evidence there.
|
|
Never overwrite previous reports, baselines, screenshots or exploration notes.
|
|
A caller's fixed artifact paths and permissions take precedence; if preserving them
|
|
safely is impossible, report the output blocker rather than expanding write authority.
|
|
|
|
**Browser surface only:** load its setup; functional-only runs skip this section.
|
|
|
|
{{SECTION:browser-setup}}
|
|
|
|
**Browser surface only:** check the test framework and use the existing bootstrap
|
|
offer if needed. Functional targets use supported native tests or report the gap;
|
|
they do not load this browser bootstrap or generate CI.
|
|
|
|
{{SECTION:test-bootstrap}}
|
|
|
|
---
|
|
|
|
{{LEARNINGS_SEARCH:query=qa testing bug regression flake fixture}}
|
|
|
|
## Test Plan Context
|
|
|
|
Prefer the richer of recent project test plans and plans in conversation over git diff:
|
|
|
|
1. **Project-scoped test plans:** Find the latest for this repo:
|
|
```bash
|
|
GSTACK_STATE_ROOT=$(~/.claude/skills/gstack/bin/gstack-paths --get GSTACK_STATE_ROOT); : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
|
|
setopt +o nomatch 2>/dev/null || true # zsh compat
|
|
{{SLUG_EVAL}}
|
|
ls -t "$GSTACK_STATE_ROOT"/projects/$SLUG/*-test-plan-*.md 2>/dev/null | head -1
|
|
```
|
|
2. **Conversation context:** Prior `/plan-eng-review` or `/plan-ceo-review` test plans.
|
|
3. Fall back to git diff only if neither exists.
|
|
|
|
---
|
|
|
|
## Phases 1-6: QA Baseline
|
|
|
|
Follow the shared section's ordered preparation, then run its probe loop.
|
|
In that loop, browser runs use qa-patterns.md's Phases 1-6 as techniques (touch: `$B device "iPhone 15"`, then `tap`),
|
|
and functional runs use system-functional.md's contract map; neither is a separate workflow.
|
|
|
|
{{SECTION:exploratory}}
|
|
|
|
Report baseline findings before fixing. Keep browser scores and functional outcomes separate.
|
|
|
|
---
|
|
|
|
## Output Structure
|
|
|
|
Under `$REPORT_DIR`, write `qa-report-{target}-{YYYY-MM-DD}.md` and the browser's
|
|
`baseline.json`. Browser `{target}` is a safe hostname.
|
|
Browser evidence goes in `screenshots/`: `initial.jpg`,
|
|
`issue-NNN-step-N.jpg`, `issue-NNN-result.jpg`, annotated `issue-NNN.png` and
|
|
`issue-NNN-after.jpg` (Phase 5 is the before). Functional reports use a safe command/service
|
|
label and sanitized command/request/state evidence.
|
|
|
|
---
|
|
|
|
## Phase 7: Triage
|
|
|
|
Sort issues by severity and apply the selected fix tier. Mark lower-tier issues and
|
|
those not fixable from source (third-party widgets, infrastructure) as "deferred."
|
|
|
|
### Refresh learnings for the component/page where the bug lives
|
|
|
|
Before the fix loop, search again for the buggy component/page. Use ONE noun containing
|
|
only letters, digits or hyphens (e.g., `checkout-button`, `payment`), never a path,
|
|
quotes, whitespace or other punctuation; simplify to an alphanumeric stem if needed.
|
|
|
|
```bash
|
|
{ _LE=$(~/.claude/skills/gstack/bin/gstack-learnings-search --query "<your-keyword>" --limit 5 2>&1 >&3 3>&-); _LR=$?; } 3>&1
|
|
[ "$_LR" = 0 ] || { _LE=${_LE%%$'\n'*}; echo "LEARNINGS: unavailable (${_LE:-exit $_LR})"; }
|
|
```
|
|
|
|
Name an applicable learning in one sentence, or continue if none applies.
|
|
|
|
---
|
|
|
|
## Phase 8: Fix Loop
|
|
|
|
For each fixable issue, in severity order:
|
|
|
|
### 8a. Diagnose and reproduce
|
|
|
|
Use the shared loop's causal hypothesis and minimized replay, recording actual versus
|
|
documented behavior before edits. Modify only responsible files. Environment failures
|
|
and unclear contracts never authorize repair.
|
|
|
|
### 8a.5. Regression test before repair
|
|
|
|
{{TEST_VALUE_BAR:qa}}
|
|
|
|
Extend an existing table or fixture when one covers the boundary; never add a production
|
|
seam for the test. Match 2-3 nearby tests' naming, imports, assertions and fixtures, and detect the command that runs them. Reproduce the failure
|
|
in a new native test. Run its detected command before repair; prove the defect caused its
|
|
failure, not a bad fixture, import or service. Attribute it in the language's comment syntax:
|
|
|
|
```text
|
|
// Regression: ISSUE-NNN — short defect description
|
|
// Found by /qa on YYYY-MM-DD
|
|
// Report: .gstack/qa-reports/qa-report-{target}-{date}.md
|
|
```
|
|
|
|
A clear, healthy uncovered contract may gain a passing test without product edits.
|
|
|
|
Apply the shared exploratory section's native unit/integration/E2E rules.
|
|
CSS-only defects may use browser evidence. Missing infrastructure stays coverage debt.
|
|
|
|
Use the component's name and native extension in auto-incrementing `{name}.regression-N.test.{ext}`.
|
|
Set N to max number + 1, starting at 1; never replace an existing file.
|
|
Keep valid red regressions; narrowly correct a proved
|
|
fixture/test error or report the unresolved bug.
|
|
|
|
### 8b. Fix
|
|
|
|
Read the surrounding source and make the **minimal fix**. No unrelated refactors or features.
|
|
|
|
### 8c. Re-test
|
|
|
|
Re-run the regression, original failing probe and adjacent happy path. Inspect each
|
|
final state; acceptance alone cannot verify a worker repair. Failed/unavailable rechecks stay unresolved:
|
|
try one revised minimal fix, else classify it reverted.
|
|
|
|
For browser defects only:
|
|
|
|
{{SECTION:browser-verify}}
|
|
|
|
### 8d. Commit verified work
|
|
|
|
```bash
|
|
git add <only-verified-source-and-regression-files>
|
|
git commit -m "fix(qa): ISSUE-NNN — short description"
|
|
```
|
|
|
|
Commit each verified fix with its regression, never unrelated fixes. Leave unresolved
|
|
repairs and valid red regressions/evidence uncommitted; tell the user what remains.
|
|
|
|
### 8e. Classify
|
|
|
|
- **verified**: passed 8c (native regression when available); disclose missing test coverage
|
|
- **best-effort**: fix applied but couldn't fully verify (e.g., needs auth state, external service)
|
|
- **reverted**: regression detected or finding unresolved → undo only this run's repair (revert its commit if already committed), retain the valid regression/evidence, and mark the issue "deferred". Never discard user changes.
|
|
|
|
### 8e.5. Regression Test record
|
|
|
|
Record the test created before repair in 8a.5 and its re-test result from 8c:
|
|
file, command, attribution, tested boundary, value card and red/green evidence, or why it is deferred.
|
|
This step records results; it does not create another test.
|
|
Healthy-contract commits use `test(qa): regression test for {contract}`.
|
|
**Self-regulation exclusion:** test-only commits do not count toward the stop rule in 8f.
|
|
|
|
### 8f. Self-Regulation (STOP AND EVALUATE)
|
|
|
|
Every 5 fixes, and after any revert, check whether the loop is doing more harm than
|
|
good. **STOP immediately** after two reverts or one edit to a file unrelated to the
|
|
finding. Also stop when fixes keep spanning many files or only Low issues remain.
|
|
Show the user what you've done so far and ask whether to continue.
|
|
|
|
**Hard cap: 50 fixes.** After 50 fixes, stop regardless of remaining issues.
|
|
|
|
---
|
|
|
|
## Phase 9: Final QA
|
|
|
|
Re-run affected contracts and adjacent happy paths on the final inputs.
|
|
Caller-required rechecks cannot be skipped as unaffected. For browser
|
|
surfaces, recheck affected pages and compute the final health score. Warn prominently
|
|
about a worse score or regressed contract; blocked/inconclusive rechecks never verify repairs.
|
|
|
|
---
|
|
|
|
## Phase 10: Report
|
|
|
|
Write the Output Structure report locally and copy the same content to project context:
|
|
```bash
|
|
{{SLUG_SETUP}}
|
|
```
|
|
Write to `<PROJECT_DIR>/{user}-{branch}-test-outcome-{datetime}.md` (`PROJECT_DIR` printed above)
|
|
from `git config user.name`, `git branch --show-current` (else `unknown-user`, `detached`;
|
|
non-alphanumerics → `-`) and UTC `YYYYMMDDTHHMMSSZ`.
|
|
|
|
**Per-issue additions:**
|
|
- Fix Status: verified / best-effort / reverted / deferred
|
|
- Commit SHA (if fixed)
|
|
- Files Changed (if fixed)
|
|
- Before/After evidence: screenshots for browser, outputs/requests/durable state for functional
|
|
|
|
**Summary:** total issues, verified/best-effort/reverted fixes and deferred issues.
|
|
For browser coverage include the score delta. For functional coverage include
|
|
passing/failing/blocked/not-run contracts, permanent regressions and remaining risks,
|
|
never a score. Keep mixed results separate.
|
|
|
|
**PR Summary:** one line, "QA found N issues, fixed M, health score X → Y."
|
|
Functional targets: contract outcomes, not a score.
|
|
|
|
---
|
|
|
|
## Phase 11: TODOS.md Update
|
|
|
|
If the repo has a `TODOS.md`:
|
|
|
|
1. **New deferred bugs** → add as TODOs with severity, category, and repro steps
|
|
2. **Fixed bugs that were in TODOS.md** → annotate with "Fixed by /qa on {branch}, {date}"
|
|
|
|
---
|
|
|
|
{{LEARNINGS_LOG}}
|
|
|
|
{{GBRAIN_SAVE_RESULTS}}
|
|
|
|
## Additional Rules (qa-specific)
|
|
|
|
**Outside an explicitly approved browser bootstrap:** Only create tests through authorized codification in Phase 8a.5. Never modify CI configuration or weaken existing tests; use new native test files.
|
|
|
|
When in doubt, stop and ask.
|