Skip to content

feat(walmart_careers): add Walmart Careers mirror (site 20, port 40019) - #86

Open
evanz37 wants to merge 16 commits into
aiming-lab:mainfrom
evanz37:feat/walmart_careers
Open

feat(walmart_careers): add Walmart Careers mirror (site 20, port 40019)#86
evanz37 wants to merge 16 commits into
aiming-lab:mainfrom
evanz37:feat/walmart_careers

Conversation

@evanz37

@evanz37 evanz37 commented Sep 7, 2026

Copy link
Copy Markdown

TL;DR

Adds a walmart_careers mirror of https://careers.walmart.com as site 20 on port 40019: a Flask + SQLAlchemy job board with deterministic search and filters, two job populations (hourly store roles / salaried corporate roles), local auth, saved roles, a two-step application flow, and 20 benchmark tasks. Paired assets PR: https://huggingface.co/datasets/ChilleD/WebHarbor/discussions/54 (seed DB md5 b57631080969fe151e1717dbef3dd372, 35 harvested images). .assets-revision is temporarily pinned to refs/pr/54 so CI can build; I will repin to the merge sha as soon as the HF PR lands.

Motivation

The current catalog has no employer careers site. Careers sites are a distinct interaction shape — faceted search over a large uniform catalog, location-radius filtering, and account-scoped stateful actions (save / apply) — that agents meet constantly in real use. Walmart Careers is a good specimen: it mixes hourly store postings (store banner, shift windows, open-position counts) with salaried corporate postings (qualification options, worker type), so a single mirror exercises both list shapes and both detail layouts.

Design

What the real site is. Next.js + AEM front end; results are fetched through an LLM "job search assistant" endpoint whose ordering is non-deterministic; job detail pages are server-rendered with structured jobDetails; login is off-domain OIDC and apply is email + OTP. The mirror keeps the visible affordances (search pill, Filters, Add your location, Sort, tabs, cards, two detail layouts, save / apply) and replaces the non-deterministic backend with plain query parameters.

Data model (single Job table, population-aware):

model rows notes
Job 246 population = hourly 168 / salaried 78; brand Walmart 184 / Sam's Club 42 / Vizio 20; every exposed filter value has ≥20 postings; every one of the 7 shift values appears on ≥25
Store 51 6 offices + 45 field locations across 13 states/territories, with lat/lng for radius search; hub stores carry hub_name / hub_blurb / hub_image
Area / Category 7 / 33 hierarchical, mirrors upstream's areaMappings
User 4 benchmark users (alice.j@test.comdavid.k@test.com, TestPass123!), werkzeug hashes hardcoded for byte-reproducible seeds
SavedJob / Application 13 / 4 pre-seeded account state (WMC-000001WMC-000004)

Routes (23): /, /results (q, area, category, brand, shift, type, rate, loc, radius, sort, page; 10 per page), /jobs/<id>, /jobs/<id>/save|unsave (POST, login required), /jobs/<id>/apply/apply/confirm/apply/submitted, six /careers-areas/<slug> index pages (+ Military; students 302s to the filtered results), /resources/location, /resources/hiring-process, /resources/terms-and-conditions, /about-us, /login, /register, /logout (POST), /account, /account/edit, /candidate-home/saved-roles, /candidate-home/applications, /_health.

Auth & CSRF. Real password hashing and sessions (no auto-login shims); CSRFProtect on every POST, zero exemptions; every next parameter validated as a same-origin relative path.

Search. Scored token overlap over title + category + area + banner + city + state + brand (description excluded so answer strings never index); stem tier tightened so technician no longer matches Technology.

Answer-leak design. Result cards are faithful to upstream — hourly: title / banner #store / City, ST ZIP / shift • pay; salaried: title / City, ST / pay — and everything a task asks for (requisition ID paired with a second field, street address, open-position count, shift start window, worker type, qualification text) renders only on the detail page. The only visible count is the Open roles tab badge; no task answer is a count of list items.

Determinism. One seeded RNG, fixed reference date, no clock reads on any seed/bootstrap path, hardcoded password hashes, sorted iteration. The seed rebuilds to the same md5 under PYTHONHASHSEED=0 and =1.

