← Back to the overview · Open the app

Build check results

Every check, on every demo branch, with the real tool output. Snapshot from Nov 8, 2026. The same checks run in GitHub Actions on every pull request.

BranchESLintCode qualityPHI guardSecuritySemgrep SASTSecurityGitleaks secretsSecuritynpm auditSecurityPlaywright + axeTests
mainBefore: no waitlistPassPassPassPassPassPass
CSD-1-testsTests first (red)PassPassPassPassPassFail
CSD-1-waitlistWaitlist code (green)PassPassPassPassPassPass
demo-broken-waitlistPlanted logic bugPassPassPassPassPassFail
demo-security-issueCSD-3 built without approvalPassFailFailPassPassPass

main

Before: no waitlist

Pass Code quality: ESLint
Pass Security: PHI guard
PHI guard: no patient data patterns found.
Pass Security: Semgrep SAST
┌─────────────┐
│ Scan Status │
└─────────────┘
  Scanning 62 files tracked by git with 3 Code rules:
  Scanning 11 files with 3 js rules.

┌──────────────┐
│ Scan Summary │
└──────────────┘
Some files were skipped or only partially analyzed.
  Scan was limited to files tracked by git.

Ran 3 rules on 11 files: 0 findings.
Pass Security: Gitleaks secrets
○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

12:06AM INF scan completed in 487ms
12:06AM INF no leaks found
Pass Security: npm audit
found 0 vulnerabilities
Pass Tests: Playwright + axe · Open Playwright report
Running 4 tests using 1 worker

  ✓  1 [chromium] › tests/accessibility.spec.js:14:3 › Accessibility › A11Y: class page has no WCAG 2.1 AA violations (1.5s)
  ✓  2 [chromium] › tests/accessibility.spec.js:20:3 › Accessibility › A11Y: messages and roster have no WCAG 2.1 AA violations (1.6s)
  ✓  3 [chromium] › tests/registration.spec.js:6:3 › Registration (baseline) › a person can register for a class with open seats (692ms)
  ✓  4 [chromium] › tests/registration.spec.js:15:3 › Registration (baseline) › name and a valid email are required (710ms)

  4 passed (5.7s)

CSD-1-tests

Tests first (red)

Pass Code quality: ESLint
Pass Security: PHI guard
PHI guard: no patient data patterns found.
Pass Security: Semgrep SAST
┌─────────────┐
│ Scan Status │
└─────────────┘
  Scanning 64 files tracked by git with 3 Code rules:
  Scanning 12 files with 3 js rules.

┌──────────────┐
│ Scan Summary │
└──────────────┘
Some files were skipped or only partially analyzed.
  Scan was limited to files tracked by git.

Ran 3 rules on 12 files: 0 findings.
Pass Security: Gitleaks secrets
○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

