Triage a CI export of 40 failures that mixes real product bugs, async flakes, data collisions, order dependence, timezone traps, and infra noise. Use AI to cluster and classify, verify every cluster with a rerun strategy, quarantine correctly — and then grade your classifications against the labeled answer key.
It is 09:10 and Divya's nightly run is a wall of red: 40 failures across four suites. The old workflow is two engineers losing a morning to log-diving. The AI workflow is clustering the failures by signature in minutes — but AI classifications are hypotheses, and a hypothesis about flakiness is only worth what your rerun strategy can confirm. Misclassify a real bug as a flake and you quarantine a regression into production; misclassify a flake as a bug and you burn a developer's day on noise. This lab drills the full loop: cluster, classify, verify, quarantine, and ship the morning triage brief.
~90 minutes hands-on · Core tier (maps to module M4 and playbooks PB-19/PB-20). Cost: $0 (the export is inline; any free AI tier works).
mkdir -p qa-lab-07 && cd qa-lab-07
touch failures.csv triage.md brief.md
failures.csv — the nightly export (run 6114, commit e9d21c7, 23:40–00:25 UTC). Save exactly:
id,test,suite,error_excerpt,duration_s,runner
1,checkout_submits_order,e2e,TimeoutError waiting for [data-test=confirm] 30s,31.2,r-04
2,order_api_create,api,500 InternalServerError: cannot read total of undefined,0.4,r-02
3,signup_new_user,api,409 duplicate key value violates unique constraint users_email_key,0.3,r-01
4,search_filters_apply,e2e,TimeoutError waiting for .results-grid 30s,30.9,r-04
5,order_api_update,api,500 InternalServerError: cannot read total of undefined,0.4,r-03
6,inventory_sync,integration,ECONNREFUSED db-primary:5432,0.1,r-07
7,report_daily_totals,unit,AssertionError: expected 2026-08-04 got 2026-08-05,0.1,r-02
8,login_remember_me,e2e,TimeoutError waiting for [data-test=dashboard] 30s,31.0,r-05
9,order_api_cancel,api,500 InternalServerError: cannot read total of undefined,0.4,r-02
10,profile_update_avatar,e2e,TimeoutError waiting for .avatar-preview 30s,30.8,r-04
11,signup_duplicate_check,api,409 duplicate key value violates unique constraint users_email_key,0.3,r-01
12,payments_refund_flow,integration,ECONNREFUSED db-primary:5432,0.1,r-07
13,cart_merge_on_login,e2e,TimeoutError waiting for [data-test=cart-count] 30s,31.1,r-05
14,order_api_list,api,500 InternalServerError: cannot read total of undefined,0.3,r-03
15,coupon_expiry_check,unit,AssertionError: expected expired=false got expired=true,0.1,r-02
16,email_verification,api,409 duplicate key value violates unique constraint users_email_key,0.2,r-01
17,wishlist_add_item,e2e,TimeoutError waiting for .wishlist-badge 30s,30.7,r-06
18,order_api_detail,api,500 InternalServerError: cannot read total of undefined,0.4,r-02
19,export_orders_csv,integration,ECONNREFUSED db-primary:5432,0.1,r-07
20,admin_bulk_edit,e2e,TimeoutError waiting for [data-test=save-toast] 30s,31.3,r-05
21,signup_password_rules,api,409 duplicate key value violates unique constraint users_email_key,0.3,r-01
22,order_api_totals,api,500 InternalServerError: cannot read total of undefined,0.4,r-03
23,notifications_badge,e2e,TimeoutError waiting for .notif-dot 30s,30.9,r-06
24,report_weekly_totals,unit,AssertionError: expected week 31 got week 32,0.1,r-02
25,user_prefs_theme,api,expected 200 got 404 Not Found /api/v1/prefs,0.2,r-01
26,shipping_rates_intl,integration,ECONNREFUSED db-primary:5432,0.1,r-07
27,checkout_guest_flow,e2e,TimeoutError waiting for [data-test=confirm] 30s,31.0,r-04
28,signup_welcome_email,api,409 duplicate key value violates unique constraint users_email_key,0.3,r-01
29,order_api_history,api,500 InternalServerError: cannot read total of undefined,0.4,r-02
30,product_gallery_zoom,e2e,TimeoutError waiting for .zoom-overlay 30s,30.8,r-06
31,session_timeout_redirect,e2e,TimeoutError waiting for [data-test=login-form] 30s,31.2,r-05
32,tax_calc_gst,unit,AssertionError: expected 118.00 got 100.00,0.1,r-03
33,user_prefs_language,api,expected 200 got 404 Not Found /api/v1/prefs,0.2,r-01
34,audit_log_write,integration,ECONNREFUSED db-primary:5432,0.1,r-07
35,signup_referral_code,api,409 duplicate key value violates unique constraint users_email_key,0.3,r-01
36,mobile_nav_drawer,e2e,TimeoutError waiting for .drawer-open 30s,30.9,r-06
37,order_api_search,api,500 InternalServerError: cannot read total of undefined,0.4,r-03
38,invoice_pdf_render,integration,ECONNREFUSED db-primary:5432,0.1,r-07
39,cart_total_rounding,unit,AssertionError: expected 99.99 got 100.00,0.1,r-03
40,loyalty_points_accrual,api,expected 200 got 404 Not Found /api/v1/prefs,0.2,r-01
Context you'd have in the room: commit e9d21c7 touched OrderService and renamed the prefs endpoint; the nightly crossed midnight UTC; runner r-07 had a maintenance window 23:55–00:10; the e2e suite runs against a shared staging environment; signup tests seed test.user@example.com.
triage.md under "AI hypothesis."triage.md the verification you would run: rerun-same-commit ×N for suspected flakes (a real bug fails N/N, a flake fails intermittently), rerun-in-isolation for suspected order dependence, rerun-on-different-runner for infra, rerun-with-fresh-data for collisions, and no rerun but a code read for suspected product bugs (rerunning a real 500 forty times is how mornings die). Every cluster gets a named strategy and a predicted outcome.triage.md: (a) the async/wait class — replace fixed 30s selector waits with web-first assertions plus one targeted app-side investigation if the shared staging env is genuinely slow; (b) the data-collision class — unique per-run emails (test.user+{runid}@example.com) or per-test fixtures with teardown. Include before/after code sketches for one representative test each.brief.md — ten lines max, the artifact a team lead reads at 09:15: N real bugs (ids, owner, severity), N flakes quarantined (classes, tickets), N infra (status), N test fixes in flight, and the one-line trend note. Every number must trace back to a cluster in triage.md.The most expensive word in triage is "flaky" applied to a real bug. A 500 with a consistent stack trace across six endpoints is not flaky — it is a regression with excellent attendance. Reruns are for intermittence; consistent failures get a code read, not a retry.
triage.md contains the AI hypothesis, your corrected clustering, a named rerun strategy per cluster with predicted outcomes, and final labels with actions.brief.md is ≤10 lines and every number traces to a cluster.Self-grading rubric (pass = 8/12):
| Dimension | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| Cluster accuracy | ≤4 of 7 clusters right | 5 right | 6 right | All 7, incl. unit-test split |
| Verification design | Reruns for everything | Mostly apt | Apt per class | Apt + product bugs get code-read not rerun |
| Quarantine discipline | Real bug quarantined | Over-quarantined flakes | Clean but unticketed | Clean, ticketed, signatures logged |
| Brief quality | Missing | Numbers untraceable | Traceable | Traceable + owners + trend line |
AI turns a wall of 40 red tests into six or seven hypotheses in a minute — but a hypothesis is not a triage. The rerun strategy is the professional layer: intermittence confirms flakes, consistency indicts code, isolation exposes order and data coupling, and nothing gets quarantined without a ticket and a signature.