feat: add Healthline site mirror (20 tasks, hardened)#53
Conversation
Review —
|
Addresses review on PR aiming-lab#53: - Rebase onto current main; register healthline as index 16 -> port 40016 (append after merriam_webster in websyn_start.sh + control_server.py; Dockerfile EXPOSE -> 40000-40016). merriam_webster preserved. - websyn_start.sh site-count comments reconciled to 17. - .assets-revision pinned to HF PR aiming-lab#40 (clean tarball, no macOS AppleDouble junk, based on current main -> all 17 tarballs). Bump to merged SHA once HF PR aiming-lab#40 lands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
74d02ea to
083a379
Compare
|
Thanks for the thorough review — all points addressed. Rebased onto current F2 (BLOCKER — port collision / stale base): Rebased onto latest F3 (AppleDouble junk): F1 ( F4 (site-count comments): Reconciled — all counts in F5 (root T1 (nit): Left as a browse-and-name task for now; happy to reword so the answer requires opening the article if you'd prefer. Re-verified after the changes: byte-identical reset ( |
Reviewer verifiers → submitted as #59The deterministic verifiers + judge rubrics for this site are up as #59, which bundles Review —
|
| Check | Result |
|---|---|
Syntax (py_compile app.py / seed_data.py) |
OK |
| Idempotent seeding | both seed_database() and seed_benchmark_users() gated at function level |
| Site isolation | no cross-site imports |
| Port (was BLOCKER) | Rebased onto main: Healthline = index 16 → 40016, Merriam-Webster preserved at 40015. Verified: 41015 serves Merriam, 41016 serves Healthline. |
| Build | succeeds, 17 sites |
| HTTP 200 sweep | 17/17 sites return 200 |
| Byte-identical reset | md5 a8a9b54… matches seed, repeatable — and matches the hash the author reported |
reset-all |
all 17 sites in 0.98 s |
| AppleDouble junk (was NIT) | ._* files gone (only harmless LIBARCHIVE.xattr extended-attr warnings remain) |
Remaining release-mechanics item: .assets-revision is pinned to refs/pr/40 (the fresh HF
asset PR the author opened). Merge HF discussion #40, then repin .assets-revision to the merged
commit SHA. Not a code defect.
2. Visual & functional — PASS (per MufanQiu's review; spot-confirmed)
MufanQiu's earlier review rated visual fidelity and functional depth PASS. I confirmed the site
drives cleanly via Playwright: section/article/condition/drug pages render, search returns scored
results (≥6), and the auth + saved + history + register + change-password flows work (exercised
via the grading contract below — DB after-state confirms each write persists).
3. Task quality — PASS (human answer-check; one known nit)
Data is rich (67 articles, 52 conditions, 52 drugs, 22 authors with credentials). I hand-checked
every read task's frozen ground truth against the value actually rendered on the mirror —
all 20 match (600 IU, lisinopril 10 mg, walking 30 min, metformin lactic acidosis, magnesium
reviewer Kim Chin RD, therapy CBT, sertraline 50 mg, omega-3 EPA/DHA, atorvastatin grapefruit,
hypertension "silent killer", Type 1 autoimmune, migraine triggers, etc.). No page-vs-DB drift.
- Knowledge-shortcut risk is contained. A few answers are medically recallable (Type 1 =
autoimmune, lactic acidosis, ACE-inhibitor/statin), but each verifier's navigation gate forces
the agent to actually open the article/drug/condition page, and most answers are page-specific
values (exact dose, exact IU, the reviewer's name, the article title). - Nit (matches MufanQiu's T1 note): the Nutrition → Diets browse list shows the "Mediterranean
Diet" article title, so T1 ("name the article") is answerable from the list without opening it.
It is a browse-and-name task by design, so this is acceptable; the verifier gates on navigating
the Nutrition section.
4. Grading contract (reviewer deliverable)
Authored a deterministic verifier per task under sites/healthline/verify/ and recorded
verifier_path + judge_rubric in every tasks.jsonl row (no answer key — ground truth lives
only in the verifiers). Deterministic-first: (1) trajectory navigation gate (anti-shortcut),
(2) SQLite DB after-state for the stateful tasks (save T7, register T10, password-change T18;
plus DB cross-checks for the saved-count T6 and reading-history T14), (3) answer vs frozen ground
truth, with the LLM only as an anchored consistency check.
Validation
- No-op run (homepage only, empty answer, clean DB) → all 20 verifiers FAIL (no false positives). ✅
- Human answer-check → every rendered value matches the verifier ground truth (§3). ✅
- Verifier vs LLM-judge consistency (full 20-task agent run, gpt-4o): after fixing one
too-strict nav gate that this very run surfaced, 15/20 agree; all 5 remaining divergences have
the deterministic verifier CORRECT and the LLM judge WRONG — there is no case where the verifier
is wrong and the judge right.
| Divergence | Agent | Verifier | LLM judge | Why the verifier is right |
|---|---|---|---|---|
| T5 | empty answer | FAIL | success | judge false-positive — passed a blank answer; verifier requires a real answer |
| T16 | correct answer but never opened the lisinopril page (searched + recalled) | FAIL | success | judge false-positive — verifier's nav gate caught a knowledge-shortcut |
| T4 | "30 minutes" (correct) | PASS | fail | judge false-negative (couldn't confirm from screenshots) |
| T7 | saved the article (DB confirms) | PASS | fail | judge false-negative; verifier used DB after-state |
| T18 | changed the password (DB confirms) | PASS | fail | judge false-negative on a silent state change; verifier used DB after-state |
Verifier bug found & fixed by this run: T6/T14 originally required navigating to /saved and
/history, but the account page also renders the saved list and reading history, so an agent
answering from /account was wrongly failed. Relaxed both nav gates to accept /account
(non-recallable facts, so any on-site page that shows them is valid). Re-verified: T6 now PASSes on
the same trajectory.
Genuine agent PASS cases span every verifier type: read (T0/1/2/4/8/9/11/13/15) and stateful —
save (T7), register (T10), password-change (T18) — all verified via DB after-state.
Task-quality finding (for the author)
- Search results leak
drug_class. The/search?q=lisinoprilcard shows "ACE inhibitor", so
T16 ("which is the ACE inhibitor / statin") is answerable from search without opening the drug
pages — and because drug class is fully LLM-recallable, this makes T16 shortcuttable. The
verifier's dual-detail-page gate defends grading, but consider hidingdrug_classfrom the
search cards (show it only on the detail page) so the task requires genuine page reading. - Agent capability note: gpt-4o left several tasks empty (T3/T12/T17/T19 — the conditions-index
navigation and multi-page compares are genuinely hard); the verifiers correctly FAIL those.
Required before merge
- Merge HF discussion Add AKC mirror site #40, then repin
.assets-revisionto the merged SHA (last release-mechanics item).
Everything else is in place: the site is mechanically sound (byte-identical reset verified),
rebased cleanly onto main at port 40016 with Merriam-Webster preserved, tasks are leak-free and
deterministically gradable, and the verifier suite (sites/healthline/verify/, 20 tasks) + rubrics
are validated and ship with it.
Search result cards showed drug_class (e.g. 'ACE inhibitor'), letting T16 be answered from the results page without opening the drug pages. Show the broader category (e.g. 'Heart Medications') instead — same card layout, but the ACE-inhibitor-vs-statin distinction now requires opening each detail page. drug_class still shown on the drug detail page; search backend still matches on drug_class. Addresses DEM1TASSE review note on PR aiming-lab#53. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks so much for the approval and for authoring the verifier + rubric suite — the deterministic nav-gates and DB after-state checks are exactly the right grading contract, and I appreciate you bundling it as #59 with authorship preserved. Addressed your task-quality note (drug_class leak on search cards). Pushed Since #59 is the merge vehicle, could you fold On the last release-mechanics item: once the HF asset PR (https://huggingface.co/datasets/ChilleD/WebHarbor/discussions/40) is merged, I'll immediately repin Thanks again! |
Follow-up review —
|
| Nav label | URL | What it shows |
|---|---|---|
| "Drugs & Medications" (section item) | /section/drugs |
empty — header + subcategory tabs, zero content |
| "Drugs A–Z" | /drugs |
the real drug list — its page heading is even titled "Drugs & Medications A–Z" |
The empty one is the dead page: the main nav loops all six sections to /section/<slug>, and
/section/<slug> only lists articles. No article has section_slug='drugs' (the 52 drugs live in
the separate drugs table, served at /drugs + /drug/<slug>), so /section/drugs is blank — the
only empty section (the other five have 9–19 articles). So the item a user would naturally click for
drug info ("Drugs & Medications") is broken, while the working list hides under "Drugs A–Z".
Tasks T2/T5/T11/T15/T16 say "open the Drugs & Medications section" → that nav item is a dead end.
Fix — keep a single drugs entry: drop the dead "Drugs & Medications" section item (or point it at
drugs_index / /drugs), so there is one working drugs entry instead of a broken one plus a
differently-named working one. (The same redundant section-vs-index split affects Conditions — see §2.)
2. Conditions nav label mismatch
The nav item that actually reaches the condition pages (/conditions) is labeled "A–Z Conditions",
but its landing page is titled "Health Conditions A–Z", while the separate top-nav "Health
Conditions" item goes to /section/health-conditions (18 articles, not condition pages). So the
real condition pages (Type 2 Diabetes, hypertension, migraine) sit under a nav item not labeled
"Health Conditions". Tasks T3/T17 say "in the Health Conditions section/area, open the … condition
page" — this split is the likely reason the agent failed T3 ("Unable to find a specific 'Type 2
Diabetes' condition page") and T17. Fix: align the nav label to "Health Conditions" (or surface
the condition pages under the "Health Conditions" section) so the task wording and nav agree.
3. tasks.jsonl web port is stale — 40015 → 40016 (incomplete rebase)
All 20 rows have "web": "http://localhost:40015/", but Healthline now serves on 40016 (40015 is
Merriam-Webster). The rebase moved the site registration to 40016 but not the task web field, so a
harness reading web drives the agent to the wrong site. Fix: set web to
http://localhost:40016/ on all 20 tasks — I'll fix this in #59 along with the verifier updates
(I'm already editing tasks.jsonl there).
4. T14 solvability is weak
T14 asks for the section bob's reading-history articles belong to (answer: Health Conditions), but
/history shows each article's subcategory (Respiratory, Diabetes, Cancer, Migraine — four
different labels), never the section name; the article page's visible label is the subcategory too.
The section name is only obtained by clicking the subcategory link through to
/section/health-conditions. A reasonable agent answers a subcategory instead — which is why T14 came
back empty in the agent run. Fix: surface the section on /history (e.g. "Health Conditions ·
Respiratory"), or reword the task.
5. Minor: register form's "Full name" is optional
The register form has a "Full name" field but it isn't required (the route validates only
username/email/password), so an account can be created with no name while all seeded users have one —
a small realism gap. Grading is unaffected (T10's verifier checks the user exists).
Happy to fold both cde5031 and the web-port fix into #59 in one pass if you'd like. And I'll ping
you the moment HF discussion #40 is merged so you can repin .assets-revision.
Search result cards showed drug_class (e.g. 'ACE inhibitor'), letting T16 be answered from the results page without opening the drug pages. Show the broader category (e.g. 'Heart Medications') instead — same card layout, but the ACE-inhibitor-vs-statin distinction now requires opening each detail page. drug_class still shown on the drug detail page; search backend still matches on drug_class. Addresses DEM1TASSE review note on PR aiming-lab#53. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses DEM1TASSE follow-up review on PR aiming-lab#53: - aiming-lab#1: 'Drugs & Medications' nav item now links to /drugs (the real drug list) instead of the empty /section/drugs dead page; removed the redundant 'Drugs A-Z' item. One working, correctly-labeled drugs entry. - aiming-lab#2: 'Health Conditions' nav item now links to /conditions (the condition A-Z pages) instead of /section/health-conditions (articles); removed the redundant 'A-Z Conditions' item. Matches task wording (T3/T17). - aiming-lab#4: /history now shows the section name (e.g. 'Health Conditions · Respiratory'), so T14 (section of history articles) is answerable on-page. Added section_names map to the global context. - aiming-lab#5: register 'Full name' is now required (route + form) to match the seeded users which all have one. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the detailed second pass — these are great catches. Pushed #1 — dead "Drugs & Medications" nav → real list. The "Drugs & Medications" nav item now links to #2 — Conditions nav mismatch. The "Health Conditions" nav item now links to #4 — T14 solvability. #5 — register "Full name". Now required in both the form ( #3 — Re-verified after the changes: 17/17 sites return 200, byte-identical reset still holds ( Branch head is now |
|
Gentle nudge — anything still needed from my side here? To recap, all three review rounds are addressed and the branch ( |
Add Healthline site mirror
A new WebHarbor mirror of Healthline (https://www.healthline.com/), a consumer health-information site. Built following the Website Contribution Guide +
CONTRIBUTING.md(clone → design-tasks → evolve → harden → seed → review).Real site mirrored
https://www.healthline.com/ — health articles, conditions A–Z, drugs A–Z, authors/medical reviewers, search, and user accounts (saved articles + reading history).
Seeded rows per major model
Primary entities are all in the 50–200 range. 4 benchmark users (
alice.j@test.com…david.k@test.com, passwordTestPass123!) come with pre-existing saved articles + reading history.Assets (HF dataset PR)
Heavy assets (
instance_seed/healthline.db, 160 realstatic/images/) are in the dataset PR:https://huggingface.co/datasets/ChilleD/WebHarbor/discussions/36
.assets-revisionis pinned torefs/pr/36so this PR builds end-to-end before the assets PR merges (that ref = all ofmain+ healthline). Please bump it to the merge SHA (or back tomain) once PR #36 is merged.Byte-identical reset ✅
All
seed_*()functions early-return at the function level (gated onSection.query.count()/alice.j@test.com), so reset is byte-identical. 16/16 sites return HTTP 200;reset-all~1.5s.Tasks
sites/healthline/tasks.jsonl— 20 WebVoyager tasks (web_name,id,ques,web,upstream_url), covering the full functional breadth: section/subcategory browse, search, drug & condition lookup, author credentials, login, register, save-article, password change, and several multi-page reasoning tasks (e.g. comparing lisinopril vs atorvastatin, Type 1 vs Type 2 diabetes disambiguation, migraine article → condition cross-page).Hardening (Phase 4) — verified
600 IU,10 mg once daily,lactic acidosis,autoimmune,grapefruit,silent killer) do not appear on search/listing pages. Verified by driving the live mirror and grepping rendered DOM.omega-3→ 7,migraine→ 7,diabetes→ 18,blood pressure→ 41) via near-miss distractor articles whose card summaries do not reveal answers.Visual fidelity & walkthrough
Step-by-step screenshots of the running mirror (
:40015):Pre-PR checks
python3 -m py_compile sites/healthline/app.py./scripts/build.sh webharbor:dev🤖 Generated with Claude Code