Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
1c1dd02
Add FedEx WebHarbor mirror
Jun 4, 2026
083a379
fix(healthline): rebase onto main, move to port 40016, clean assets
JeremyJC67 Jul 2, 2026
1ca0c9f
Add Healthline task verifiers and judge rubrics
DEM1TASSE Jul 4, 2026
5d86aaf
fix(healthline): hide drug_class from search cards (T16 anti-shortcut)
JeremyJC67 Jul 4, 2026
55aaf56
tasks.jsonl: fix stale web port (40015->40016) and enrich two rubrics
DEM1TASSE Jul 4, 2026
d481974
chore(fedex): merge current main and resolve registration
jackjin1997 Aug 19, 2026
7cd2926
fix(fedex): address review blockers
jackjin1997 Aug 19, 2026
a59f309
fix(assets): exclude macOS metadata from archives
jackjin1997 Aug 19, 2026
0306473
feat(fedex): add reviewed task contract
jackjin1997 Aug 19, 2026
70a8e38
fix(fedex): strengthen support task distractors
jackjin1997 Aug 19, 2026
0ebb58c
fix(fedex): reject contradictory verifier answers
jackjin1997 Aug 19, 2026
3619585
chore(assets): pin reviewed FedEx archive
jackjin1997 Aug 19, 2026
ad0ec98
fix(fedex): disambiguate Dallas invoice task
jackjin1997 Aug 19, 2026
e0e38f3
fix(fedex): harden reviewed task contract
jackjin1997 Aug 20, 2026
c5e055f
fix(fedex): reject replayed quote evidence
jackjin1997 Aug 20, 2026
ed178c3
fix(fedex): bind verifier evidence to trusted execution
jackjin1997 Sep 10, 2026
14cfcb7
chore(fedex): merge upstream main
jackjin1997 Sep 10, 2026
70f1329
chore(assets): pin rebased FedEx candidate
jackjin1997 Sep 10, 2026
8b607c7
fix(fedex): bind verifier to configured site port
jackjin1997 Sep 10, 2026
35d826c
chore(assets): align FedEx candidate with code baseline
jackjin1997 Sep 10, 2026
5d18649
docs: align site count after FedEx integration
jackjin1997 Sep 10, 2026
b6282b9
fix(fedex): restore homepage fidelity and strengthen tasks
jackjin1997 Sep 10, 2026
cecf1fb
chore(assets): pin refreshed FedEx homepage candidate
jackjin1997 Sep 10, 2026
189ebc6
fix(fedex): align business section and responsive footer
jackjin1997 Sep 10, 2026
b5cce82
fix(fedex): validate registration and contain narrow shipment form
jackjin1997 Sep 10, 2026
4b77691
docs(fedex): publish final review evidence and task quality matrix
jackjin1997 Sep 10, 2026
4fe15e8
feat(webmd_doctor): add WebMD Doctor mirror (site 24, port 40024)
evanz37 Sep 10, 2026
c88d2ea
feat(webmd_doctor): add 20 benchmark tasks
evanz37 Sep 10, 2026
0362f46
fix(webmd_doctor): evolve mirror to support all tasks
evanz37 Sep 10, 2026
a3167ad
fix(webmd_doctor): visual parity with reference captures
evanz37 Sep 10, 2026
0bbd841
fix(webmd_doctor): finalize deterministic build-generated seed
evanz37 Sep 10, 2026
00365d1
docs: bump site count to 25 (ports 40000-40024)
evanz37 Sep 10, 2026
53ccc69
fix(fedex): harden the application, regenerate the seed, and derive g…
Raibows Sep 10, 2026
ada6f55
test(fedex): prove the grading contract and document scope and proven…
Raibows Sep 10, 2026
fb001c5
fix(assets): scope the fetch to registered sites and derive registry …
Raibows Sep 10, 2026
503d7cc
docs(fedex): state the SQLite runtime caveat for seed byte-identity
Raibows Sep 10, 2026
a50d26d
test(fedex): check the session-key property structurally
Raibows Sep 10, 2026
8b84eaa
fix(fedex): make action and focus colors meet WCAG contrast
Raibows Sep 10, 2026
a2b4c7f
fix(webmd_doctor): ship images via HF tarball (build-generated DB unc…
evanz37 Sep 10, 2026
a6ece6e
chore(webmd_doctor): pin assets to HF dataset PR (ChilleD/WebHarbor d…
evanz37 Sep 10, 2026
434b3cc
fix(webmd_doctor): audit B hardening — payer-row consistency, unmatch…
evanz37 Sep 10, 2026
b26a1d4
fix(webmd_doctor): faithful empty state, per-office phones, perspecti…
evanz37 Sep 10, 2026
3859db9
fix(webmd_doctor): audit-C fixes (task wording, booking reference, sp…
evanz37 Sep 11, 2026
273ca14
fix(webmd_doctor): audit-D realism fixes (curated specialty pools, tr…
evanz37 Sep 11, 2026
3c22d4a
fix(webmd_doctor): audit-D nits (logout clears the session, stricter …
evanz37 Sep 11, 2026
5657fdd
test(webmd_doctor): add deterministic task verifiers and verify_lib
evanz37 Sep 11, 2026
82af7dd
chore(webmd_doctor): backfill verifier_path + judge_rubric
evanz37 Sep 11, 2026
df19ae7
test(webmd_doctor): harden verifiers from the validation matrix
evanz37 Sep 11, 2026
e7862ed
chore(webmd_doctor): polish judge rubrics from real agent runs
evanz37 Sep 11, 2026
5da2bd1
chore(assets): pin the merged FedEx media bundle
Raibows Sep 11, 2026
ae3fb65
fix(fedex): stop the interface from pre-supplying task steps
Raibows Sep 11, 2026
b87db8f
Harden the WebMD Doctor mirror after full-stack review
Chilled Sep 11, 2026
317bb13
Remove booking-widget patient-type preselection; fix enhanced-profile…
Chilled Sep 11, 2026
79fcb38
fix(fedex): polish review details
jackjin1997 Sep 11, 2026
a03a8af
Bind the T5 entity leak test to answer facts and restore the tarball …
Chilled Sep 11, 2026
74ddb0b
Darken the bio meet accent to meet WCAG AA for normal text
Chilled Sep 11, 2026
cdf5865
review(healthline): accurate verifier predicates, port 40024, integra…
TabsPhasers Sep 12, 2026
78ef77b
Add Kaggle mirror + task verifiers (site by @KaKituken, verifiers by …
Sep 12, 2026
46e6e53
Add NVIDIA mirror site
KaKituken Jun 25, 2026
5836de9
Add NVIDIA task verifiers and judge rubrics
DEM1TASSE Jul 3, 2026
07980a2
Rebase NVIDIA onto current main: register as site 24 on port 40023
TabsPhasers Sep 12, 2026
4d47e7e
Harden NVIDIA task verifiers: deterministic explicit-input grading, t…
TabsPhasers Sep 12, 2026
84bfe58
NVIDIA site fixes: series and buying pages, retired commerce, respons…
TabsPhasers Sep 12, 2026
de50489
fix(healthline): B1 pin assets to an immutable commit sha instead of …
Raibows Sep 12, 2026
7bf63fd
merge: integrate origin/main (3600493) into review/pr-105 so the PR t…
Raibows Sep 12, 2026
01d8619
fix(healthline): B3 derive SECRET_KEY from the environment or a rando…
Raibows Sep 12, 2026
66da5ee
fix(kaggle): B1 pin assets at the HF revision that actually carries k…
Raibows Sep 12, 2026
465f58b
fix(healthline): B19 treat the session user id as untrusted input ins…
Raibows Sep 12, 2026
bda0cf7
fix(healthline): B14 make GET /article/<slug> side-effect free and mo…
Raibows Sep 12, 2026
72506e0
fix(healthline): B10 stop rendering the saved-article count in the gl…
Raibows Sep 12, 2026
c46db85
fix(healthline): B11 hide drug_class from the Drugs A-Z cards and the…
Raibows Sep 12, 2026
7db73ce
fix(healthline): B18 make logout POST-only with CSRF so GET/HEAD cann…
Raibows Sep 12, 2026
7651d82
fix(kaggle): B2 gate asset coverage by registered site name
Raibows Sep 12, 2026
3900287
fix(healthline): B20 validate and bound registration, login and profi…
Raibows Sep 12, 2026
575fa96
fix(healthline): B21 add branded 400/404/413/500 error handlers and t…
Raibows Sep 12, 2026
fc66d79
fix(healthline): B22 reject invalid filter, page, sort and search-sco…
Raibows Sep 12, 2026
87ef28f
fix(nvidia): B3 verifier CLI and trajectory contract
Raibows Sep 12, 2026
0001437
fix(healthline): B25 set an explicit MAX_CONTENT_LENGTH instead of re…
Raibows Sep 12, 2026
f789abf
fix(kaggle): B5 accept ancestor directory entries in asset archives
Raibows Sep 12, 2026
9dae360
fix(nvidia): H1 make the mechanical UI contract suite runnable
Raibows Sep 12, 2026
3b8d586
fix(healthline): B12 let the header wrap and the search box shrink so…
Raibows Sep 12, 2026
ad0b1bf
fix(kaggle): B3 register kaggle in all three registries
Raibows Sep 12, 2026
ef5eb15
fix(nvidia): H2 scope the frozen-catalog negation exemption to T9/T10
Raibows Sep 12, 2026
6b21ab8
fix(healthline): B13 add accessible action/link/focus tokens and visi…
Raibows Sep 12, 2026
8f64dc5
fix(healthline): B15 assign medication-appropriate drug imagery and s…
Raibows Sep 12, 2026
d145806
fix(healthline): B16 prune unreferenced archive images at build time …
Raibows Sep 12, 2026
3f48ee8
fix(healthline): B17 add a tracked asset provenance manifest with per…
Raibows Sep 12, 2026
022c272
fix(kaggle): B4 make the verifier contract work under the production …
Raibows Sep 12, 2026
c85707f
fix(kaggle): H1 remove the shipped Flask secret
Raibows Sep 12, 2026
7a488a7
Revert "fix(kaggle): B5 accept ancestor directory entries in asset ar…
Raibows Sep 12, 2026
4b60f0d
fix(nvidia): B1 pin .assets-revision to the nvidia-bearing dataset re…
Raibows Sep 12, 2026
d132ce3
fix(nvidia): B2 document the archive re-pack that clears the validato…
Raibows Sep 12, 2026
188d177
fix(nvidia): H3 bind the verdict to decodable screenshot evidence
Raibows Sep 12, 2026
9e0cd0f
fix(kaggle): B1/B5 record why the pin stays on refs/pr/74 and what bl…
Raibows Sep 12, 2026
2ec5508
fix(kaggle): H2 require an unchanged database for the 12 read-only tasks
Raibows Sep 12, 2026
cfe8556
fix(nvidia): M8 make wishlist saves idempotent
Raibows Sep 12, 2026
a2f9a2b
fix(nvidia): M11 require an explicit review rating
Raibows Sep 12, 2026
77c1058
fix(healthline): B23 correct the .gitignore comment about the reposit…
Raibows Sep 12, 2026
b5fcaf4
fix(healthline): B24 pin the site requirements and declare every dire…
Raibows Sep 12, 2026
96efc45
fix(kaggle): H3 bind screenshot evidence deterministically
Raibows Sep 12, 2026
0340635
fix(healthline): B27 add a pytest regression suite for the site invar…
Raibows Sep 12, 2026
9b23077
fix(kaggle): M10 bind navigation evidence to the local mirror origin
Raibows Sep 12, 2026
443f9f6
fix(nvidia): M1/M2 separate action, focus and rating colours from the…
Raibows Sep 12, 2026
958df70
fix(healthline): B4+B7 make the verifier harness contract self-consis…
Raibows Sep 12, 2026
2a7b556
fix(healthline): B5+B6 bind screenshot evidence and require read-only…
Raibows Sep 12, 2026
5e9d561
fix(healthline): B8+B9+B28 add negation-aware answer checks and state…
Raibows Sep 12, 2026
822d565
fix(nvidia): M9 treat loopback host spellings as one origin
Raibows Sep 12, 2026
9bdedd6
fix(kaggle): H6 gate the four listing tasks on the filter the rubric …
Raibows Sep 12, 2026
c3d770b
fix(healthline): B2 update the READMEs for the 25-site registry and p…
Raibows Sep 12, 2026
c02dce6
fix(nvidia): M10 give desktop a visible primary navigation
Raibows Sep 12, 2026
f83f4a7
fix(kaggle): H7 make the answer matchers negation aware
Raibows Sep 12, 2026
85ca49c
fix(nvidia): M3 bound integer ids and add a 500 handler
Raibows Sep 12, 2026
d6edd67
fix(kaggle): H8 return a structured verdict for malformed run directo…
Raibows Sep 12, 2026
fa7d878
fix(kaggle): M1 tolerate malformed session user ids in load_user
Raibows Sep 12, 2026
6dc7cb4
fix(nvidia): M4 stop signing sessions with a committed literal key
Raibows Sep 12, 2026
5ed21f6
fix(kaggle): M2 make sign-out a CSRF-protected POST
Raibows Sep 12, 2026
6bbd3f4
fix(kaggle): M2 finish the health probe's logout leg as a POST
Raibows Sep 12, 2026
85f183b
fix(nvidia): M5 make logout POST-only
Raibows Sep 12, 2026
8e60e81
fix(kaggle): M3 restrict the post-login next parameter to local paths
Raibows Sep 12, 2026
b3f71a6
fix(nvidia): M6 bound request bodies and newsletter field values
Raibows Sep 12, 2026
380c637
fix(kaggle): M4 give every form control an accessible name
Raibows Sep 12, 2026
c8cc85f
fix(kaggle): L1 render the forum validation error
Raibows Sep 12, 2026
3f8175d
fix(nvidia): L1 remove the two dead checkout templates
Raibows Sep 12, 2026
c7f51d1
fix(nvidia): L6 caption every product image
Raibows Sep 12, 2026
4f33ef1
fix(nvidia): L7 make the default catalogue ordering neutral
Raibows Sep 12, 2026
89ab86f
fix(nvidia): L3 add the asset inventory manifest
Raibows Sep 12, 2026
0b50fae
fix(nvidia): L4 pin demo password hashes for a deterministic seed
Raibows Sep 12, 2026
3a784a0
docs(nvidia): M7 record the answer-bearing rubric deviation
Raibows Sep 12, 2026
a00324c
fix(healthline): B12 stack the detail header and wrap long words on s…
Raibows Sep 12, 2026
47dd069
fix(kaggle): L2 stop preselecting a forum in the new-discussion form
Raibows Sep 12, 2026
1b82a8e
fix(kaggle): M5 reach WCAG AA contrast and add a visible focus ring
Raibows Sep 12, 2026
982046c
fix(kaggle): H4 wrap the header below 980px so 768px stops overflowing
Raibows Sep 12, 2026
17f4d54
fix(kaggle): L3 link the standalone leaderboard route
Raibows Sep 12, 2026
5cab298
fix(kaggle): L4 order hosted competitions neutrally
Raibows Sep 12, 2026
5dc8062
fix(kaggle): L5 make the notebooks sort control consistent
Raibows Sep 12, 2026
02b1bca
fix(kaggle): L6 make the dataset download a CSRF-protected POST
Raibows Sep 12, 2026
aa75773
fix(kaggle): L7 bound the request body and answer 413 with the site page
Raibows Sep 12, 2026
c8a4e25
fix(kaggle): M7a stop using one user's photo as the default avatar
Raibows Sep 12, 2026
3a8da33
docs(healthline): add the PR #105 final audit report
Raibows Sep 12, 2026
ac908ad
fix(kaggle): M7a import the avatar macro in base.html
Raibows Sep 12, 2026
2cbaca8
fix(kaggle): M8 enforce foreign keys and clean up dependent rows on a…
Raibows Sep 12, 2026
cdf7d6f
docs(nvidia): L5 replace the validation claims with reproducible counts
Raibows Sep 12, 2026
f067f65
docs(nvidia): L8 state the external-reference scope
Raibows Sep 12, 2026
4ae1773
docs(nvidia): add the PR-107 final audit report
Raibows Sep 12, 2026
c1f79b5
fix(kaggle): H9 require a finished run, not a truncated recording
Raibows Sep 12, 2026
b83eca7
docs(kaggle): add the PR #106 review and remediation audit
Raibows Sep 12, 2026
e7f8a5d
Merge pull request #82 from jackjin1997/review/pr-50-fedex
Raibows Sep 13, 2026
f47b6a8
Merge upstream main (FedEx mirror, WebHarbor #82) into the WebMD Doct…
Chilled Sep 13, 2026
f20b5ee
Merge pull request #95 from evanz37/feat/webmd_doctor
Raibows Sep 13, 2026
c3fd9b2
merge: PR #105 (healthline) onto main f20b5ee; re-slot healthline to …
Raibows Sep 13, 2026
431e8b0
fix(healthline): accept the positional seed path used by scripts/fetc…
Raibows Sep 13, 2026
ea2263f
docs: align site inventory to 27 sites / 40000-40026
Raibows Sep 13, 2026
a437bd4
Merge pull request #105 from TabsPhasers/review/pr-59-healthline
Raibows Sep 13, 2026
37fca8f
merge: PR #106 (kaggle) onto current main a437bd4; re-slot kaggle to …
Raibows Sep 13, 2026
4a0f1f6
docs: align site inventory to 28 sites / 40000-40027 and refresh the …
Raibows Sep 13, 2026
145b200
Merge pull request #106 from TabsPhasers/review/pr-70-kaggle
Raibows Sep 13, 2026
02ccde6
merge: PR #107 (nvidia) onto current main 145b200; re-slot nvidia to …
Raibows Sep 13, 2026
9bf0367
fix(nvidia): replace 12 duplicated/mismatched product images with off…
Raibows Sep 14, 2026
514b187
fix(nvidia): align verifiers with rubric wording and strengthen evide…
Raibows Sep 14, 2026
076ebb7
fix(nvidia): remove answer-ordered listings, accessibility and footpr…
Raibows Sep 14, 2026
4421f12
fix(nvidia): replace remaining mismatched and duplicated product imag…
Raibows Sep 14, 2026
ededad7
fix(nvidia): normalise the remaining outlier product image aspect ratios
Raibows Sep 14, 2026
8fae5d4
docs: align site inventory to 29 sites / 40000-40028 and refresh the …
Raibows Sep 14, 2026
3c0d430
fix(nvidia): pin assets at the HF revision that carries the distinct …
Raibows Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
40 changes: 39 additions & 1 deletion .assets-revision
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,43 @@
# fetch_assets.sh uses the `hf download` CLI. The pin below
# is a git revision (branch name like `main`, a tag, or a specific commit
# sha). Override at runtime with the ASSETS_REVISION env var.
#
# The revision is a commit sha, never a moving branch name.
#
# Current pin = the commit that HF dataset `main` points at (verified
# 2026-09-13): the squash-merge commit of HF dataset PR #85 ("Upload nvidia.tar.gz
# with distinct official product and hero images (#107 follow-up)"), which sits on
# top of the merged PR #84 ("Upload repacked nvidia.tar.gz with de-duplicated
# official product images (#107)"), PR #75 ("Add reviewed NVIDIA asset bundle") and
# PR #74 ("Upload kaggle.tar.gz with huggingface_hub"), so this sha is on HF `main`.
#
# Its nvidia.tar.gz is the repacked bundle (sha256
# 617a3e3740ba6706bcab786c8a5c3f9a22ecbb39eff5728ad2c12e4992cb098b, 16340955 bytes,
# 37 file members and no directory entries), which carries the official NVIDIA
# renders for 33 product/news images plus three dedicated hero images under
# static/images/heroes/: 36 images with 36 distinct sha256, so
# sites/nvidia/static/images/ has no byte-identical duplicate and no page reuses
# one file twice. It supersedes the 9927312-byte PR #84 archive (sha256
# ee8c6ba966e7a8f7fb5ad2d7ff0134ab98e7b80d6cc77f3328217405b8b34e2f) and the
# original 6706395-byte bundle (blob 0f1d8068af602748d0dec19ef04b52c7559fef28),
# which carried duplicates.
#
# Why this sha and not the other candidate (refs/pr/37, resolved
# 600a3e1de158ae56dc82a5fab56c2ca25acb1e27):
# * this revision carries an archive for every registered site (29 of 29), and
# the kaggle seed DB it ships was found identical to the seed the site's own
# code generates (13/13 tables, row by row) in the PR #106 audit;
# * refs/pr/37 ships an older kaggle seed (models table has 10 rows instead of
# 11: densenet121-chestxray is absent) and its archives cover only 17 of the
# 29 registered sites, so pinning there would break fetch_assets.sh.
# * this revision's kaggle.tar.gz (sha256
# dd6f1ab34f99989b300e3366225a8f8b0932d49d033b48f141938d16f1c0607d,
# 11278106 bytes) passes the repository's own
# scripts/validate_asset_archive.py:
# [fetch] validated 73 managed members for kaggle
# That 73-member pack has no directory entries, so the earlier
# `ValueError: unexpected managed path: 'kaggle/static'` rejection (from the
# superseded 11278264-byte pack, sha256 c533c283...) no longer applies and
# `scripts/fetch_assets.sh` installs sites/kaggle's assets from this pin.
repo: ChilleD/WebHarbor
revision: 65c479f894763f64c6073e0d180ebf542d1d2c02
revision: b7e605c0ec5fc47de85b09e7427162cc50e38980
4 changes: 2 additions & 2 deletions .claude/skills/clone-website/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ Then run the site once locally to produce `instance/<site>.db`, copy it to
```bash
./scripts/build.sh webharbor:dev
docker run -d --rm --name wh-test \
-p 8201:8101 -p 41000-41014:40000-40014 webharbor:dev
-p 8201:8101 -p 41000-41028:40000-40028 webharbor:dev

# your new site is on port 41000 + its index
curl -so /dev/null -w "%{http_code}\n" http://localhost:41000NN/
Expand All @@ -228,7 +228,7 @@ After Phase 1, you should have:
- `sites/<your_site>/static/` with real CSS/JS/icons (and images under HF assets)
- `sites/<your_site>/instance_seed/<site>.db` with seeded data
- Site registered in `websyn_start.sh`, `control_server.py`, `Dockerfile`
- All 15 sites still return 200 on the alt-port container
- All 29 sites still return 200 on the alt-port container
- Byte-identical reset passes

## Next step
Expand Down
6 changes: 3 additions & 3 deletions .claude/skills/evolve-env/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ through `BASE_DIR = os.path.dirname(os.path.abspath(__file__))`.
After any DB-affecting change:

```bash
# 1. Stop test container (don't touch user's working container on :40000-40014)
# 1. Stop test container (don't touch user's working container on :40000-40028)
docker stop wh-test 2>/dev/null || true

# 2. Rebuild
./scripts/build.sh webharbor:dev

# 3. Run on alt ports
docker run -d --rm --name wh-test \
-p 8201:8101 -p 41000-41014:40000-40014 webharbor:dev
-p 8201:8101 -p 41000-41028:40000-40028 webharbor:dev

# 4. Reset your site and confirm byte-identity
curl -X POST http://localhost:8201/reset/<your_site>
Expand Down Expand Up @@ -149,7 +149,7 @@ After Phase 3:
- Every task in `tasks.jsonl` is hand-verified to work end-to-end
- The mirror has no obvious leaks, broken forms, or empty pages
- Byte-identical reset passes
- All 15 sites still return 200
- All 29 sites still return 200

## Next step

Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/harden-env/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Hardening changes seed data. After any DB change:
```bash
./scripts/build.sh webharbor:dev
docker run -d --rm --name wh-test \
-p 8201:8101 -p 41000-41014:40000-40014 webharbor:dev
-p 8201:8101 -p 41000-41028:40000-40028 webharbor:dev
curl -X POST http://localhost:8201/reset/<your_site>
docker exec wh-test md5sum \
/opt/WebSyn/<your_site>/instance/<your_site>.db \
Expand Down
10 changes: 5 additions & 5 deletions .claude/skills/review-env/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ gh pr checkout <pr-number>
./scripts/fetch_assets.sh # pull the pinned HF revision
./scripts/build.sh webharbor:dev
docker run -d --rm --name wh-review \
-p 8201:8101 -p 41000-41016:40000-40016 webharbor:dev
-p 8201:8101 -p 41000-41028:40000-40028 webharbor:dev
```

Confirm the new/changed site is on the expected port (40000 + index). Note: the image now runs 17 sites (40000-40016).
Confirm the new/changed site is on the expected port (40000 + index). Note: the image now runs 29 sites (40000-40028).

### Step 2: The mechanical checks (5 minutes)

Run the same Pre-PR checks the contributor was supposed to run.

```bash
# 1. all 17 sites return 200
for p in $(seq 41000 41016); do
# 1. all 29 sites return 200
for p in $(seq 41000 41028); do
curl -so /dev/null -w "$p:%{http_code}\n" http://localhost:$p/
done

Expand Down Expand Up @@ -231,7 +231,7 @@ Leave a structured comment on the PR:
## Review: <site_name>

### Mechanical checks: PASS / FAIL
- [x] All 17 sites return 200
- [x] All 29 sites return 200
- [x] Control plane healthy
- [x] Byte-identical reset (md5 match)
- [x] Parallel reset <10s
Expand Down
10 changes: 6 additions & 4 deletions .claude/skills/seed-database/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ gh pr create
./scripts/check_assets.sh # every site has instance_seed/
./scripts/build.sh webharbor:dev # docker build succeeds
docker run -d --rm --name wh-test \
-p 8201:8101 -p 41000-41014:40000-40014 webharbor:dev
-p 8201:8101 -p 41000-41028:40000-40028 webharbor:dev

# all 15 sites return 200
for p in $(seq 41000 41014); do
# all 29 sites return 200
for p in $(seq 41000 41028); do
curl -so /dev/null -w "$p:%{http_code}\n" http://localhost:$p/
done

Expand All @@ -182,7 +182,9 @@ time curl -X POST http://localhost:8201/reset-all
# byte-identity for every site
for s in allrecipes amazon apple arxiv bbc_news booking github \
google_flights google_map google_search huggingface \
wolfram_alpha cambridge_dictionary coursera espn; do
wolfram_alpha cambridge_dictionary coursera espn \
merriam_webster ikea phys_org target ted osu rotten_tomatoes \
compass walmart_careers fedex; do
docker exec wh-test md5sum \
/opt/WebSyn/$s/instance/$s.db \
/opt/WebSyn/$s/instance_seed/$s.db
Expand Down
12 changes: 6 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A coding agent (Claude Code, Cursor, Aider, Codex, ...) is reading this. Read on

## What it is

23 Flask mirror websites (Amazon, GitHub, BBC News, ...) packaged into one Docker image, plus a control plane on `:8101` for resetting per-site state. Used as a deterministic offline environment for web-agent benchmarks. ~3 GB image.
29 Flask mirror websites (Amazon, GitHub, BBC News, ...) packaged into one Docker image, plus a control plane on `:8101` for resetting per-site state. Used as a deterministic offline environment for web-agent benchmarks. ~3 GB image.

Two repos:
- **code** (this one) — Flask apps, control plane, scripts.
Expand Down Expand Up @@ -48,17 +48,17 @@ Inside the image, sites live at `/opt/WebSyn/<site>/`. The path predates the ren
# fresh clone
./scripts/fetch_assets.sh # pulls assets from HF
./scripts/build.sh # docker build -t webharbor:dev .
docker run -d -p 8101:8101 -p 40000-40023:40000-40023 webharbor:dev
docker run -d -p 8101:8101 -p 40000-40028:40000-40028 webharbor:dev
```

Or use the published image directly:

```bash
docker run -d -p 8101:8101 -p 40000-40023:40000-40023 \
docker run -d -p 8101:8101 -p 40000-40028:40000-40028 \
battalion7244/webharbor:latest
```

Sites are on `40000`-`40023` in the order declared by `SITES=( ... )` in `websyn_start.sh`. Control plane:
Sites are on `40000`-`40028` in the order declared by `SITES=( ... )` in `websyn_start.sh`. Control plane:

| Method | Path | Purpose |
|--------|---------------------|-------------------------------------------|
Expand Down Expand Up @@ -136,13 +136,13 @@ python3 -m py_compile sites/<site>/app.py

# 3. run on alt ports (don't collide with anything you already have running)
docker run -d --rm --name wh-test \
-p 8201:8101 -p 41000-41023:40000-40023 webharbor:dev
-p 8201:8101 -p 41000-41028:40000-40028 webharbor:dev

# 4. control plane healthy, all sites alive
curl -s http://localhost:8201/health | python3 -m json.tool | head

# 5. every site renders 200
for p in $(seq 41000 41023); do
for p in $(seq 41000 41028); do
curl -so /dev/null -w "$p:%{http_code}\n" http://localhost:$p/
done

Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ The full agent guide is loaded above via `@AGENTS.md`. The notes below apply onl

## Existing containers

If a container is already running on `:8101` / `:40000-40023`, treat it as the user's working environment — don't `docker stop` or `docker rm` it without explicit confirmation. Spin up your test container under a different name on alt ports (`:8201`, `:41000-41023`).
If a container is already running on `:8101` / `:40000-40028`, treat it as the user's working environment — don't `docker stop` or `docker rm` it without explicit confirmation. Spin up your test container under a different name on alt ports (`:8201`, `:41000-41028`).
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ git clone https://github.com/<you>/webharbor && cd webharbor
./scripts/fetch_assets.sh # pull current assets
./scripts/new_site.py mywebsite # OR edit an existing site
./scripts/build.sh && docker run -d --rm \
-p 8101:8101 -p 40000-40023:40000-40023 webharbor:dev
-p 8101:8101 -p 40000-40028:40000-40028 webharbor:dev
# iterate locally...

./scripts/extract_assets.sh ../webharbor-static-pr/ # split assets out
Expand Down
26 changes: 23 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# WebHarbor — slim, self-contained image.
# 24 Flask mirror sites + control plane on :8101.
# 29 Flask mirror sites + control plane on :8101.

FROM python:3.12-slim-bookworm

Expand Down Expand Up @@ -50,10 +50,30 @@ RUN python3 /opt/check_asset_inventory.py /opt/WebSyn/walmart_careers && \
RUN cd /opt/WebSyn/walmart_careers && rm -rf instance instance_seed && \
PYTHONHASHSEED=0 python seed_data.py && rm -rf instance

# FedEx validates its downloaded homepage media against the tracked inventory and
# rebuilds its deterministic, version-marked SQLite seed from tracked source data.
RUN python3 /opt/check_asset_inventory.py /opt/WebSyn/fedex
RUN cd /opt/WebSyn/fedex && rm -rf instance instance_seed && \
PYTHONHASHSEED=0 python seed_data.py && rm -rf instance

# WebMD Doctor's generated avatars / posters come from the pinned asset bundle,
# while its SQLite seed is rebuilt deterministically from tracked source code.
# The inventory gate enforces exact coverage + per-file SHA-256 + PNG decode of
# all 317 generated images (same contract as the compass / walmart inventories).
RUN python3 /opt/WebSyn/webmd_doctor/check_generated_assets.py
RUN cd /opt/WebSyn/webmd_doctor && rm -rf instance instance_seed && \
PYTHONHASHSEED=0 python seed_data.py && rm -rf instance __pycache__
# Healthline's downloaded seed carries tracked corrections (image reassignment) and the
# pinned archive bundles unreferenced images; apply the deterministic migration and prune
# the unreferenced files before they are shipped.
RUN cd /opt/WebSyn/healthline && test -f instance_seed/healthline.db && \
PYTHONHASHSEED=0 python3 migrate_seed.py && \
python3 prune_unreferenced_images.py --apply && rm -rf instance

COPY websyn_start.sh /opt/websyn_start.sh
COPY control_server.py /opt/control_server.py
COPY site_runner.py /opt/site_runner.py
RUN chmod +x /opt/websyn_start.sh
RUN sed -i 's/\r$//' /opt/websyn_start.sh && chmod +x /opt/websyn_start.sh

# OSU's real-site image bundle is required, while its database is generated
# deterministically from tracked source data.
Expand All @@ -72,6 +92,6 @@ os.makedirs('instance_seed', exist_ok=True); \
shutil.copy2('instance/rotten_tomatoes.db', 'instance_seed/rotten_tomatoes.db'); \
print('Rotten Tomatoes seed DB generated at build time.')" && rm -rf /opt/WebSyn/rotten_tomatoes/instance

EXPOSE 8101 40000-40023
EXPOSE 8101 40000-40028

CMD ["/opt/websyn_start.sh"]
Loading