Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
194 commits
Select commit Hold shift + click to select a range
59d3bd0
Add drugs.com mirror site (port 40015)
boyugou May 13, 2026
61bc7c2
Auto-login as alice; make login/register always succeed
boyugou May 13, 2026
122054a
Redesign all templates to match real drugs.com UI/layout
boyugou May 13, 2026
cb9ce4a
Fix my_med_list toggle form POST, conditions 0-9 duplicate, med list …
boyugou May 13, 2026
64f27c2
Massively expand drugs.com mirror: 212 drugs, 64 news, new pages and …
boyugou May 13, 2026
b600cce
Fix seed_database idempotency for byte-identical /reset
boyugou May 13, 2026
470cf67
Add drug dosage/side-effects pages, improve class/condition/drug deta…
boyugou May 13, 2026
169056d
Add drug pregnancy/interactions pages, improve homepage with health t…
boyugou May 13, 2026
4709544
Add drug reviews page, account subscriptions, improve account settings
boyugou May 13, 2026
50af02e
drugs_com: text formatting, dark mode, news search, UI improvements
boyugou May 13, 2026
672a07d
drugs_com: fix tab switching, compare drugs, sidebar bugs, drug_az route
boyugou May 13, 2026
3a38fb2
drugs_com: drug images, helpful votes, search improvements, side effe…
boyugou May 13, 2026
6206f96
drugs_com: prices, related drugs, pill identifier, warnings, news art…
boyugou May 13, 2026
c747821
drugs_com: autocomplete, utility bar, recently viewed, homepage impro…
boyugou May 13, 2026
1dec011
drugs_com: symptom checker, drug class sorting, pregnancy/dosage impr…
boyugou May 13, 2026
d7acebb
drugs_com: FAQ accordion, login/register polish, account settings, Do…
boyugou May 13, 2026
4aa4020
drugs_com: pro calculators, FDA alerts sidebar, related news, symptom…
boyugou May 13, 2026
8e39fea
drugs_com: condition route alias, review delete, med list notes editing
boyugou May 13, 2026
4f7c9d6
drugs_com: star ratings display, prominent med list CTA, Rx/OTC badge…
boyugou May 13, 2026
dcd35e2
drugs_com: drug class descriptions, conditions grouped A-Z, A-Z lette…
boyugou May 13, 2026
4ccfb72
drugs_com: homepage browse tabs, search related suggestions, class de…
boyugou May 13, 2026
c2890d9
drugs_com: what-to-avoid section, before-taking improvements, avoid_i…
boyugou May 13, 2026
d5838fc
drugs_com: add 16 more news articles (FDA alerts, approvals, trials, …
boyugou May 13, 2026
b13386d
drugs_com: drug images page, interaction checker empty state, two-ton…
boyugou May 13, 2026
733d66c
drugs_com: print CSS, Web Share API, speech synthesis pronunciation
boyugou May 13, 2026
a644523
drugs_com: prices with quantity tiers, GoodRx coupon UI, account impr…
boyugou May 13, 2026
b33b3f1
drugs_com: drug A-Z sidebar, sitemap columns, contact form, newslette…
boyugou May 13, 2026
064fa2b
drugs_com: pro edition content, drug classes with descriptions and to…
boyugou May 13, 2026
501d5e5
drugs_com: 10-star review selector, review card improvements, char co…
boyugou May 13, 2026
6e20362
drugs_com: filter chemistry boilerplate from FDA label text, pill ide…
boyugou May 13, 2026
2ab67ab
drugs_com: per-drug interactions page, condition standard treatments …
boyugou May 13, 2026
d14d51c
drugs_com: drug header SVG, similar drugs cards, status sidebar fixes
boyugou May 13, 2026
2d7777f
drugs_com: continuous scroll drug detail, A-Z sources sections, homep…
boyugou May 13, 2026
bcfb246
drugs_com: interaction checker GET support, compare drugs detailed view
boyugou May 13, 2026
c532c0c
drugs_com: reviews page rating bars + sidebar, drug images pill ident…
boyugou May 13, 2026
5726edf
drugs_com: fix reviews page rating bar rendering
boyugou May 13, 2026
1d4c5a6
drugs_com: condition page drug-class filter, CSS polish, dark mode ad…
boyugou May 13, 2026
60e39c9
drugs_com: photorealistic pill SVGs, real NIH images, homepage health…
boyugou May 13, 2026
01c8581
drugs_com: symptom checker results, search tabs, drug detail callouts…
boyugou May 13, 2026
216825e
drugs_com: conditions filter search, drug classes popular section, do…
boyugou May 13, 2026
ad5a96b
drugs_com: fix metformin seed content, larger pill thumbnail, brand c…
boyugou May 13, 2026
a10a091
drugs_com: account page, alice med list, news badge colors, drug A-Z …
boyugou May 13, 2026
4739c90
drugs_com: fix letter-btn dark background in light mode, use flex wra…
boyugou May 13, 2026
a48abb7
drugs_com: reviewer variety, expanded news articles, drug class table…
boyugou May 13, 2026
1267c62
drugs_com: content quality, clean_desc filter, websyn 16-site fix
boyugou May 13, 2026
cd3dddc
drugs_com: pill identifier fix, CSS polish, condition descriptions
boyugou May 13, 2026
c5fff3d
drugs_com: add URL aliases, empty-stomach FAQ, pill form pre-population
boyugou May 13, 2026
4c0bfde
drugs_com: major search, UI, and layout improvements
boyugou May 13, 2026
ff79145
drugs_com: improve UI for pill identifier, compare, class, med list, …
boyugou May 13, 2026
6e49017
drugs_com: migrate all inline styles from templates to main.css
boyugou May 13, 2026
93c4967
drugs_com: remove accidentally committed runtime/scratch files
boyugou May 13, 2026
e171218
drugs_com: add pro monograph route, comma-separated interaction param…
boyugou May 13, 2026
1de7a67
drugs_com: improve news thumbnails, drug detail sidebar badges, relat…
boyugou May 14, 2026
a1495a2
drugs_com: remove runtime/scratch files from index again
boyugou May 14, 2026
cecc1d6
gitignore: add ralph-loop, site .claude/, download_pill_images.py
boyugou May 14, 2026
bc58344
drugs_com: improve content quality - before_taking overrides, dosage …
boyugou May 14, 2026
fb53ef7
drugs_com: remove runtime files from index
boyugou May 14, 2026
88b7d76
gitignore: explicitly exclude drugs_com instance/ and scraped_data/
boyugou May 14, 2026
c544204
drugs_com: fix alcohol as lifestyle substance in interaction checker
boyugou May 14, 2026
2a72dc5
drugs_com: improve nav dropdown, interaction results, conditions side…
boyugou May 14, 2026
c75c0a7
drugs_com: improve search aliases, drug detail sidebar, pro edition page
boyugou May 14, 2026
69c819f
drugs_com: richer black-box warnings, symptom checker CSS, search ali…
boyugou May 14, 2026
af47246
drugs_com: fix pill identifier GET param handling and form action URL
boyugou May 14, 2026
bb2119a
drugs_com: FDA pregnancy categories, detailed side-effects, quick-fac…
boyugou May 14, 2026
e6afe61
drugs_com: add /news/category/<category> route alias
boyugou May 14, 2026
65ab65a
drugs_com: compare page similarities/differences, popular pairs update
boyugou May 14, 2026
6b78a26
drugs_com: drug detail enhancements - pricing CTA, interaction widget…
boyugou May 14, 2026
9a22a8a
drugs_com: richer drug class pages, hero autocomplete, dosage tabs
boyugou May 14, 2026
a753c17
drugs_com: write-review page, reviews condition filter, warnings callout
boyugou May 14, 2026
b83a2c8
drugs_com: fix inline styles, update breadcrumb to 'Dosage Guide'
boyugou May 14, 2026
9406f8d
drugs_com: add 4 more ACE inhibitors to seed data (216 drugs total)
boyugou May 14, 2026
d9d039c
drugs_com: add 18 more drugs to fill sparse classes (234 drugs total)
boyugou May 14, 2026
1f78e4c
drugs_com: conditions callout chip block at top of drug detail Uses s…
boyugou May 14, 2026
64e4b8a
drugs_com: pill identifier shape/color pickers, search results improv…
boyugou May 14, 2026
36074cc
Improve drug class pages, fix ciprofloxacin content, add runtime cont…
boyugou May 14, 2026
9e3c98c
Add before_taking content overrides for 12 additional drugs
boyugou May 14, 2026
b2e331e
Add supplemental conditions and drug-condition links via seed_supplem…
boyugou May 14, 2026
6ff3478
Improve search ranking: exact and partial generic name matches boosted
boyugou May 14, 2026
273b9e3
Add extended drug class descriptions for 5 more classes
boyugou May 14, 2026
12207ba
Fix duplicate reviews and raw condition slug display in review bodies
boyugou May 14, 2026
ba78f51
Add accurate pregnancy risk categories for 60+ drugs
boyugou May 14, 2026
d6bc55e
Add rich content overrides for 7 more commonly searched drugs
boyugou May 14, 2026
94288ce
Add content overrides for 5 more commonly accessed drugs
boyugou May 14, 2026
6003296
Add content overrides for 10 more commonly accessed drugs
boyugou May 14, 2026
a37d57a
Fix pregnancy category badge to display correctly for full-text risk …
boyugou May 14, 2026
54e2f06
Add content overrides for 8 more high-traffic drugs
boyugou May 14, 2026
63b9624
Fix duplicate news category tabs on news_category pages
boyugou May 14, 2026
321206b
Add content overrides for fluoxetine, gabapentin, pregabalin, warfari…
boyugou May 14, 2026
b7c31be
Add content overrides for levofloxacin, levothyroxine, alprazolam, ox…
boyugou May 14, 2026
0651084
Add content overrides for 20 more high-traffic drugs
boyugou May 14, 2026
3dd3f8a
Add content overrides for 35 more drugs
boyugou May 14, 2026
e366c28
Add content overrides for 12 more drugs
boyugou May 14, 2026
3443f74
Add content overrides for 15 more high-traffic drugs
boyugou May 14, 2026
abbb65f
Add content overrides for 9 more drugs
boyugou May 14, 2026
1c7c837
Add content overrides for 13 more drugs
boyugou May 14, 2026
f97cdd6
Add content overrides for 10 more drugs
boyugou May 14, 2026
ee29242
Add content overrides for 11 more drugs
boyugou May 14, 2026
595e8e4
Add content overrides for 11 more drugs
boyugou May 14, 2026
e4514d4
Add content overrides for methadone, bisoprolol, chlorthalidone, inda…
boyugou May 14, 2026
2f6c4f2
Fix seed_extra_reviews gate to prevent post-reset byte-identity breakage
boyugou May 14, 2026
9205639
Fix dosage forms display for injectable, inhaled, and topical drugs
boyugou May 14, 2026
6833b52
Fix dosage forms in compare_drugs route for injectable/inhaled drugs
boyugou May 14, 2026
996a2b0
Add content overrides for 57 more drugs
boyugou May 14, 2026
0f3d938
Apply DRUG_CONTENT_OVERRIDES to dosage, side-effects, warnings sub-pages
boyugou May 14, 2026
fb518d6
Fix DRUG_CONTENT_OVERRIDES lookup for hyphenated keys; add drug-speci…
boyugou May 14, 2026
f9b83cb
Add drug-specific dosage table rows from override content
boyugou May 14, 2026
ce4ea99
Fix all 21 benchmark tasks: lisinopril Category D, amoxicillin 250 mg…
boyugou May 14, 2026
4946c2e
Remove duplicate DRUG_CONTENT_OVERRIDES keys that overrode richer ent…
boyugou May 14, 2026
c04bba2
Fix several display issues on drugs_com mirror site
boyugou May 14, 2026
adfd692
Fix FDA label artifacts in drug interactions text and clean up compar…
boyugou May 14, 2026
2425196
Fix content quality and interaction checker UX
boyugou May 14, 2026
3589de1
Suppress raw FDA structured table text from interactions section
boyugou May 14, 2026
9ab7e7c
Add ratings for all drugs, fix "drugs drugs" label, expand review see…
boyugou May 14, 2026
84c4f1c
Fix byte-identity invariant: gate supplemental seed functions
boyugou May 14, 2026
151188d
Fix I-2 pill shape to Oval and deduplicate dosage strengths list
boyugou May 14, 2026
57b17f8
Improve UI fidelity: fix interaction FAQ byline, section tabs, news p…
boyugou May 14, 2026
32826a4
Expand homepage: 11-tile feature carousel, richer right-rail, top-100…
boyugou May 14, 2026
4b32349
Fix dead placeholder links in pill identifier sidebar and register page
boyugou May 14, 2026
c28cd63
Fix form routing bugs, dosage display, and med-list fetch error handling
boyugou May 14, 2026
f38f5f8
Fix interaction checker sidebar dead links
boyugou May 14, 2026
ad15fc8
Improve UI fidelity: 3-col homepage, condition-grouped compare, simpl…
boyugou May 14, 2026
79bc998
Fix Compare Drugs nav link to use url_for
boyugou May 14, 2026
8e56283
Improve search, drug A-Z, and content quality
boyugou May 14, 2026
93b9e08
drugs_com: visual audit fixes — remove fabricated sections, align wit…
boyugou May 14, 2026
894acc2
drugs_com: simplify reviews block, remove duplicate med-list CTA
boyugou May 14, 2026
b39af9a
drugs_com: fix Jinja2 slice-after-filter syntax error in drug_detail
boyugou May 14, 2026
8f98259
drugs_com: show all FAQ items with answers, not truncated links
boyugou May 14, 2026
99b67cc
drugs_com: add J/U/X/Y drugs, fix pill shapes, tabs, trending, FAQs
boyugou May 14, 2026
e8729d4
drugs_com: style drug A-Z search form to match rest of site
boyugou May 14, 2026
3c7d0d0
drugs_com: remove duplicate popular-searches block, fix sidebar grid,…
boyugou May 14, 2026
c32cd27
drugs_com: fix page-with-sidebar layout, add /compare-drugs route alias
boyugou May 14, 2026
ecc0de0
drugs_com: add /drug-classes/<slug> route alias for drug class pages
boyugou May 14, 2026
27bf65f
drugs_com: use minmax() in detail-grid to prevent sidebar clipping
boyugou May 14, 2026
a60fa95
drugs_com: normalize hyphen/underscore slugs for condition and drug c…
boyugou May 14, 2026
abcf9cb
drugs_com: redirect brand name URLs to generic drug page
boyugou May 14, 2026
26c7cfd
drugs_com: fix ezetimibe drug class (Statins → Cholesterol absorption…
boyugou May 14, 2026
a86e579
drugs_com: optimize brand name redirect to use DB LIKE search instead…
boyugou May 14, 2026
6901a79
drugs_com: update seed DB (ezetimibe drug class fix)
boyugou May 14, 2026
6796edd
drugs_com: add section tabs to sub-pages, fix news article key takeaways
boyugou May 14, 2026
4aeeea3
drugs_com: add /<slug>/drug-interactions route alias
boyugou May 14, 2026
30b82be
drugs_com: add /pro/<slug> route alias for drug professional monograph
boyugou May 14, 2026
aafd068
feat(drugs_com): convert FAQ section to collapsible accordion
boyugou May 14, 2026
4da4791
feat(drugs_com): fix warnings page for single-paragraph boxed warning…
boyugou May 14, 2026
17ee62a
fix: FAQ answers truncated mid-sentence
boyugou May 14, 2026
75cf8fe
feat: add 5 missing drugs referenced on homepage
boyugou May 14, 2026
410e2da
fix: add .html aliases for /terms and /privacy routes
boyugou May 14, 2026
0da8a7f
Add .html URL aliases and news shortcut routes
boyugou May 14, 2026
a203b55
Add more URL aliases and fix drug detail nav tabs
boyugou May 14, 2026
e310884
Add /advertise alias and minor route completeness
boyugou May 14, 2026
656a7a4
drugs_com: add lecanemab/conditions, fix carousel overflow clipping
boyugou May 14, 2026
d57e64e
drugs_com: add write-review URL aliases
boyugou May 14, 2026
92c4f3f
drugs_com: fix password autocomplete attributes
boyugou May 14, 2026
3c4e4c0
gitignore: exclude .claude/ralph-loop.local.md from tracking
boyugou May 14, 2026
667fb64
drugs_com: add /<slug>/monograph route aliases
boyugou May 14, 2026
6d5cee9
expand seed_extra_reviews: more drugs, raise gate, recompute ratings
boyugou May 14, 2026
7b73a51
stop tracking instance_seed/drugs_com.db (goes to HuggingFace)
boyugou May 14, 2026
567568e
add more drugs to review seed list, fix tirzepatide/sumatriptan/diphe…
boyugou May 14, 2026
bf30924
fix: compare drugs autocomplete and med list Rx/OTC counts
boyugou May 14, 2026
48cd177
fix: replace datalist with JS autocomplete on interaction checker input
boyugou May 14, 2026
9ee154b
fix: deduplicate seed reviews and make seed_extra_reviews idempotent
boyugou May 14, 2026
086fb7f
fix: replace hardcoded pink SVG with render_pill macro in Drug Images…
boyugou May 14, 2026
5e59256
fix: correct canonical URLs for drug_az, pill_identifier, interaction…
boyugou May 14, 2026
8495b61
fix: correct more canonical URLs and fix More... dropdown links
boyugou May 14, 2026
70692c4
fix: add price-guide URL alias and case-insensitive news category filter
boyugou May 14, 2026
306e386
fix: prevent duplicate drug entries in interaction checker
boyugou May 14, 2026
2c21c2a
feat: comprehensive UI/UX polish and functionality additions
boyugou May 15, 2026
f753902
docs(drugs_com): add CLAUDE.md with architecture and dev guide
boyugou May 15, 2026
daad795
Merge upstream/main; reconcile 16th-site collision (drugs_com -> 40016)
boyugou Jun 25, 2026
399cb3c
fix(drugs_com): clean asset packing, task-10 FAQ, prune unused dep
boyugou Jun 25, 2026
0d2e343
chore: exclude .venv from image context; clarify drugs_com asset docs
boyugou Jun 25, 2026
d67e810
fix(drugs_com): remove answer-leak from search results
boyugou Jul 9, 2026
08f8b23
fix(drugs_com): real auth, CSRF protection, seed data-quality fixes
boyugou Jul 9, 2026
3c9d0f8
fix(drugs_com): findings from independent Codex review pass
boyugou Jul 9, 2026
965e516
fix(drugs_com): findings from 4 parallel Codex reviews (leaks, data i…
boyugou Jul 9, 2026
b2fccfa
docs(drugs_com): document current PR/asset status, auth/CSRF/leak-gua…
boyugou Jul 9, 2026
d1f096f
feat(drugs_com): add drugs.com mirror site
boyugou Jul 10, 2026
588cbab
fix(drugs_com): remove orphaned share-btn handler, document rating-ro…
boyugou Jul 10, 2026
73eba14
Add Drugs.com task verifiers (site by @boyugou, verifiers by reviewer)
Django-Jiang Jul 20, 2026
8080a5c
Add reviewed Drugs.com mirror and deterministic verifiers
Raibows Sep 9, 2026
e95ac74
Harden Drugs.com release and verification contracts
Raibows Sep 10, 2026
0be0a25
Close immutable PR 71 audit findings
Raibows Sep 10, 2026
5fc1dbb
Resolve final verifier and release follow-ups
Raibows Sep 10, 2026
6111971
Lock release inputs and close UI follow-ups
Raibows Sep 10, 2026
d64c704
Isolate control credentials and complete verifier binding
Raibows Sep 10, 2026
03a07b6
Enforce remaining identity, seed, and UI contracts
Raibows Sep 10, 2026
92c1908
Bound authentication inputs and backup residue
Raibows Sep 10, 2026
1870688
Complete semantic verifier relations
Raibows Sep 10, 2026
6dba6f9
Close remaining answer and interaction semantics
Raibows Sep 10, 2026
1d4b291
Bind every task fact to its requested entity
Raibows Sep 10, 2026
256e47c
Close final Drugs.com UI and provenance gaps
Raibows Sep 10, 2026
9c38a2a
Close final verifier and release integrity findings
Raibows Sep 10, 2026
92e123a
Define closed structured task answer contracts
Raibows Sep 10, 2026
ed4def2
Close orphan process and structured result edge cases
Raibows Sep 10, 2026
48be0d7
Close final alias contrast and parser findings
Raibows Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .assets-revision
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# (instance_seed/*.db, static/images/, static/external_cache/).
#
# 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.
# is an immutable commit SHA. ASSETS_REVISION may assert this exact value;
# fetch_assets.sh rejects every differing override to prevent mislabeled trees.
repo: ChilleD/WebHarbor
revision: 65c479f894763f64c6073e0d180ebf542d1d2c02
revision: 18e64e4d230794f990199f3327432d26db36866f
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# HF download metadata produced by `hf download` — not part of the image.
sites/.cache/
sites/.assets-state.json
sites/**/*.asset-backup
**/.cache/huggingface/

# Don't ship — websyn_start.sh recreates instance/ from instance_seed/ at boot.
Expand All @@ -12,8 +14,10 @@ sites/*/scraped_data/
sites/*/scripts_dev/
sites/*/tests/
sites/*/verify/tests/
sites/*/verify/test*.py
agent_demo/runs/
.venv/
**/.venv/

# Don't ship — bytecode / venvs.
sites/*/__pycache__/
Expand All @@ -26,6 +30,13 @@ sites/*/*.pyc
# extracted content. Shipping both doubles the COPY layer.
sites/*.tar.gz

# Never admit Git-ignored local configuration or secret-key material into a layer.
**/.env
**/.env.*
**/secrets.json
**/*.pem
**/*.key

# Build / CI workspace not part of the image.
build/
.assets/
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ sites/*/venv/

# HF download metadata produced by `hf download`.
sites/.cache/
sites/.assets-state.json
**/.cache/huggingface/

# HF dataset auto-artifacts that arrive together with the assets but belong
Expand Down
44 changes: 22 additions & 22 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.
25 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 All @@ -27,14 +27,16 @@ sites/<site>/
├── static/{css,js,icons}/ small UI, in git
├── static/images/ heavy, in HF dataset
├── static/external_cache/ optional, in HF dataset
└── instance_seed/<site>.db seed DB, in HF dataset
└── instance_seed/<database>.db exactly one valid SQLite seed (new sites should use <site>.db)

control_server.py :8101 control plane
site_runner.py per-site supervisor (setsid + killpg)
websyn_start.sh container entrypoint
Dockerfile
requirements.lock exact Docker dependency versions and wheel SHA-256 values
.assetpaths paths managed via HF
.assets-revision pins HF dataset repo + revision
assets-manifest.json tracked SHA-256/size map for all HF archives plus extracted-tree digest
scripts/{fetch,extract,check}_assets.sh
scripts/build.sh
scripts/new_site.py
Expand All @@ -48,21 +50,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
export WEBSYN_CONTROL_TOKEN="$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')"
docker run -d -e WEBSYN_CONTROL_TOKEN -p 8101:8101 -p 40000-40024:40000-40024 webharbor:dev
```

Or use the published image directly:
A published image may lag the repository. Do not treat it as evidence for the checked-out source revision; build and test the local image when reviewing a PR.

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

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

| Method | Path | Purpose |
|--------|---------------------|-------------------------------------------|
| GET | `/health` | per-site PID + alive |
| GET | `/health` | authenticated per-site PID + alive |
| POST | `/reset/<site>` | wipe `instance/`, restore from seed, respawn |
| POST | `/reset-all` | parallel reset of every site |
| POST | `/restart/<site>` | respawn process; **DB not reset** |
Expand Down Expand Up @@ -135,23 +133,25 @@ python3 -m py_compile sites/<site>/app.py
./scripts/build.sh webharbor:dev

# 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
export WEBSYN_CONTROL_TOKEN="$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')"
docker run -d --rm --name wh-test -e WEBSYN_CONTROL_TOKEN \
-p 8201:8101 -p 41000-41024:40000-40024 webharbor:dev

# 4. control plane healthy, all sites alive
curl -s http://localhost:8201/health | python3 -m json.tool | head
# 4. authenticated control plane healthy, all sites alive
curl -s -H "Authorization: Bearer $WEBSYN_CONTROL_TOKEN" 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 41024); do
curl -so /dev/null -w "$p:%{http_code}\n" http://localhost:$p/
done

# 6. byte-identical reset (the strict invariant)
curl -X POST http://localhost:8201/reset/<your_site>
docker exec wh-test md5sum \
/opt/WebSyn/<your_site>/instance/<your_site>.db \
/opt/WebSyn/<your_site>/instance_seed/<your_site>.db
# the two md5s MUST match — if not, see "Idempotent seeding"
curl -X POST -H "Authorization: Bearer $WEBSYN_CONTROL_TOKEN" http://localhost:8201/reset/<your_site>
DB_NAME=$(docker exec wh-test sh -ec 'set -- /opt/WebSyn/<your_site>/instance_seed/*.db; test "$#" -eq 1; basename "$1"')
docker exec wh-test sha256sum \
"/opt/WebSyn/<your_site>/instance/$DB_NAME" \
"/opt/WebSyn/<your_site>/instance_seed/$DB_NAME"
# the two SHA-256 values MUST match — if not, see "Idempotent seeding"

# 7. teardown
docker stop wh-test
Expand Down Expand Up @@ -209,7 +209,7 @@ Per-row gates aren't enough — even a no-op `db.session.commit()` bumps SQLite

### Runtime data lives in `instance_seed/*.db`, not JSON

HTTP handlers must read from SQLAlchemy, not from `scraped_data/*.json`. If you have intermediate scrape JSON, fold it into `instance_seed/<site>.db` at build time via `seed_data.py`. The `scraped_data/` dir is gitignored + dockerignored — never shipped.
HTTP handlers must read from SQLAlchemy, not from `scraped_data/*.json`. If you have intermediate scrape JSON, fold it into the site's single `instance_seed/*.db` at build time via `seed_data.py`. The `scraped_data/` dir is gitignored + dockerignored — never shipped.

### Sites are isolated

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-40024`, 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-41024`).
49 changes: 28 additions & 21 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,24 @@ Workflows A and B below are the **contributor's** job. The **Reviewer role** sec
## TL;DR

```bash
# fork github.com/webharbor/webharbor + huggingface.co/datasets/ChilleD/WebHarbor
# fork github.com/aiming-lab/WebHarbor + huggingface.co/datasets/ChilleD/WebHarbor
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
./scripts/build.sh
export WEBSYN_CONTROL_TOKEN="$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')"
docker run -d --rm -e WEBSYN_CONTROL_TOKEN \
-p 8101:8101 -p 40000-40024:40000-40024 webharbor:dev
# iterate locally...

./scripts/extract_assets.sh ../webharbor-static-pr/ # split assets out
cd ../webharbor-static-pr
hf upload-large-folder <your-fork>/WebHarbor . --repo-type dataset
# open PR on HF first → grab the merge sha
cd ../webharbor
echo "revision: <hf-merge-sha>" > .assets-revision
sed -i "s/^revision:.*/revision: <hf-merge-sha>/" .assets-revision
./scripts/fetch_assets.sh --refresh-manifest # full fetch; rewrites tracked archive/tree digests
git add .assets-revision assets-manifest.json
git commit -am "feat(mywebsite): add site + bump assets to <sha>"
gh pr create
```
Expand Down Expand Up @@ -64,7 +68,7 @@ mywebsite/
├── requirements.txt ← only Flask by default
├── templates/index.html
├── static/{css,js,icons,images,external_cache}/
├── instance_seed/ ← drop your seed DB here as <name>.db
├── instance_seed/ ← exactly one valid SQLite DB; new sites should use <name>.db
├── instance/ ← gitignored, recreated at boot
└── scraped_data/ ← gitignored, build-time only
```
Expand All @@ -77,8 +81,8 @@ A typical seed flow:

1. Define SQLAlchemy models in `app.py` (User, Product, Article, ...)
2. Write a `seed_data.py` that materializes a dataset into the DB. Make the function **idempotent** — `if Foo.query.count() > 0: return` at the top.
3. Run once locally to produce `instance/<name>.db`.
4. Copy it to `instance_seed/<name>.db`. **This is your seed.**
3. Run once locally to produce the application-defined database filename (new sites should use `instance/<name>.db`).
4. Copy that single database to `instance_seed/` with the same filename. **This is your seed.**

### 4. Functional checklist

Expand All @@ -94,18 +98,20 @@ If your site has multiple categories / pages / topics, make sure the seed DB has

```bash
./scripts/build.sh
docker run -d --rm --name wh-test \
export WEBSYN_CONTROL_TOKEN="$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')"
docker run -d --rm --name wh-test -e WEBSYN_CONTROL_TOKEN \
-p 8101:8101 -p 40000-400NN:40000-400NN webharbor:dev

# the new site should be on port 40000+i
curl -so /dev/null -w "%{http_code}\n" http://localhost:400NN/
curl -X POST http://localhost:8101/reset/mywebsite

# make sure /reset/mywebsite keeps the DB byte-identical to the seed
docker exec wh-test md5sum \
/opt/WebSyn/mywebsite/instance/<name>.db \
/opt/WebSyn/mywebsite/instance_seed/<name>.db
# both md5s MUST match — see "Idempotent seeding" below
curl -X POST -H "Authorization: Bearer $WEBSYN_CONTROL_TOKEN" http://localhost:8101/reset/mywebsite

# make sure /reset/mywebsite keeps the one application-defined DB byte-identical to the seed
DB_NAME=$(docker exec wh-test sh -ec 'set -- /opt/WebSyn/mywebsite/instance_seed/*.db; test "$#" -eq 1; basename "$1"')
docker exec wh-test sha256sum \
"/opt/WebSyn/mywebsite/instance/$DB_NAME" \
"/opt/WebSyn/mywebsite/instance_seed/$DB_NAME"
# both SHA-256 values MUST match — see "Idempotent seeding" below
```

### 6. Write the tasks (`tasks.jsonl`)
Expand Down Expand Up @@ -140,9 +146,10 @@ hf upload mywebsite.tar.gz <your-fork>/WebHarbor mywebsite.tar.gz --repo-type da
# After it's merged, copy the merge commit sha.

cd ../webharbor
# bump the pin
# bump the pin and bind every downloaded archive plus the extracted tree
sed -i "s/^revision:.*/revision: <hf-merge-sha>/" .assets-revision
git add .
./scripts/fetch_assets.sh --refresh-manifest
git add .assets-revision assets-manifest.json .
git commit -m "feat(mywebsite): add new site

Adds Flask app, templates, and seed DB for <real-site-name>.
Expand Down Expand Up @@ -172,7 +179,7 @@ hf upload amazon.tar.gz <your-fork>/WebHarbor amazon.tar.gz --repo-type dataset
# (single-file upload keeps the PR scoped to one site)
```

Open the HF PR; once merged, bump `.assets-revision` in this repo and open the GitHub PR. CI on the GitHub PR will fail-closed if the pinned revision isn't reachable.
Open the HF PR; once merged, bump `.assets-revision`, run `./scripts/fetch_assets.sh --refresh-manifest`, commit `assets-manifest.json`, and open the GitHub PR. CI on the GitHub PR will fail-closed if the pinned revision isn't reachable.

## Reviewer role — validate the site and grade the tasks

Expand All @@ -182,7 +189,7 @@ The reviewer picks up a contributor's PR (site + `tasks.jsonl` with the basic ke

Build the image from the branch and run it on alt ports (see AGENTS.md "Pre-PR checks" for the exact commands). Then:

1. **Mechanical** — every site returns 200; `/health` all alive; `POST /reset/<site>` wipes runtime writes and restores the DB **byte-identical** to the seed (`md5(instance) == md5(instance_seed)`); `reset-all` completes in ~1s.
1. **Mechanical** — every site returns 200; `/health` all alive; `POST /reset/<site>` wipes runtime writes and restores the DB **byte-identical** to the seed (`sha256(instance) == sha256(instance_seed)`); verify reset-all completion from its structured per-site response.
2. **Functional** — drive the site's routes (auth, search, list/detail, any stateful action) and confirm each renders correct, non-empty content. The contributor's tasks must be genuinely completable on these pages.
3. **Task feasibility** — for each task in `tasks.jsonl`, confirm it is **solvable by navigating the site** and is **not trivially answerable from an LLM's prior knowledge**. Drive a few tasks end-to-end (manually or with `agent_demo/agent.py`). Reject — and send back to the contributor — tasks that:
- can be answered without ever opening the site (e.g. a common dictionary definition),
Expand Down Expand Up @@ -258,10 +265,10 @@ Per-row gates are not enough: the bare act of opening a SQLAlchemy session and c
If you have *multiple* seed phases (`seed_database`, `seed_benchmark_users`, `seed_extras`), gate **each** of them. After a fresh seed, re-running the boot path should be a no-op. Test with:

```bash
docker exec wh-test md5sum /opt/WebSyn/<site>/instance{,_seed}/<site>.db
docker exec wh-test sh -ec 'set -- /opt/WebSyn/<site>/instance_seed/*.db; test "$#" -eq 1; db=$(basename "$1"); sha256sum "/opt/WebSyn/<site>/instance/$db" "/opt/WebSyn/<site>/instance_seed/$db"'
# must match
docker restart wh-test && sleep 5
docker exec wh-test md5sum /opt/WebSyn/<site>/instance{,_seed}/<site>.db
docker exec wh-test sh -ec 'set -- /opt/WebSyn/<site>/instance_seed/*.db; test "$#" -eq 1; db=$(basename "$1"); sha256sum "/opt/WebSyn/<site>/instance/$db" "/opt/WebSyn/<site>/instance_seed/$db"'
# must STILL match
```

Expand Down
34 changes: 18 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
# WebHarbor — slim, self-contained image.
# 24 Flask mirror sites + control plane on :8101.
# 25 Flask mirror sites + control plane on :8101.

FROM python:3.12-slim-bookworm
FROM python:3.12-slim-bookworm@sha256:782412e85d0f0984994c290652577d4018aff08145c85b262bb63dc0c7522254

ENV PYTHONUNBUFFERED=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
LANG=C.UTF-8

RUN pip3 install --no-cache-dir \
Flask==3.1.0 \
Flask-SQLAlchemy==3.1.1 \
Flask-Login==0.6.3 \
Flask-WTF==1.2.2 \
Flask-Bcrypt==1.0.1 \
bcrypt==5.0.0 \
Werkzeug==3.1.3 \
Jinja2==3.1.4 \
SQLAlchemy==2.0.36 \
WTForms==3.2.1 \
email-validator==2.2.0 \
Pillow==11.0.0
COPY requirements.lock /opt/requirements.lock
RUN pip3 install --no-cache-dir --require-hashes -r /opt/requirements.lock

WORKDIR /opt/WebSyn

# Sites tree. Build context must contain the heavy assets (instance_seed/,
# static/images/, static/external_cache/) — either commit them locally or
# run scripts/fetch_assets.sh to pull them from Hugging Face first.
COPY sites/ /opt/WebSyn/
COPY .assets-revision /opt/.assets-revision
COPY assets-manifest.json /opt/assets-manifest.json
COPY scripts/check_asset_inventory.py /opt/check_asset_inventory.py
COPY scripts/check_seed_databases.py /opt/check_seed_databases.py
COPY scripts/asset_state.py /opt/asset_state.py
RUN python3 /opt/asset_state.py verify /opt/WebSyn /opt/.assets-revision /opt/assets-manifest.json

# IKEA's seed is reproducibly materialized from the tracked source catalog so code-only content fixes do not require an asset-repository write. Product images still come from the pinned asset bundle.
RUN cd /opt/WebSyn/ikea && PYTHONHASHSEED=0 python seed_data.py && rm -rf instance
Expand All @@ -50,6 +44,11 @@ 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

# Drugs.com uses database-backed inline pill renderings and rebuilds its versioned deterministic SQLite seed from tracked source data without network access.
RUN python3 /opt/check_asset_inventory.py /opt/WebSyn/drugs_com
RUN cd /opt/WebSyn/drugs_com && rm -rf instance instance_seed && \
PYTHONHASHSEED=0 python seed_data.py && 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
Expand All @@ -72,6 +71,9 @@ 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
# Final fail-closed package gate after every tracked seed generator and migration.
RUN python3 /opt/check_seed_databases.py /opt/WebSyn

EXPOSE 8101 40000-40024

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