| name | hol-run-lab |
| description | Validate a HOL lab by simulating a participant. Walks through all 5 Acts (Explore, Fix, Spec, Build, Show & Tell) and produces a validation report with pass/fail, timing, and facilitator recommendations. |
HOL Lab Validator
You are simulating a workshop participant to validate that a HOL lab works end-to-end. Walk through all 5 Acts as if you were seeing the codebase for the first time. Be honest about what's confusing, what's too easy, and what doesn't work.
Important Rules
- Do NOT read
.hol/bugs/answers.md until AFTER you've attempted Act 2. The whole point is to validate that the bugs are discoverable without the answer key.
- Time your work mentally — note when each act starts and roughly how long it takes you. Human participants will take 2-3x longer.
- Be critical — if something is confusing, broken, or too easy, say so. A failed validation now saves 20 frustrated participants later.
Act 1 — Explore (Target: 10 min for humans)
Simulate a cold start. You've never seen this repo before.
- Read
CLAUDE.md — is it clear enough to get started?
- Install and run:
uv sync
uv run python seed.py
uv run pytest
uv run uvicorn main:app --reload
- Open the web UI at
http://localhost:8000 — switch the "Browsing as" persona dropdown, click an itinerary card, change cabin types in the detail view, click "My Account". Confirm the three views (Browse / Detail / Profile) all render.
- Explore the codebase — map the architecture (note the static frontend under
web/), understand the domain.
- Trace one main data flow (e.g., "how does a booking get created?")
- Hit a few API endpoints (
/docs, /itineraries/, /guests/) to confirm the data behind the UI.
Evaluate:
Act 2 — Fix (Target: 20 min for humans)
Find and fix the planted bugs WITHOUT reading the answer keys.
- Run
pytest and examine the failures
- Cross-check in the UI: with uvicorn running, switch the persona dropdown to a Gold-tier guest (e.g. "Sarah Chen — Gold"), open any itinerary. The price card shows the bug as "Gold loyalty discount: −5%" (should be −10%). Confirm Platinum still shows −15%. This visual surfacing is the lab's strongest "aha" moment — note whether it lands.
- For each failing test:
- Read the test to understand what it expects
- Trace the failure through the codebase (router → service → model → schema)
- Identify the root cause
- Apply the fix
- Write a regression test
- Run
pytest — all tests should pass after fixes
- Reload the detail view in the browser and confirm the Gold price card now shows −10%
Evaluate:
After fixing: Now read .hol/bugs/answers.md and compare:
- Did you find the same root cause?
- Was your fix the same or equivalent?
- How long did it take vs the 20-min target?
Act 3 — Spec (Target: 20 min for humans)
- Read
.hol/features/proposals.md
- Pick the recommended feature (or any feature)
- Read the feature brief (the 1-2 sentence description)
- Fill out
.hol/templates/feature-spec.md for the chosen feature
- Save the spec to
.hol/validation/feature-spec-filled.md
Evaluate:
Act 4 — Build (Target: 30 min for humans)
Implement the feature from your spec.
UI integration note — only if you chose Personalized Recommendations:
The frontend already has a "Personalized for you" panel on the itinerary detail view that calls GET /itineraries/{id}/recommendations?guest_id={id} and currently shows "Coming soon" because the endpoint 404s. When your endpoint exists and returns 200, the panel auto-populates. The panel reads these exact keys per recommendation:
itinerary_id — the trip to link to (clicks call openItinerary(itinerary_id))
name
ship_name
base_price
reason — short string explaining why this was recommended
.hol/features/proposals.md Proposal 1 also documents this contract. If your endpoint returns the raw ItineraryResponse + relevance_score shape, the cards will render blank (field names won't match). Either shape your response to the panel's contract or update the panel — but pick one explicitly.
- Create the implementation: new/modified service functions, router endpoints, models if needed
- Write tests for the new feature
- Run the full test suite — everything should pass
- Verify the feature works via API and (if Personalized Recommendations) confirm the UI panel populates with non-empty cards on the detail view
Evaluate:
Act 5 — Report
Generate a validation report at .hol/validation/report.md:
# Lab Validation Report — {App Name}
Date: {today}
## Summary
- Overall: PASS / FAIL / PASS WITH NOTES
- Lab is ready for: {audience} participants
## Act-by-Act Results
### Act 1 — Explore
- Status: PASS / FAIL
- Notes: {observations}
- Estimated human time: {X} min (target: 10 min)
### Act 2 — Fix
- Status: PASS / FAIL
- Bugs found: {N} / {N total}
- Diagnosis quality: {GOOD / FAIR / POOR — explain}
- Notes: {observations}
- Estimated human time: {X} min (target: 20 min)
### Act 3 — Spec
- Status: PASS / FAIL
- Notes: {observations}
- Estimated human time: {X} min (target: 20 min)
### Act 4 — Build
- Status: PASS / FAIL
- Feature built: {name}
- Complications: {any}
- Estimated human time: {X} min (target: 30 min)
## Issues Found
1. {issue — severity — recommendation}
2. ...
## Facilitator Recommendations
- {recommendation 1}
- {recommendation 2}
- ...
## Verdict
{Final assessment: is this lab ready for a live workshop?}
Undo all your changes after generating the report (the lab should be left in its "bugged" state for participants):
git checkout -- .
Keep only the validation report:
git checkout HEAD -- .hol/validation/