Skip to content

Fix reviewed Discogs pagination, comparison tasks, and grading (#109) - #142

Merged
QianhuiWu merged 24 commits into
mainfrom
integrate/pr109-discogs-final
Sep 20, 2026
Merged

QianhuiWu merged 24 commits into
mainfrom
integrate/pr109-discogs-final

Conversation

@QianhuiWu

Copy link
Copy Markdown
Collaborator

Discogs Search and Marketplace pagination now retain filters, narrow-screen Marketplace layout no longer overflows, and task grading rejects swapped facts and contradictory answers. Tasks 4 and 6 require meaningful two-release comparisons; all 15 tasks retain natural answer formats.

Based on original contribution #34 by @hqhq1025 and reviewer continuation #109 by @jackjin1997. Merge order is #34#109 → this follow-up, using regular merge commits. Discogs is registered at port 40046; all previous site ports are preserved.

Required assets are integrated: HF #24 and HF #76 are merged. The code pins immutable merged revision ebe2e47a2ce53196ab8a4b18f22b56c7082b5004; all 50 pre-existing dataset files remain unchanged.

Validation: fresh 47-site asset fetch and manifest verification; full Docker build; 47 healthy sites and 47 HTTP-200 homepages; 83 tests and 398 subtests; 15/15 preserved browser runs regraded by the official deterministic evaluator; fresh Chromium pagination/mobile checks; real UI mutation followed by byte-identical reset and restart. See review-reports/discogs-pr109-integration.md for evidence and infrastructure workarounds. No image publication or deployment.

Builder and others added 24 commits May 26, 2026 16:17
Adds the 16th WebHarbor mirror at https://discogs.com — the world's
largest music release database and marketplace. Real catalogue of 7,042
releases / 5,031 artists / 3,938 labels / 6,825 master records pulled
from the Discogs public API + MusicBrainz, plus 323 real album covers
from Wikipedia. Backed by a benchmark community of 29 users with seeded
ratings, reviews, collections, wantlists, lists, marketplace listings,
and forum threads.

Registered as the 16th site at port 40015. Image bumps to 16 mirrors
total; EXPOSE 40000-40015.

## Site features
- Release / master / artist / label / genre / style / format pages
- Token-overlap scored search across releases, artists, labels with
  genre / style / format / year / country facets
- Marketplace with media-condition + genre filters, per-listing
  comments, grades, currencies, sellers
- User collection (5 folders: Uncategorized / All / Vinyl / CD /
  Wishlist Bought) with media + sleeve grades per item
- Wantlist with min-grade preferences
- User-curated public lists (CRUD)
- Forums (10 topical boards) with threaded replies
- Rating (1-5) + Review submission with helpful counts
- Auth (Flask-Login + bcrypt + CSRF), register / settings / logout
- 20 WebVoyager-format tasks in sites/discogs/tasks.jsonl

## Data scale
- releases: 7,042 (3,522 from Discogs API + 3,520 from MusicBrainz)
- artists: 5,031, labels: 3,938, masters: 6,825
- ratings: 86,714, reviews: 3,253
- collection_items: 4,207, wantlist_items: 1,374
- lists: 40, listings: 2,640, threads: 43, posts: 333
- benchmark users: alice_crate, bob_vinyl, carol_jazz, dave_techno
  (passwords: alice12345 / bob123456 / carol12345 / dave12345)
- + 25 collector-style users with realistic locations & seller status

## Determinism work
- MIRROR_REFERENCE_DATE = datetime(2026,5,26) pins all date fields so
  re-seeding from scraped_data/ is bit-for-bit reproducible
- random.Random(42) seed for the community generator
- Idempotent gates on every seed_*() function (count() > 0 → early
  return); byte-identical reset verified

## Verification
- Docker build green; all 16 sites return 200
- POST /reset/discogs keeps DB byte-identical to seed
- All 20 tasks pass when walked via Playwright (Chromium)

## Paired Hugging Face assets
- Heavy assets shipped via the ChilleD/WebHarbor HF dataset:
  - sites/discogs/instance_seed/discogs.db (13 MB)
  - sites/discogs/static/images/release/*.jpg (323 covers, 32 MB)
- .assets-revision is left at `revision: main` so the HF merge will
  roll in automatically (same approach as TED / Phys.org PRs).
The Owner compared the mirror with discogs.com side by side and rejected the
homepage: the top menu was completely different, the release rows used a
scrollbar instead of the live prev/next arrows, the footer differed
substantially, and the pages behind the benchmark tasks did not follow the
original site closely enough.

Measured the live site as a guest at 1440px (full-page captures, shadow-DOM
markup for the header and footer components, computed styles for ~90 elements)
and rebuilt against those measurements:

- Header: the live two-row structure, the search component with its category
  panel, the cart and Sign Up / Log In controls, and the five dropdown menus
  with all 33 destinations. Menus are native <details>, so they work with or
  without JavaScript; narrow widths collapse to the live drawer.
- Homepage: hero, three release carousels and the app promo in the live order.
  Carousels page with prev/next buttons and bullets instead of a scrollbar, and
  the cards carry the live field set. The homepage community block, which the
  live site does not have, is gone.
- Footer: the live three-column plus social layout, labels, social icons,
  newsletter form, app badges, language selector, legal links and the keyboard
  shortcuts dialog.
- Task-path pages: search results with entity tabs and in-result facet counts,
  release detail with the live two-column layout and right rail, marketplace
  with the You Selected chips and seven facet groups, List Explorer, list
  detail, forum index, board, thread, login and register.
- Twelve routes added so every menu and footer destination resolves locally,
  plus marketplace format/ships-from/year/price filters and label, catalog
  number and barcode filters behind an advanced search form.

Ranking carousels are computed from the benchmark's own marketplace and
collection state and labelled as such; no source ranking is fabricated. Route
paths and query parameter names used by verifiers are unchanged, the seed
database is untouched and reset stays byte-identical.

48/48 application tests and 23/23 verifier-contract tests pass.
The footer newsletter input carried name="email", which collided with the
register form's own email field on /register, so a form-filling agent saw two
elements named "email" on that page. The live Discogs footer input has no name
attribute; match it. Found while re-walking the 15 task paths on the repaired UI.

48/48 application tests pass.
Matching the live search card meant showing the full format description, which
put "Album, Dolby System" and "Album, Repress" on the results page. Task 3 asked
for exactly that descriptor plus each release ID, so two of its three facts became
readable without opening either detail page, while the verifier still demanded
both detail visits. That is a task-versus-verifier contradiction: a completion the
question allows was rejected by a navigation condition the question never stated.

Re-anchor the task on identifier facts that only the detail pages carry. One of
the two Spanish 1978 cassettes lists an extra "Impuesto de lujo" entry (Num. 6649)
that the other does not, and both share a "Deposito Legal" value; neither appears
on a search card. The question now asks for both release IDs, which edition
carries the extra entry and its value, and the shared value.

Replace the generic nearest-token association for this task with an explicit
attribution check: the nearest release ID preceding the fact decides the binding,
so a swapped answer fails even though every requested token is present. Proximity
alone did not do this, because sentence order could place the correct ID closer
than the wrong one.

Tests: swapped-binding and results-page-only answers now fail, a second natural
paraphrase passes, and the full verifier suite plus 48 application tests pass.
The verifiers accepted a step URL only when its port was exactly 40024. That
pinned grading to one operator choice while implementing no control: the
adversarial test that justified it rewrites the origin to
https://attacker.invalid, which differs in scheme and host, so the port never
took part in rejecting it. It also made the workflow AGENTS.md prescribes
ungradeable, since that guide runs the image on 41000+ when the default range
is busy.

Replace it with checks on what actually matters, asserted explicitly on every
task rather than used as a silent filter:

  no_foreign_origins      any non-loopback step fails
  single_origin           a trajectory spanning two origins fails
  origin_matches_expected optional exact pin via WHR_EXPECTED_ORIGIN

single_origin rejects a trajectory stitched together from two local services,
which the port pin could not detect at all.

Tests: all 15 tasks grade identically when re-hosted on 127.0.0.1:41024; the
foreign-origin spoof still fails all 15; a mixed-origin trajectory fails all 15
with reason single_origin; the optional pin accepts its origin and rejects
another. Suite 24/24.

Also make the fixture's subprocess cap WHR_VERIFIER_TIMEOUT (default 180s). A
verifier takes ~19s on a host running many environments at once, and the old
30s cap failed runs for lack of CPU rather than for verifier behaviour.
main added two sites since this branch's base, so the three registration
places conflicted and discogs no longer fits at index 24 -- FedEx holds that
index, and therefore port 40024, on main. Appending discogs after webmd_doctor
puts it at index 26, port 40026, with 27 sites in the image.

Resolved by appending discogs last in websyn_start.sh, control_server.py and
the Dockerfile EXPOSE range, then following the consequences:

  tasks.jsonl            web -> http://localhost:40026/ in all 15 rows
  test_environment_quality.py  asserts that value; would have failed
  test_verifiers.py      fixture origins moved off 40024 (now FedEx), which
                         changes nothing about what is tested
  docs                   port range and site count in README, CONTRIBUTING,
                         AGENTS, CLAUDE, agent_demo/README and the skills;
                         README's site list now names Discogs

The site itself is untouched by the merge: app.py, templates, seed database and
verifier logic are identical, so the questions, answers and acceptable paths do
not change. Grading is origin-agnostic -- it requires only that every recorded
step share one loopback origin -- so the frozen task executions remain valid
across this port move.

Verified on the merged tree: discogs application suite 48/48, verifier and
environment-quality suites 27/27. The 27-site integration build is not re-run
here; assets for twelve sites are absent locally and the host lacks the space.
…se relative times

Two defects found while walking the authenticated task paths against the live site.

"All" is the unfiltered view, not a folder, but it sat in COLLECTION_FOLDERS. So it
was offered in the folder select, accepted by the write path, and then unreachable:
the collection list treats folder == "All" as "do not filter", so a row stored with
that folder could never be viewed as a folder again. Confirmed by posting one and
finding it in the database. The template also rendered the tab row as
["All"] + COLLECTION_FOLDERS, which duplicated the tab.

The sentinel now has its own name, UNFILTERED_FOLDER, and the template takes it from
the route instead of hard-coding the literal a second time -- that duplication is
what allowed the two meanings to drift apart.

Relative timestamps had no singular form, so the forum showed "1 years ago", and the
minute unit was abbreviated. Live Discogs writes "1 day ago" and "12 minutes ago",
per the captured reference pages.

Tests: three regressions covering the enum, a rejected folder writing no row, the tab
row listing "All" exactly once, and eight relative-time cases. Application suite
51/51, verifier and environment-quality suites 27/27.
…ex 28

main added two more sites since the last merge, and Healthline took index 26 --
the slot discogs held. Appending discogs after Kaggle puts it at index 28, port
40028, giving 29 sites in the image.

Conflicts were the same three registration places plus the port range and site
count in the docs, all resolved by taking main's text and then adding the 29th
site on top of it. Nothing in sites/discogs/ conflicted.

Followed through, as before:

  tasks.jsonl            web -> http://localhost:40028/ in all 15 rows
  test_environment_quality.py  asserts that value
  test_verifiers.py      fixture origins moved off 40026 (now Healthline)
  docs                   range and count in README, CONTRIBUTING, AGENTS,
                         CLAUDE, agent_demo/README and the skills; README's
                         site list now names Discogs

The site is untouched by the merge: app.py, templates, seed and verifier logic
are identical, so the questions, answers and acceptable paths do not change.
Grading requires only that every recorded step share one loopback origin, so the
frozen executions remain valid across this second port move.

Application suite 51/51 on the merged tree.
Merge upstream main at 7ace1c7, preserve NVIDIA at index 28, and append Discogs at index 29 (port 40029). Update registry declarations, task URLs, verifier fixtures, and active documentation to the 30-site range.
@QianhuiWu
QianhuiWu merged commit 29540ce into main Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants