Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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.
24 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-40022:40000-40022 webharbor:dev
docker run -d -p 8101:8101 -p 40000-40023:40000-40023 webharbor:dev
```

Or use the published image directly:

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

Sites are on `40000`-`40022` in the order declared by `SITES=( ... )` in `websyn_start.sh`. Control plane:
Sites are on `40000`-`40023` 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-41022:40000-40022 webharbor:dev
-p 8201:8101 -p 41000-41023:40000-40023 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 41022); do
for p in $(seq 41000 41023); 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-40022`, 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-41022`).
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`).
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-40022:40000-40022 webharbor:dev
-p 8101:8101 -p 40000-40023:40000-40023 webharbor:dev
# iterate locally...

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

FROM python:3.12-slim-bookworm

Expand Down Expand Up @@ -66,6 +66,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-40022
EXPOSE 8101 40000-40023

CMD ["/opt/websyn_start.sh"]
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ WebHarbor takes a different approach. We leverage coding agent (e.g., Claude Cod
- **Deep features unlocked** — carts, checkouts, accounts, all fully testable
- **Evolving** — harder tasks drive richer mirrors; the environment grows with agents
- **RL-ready** — sub-second database resets between rollouts
- **Community-driven** — 23 sites today, scaling to 100+ together
- **Community-driven** — 24 sites today, scaling to 100+ together

## 🚀 Quickstart

One command to run all web environments:

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

Then point your agent at `http://localhost:40000` through `http://localhost:40022` to explore 23 local mirrors of WebVoyager sites: `Allrecipes, Amazon, Apple, ArXiv, BBC News, Booking, GitHub, Google Flights, Google Maps, Google Search, Hugging Face, Wolfram Alpha, Cambridge Dictionary, Coursera, ESPN, Merriam-Webster, IKEA, Phys.org, Target, TED, Ohio State University, Rotten Tomatoes, and Compass`.
Then point your agent at `http://localhost:40000` through `http://localhost:40023` to explore 24 local mirrors of WebVoyager sites: `Allrecipes, Amazon, Apple, ArXiv, BBC News, Booking, GitHub, Google Flights, Google Maps, Google Search, Hugging Face, Wolfram Alpha, Cambridge Dictionary, Coursera, ESPN, Merriam-Webster, IKEA, Phys.org, Target, TED, Ohio State University, Rotten Tomatoes, Compass, and 4shared`.

For sub-second reset between rollouts, expose the control plane and call `/reset/<site>`:

Expand All @@ -65,7 +65,7 @@ git clone https://github.com/aiming-lab/WebHarbor && cd WebHarbor

## 🤝 Contribute

We have built 23 high-quality mirrors covering the [WebVoyager](https://github.com/MinorJerry/WebVoyager) benchmark. The next goal is **100+ sites**, covering everything in [Online-Mind2Web](https://huggingface.co/datasets/osunlp/Online-Mind2Web). We are inviting the community to build this together.
We have built 24 high-quality mirrors covering the [WebVoyager](https://github.com/MinorJerry/WebVoyager) benchmark. The next goal is **100+ sites**, covering everything in [Online-Mind2Web](https://huggingface.co/datasets/osunlp/Online-Mind2Web). We are inviting the community to build this together.

There are two ways to join the author list:

Expand Down
2 changes: 1 addition & 1 deletion control_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
'allrecipes', 'amazon', 'apple', 'arxiv', 'bbc_news', 'booking',
'github', 'google_flights', 'google_map', 'google_search',
'huggingface', 'wolfram_alpha', 'cambridge_dictionary',
'coursera', 'espn', 'merriam_webster', 'ikea', 'phys_org', 'target', 'ted', 'osu', 'rotten_tomatoes', 'compass',
'coursera', 'espn', 'merriam_webster', 'ikea', 'phys_org', 'target', 'ted', 'osu', 'rotten_tomatoes', 'compass', '4shared',
]
BASE_PORT = 40000
WEBSYN_DIR = '/opt/WebSyn'
Expand Down
89 changes: 89 additions & 0 deletions review-reports/PR-90-FINAL-AUDIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# PR #90 final audit — 4shared

## Result

**PASS — 20/20 tasks, 252 visible-browser steps, 0 unresolved findings.**

The review was rerun against the packaged `webharbor:dev` image after all
remediation. Every task started from the configured homepage, used Playwright
visible-element locators, and finished with a persistence check. The site was
reset before and after every task; every reset restored a byte-identical
runtime/seed pair with MD5 `b577adc216900a6f0e3974a80e51c04c`.

Complete action traces and task screenshots are retained outside the
agent-visible repository to avoid creating answer-bearing benchmark artifacts.
The table below records sanitized endpoints and evidence classes.

## Per-task review

| Task | Steps | Screenshot | URL | Issue | Evidence | Impact | Severity | Reproduction |
| --- | ---: | --- | --- | --- | --- | --- | --- | --- |
| 4shared--0 | 15 | `4shared--0-15-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Search, category filter, candidate inspection, metadata comparison, reload | Requested identification remained visible | None | Reset → homepage → follow task |
| 4shared--1 | 24 | `4shared--1-24-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Images browse, multiple detail inspections, metadata comparison, reload | Requested image evidence remained visible | None | Reset → homepage → follow task |
| 4shared--2 | 7 | `4shared--2-07-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Search, category filter, detail inspection, reload | Requested book comparison completed | None | Reset → homepage → follow task |
| 4shared--3 | 15 | `4shared--3-15-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Broad search, candidate inspection, detail verification, reload | Multi-clue identification completed | None | Reset → homepage → follow task |
| 4shared--4 | 7 | `4shared--4-07-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Broad search, candidate inspection, license/detail verification | Multi-clue identification completed | None | Reset → homepage → follow task |
| 4shared--5 | 6 | `4shared--5-06-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Category browse, both detail pages opened, runtimes compared | Cross-item comparison completed | None | Reset → homepage → follow task |
| 4shared--6 | 6 | `4shared--6-06-reload-persistence-check.png` | `/download/<id>` | None — PASS | Six-result search, target at position 6, detail check, download confirmation | Download state changed exactly as requested | None | Reset → homepage → follow task |
| 4shared--7 | 12 | `4shared--7-12-reload-persistence-check.png` | `/favorites` | None — PASS | Login, eight-result search, target at position 6, favorite, reload | Favorite persisted for the requested account | None | Reset → homepage → follow task |
| 4shared--8 | 12 | `4shared--8-12-reload-persistence-check.png` | `/saved` | None — PASS | Login, search, save, Saved files navigation, reload | Saved-file state persisted | None | Reset → homepage → follow task |
| 4shared--9 | 11 | `4shared--9-11-reload-persistence-check.png` | `/account/edit` | None — PASS | Login, profile fields edited, saved, reopened, reloaded | Both account fields persisted | None | Reset → homepage → follow task |
| 4shared--10 | 9 | `4shared--10-09-reload-persistence-check.png` | `/my-files` | None — PASS | Login, root folder creation, reload | Folder persisted at root | None | Reset → homepage → follow task |
| 4shared--11 | 12 | `4shared--11-12-reload-persistence-check.png` | `/my-files?folder=<id>` | None — PASS | Login, upload form, folder/size/description, Documents classification, reload | Private PDF metadata persisted consistently | None | Reset → homepage → follow task |
| 4shared--12 | 12 | `4shared--12-12-reload-persistence-check.png` | `/my-files?folder=<id>` | None — PASS | Login, source folder, rename, move, destination verification, reload | Name and folder changed together | None | Reset → homepage → follow task |
| 4shared--13 | 9 | `4shared--13-09-reload-persistence-check.png` | `/my-files` | None — PASS | Login, Recycle Bin, restore, root verification, reload | Restored file persisted outside Trash | None | Reset → homepage → follow task |
| 4shared--14 | 13 | `4shared--14-13-reload-persistence-check.png` | `/file/<id>/share` | None — PASS | Login, private file navigation, label/permission submission, reload | Share-link state persisted | None | Reset → homepage → follow task |
| 4shared--15 | 11 | `4shared--15-11-reload-persistence-check.png` | `/file/<slug>` | None — PASS | Login, public search, detail, comment submission, reload | Exact comment persisted | None | Reset → homepage → follow task |
| 4shared--16 | 12 | `4shared--16-12-reload-persistence-check.png` | `/account` | None — PASS | Login, annual 100GB selection, demo checkout, account reload | Plan and storage allowance persisted | None | Reset → homepage → follow task |
| 4shared--17 | 22 | `4shared--17-22-reload-persistence-check.png` | `/file/<id>/share` | None — PASS | Folder create, auto-classified PDF upload, rename, preview-only share, reload | All dependent state changes persisted | None | Reset → homepage → follow task |
| 4shared--18 | 21 | `4shared--18-21-reload-persistence-check.png` | `/saved` | None — PASS | Three detail pages compared, login, selected book saved, reload | Comparison and saved state completed | None | Reset → homepage → follow task |
| 4shared--19 | 16 | `4shared--19-16-reload-persistence-check.png` | `/favorites` | None — PASS | Login, broad search, candidate inspection, favorite, download, reload | Both requested mutations persisted | None | Reset → homepage → follow task |

## Hardening audit

- **De-leak:** search results expose titles and summary metadata, not decisive
detail facts. Full task trajectories are not committed. Exact-name action
tasks 6 and 7 now have 6 and 8 results respectively, with each target at
position 6.
- **Distractors:** broad searches used by the tasks return 6–40 plausible
candidates. Near matches deliberately differ in detail metadata or package
purpose.
- **Catalog breadth:** 122 public records cover Music, Video, Apps, Images,
Books, Documents, and Archives. All 16 image records use real, locally served
photographs.
- **Cross-field consistency:** filenames, extensions, categories, MIME-facing
behavior, plan names, plan prices, storage allowances, saved-state labels,
and upload classification were checked across list, detail, confirmation,
and account pages.
- **Known leak archetypes:** no prompt-embedded answer, target-count badge,
decisive result-card fact, pre-sorted unique target, first-item target,
insufficient candidate set, direct-route dependency, self-reported-only
completion, visit-only completion, broad mutation, cross-user mutation,
reset drift, or answer-bearing repository artifact remains.

## Visual and functional validation

- 51 responsive page checks: 17 representative pages at 1440×900, 390×844,
and 320×720.
- Zero document overflow, broken images, stretched images, out-of-bounds
controls, or unresolved title truncation.
- Seven supplementary flows pass: signed-out upload entry, registration,
re-login, 500GB checkout selection, 1TB checkout selection, three distinct
footer destinations, and explicit public-search scope while authenticated.
- Homepage uses the captured 4shared upload illustration, real mobile-app QR
code/frame, and source store logos. Asset provenance is recorded in
`sites/4shared/ASSET_SOURCES.md`.
- Fresh deterministic seed: 146 files total (122 public), 4 users, 16 folders,
16 favorites, 12 saved files, 8 downloads, 12 comments, 4 share links, and
1 plan order. Calling both seed functions twice leaves counts unchanged.

## PR-safe screenshots

Only non-answer-bearing homepage screenshots are committed for PR display:

- `review-reports/assets/pr-90-4shared-homepage-1440.png`
- `review-reports/assets/pr-90-4shared-homepage-390.png`

The Hugging Face asset PR must merge before `.assets-revision` can be pinned to
its immutable commit. No GitHub or Hugging Face merge is performed by this
review.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added sites/4shared/.requires-images
Empty file.
54 changes: 54 additions & 0 deletions sites/4shared/ASSET_SOURCES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# 4shared asset provenance

All catalog thumbnails are real photographic assets. No generated image, generic
placeholder, or network-loaded runtime image is used. The files live in the
pinned Hugging Face asset bundle because `static/images/` is intentionally
ignored by Git.

## Existing WebHarbor photographs

| 4shared path | Existing WebHarbor source path | SHA-256 |
| --- | --- | --- |
| `static/images/london.jpg` | `sites/google_search/static/images/google_real/london.jpg` | `dd11fcb9d34fff87ce03e9008a68adadd0e182c7bfcb7c657fbd608d7b8ef65c` |
| `static/images/new-york.jpg` | `sites/google_search/static/images/google_real/new_york_city.jpg` | `2bb9a4689eb0e3ed5b5c0d654a4db3eb47304ebca2a82f65bd87e8d2898de24b` |
| `static/images/denali.jpg` | `sites/google_search/static/images/google_real/mount_denali_mckinley_elevation.jpg` | `6857da22b8620bd28791d05340eebb5236497b4a1b0bb65452d2a2754215ff5e` |

## Wikimedia Commons photographs

The remaining photographs were downloaded as 900-pixel thumbnails from their
Commons file pages, visually checked against the corresponding catalog record,
and converted to optimized JPEGs.

| Local file | Commons source | Creator | License |
| --- | --- | --- | --- |
| `library-reading-room.jpg` | [Library of Congress main reading room](https://commons.wikimedia.org/wiki/File:INTERIOR,_MAIN_READING_ROOM,_LOOKING_NORTHEAST_-_Library_of_Congress,_Northeast_corner_of_First_Street_and_Independence_Avenue_Southeast,_Washington,_District_of_Columbia,_DC_HABS_DC,WASH,461A-12.tif) | Library of Congress HABS | Public domain |
| `atlantic-boardwalk.jpg` | [Dunes and Boardwalk at Bethany Beach](https://commons.wikimedia.org/wiki/File:Dunes_and_Boardwalk_at_Bethany_Beach,_Delaware.jpg) | PointsofNoReturn | CC BY-SA 4.0 |
| `garden-pollinators.jpg` | [Bee on a blue flower](https://commons.wikimedia.org/wiki/File:Bee-Mating-Blue-Flower-large_ForestWander.jpg) | ForestWander | CC BY-SA 3.0 US |
| `alpine-lake-mist.jpg` | [Sunrise over Shadow Mountain Lake](https://commons.wikimedia.org/wiki/File:Sunrise_over_Shadow_Mountain_Lake,_CO_9-12_(19957710950).jpg) | Don Graham | CC BY-SA 2.0 |
| `ceramic-workbench.jpg` | [Ceramics workshop in Fes](https://commons.wikimedia.org/wiki/File:Inside_of_ceramics_workshop_Fes_Morrocco.jpg) | cliffwilliams | CC BY-SA 2.0 |
| `red-bicycle-brick-wall.jpg` | [Bicycles at a brick wall](https://commons.wikimedia.org/wiki/File:0020-fahrradsammlung-RalfR.jpg) | Ralf Roletschek | Free Art License |
| `winter-pines-snow.jpg` | [Heavy snow on pine branches](https://commons.wikimedia.org/wiki/File:Heavy_snow_on_pine_branches_in_Tuntorp_8.jpg) | W.carter | CC BY-SA 4.0 |
| `notebook-fountain-pen.jpg` | [Pen and notebook](https://commons.wikimedia.org/wiki/File:Pen_and_notebook_-_Narei.jpg) | Kaori Kita | CC BY-SA 3.0 |
| `harbor-boats-fog.jpg` | [Boats in San Francisco fog](https://commons.wikimedia.org/wiki/File:At_San_Francisco_2015_057.jpg) | Mike Peel | CC BY-SA 4.0 |
| `wildflower-trail.jpg` | [Wildflower-lined trail](https://commons.wikimedia.org/wiki/File:Wildflower_lined_trail_(52013518556).jpg) | Joshua Tree National Park | Public domain |
| `classic-camera.jpg` | [Vintage Canon A-1 camera](https://commons.wikimedia.org/wiki/File:Vintage_Canon_35mm_SLR_Camera,_Model_A-1,_All-Digital_Control,_Made_In_Japan,_Circa_1978_(13366931504).jpg) | Joe Haupt | CC BY-SA 2.0 |
| `rainy-window-lights.jpg` | [Rain Drops](https://commons.wikimedia.org/wiki/File:Rain_Drops_-_panoramio.jpg) | M. PINARCI | CC BY-SA 3.0 |
| `map-compass.jpg` | [Suunto compass and map](https://commons.wikimedia.org/wiki/File:Suunto_compass_%26_map_(48995280172).jpg) | Olgierd | CC BY 2.0 |

## Captured 4shared interface assets

These public interface assets were harvested from the contributor's sanitized
September 2026 Playwright capture. Only the named public files were copied; no
browser profile, cookies, account state, or private capture material is shipped.

| Local file | Live source URL |
| --- | --- |
| `static/images/ui/upload-image-initial.svg` | `https://static.4shared.com/images/upload-image-initial.svg` |
| `static/images/ui/qr-code-frame.svg` | `https://static.4shared.com/images/QR-code-frame.svg` |
| `static/images/ui/mob-app-qr-code.svg` | `https://static.4shared.com/images/mob-app-deeplink-QR-code.svg` |
| `static/images/ui/logo-google.svg` | `https://static.4shared.com/images/d1new/Google.svg` |
| `static/images/ui/logo-apple.svg` | `https://static.4shared.com/images/logo-apple-color.svg` |
| `static/images/ui/logo-huawei.svg` | `https://static.4shared.com/images/logo-huawei-color.svg` |

The repository-native logo mark remains in `static/icons/mark.svg` and is
tracked with the application code.
3 changes: 3 additions & 0 deletions sites/4shared/_health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Per-site health probe (optional, called by control_server)."""
def health():
return {"ok": True, "site": "4shared"}
Loading