12:07AM INF scan completed in 162ms
12:07AM INF no leaks found
Pass Security: npm audit
found 0 vulnerabilities
Fail Tests: Playwright + axe · Open Playwright report
r({ hasText: 'Riley Chen' }).getByRole('button', { name: 'Accept offer' })

      75 |
      76 |     await page.getByTestId('advance-23h').click(); // 23 hours later: still inside 24 hours
    > 77 |     await seatRow(page, 'Riley Chen').getByRole('button', { name: 'Accept offer' }).click();
         |                                                                                     ^
      78 |
      79 |     await expectSeatStatus(page, 'Riley Chen', 'Confirmed');
      80 |     await snap(page, 'AC5 offer accepted');
        at /home/claude/repo/tests/waitlist.spec.js:77:85

    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-372a6-ffer-inside-the-hold-window-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/waitlist-CSD-1-Class-waitl-372a6-ffer-inside-the-hold-window-chromium/error-context.md

    attachment #3: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-372a6-ffer-inside-the-hold-window-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/waitlist-CSD-1-Class-waitl-372a6-ffer-inside-the-hold-window-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  6) [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it

    Error: expect(locator).toContainText(expected) failed

    Locator: getByTestId('seat-row').filter({ hasText: 'Riley Chen' })
    Expected substring: "Offered"
    Timeout: 5000ms
    Error: element(s) not found

    Call log:
      - Expect "toContainText" getByTestId('seat-row').filter({ hasText: 'Riley Chen' }) with timeout 5000ms
      - waiting for getByTestId('seat-row').filter({ hasText: 'Riley Chen' })

       at helpers.js:32

      30 |
      31 | export async function expectSeatStatus(page, name, statusText) {
    > 32 |   await expect(seatRow(page, name)).toContainText(statusText);
         |                                     ^
      33 | }
      34 |
      35 | // Attach a named screenshot to the test report. Use it at the moments that prove a rule.
        at expectSeatStatus (/home/claude/repo/tests/helpers.js:32:37)
        at /home/claude/repo/tests/waitlist.spec.js:91:11

    attachment #2: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  7) [chromium] › tests/waitlist.spec.js:100:3 › CSD-1 Class waitlist › AC7: confirmed plus offered seats never go above capacity

    Error: expect(locator).toHaveCount(expected) failed

    Locator:  getByTestId('seat-row')
    Expected: 3
    Received: 1
    Timeout:  5000ms

    Call log:
      - Expect "toHaveCount" getByTestId('seat-row') with timeout 5000ms
      - waiting for getByTestId('seat-row')
        14 × locator resolved to 1 element
           - unexpected value "1"

      107 |
      108 |     await snap(page, 'AC7 seats and waitlist');
    > 109 |     await expect(seatRows(page)).toHaveCount(3);
          |                                  ^
      110 |     await expect(waitlistRows(page)).toHaveCount(1);
      111 |   });
      112 | });
        at /home/claude/repo/tests/waitlist.spec.js:109:34

    attachment #2: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-48466-ats-never-go-above-capacity-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/waitlist-CSD-1-Class-waitl-48466-ats-never-go-above-capacity-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-48466-ats-never-go-above-capacity-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/waitlist-CSD-1-Class-waitl-48466-ats-never-go-above-capacity-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  7 failed
    [chromium] › tests/waitlist.spec.js:23:3 › CSD-1 Class waitlist › AC1: a full class puts a new person on the waitlist
    [chromium] › tests/waitlist.spec.js:33:3 › CSD-1 Class waitlist › AC2: the waitlist keeps the order people joined
    [chromium] › tests/waitlist.spec.js:44:3 › CSD-1 Class waitlist › AC3: the same email cannot register twice (seat or waitlist)
    [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer
    [chromium] › tests/waitlist.spec.js:71:3 › CSD-1 Class waitlist › AC5: a person can accept the offer inside the hold window
    [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it
    [chromium] › tests/waitlist.spec.js:100:3 › CSD-1 Class waitlist › AC7: confirmed plus offered seats never go above capacity
  4 passed (53.3s)

CSD-1-waitlist

Waitlist code (green)

Pass Code quality: ESLint
Pass Security: PHI guard
PHI guard: no patient data patterns found.
Pass Security: Semgrep SAST
┌─────────────┐
│ Scan Status │
└─────────────┘
  Scanning 64 files tracked by git with 3 Code rules:
  Scanning 12 files with 3 js rules.

┌──────────────┐
│ Scan Summary │
└──────────────┘
Some files were skipped or only partially analyzed.
  Scan was limited to files tracked by git.

Ran 3 rules on 12 files: 0 findings.
Pass Security: Gitleaks secrets
○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

12:08AM INF scan completed in 211ms
12:08AM INF no leaks found
Pass Security: npm audit
found 0 vulnerabilities
Pass Tests: Playwright + axe · Open Playwright report
Running 11 tests using 1 worker

  ✓   1 [chromium] › tests/accessibility.spec.js:14:3 › Accessibility › A11Y: class page has no WCAG 2.1 AA violations (1.4s)
  ✓   2 [chromium] › tests/accessibility.spec.js:20:3 › Accessibility › A11Y: messages and roster have no WCAG 2.1 AA violations (1.4s)
  ✓   3 [chromium] › tests/registration.spec.js:6:3 › Registration (baseline) › a person can register for a class with open seats (680ms)
  ✓   4 [chromium] › tests/registration.spec.js:15:3 › Registration (baseline) › name and a valid email are required (717ms)
  ✓   5 [chromium] › tests/waitlist.spec.js:23:3 › CSD-1 Class waitlist › AC1: a full class puts a new person on the waitlist (904ms)
  ✓   6 [chromium] › tests/waitlist.spec.js:33:3 › CSD-1 Class waitlist › AC2: the waitlist keeps the order people joined (1.0s)
  ✓   7 [chromium] › tests/waitlist.spec.js:44:3 › CSD-1 Class waitlist › AC3: the same email cannot register twice (seat or waitlist) (1.1s)
  ✓   8 [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer (1.1s)
  ✓   9 [chromium] › tests/waitlist.spec.js:71:3 › CSD-1 Class waitlist › AC5: a person can accept the offer inside the hold window (1.1s)
  ✓  10 [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it (1.2s)
  ✓  11 [chromium] › tests/waitlist.spec.js:100:3 › CSD-1 Class waitlist › AC7: confirmed plus offered seats never go above capacity (1.1s)

  11 passed (13.0s)

demo-broken-waitlist

Planted logic bug

Pass Code quality: ESLint
Pass Security: PHI guard
PHI guard: no patient data patterns found.
Pass Security: Semgrep SAST
┌─────────────┐
│ Scan Status │
└─────────────┘
  Scanning 64 files tracked by git with 3 Code rules:
  Scanning 12 files with 3 js rules.

┌──────────────┐
│ Scan Summary │
└──────────────┘
Some files were skipped or only partially analyzed.
  Scan was limited to files tracked by git.

Ran 3 rules on 12 files: 0 findings.
Pass Security: Gitleaks secrets
○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

12:09AM INF scan completed in 263ms
12:09AM INF no leaks found
Pass Security: npm audit
found 0 vulnerabilities
Fail Tests: Playwright + axe · Open Playwright report
Running 11 tests using 1 worker

  ✓   1 [chromium] › tests/accessibility.spec.js:14:3 › Accessibility › A11Y: class page has no WCAG 2.1 AA violations (1.5s)
  ✓   2 [chromium] › tests/accessibility.spec.js:20:3 › Accessibility › A11Y: messages and roster have no WCAG 2.1 AA violations (1.7s)
  ✓   3 [chromium] › tests/registration.spec.js:6:3 › Registration (baseline) › a person can register for a class with open seats (631ms)
  ✓   4 [chromium] › tests/registration.spec.js:15:3 › Registration (baseline) › name and a valid email are required (728ms)
  ✓   5 [chromium] › tests/waitlist.spec.js:23:3 › CSD-1 Class waitlist › AC1: a full class puts a new person on the waitlist (831ms)
  ✓   6 [chromium] › tests/waitlist.spec.js:33:3 › CSD-1 Class waitlist › AC2: the waitlist keeps the order people joined (1.1s)
  ✓   7 [chromium] › tests/waitlist.spec.js:44:3 › CSD-1 Class waitlist › AC3: the same email cannot register twice (seat or waitlist) (991ms)
  ✘   8 [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer (6.1s)
  ✓   9 [chromium] › tests/waitlist.spec.js:71:3 › CSD-1 Class waitlist › AC5: a person can accept the offer inside the hold window (1.0s)
  ✘  10 [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it (6.1s)
  ✓  11 [chromium] › tests/waitlist.spec.js:100:3 › CSD-1 Class waitlist › AC7: confirmed plus offered seats never go above capacity (1.4s)

  1) [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer

    Error: expect(locator).toContainText(expected) failed

    Locator: getByTestId('seat-row').filter({ hasText: 'Riley Chen' })
    Expected substring: "Offered"
    Timeout: 5000ms
    Error: element(s) not found

    Call log:
      - Expect "toContainText" getByTestId('seat-row').filter({ hasText: 'Riley Chen' }) with timeout 5000ms
      - waiting for getByTestId('seat-row').filter({ hasText: 'Riley Chen' })

       at helpers.js:32

      30 |
      31 | export async function expectSeatStatus(page, name, statusText) {
    > 32 |   await expect(seatRow(page, name)).toContainText(statusText);
         |                                     ^
      33 | }
      34 |
      35 | // Attach a named screenshot to the test report. Use it at the moments that prove a rule.
        at expectSeatStatus (/home/claude/repo/tests/helpers.js:32:37)
        at /home/claude/repo/tests/waitlist.spec.js:63:11

    attachment #3: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-d326e-st-person-gets-a-seat-offer-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/waitlist-CSD-1-Class-waitl-d326e-st-person-gets-a-seat-offer-chromium/error-context.md

    attachment #5: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-d326e-st-person-gets-a-seat-offer-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/waitlist-CSD-1-Class-waitl-d326e-st-person-gets-a-seat-offer-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  2) [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it

    Error: expect(locator).toContainText(expected) failed

    Locator: getByTestId('seat-row').filter({ hasText: 'Riley Chen' })
    Expected substring: "Offered"
    Timeout: 5000ms
    Error: element(s) not found

    Call log:
      - Expect "toContainText" getByTestId('seat-row').filter({ hasText: 'Riley Chen' }) with timeout 5000ms
      - waiting for getByTestId('seat-row').filter({ hasText: 'Riley Chen' })

       at helpers.js:32

      30 |
      31 | export async function expectSeatStatus(page, name, statusText) {
    > 32 |   await expect(seatRow(page, name)).toContainText(statusText);
         |                                     ^
      33 | }
      34 |
      35 | // Attach a named screenshot to the test report. Use it at the moments that prove a rule.
        at expectSeatStatus (/home/claude/repo/tests/helpers.js:32:37)
        at /home/claude/repo/tests/waitlist.spec.js:91:11

    attachment #2: screenshot (image/png) ──────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/error-context.md

    attachment #4: trace (application/zip) ─────────────────────────────────────────────────────────
    test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/trace.zip
    Usage:

        npx playwright show-trace test-results/waitlist-CSD-1-Class-waitl-e83cd-and-the-next-person-gets-it-chromium/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────

  2 failed
    [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer
    [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it
  9 passed (25.0s)

demo-security-issue

CSD-3 built without approval

Pass Code quality: ESLint
Fail Security: PHI guard
PHI guard: 4 problem(s) found.

  public/data.js:17  [phone] Phone number pattern
    { name: 'Alex Rivera', email: 'alex.rivera@example.com', status: 'confirmed', phone: '616-555-0142', dob: '1990-04-12' }
  public/data.js:17  [phi-field] Patient data field (phone, dob, ssn, mrn, diagnosis, insurance)
    { name: 'Alex Rivera', email: 'alex.rivera@example.com', status: 'confirmed', phone: '616-555-0142', dob: '1990-04-12' }
  public/data.js:18  [phone] Phone number pattern
    { name: 'Sam Lee', email: 'sam.lee@example.com', status: 'confirmed', phone: '616-555-0187', dob: '1985-11-02' },
  public/data.js:18  [phi-field] Patient data field (phone, dob, ssn, mrn, diagnosis, insurance)
    { name: 'Sam Lee', email: 'sam.lee@example.com', status: 'confirmed', phone: '616-555-0187', dob: '1985-11-02' },

Remove the data, or use fictional test data that does not look like PHI.
Fail Security: Semgrep SAST
┌─────────────┐
│ Scan Status │
└─────────────┘
  Scanning 64 files tracked by git with 3 Code rules:
  Scanning 12 files with 3 js rules.

┌────────────────┐
│ 1 Code Finding │
└────────────────┘

    public/app.js
   ❯❯❱ dom-xss-innerhtml-concat
          HTML is built from a variable. If the value comes from a user (for example a name), a script can run
          in the browser (XSS). Use textContent or createElement instead.

          158┆ contact.innerHTML = '<small>' + (s.phone || '') + ' · ' + (s.dob || '') + '</small>';

┌──────────────┐
│ Scan Summary │
└──────────────┘
Some files were skipped or only partially analyzed.
  Scan was limited to files tracked by git.

Ran 3 rules on 12 files: 1 finding.
Pass Security: Gitleaks secrets
○
    │╲
    │ ○
    ○ ░
    ░    gitleaks

12:09AM INF scan completed in 264ms
12:09AM INF no leaks found
Pass Security: npm audit
found 0 vulnerabilities
Pass Tests: Playwright + axe · Open Playwright report
Running 11 tests using 1 worker

  ✓   1 [chromium] › tests/accessibility.spec.js:14:3 › Accessibility › A11Y: class page has no WCAG 2.1 AA violations (1.5s)
  ✓   2 [chromium] › tests/accessibility.spec.js:20:3 › Accessibility › A11Y: messages and roster have no WCAG 2.1 AA violations (1.6s)
  ✓   3 [chromium] › tests/registration.spec.js:6:3 › Registration (baseline) › a person can register for a class with open seats (741ms)
  ✓   4 [chromium] › tests/registration.spec.js:15:3 › Registration (baseline) › name and a valid email are required (693ms)
  ✓   5 [chromium] › tests/waitlist.spec.js:23:3 › CSD-1 Class waitlist › AC1: a full class puts a new person on the waitlist (932ms)
  ✓   6 [chromium] › tests/waitlist.spec.js:33:3 › CSD-1 Class waitlist › AC2: the waitlist keeps the order people joined (1.2s)
  ✓   7 [chromium] › tests/waitlist.spec.js:44:3 › CSD-1 Class waitlist › AC3: the same email cannot register twice (seat or waitlist) (1.1s)
  ✓   8 [chromium] › tests/waitlist.spec.js:54:3 › CSD-1 Class waitlist › AC4: when a person cancels, the FIRST waitlist person gets a seat offer (1.2s)
  ✓   9 [chromium] › tests/waitlist.spec.js:71:3 › CSD-1 Class waitlist › AC5: a person can accept the offer inside the hold window (1.2s)
  ✓  10 [chromium] › tests/waitlist.spec.js:83:3 › CSD-1 Class waitlist › AC6: an offer expires after 24 hours and the next person gets it (1.2s)
  ✓  11 [chromium] › tests/waitlist.spec.js:100:3 › CSD-1 Class waitlist › AC7: confirmed plus offered seats never go above capacity (1.3s)

  11 passed (13.9s)