~cytrogen/gstack

cddf8ee3bdfe32fdd275e68588cdff1ca13ed382 — Garry Tan a month ago 4a56b88
fix: simplify planted-bug eval prompts for reliable 25-turn completion

The QA agent was spending all 50 turns reading qa/SKILL.md and browsing
without ever writing a report. Replace verbose QA workflow prompt with
concise, direct bug-finding instructions. The /qa quick test already
validates the full QA workflow E2E — planted-bug evals test "can the
agent find bugs with browse", not the QA workflow documentation.

- 25 maxTurns (was 50) — more focused, less cost (~$0.50 vs ~$1.00)
- Direct step-by-step instructions instead of "read qa/SKILL.md"
- 180s timeout (was 300s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 files changed, 35 insertions(+), 25 deletions(-)

M test/skill-e2e.test.ts
M test/skill-e2e.test.ts => test/skill-e2e.test.ts +35 -25
@@ 374,35 374,45 @@ describeOutcome('Planted-bug outcome evals', () => {

  /**
   * Shared planted-bug eval runner.
   * Runs /qa Standard on a fixture page, then scores with outcomeJudge.
   * Gives the agent concise bug-finding instructions (not the full QA workflow),
   * then scores the report with an LLM outcome judge.
   */
  async function runPlantedBugEval(fixture: string, groundTruthFile: string, label: string) {
    const reportDir = path.join(outcomeDir, `reports-${label}`);
    fs.mkdirSync(path.join(reportDir, 'screenshots'), { recursive: true });
    const reportPath = path.join(reportDir, 'qa-report.md');

    // Phase 1: runs /qa Standard
    // Phase 1: Direct bug-finding with browse. Keep prompt concise — the agent
    // only has 25 turns so every turn must count (no reading long SKILL.md docs).
    const result = await runSkillTest({
      prompt: `You have a browse binary at ${browseBin}. Assign it to B variable like: B="${browseBin}"
      prompt: `You have a headless browser binary. Run these commands to find bugs on a web page.

Read the file qa/SKILL.md for the QA workflow instructions.
B="${browseBin}"

Step 1 — Navigate and inspect:
$B goto ${testServer.url}/${fixture}
$B console --errors
$B snapshot -i

Step 2 — Test interactively (click links, fill forms, check states):
- Click every navigation link, check for broken routes/404s
- Fill and submit every form with valid AND invalid data (empty, bad email, etc.)
- Check $B console --errors after each action

Step 3 — Check visual/accessibility:
$B snapshot -c
$B accessibility

Navigate to ${testServer.url}/${fixture} and run a Standard-depth QA test.
Do NOT use AskUserQuestion — run Standard tier directly.
Write your report to ${reportPath}
Save screenshots to ${reportDir}/screenshots/

IMPORTANT — be methodical and check ALL of these:
1. Run $B console --errors to check for JavaScript errors/warnings
2. Click every link and check for 404s or broken routes
3. Fill out and submit every form — test edge cases (empty fields, invalid input)
4. Run $B snapshot -i to check interactive elements and their states
5. Check for visual issues: overflow, clipping, layout problems
6. Check accessibility: missing alt text, missing aria attributes
7. Test with different viewport sizes if relevant`,
Step 4 — Write your findings to ${reportPath}
List every bug found with:
- Category: functional / visual / accessibility / console
- Severity: high / medium / low
- Description with evidence (what you saw, what command showed it)

Be thorough but efficient. Check console errors, test every link, test every form, check accessibility.`,
      workingDirectory: outcomeDir,
      maxTurns: 50,
      timeout: 300_000,
      maxTurns: 25,
      timeout: 180_000,
    });

    logCost(`/qa ${label}`, result);


@@ 470,19 480,19 @@ IMPORTANT — be methodical and check ALL of these:
  }

  // B6: Static dashboard — broken link, disabled submit, overflow, missing alt, console error
  test('/qa standard finds >= 3 of 5 planted bugs (static)', async () => {
  test('/qa finds >= 2 of 5 planted bugs (static)', async () => {
    await runPlantedBugEval('qa-eval.html', 'qa-eval-ground-truth.json', 'b6-static');
  }, 360_000);
  }, 240_000);

  // B7: SPA — broken route, stale state, async race, missing aria, console warning
  test('/qa standard finds >= 3 of 5 planted SPA bugs', async () => {
  test('/qa finds >= 2 of 5 planted SPA bugs', async () => {
    await runPlantedBugEval('qa-eval-spa.html', 'qa-eval-spa-ground-truth.json', 'b7-spa');
  }, 360_000);
  }, 240_000);

  // B8: Checkout — email regex, NaN total, CC overflow, missing required, stripe error
  test('/qa standard finds >= 3 of 5 planted checkout bugs', async () => {
  test('/qa finds >= 2 of 5 planted checkout bugs', async () => {
    await runPlantedBugEval('qa-eval-checkout.html', 'qa-eval-checkout-ground-truth.json', 'b8-checkout');
  }, 360_000);
  }, 240_000);

  // Ship E2E deferred — too complex (requires full git + test suite + VERSION + CHANGELOG)
  test.todo('/ship completes without browse errors');