← 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.
| Branch | ESLintCode quality | PHI guardSecurity | Semgrep SASTSecurity | Gitleaks secretsSecurity | npm auditSecurity | Playwright + axeTests |
|---|---|---|---|---|---|---|
| mainBefore: no waitlist | Pass | Pass | Pass | Pass | Pass | Pass |
| CSD-1-testsTests first (red) | Pass | Pass | Pass | Pass | Pass | Fail |
| CSD-1-waitlistWaitlist code (green) | Pass | Pass | Pass | Pass | Pass | Pass |
| demo-broken-waitlistPlanted logic bug | Pass | Pass | Pass | Pass | Pass | Fail |
| demo-security-issueCSD-3 built without approval | Pass | Fail | Fail | Pass | Pass | Pass |
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 foundPass 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 foundPass 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 foundPass 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 foundPass 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 foundPass 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)