Data policy. All postings, stores, users and qualification texts are synthetic; requisition IDs are synthetic and look like upstream's (R-24xxxxx, CP-<store>-1xxxx). Only site chrome (logo, spark, icons, fonts, lifestyle/hub photos) is harvested from the real site. No task is answerable from careers.walmart.com or from prior knowledge.

Registration

  • websyn_start.sh and control_server.py: walmart_careers appended as index 19 (arrays verified identical); Dockerfile: EXPOSE 8101 40000-40019.
  • Shared docs (README.md, AGENTS.md, CONTRIBUTING.md, CLAUDE.md, agent_demo/README.md): site count 20, port range 40019.
  • History note: the branch merges upstream/main (phys_org and target landed as sites 18 and 19 while this was in progress); the site moved 40017 → 40019 in a9ab990, and the docs sweep is 4916213.
  • Two small root changes: .dockerignore gains sites/*/scripts_dev/ (dev-only Playwright drivers never ship); root .gitignore gains /scraped_data/.

HF assets

  • PR: https://huggingface.co/datasets/ChilleD/WebHarbor/discussions/54 — one file, walmart_careers.tar.gz (11 MB): instance_seed/walmart_careers.db (md5 b57631080969fe151e1717dbef3dd372) + static/images/ (35 files). Zero AppleDouble entries, zero .gitkeep.
  • .assets-revision: revision: refs/pr/54 for now (that ref is a strict superset of main); will be replaced by the merge sha in a follow-up commit.
  • The two EverydaySansUI font files (176 KB) are tracked in git rather than HF so the mirror renders without the asset bundle; happy to move them if you prefer.

Tasks (20)

- Walmart Careers--0 — Search for Optician roles and open the posting at the Neighborhood Market in Wichita, KS. Report its requisition ID and the street address shown on the posting.

- Walmart Careers--1 — Find the Staff, Software Engineer posting located in Sunnyvale, CA and quote the exact text of "Option 2" under Minimum Qualifications.

- Walmart Careers--2 — Open the Freight Handler posting at eComm Whse Logistics #9054 in Porterville, CA. What shift start window does it list, and how many open positions does it show?

- Walmart Careers--3 — From the Healthcare career area page, go to its open roles and open the Pharmacy Technician posting in Bentonville, AR. What hashtag appears at the end of the "What you'll bring" section, and how many open positions does the posting list?

- Walmart Careers--4 — Using the filters, find Sam's Club Part time roles with a Weekend Overnight shift whose posted pay range tops out at $20.00/hr or less. Open the one in Texas and report its requisition ID and number of open positions.

- Walmart Careers--5 — Find Full time Technology roles in Hoboken, NJ whose salary range tops out above $200,000. Open the matching posting and report its requisition ID and the degree named in "Option 1" of its Minimum Qualifications.

- Walmart Careers--6 — Set your location to Cleveland, OH within 25 miles, filter to Full time roles on a Weekday Day shift, and open the Online Order Filling Team Supervisor posting. Report the street address and the number of open positions.

- Walmart Careers--7 — Filter to the Students career area, the Intern employment type and the Sam's Club brand, then open the merchandising internship in Bentonville, AR. Report the worker type chip shown on the posting and the street address listed for its location.

- Walmart Careers--8 — There are Auto Care Center Technician postings at two Mississippi stores. Open both and report which store number has more open positions and how many.

- Walmart Careers--9 — Two Freight Handler postings are located in Marcy, NY at different facilities. Which one has the earlier shift start time? Report its requisition ID and that start window.

- Walmart Careers--10 — Compare the Senior Manager, Delivery Search, Arrival & Matching (Last Mile Delivery) postings in Bentonville, AR and Hoboken, NJ. Which one requires more years of experience under "Option 2" of its Minimum Qualifications? Report that posting's requisition ID and the number of years.

- Walmart Careers--11 — Log in with the demo account (email: alice.j@test.com, password: TestPass123!), search for Yard Driver roles and save the Williamsburg, VA posting to your Saved roles.

- Walmart Careers--12 — Log in as bob.c@test.com (password: TestPass123!), open your Saved roles, and remove the saved role that is at a Neighborhood Market store.

- Walmart Careers--13 — Log in as carol.d@test.com (password: TestPass123!), apply to the Pharmacy Technician posting in Tacoma, WA using phone number 253-555-0142, and report the confirmation number shown after submitting.

- Walmart Careers--14 — Register a new account with an email and password of your choice, then save the eCom Warehouse Worker posting at eComm Whse Logistics #9046 in Marcy, NY to your Saved roles.

- Walmart Careers--15 — Log in as david.k@test.com (password: TestPass123!) and update your account so the city is Rogers and the state is AR, then open My applications and report the confirmation number of your existing application.

- Walmart Careers--16 — Set the location to Puerto Rico, then use the Shift filter for Weekday Day and the Rate filter for Hourly. Among the Cashier postings, report the requisition ID of the one with the most open positions and that number.

- Walmart Careers--17 — Log in as alice.j@test.com (password: TestPass123!). Exactly one of your saved roles is a Part time job; apply to it with your account email, then report that posting's shift start window and your confirmation number.

- Walmart Careers--18 — Open the Supply Chain and Transportation career area page, go to its Drivers category, and compare the Class A CDL Truck Driver postings at the Ottawa, KS and Williamsburg, VA facilities. For whichever of the two lists more open positions, report its requisition ID, its shift start window and that number of open positions.

- Walmart Careers--19 — Log in as bob.c@test.com (password: TestPass123!). From the Stores and Clubs career area page, open the Digital Pickup and Delivery category, filter it to Full time roles, and open the posting with the fewest open positions. Save that role to your Saved roles, then report its requisition ID and the street address shown on the posting.

Design notes for the reviewer / verifier author:

  • Every non-stateful task has a unique detail-page URL as its navigation gate; the answer is always a detail-only field (requisition ID is never the sole answer because card hrefs expose it).
  • Stateful tasks leave DB traces: saved_jobs (11, 14, 19), unsave (12), applications (13, 17), new users row (14), users update (15).
  • Tasks 13 and 17 both yield WMC-000005 from a fresh reset; verifiers should match the applications row (user, job, phone), not the string.
  • Task 15 ends on /candidate-home/applications, reading david's pre-seeded WMC-000004.
  • Hard tasks: 10, 16, 17, 18, 19 (multi-page comparison and/or three-hop navigation with a stateful action).

Verification

check result
python3 -m py_compile sites/walmart_careers/*.py clean
./scripts/build.sh → run on -p 8201:8101 -p 41000-41019:40000-40019 all 20 ports 200; /health 20/20 alive
POST /reset/walmart_careers {"pid":213,"ready":true,"site":"walmart_careers"}
md5 instance vs instance_seed after reset b57631080969fe151e1717dbef3dd372 == b57631080969fe151e1717dbef3dd372
same after docker restart identical
seed rebuilt twice (PYTHONHASHSEED=0) and once with =1 identical md5
POST /reset-all 1.4–1.7 s, 20/20 ready
Playwright walkthrough, all 20 tasks, control-plane reset before each 20/20 solvable through the UI only
leak audit: home / natural results page / area page / locations, rendered HTML incl. hidden nodes and comments 0 leaks (task 8: store number visible on card, count detail-only)
distractor invariants (build-time): every non-stateful task ≥6 results, ≤50% full matches, target never rank 1
cross-field consistency (FK check, category↔area, store coordinates within state, pay_frequency↔population, Intern⊂Students) 0 violations
smoke (24 flow assertions) / robustness (26) 24/24, 26/26
horizontal overflow at 768 / 1024 / 1440 px on home, results, both detail layouts none
tarball dry-run 1 DB + 35 images, 0 ._*

Deviations & non-goals

  • Maps are deterministic server-rendered SVGs (cluster map on results, pin card on detail), not Google Maps.
  • No LLM search assistant / Chat panel, no "Go back" link, no count badges on the Future roles / Content tabs (they render explicit empty states), Filters is a multi-column panel rather than a single scrolling column.
  • Auth is local email + password; apply is a two-step contact → confirm form (upstream: OIDC + OTP).
  • Upstream serves two salaried detail templates; the mirror implements the masthead variant captured in the reference screenshot.
  • (USA) title prefixes are stripped; testimonial copy is mirror copy; no video blocks or carousels.
  • Location search additionally accepts a whole state/territory (mirror-only affordance; task 16 also works through a city + 60-mile radius).
  • Dallas hub photo is a real Global Tech office interior from the same CMS (upstream has no Dallas image; its dc-metro-area.png is a Hoboken duplicate).
  • Job count (246) sits above the 50–200 guideline so that every exposed filter value has ≥20 postings and every task query returns ≥6 results; categories (33) keep a floor of 4 postings each.

Not actioned, with reasoning

  • .claude/skills/* port/site-count mentions left as-is (maintainer-owned; the phys_org PR skipped them too).
  • AGENTS.md "~3 GB image" statement (already inaccurate on main; unrelated to this site).
  • Dockerfile-side seed regeneration (as IKEA does) would let the image build without the HF bundle — a good follow-up, out of scope here.
  • CONTRIBUTING nit: the hf upload example lists arguments as <file> <repo> <path>, but the CLI signature is hf upload <repo_id> <local_path> <path_in_repo>.

Review history

Before opening this PR the branch went through four independent read-only audit passes (CONTRIBUTING compliance, guide-page hardening, a reviewer simulation using the review-env skill, and a regression audit for the failure modes caught in #9 / #53 / #71 / #77 / #83). Findings that were fixed: an answer table that had crept into a tracked file, six task targets at rank 1, three under-populated filter values, an over-broad stem matcher, real upstream requisition IDs and boilerplate qualification text on three postings, a 768 px header overflow, and a mislabeled hub photo. The build was driven with Claude Code; every finding was verified against the code before it was actioned.

Screenshots

page upstream (reference) mirror
Home home home
Results results results
Job detail job_detail job_detail
Career area (Stores and Clubs) area_stores area_stores
Sign in login login

evanz37 and others added 15 commits September 5, 2026 23:38
Mirrors https://careers.walmart.com as WebHarbor site 18 on port 40017.

Backend: single Job table with a salaried|hourly discriminator plus Area,
Category, Store, User, SavedJob and Application. Routes cover the home page,
scored search at /results (token overlap over title/category/area/banner/
city/state/brand, never a strict AND), job detail, save/unsave, a two-step
apply flow with a WMC- confirmation number, career-area and resources pages,
local email/password auth, account editing, saved roles and applications.
Flask-WTF CSRF protects every POST; ?next= is validated as a same-origin
relative path.

Seed: 200 jobs / 44 stores / 33 categories / 7 areas / 4 benchmark users /
10 saved roles / 4 applications, generated from catalog_source.py by one
RNG (random.Random(20260905)) with MIRROR_REFERENCE_DATE instead of any
wall-clock read and hard-coded werkzeug hashes. build_seed_database() runs
_assert_distractors() at freeze time only; both seed_*() functions are gated
as a whole, so /reset restores the DB byte-identically.

Frontend: 19 Jinja2 templates on the real Living Design palette, with real
brand chrome, fonts and photography harvested from cms.careers.walmart.com
and i5.walmartimages.com. Google Maps is replaced by a deterministic
server-rendered SVG cluster map on /results and an SVG pin card on the
detail page; the LLM search assistant is replaced by ordinary query params.

Verified: all 18 sites return 200 on the alt-port container, /reset returns
ready:true, and md5(instance) == md5(instance_seed) both before and after a
docker restart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1NUPpd54bZirE5uzkBgK3
Adds Walmart Careers to the mirror list and moves every published port range
from 40000-40016 to 40000-40017 (41000-41017 for the alt-port test container).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1NUPpd54bZirE5uzkBgK3
Contributor-side task definitions only: web_name, id, ques, web, upstream_url.
No verifier_path, no judge_rubric, no answer key anywhere in the repo.

Coverage: keyword search and detail lookup (0-3), multi-constraint filtering
including brand/shift/rate/pay, location radius and career-area + employment
type (4-7), cross-page comparison (8-10), stateful save, unsave, apply,
register and profile edit (11-15), and five hard multi-hop tasks that need a
career-area page, a category, filters and two or more detail pages before an
answer exists (10, 16-19). Login tasks carry the demo credentials in ques.

Every answer is a detail-only field (requisition ID paired with another
detail-only value, street address, open positions, shift start window,
qualification text, worker-type chip, hashtag, confirmation number) or a
database change. No task depends on the current date, a posted date, a tab
count, or knowledge available without opening the site.

Verified: image rebuilds, :41017 returns 200, /reset/walmart_careers returns
ready:true and leaves md5(instance) == md5(instance_seed).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1NUPpd54bZirE5uzkBgK3
…chrome

Phase 3 (evolve-env). Rebuilt the page chrome against scraped_data/reference/*.png
and extended the mirror where a task could not be driven through the real UI.

Header: the full spark + <> + "Careers" lockup, then Career areas (a dropdown
listing all six areas), Brands, Resources, About Us and Military; a white search
pill with a blue circular button; and a user-icon popover holding My account /
Saved roles / Login-Signup / EN (initials avatar plus My applications / Log out
once signed in). Nothing wraps at 1440px and the bar spans the full viewport.

Results: heading is "N open roles" with no query echo, the count badge sits on the
Open roles tab only, "Add your location" and "Filters" open popovers instead of
permanently expanded sidebar panels, and "Sort by: Relevance" is a dropdown. The
left column is now the cluster map alone. Active facets render as removable chips
under the toolbar so filter state stays readable with the popover closed. Cards are
population-aware — salaried postings drop the "banner #store" line — and both
buttons are styled as the live outlined "Select +" pill.

Job detail: two layouts branched on job.population, both matching their reference
capture — three-photo masthead with the identity card (solid ld-blue for salaried,
blue-over-navy for hourly), the left Role Details rail (sub-items for hourly only),
the address block with a map card, and three dark navy chips. "Apply now" is
ld-blue on both.

Also in this phase:
- new GET /about-us page behind the header's About Us item
- the location box accepts a whole state or territory ("Puerto Rico", "PR"), which
  selects every posting in that state and ignores the radius; cities and ZIPs keep
  the haversine radius. Task 16 needs a reliable route to all five PR postings.
- related_jobs() excludes the current store in its fallback branch too, so
  "Related roles" can no longer surface another posting at the same location
- the results cluster map keeps its geographic aspect ratio; the detail page map
  card is a small SVG with roads and a pin
- tasks 3 and 7 now answer with detail-only fields (3 pairs the hashtag with the
  open-position count, 7 swaps the card-visible pay range for the street address);
  task 15's upstream_url points at /us/en/candidate-home

_content.py also carries the Phase 4 trending-role retarget (same file): the home
page no longer links straight to the targets of tasks 1, 10 and 14.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uso3TzMAGoE9CanJMW6wcJ
Phase 4 (harden-env). Audited every task on the four dimensions and the 13 leak
archetypes against the running container's rendered HTML; the task x page matrix
is in sites/walmart_careers/VERIFICATION.md.

De-leaking:
- hashtags are now unique per title family (37 values, e.g. #pharmacytechjobs,
  #opticianjobs) instead of one shared value per career area, so task 3's answer
  no longer identifies six different families
- the logged-in saved-roles page no longer renders trending roles alongside the
  saved list task 17 has to read; logged out it still shows them, as upstream does

_assert_distractors() now covers all 20 tasks instead of 8:
- a TASK_TARGETS table asserts each task's locator (title + city, or title +
  store) resolves to exactly one posting, and to the expected requisition id
- "full match" means "satisfies every constraint the task states", not "shares the
  target's title"; every task's result set is checked for >= 6 rows with <= 50%
  full matches
- new per-task blocks for tasks 0-3, 6, 7, 11-15, 18 and 19, plus global checks
  that hashtags and salaried qualification texts are unique and that no trending
  role is a task target
- the relevance check now covers tasks 0, 2 and 13: no target may be rank 1 for
  its own natural query

Catalog fixes the new assertions caught:
- the Optician family's placements were reordered so the task 0 target is not the
  first result for q=optician (this reassigns the four Optician requisition ids;
  the target is now CP-5991-11240)
- task 4's target is the Plano TX Merchandising and Stocking Associate, not the
  Freezer/Cooler Associate at the same club: both are Sam's Club Part time Weekend
  Overnight postings and only one is at or under $20/hr

The freezer still builds byte-identically across consecutive runs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uso3TzMAGoE9CanJMW6wcJ
Phase 5 (seed-database). The seed database is frozen and reproducible: two
consecutive `PYTHONHASHSEED=0 python seed_data.py` runs produce the identical
file (md5 faf1c03a780314e71f9586d5b0edc69b), and inside the container the
instance and instance_seed copies match both after POST /reset/walmart_careers
and after a docker restart.

VERIFICATION.md records the md5 outputs, seeded rows per model, the 20/20 task
walkthrough (driven through Chromium with a control-plane reset before each
task), the answer-leak task x page matrix (0 leaks), the near-miss and breadth
measurements, 26/26 interaction-robustness checks, the visual-fidelity diff
against scraped_data/reference/*.png, every file that references port 40017, and
the list of things that still need human judgment — including that tasks 13 and
17 both yield WMC-000005 when each is run from a fresh reset.

instance_seed/walmart_careers.db itself is HF-managed and gitignored; it ships in
the assets PR, pinned afterwards through .assets-revision.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uso3TzMAGoE9CanJMW6wcJ
Three review fixes.

1. A salaried result card now shows title / "City, ST" / annual pay range only,
   matching the upstream results page for searchQuery=manager. Hourly cards are
   unchanged: "banner #store", "City, ST zip", "shift • $x - $y/hr". The card
   branches on job.population rather than on whether the store is an office.
2. Task 2's upstream_url pointed at the same posting as task 14's. It now points
   at https://careers.walmart.com/us/en/jobs/CP-9054-11013, the real upstream
   Freight Handler posting at store #9054 in Porterville, CA (harvested in
   scraped_data/recon_raw/results_gql_full.json). All 20 upstream_urls are now
   distinct.
3. VERIFICATION.md §9 records that upstream serves two salaried detail templates
   — the three-photo masthead captured in reference/job_detail_corp.png and a
   Workday-style variant with a white sticky bar and no masthead — and that the
   mirror implements the masthead variant. §7 and §9 are re-synced with the card
   change.

Re-verified against a rebuilt image: /reset returns ready:true, the instance and
instance_seed md5s both stay faf1c03a780314e71f9586d5b0edc69b, 20/20 task
walkthroughs pass and the leak audit still reports 0 leaks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uso3TzMAGoE9CanJMW6wcJ
Upstream added two mirrors (phys_org at index 17 / port 40017 and target at
index 18 / port 40018), so walmart_careers moves from index 17 to index 19 and
the repo now ships 20 sites on 40000-40019.

Conflict resolutions:
- websyn_start.sh: upstream's dynamic SITE_COUNT/END_PORT wins; walmart_careers
  is appended after phys_org and target as the 20th entry
- control_server.py: same 20 names in the same order as websyn_start.sh
- Dockerfile: EXPOSE 8101 40000-40019, "20 Flask mirror sites"
- README.md, AGENTS.md, CONTRIBUTING.md, CLAUDE.md: upstream's text with only the
  site count bumped 19 -> 20 and the port range upper bound 40018 -> 40019;
  README's mirror list gains Walmart Careers
- .assets-revision: upstream's pin, unchanged
  (revision 8d8e4069588ef55594622fee1ab9fa51c2011d07)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uso3TzMAGoE9CanJMW6wcJ
Follow-up to the upstream merge: every remaining reference to the old slot moves
from 40017/41017 to 40019/41019.

- tasks.jsonl: all 20 rows now carry "web": "http://localhost:40019/"
- sites/walmart_careers/CLAUDE.md: port 40019, index 19 (the 20th and last site),
  alt-port 41019
- sites/walmart_careers/VERIFICATION.md: the alt-port docker run line, the port
  scan, the /health line and the port-reference table; the site count in that
  section goes from 18 to 20 and the README row from an 18- to a 20-mirror list

phys_org keeps 40017 and target keeps 40018 — those are upstream's own slots.
`grep -rn 40017 --exclude-dir=.git --exclude-dir=scraped_data .` now only matches
sites/phys_org/.

Re-verified on the 20-site image: all 20 ports 200, /health reports 20 sites all
alive with walmart_careers on 40019, POST /reset/walmart_careers returns
ready:true, the instance and instance_seed md5s both stay
faf1c03a780314e71f9586d5b0edc69b before and after a docker restart, POST
/reset-all resets all 20 sites in 1.71 s, the freezer re-runs
_assert_distractors and reproduces the same seed byte for byte, the leak audit
reports 0 leaks and all 20 task walkthroughs pass against port 41019.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uso3TzMAGoE9CanJMW6wcJ
…lance filter coverage; store hub content in the DB

Compliance audit follow-up.

Ground truth out of the shipped tree
- VERIFICATION.md moves to scripts_dev/ (git- and docker-ignored) and is
  untracked; `git ls-files sites/walmart_careers | grep -i verification` is empty.
- TASK_TARGETS, _assert_distractors() and _years_in() move out of seed_data.py
  into scripts_dev/assert_distractors.py, which exposes assert_distractors().
  build_seed_database() loads it by path only when the file exists, so the
  freezer still enforces every invariant locally while a tree without it builds
  the byte-identical database and says the checks were skipped.
- CLAUDE.md now describes structure and conventions only.

Catalog rebalancing (200 -> 223 jobs)
- Vizio 6 -> 20, Intern 12 -> 21, Students 12 -> 21, so every exposed brand,
  employment-type, rate, shift and career-area filter value returns >= 20 roles.
  Added placements reuse existing title families: 14 salaried roles at the VIZIO
  Irvine campus and 9 more internships. The Students/Intern/Sam's Club
  merchandising internship stays unique and every other task target is still
  unique; 20/20 tasks still walk through.

Hub copy and trending roles in the database
- New Store.hub_name / hub_blurb / hub_image and Job.is_trending, seeded from
  catalog_source.HUB_COPY and TRENDING_JOB_IDS; locations.html, area.html and
  trending_jobs() read the columns. _content.py keeps only static chrome.
- The three trending postings pin their job_id so the list cannot drift.

Also adds static/js/.gitkeep.

Verified on a fresh build (-p 8201:8101 -p 41000-41019:40000-40019): all 20 ports
200, /health alive on all 20, POST /reset/walmart_careers ready:true, instance ==
instance_seed md5 918eca54a717c180f284ede81f88cab7 before and after docker
restart, reset-all 20/20 ready in ~1.6s, leak audit 0 leaks across all 20 tasks,
20/20 task walkthrough, 26/26 robustness checks, and two PYTHONHASHSEED=0 freezer
runs producing identical md5s with the distractor assertions clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F8BbRAQLRFrPW1EtkPFNp3
…sets, tighten search, fix visual fidelity per audit

Catalog and tasks
- 7 new stores (Store 44 -> 51), three of them within 25 miles of Cleveland OH,
  plus 23 placements so every non-stateful task's natural result set has >= 6
  rows with <= 50% full matches; alice's seeded saved list grows to 6 roles
- every non-stateful task's answer now sits off rank 1 of its natural result
  set (build-time invariant, extended from 3 tasks to all 16)
- search: stem tier needs a 6-char shared prefix with lengths within 3, and the
  substring tier became a word-prefix tier, so "technician" no longer matches
  "Technology" and "care" no longer lights up Healthcare
- task 4 reworded to "whose posted pay range tops out at $20.00/hr or less";
  task 15 continues to My applications and reports the existing confirmation
- /careers-areas/students 302s to /results?area=students instead of 404
- Dallas hub image: loc-dallas.jpg (upstream carries no Dallas photo; the
  Global Tech office interior from the same CMS), loc-dc-metro.jpg deleted

Visual fidelity (templates + CSS)
- home: left-aligned hero and pill, no header pill on "/", button-less trending
  cards, career-area ribbon, values bento, benefits grid, milestone badges,
  associates strip and the white closing search
- career-area pages: floating card over the undarkened photo, photo-left "Join
  our team" with a plain category list, benefits tiles, bento, quote band, hub
  links / associates strip, testimonial cards; Military uses the banner
- results: one "Select +" pill per card with the whole card clickable, no
  filter count badge, globe glyph before EN in the inset account popover
- locations: hero photo card and 3-across hub tiles with bare arrow links
- login/register render through a stripped base; saved roles leads with the
  "Get more out of Walmart Careers" promo block
- 12 unreferenced images and their dead constants removed

Seed re-frozen with PYTHONHASHSEED=0: e8b680d00078eb591fd5b14f5918eeab (twice).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHd2JXJyHCSEKjBjSH8G47
…15/16, fix 768px overflow

Seed (instance_seed md5 b57631080969fe151e1717dbef3dd372, reproducible under
PYTHONHASHSEED=0; auto-generated ids unchanged):
- every pinned requisition ID copied from careers.walmart.com is now synthetic:
  R-2463275 -> R-2468347 (task 1), R-2451180 -> R-2456729 (task 10),
  CP-9046-11101 -> CP-9046-11274 (task 14), R-2413636 -> R-2417063,
  R-2414279 -> R-2418512, CP-1236-10888 -> CP-1236-10741 (trending)
- placements may carry a qual_clause appended to both minimum-qualification
  options; the four postings behind tasks 1, 5 and 10 use it with
  non-boilerplate year counts so their texts cannot be recalled from upstream
- Job.about_team column; salaried postings get per-category "What you'll
  bring" bullets (catalog_source.SALARIED_BRING, location slots only)

Tasks: 15 asks for city Rogers + state AR only; 16 is driven through the
location picker plus the Shift (Weekday Day) and Rate (Hourly) filters.

Templates/CSS: header wraps below 1024px so /results and /jobs/<id> no longer
overflow at 768px (verified 768/1024/1440 on home, results, detail); footer
social glyphs inverted to white; salaried detail pages carry the reference's
About the team / What you'll bring / About area / hybrid / Benefits / EEO /
pay blocks ahead of the qualification sections.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsqvyH5ufJmpem5Vg6kayD
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186UtcQJMrSgZhYdqgYfmXv
Remove the per-category and per-hub job-count queries that no template
consumed, and replace the User.query.count()+1 username disambiguation
with an incrementing-suffix loop so two registrations sharing an email
local part can never collide.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186UtcQJMrSgZhYdqgYfmXv
…r discussions/54; temporary, repin to merge sha after HF merge)
@evanz37
evanz37 force-pushed the feat/walmart_careers branch from d77d269 to 7137d29 Compare September 7, 2026 04:31
@evanz37

evanz37 commented Sep 7, 2026

Copy link
Copy Markdown
Author

Port slot note: this site takes index 19 / port 40019 on top of main@90afddb (19 sites). If another site merges first I'll rebase and migrate — port references are confined to the registration files, tasks.jsonl, the site's CLAUDE.md and the shared docs.

…l and shared sections; refresh mirror shots

Templates, CSS and chrome copy only; the frozen seed is untouched
(b57631080969fe151e1717dbef3dd372 before and after docker restart).

- footer: social glyphs on 44px white discs (the CSS-filter inversion was dropped
  in full-page captures), 9.2% padding, 240px columns, EEO "applicant rights" link
- job detail: one 236px-nav / 1000px-main layout with Benefits and Life at Walmart
  inside the main column; requisition ID and hashtag are links; auto-width chips;
  salaried body uses Workday-style run-in headings and the Bentonville home-office
  Life copy; related roles as three compact cards
- shared partials _benefits.html (three tiles + two-column 90px icon rows) and
  _life.html (lead, text/photo grid, full-bleed quote band, closing lines) used by
  both detail layouts, every career-area page and About Us
- career areas: Stores gets the "Meet Brandon" block; Military gets the SkillBridge
  and skills-translator rows and the three program tiles, benefits after the stories
- hiring: photo hero with floating card, icon+intro beside each FAQ accordion,
  "Experience a day in the role", compact trending cards
- apply flow: light page, blue band and floating white card on all three steps
- home: spark card rendered as a spark (class clash with the yellow mini tile),
  solid blue video posters
- scraped_data/mirror re-shot from the rebuilt container (apply.png and
  sams_home.png added; detail shots use IDs that exist in the seed)

Verified on the rebuilt container: leak audit 0/20, overflow-free at 768/1024/1440
on home, results and both detail layouts, walkthrough 20/20, robustness 26/26.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPsbjtW5r9ubPyouPX8yRE
@evanz37

evanz37 commented Sep 7, 2026

Copy link
Copy Markdown
Author

Pushed f7f5bf1: Benefits cards, Life at Walmart, footer icons and plain-text requisition ID / hashtag now match the reference layouts on job detail and shared sections; mirror screenshots in the description refreshed from this commit.

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.

1 participant