HKPL Committee Walkthrough · complete record · 2026-06-29

Every bug reported from day-one UAT through today's committee batch — including the video reports — with the original message, the screenshot you sent, what we fixed, and how to verify it. Then a role-by-role walk proving every committee member can do every function on the live site.

74
total bug reports addressed
51
round 1–5 audit bugs
22
committee bugs (this batch)
1
video-reported bug
3
new features
33/33
role journeys verified

✨ New features added for you 3 SHIPPED

NEW bug-058 · Public AI Chatbot — floating widget on every public page
Shipped 2026-06-29
What we built: Floating 💬 button bottom-right. Click → chat panel with greeting + 4 sample chips. Hits /api/v1/public/help-desk/ask (Gemini-backed, grounded in the live HKPL rulebook). EN→EN, 繁→繁, 简→简. Network-blip auto-retry.
How to try it: /faq.html as anonymous
Open /faq.html. Bottom-right see green button. Click it. Ask "How do I sign up?" → rule-grounded reply with [§1.1]/[§1.3] citations.
NEW bug-012 · Invoices & Receipts panel on Club Managers
Shipped 2026-06-29
SUGGESTION: ADD A GENERATE INVOICE + RECEIPT Button.
What we built: New "🧾 Invoices & Receipts" section inside the per-club expandable panel. Click Refresh → pulls registrations → one row per team with a one-click PDF link. Auto-flips between Invoice (unpaid) and Official Receipt (admin-verified).
How to try it: /admin.html#club-managers as tenant admin
Admin Console → Club Managers tab → "Manage" next to a club → scroll to "🧾 Invoices & Receipts" → Refresh → click any team's Invoice/Receipt link.
NEW bug-047 · Name-based player picker on Matchup
Shipped 2026-06 (prior — AUTH-AWARE-SEARCH-V1)
What we built: /matchup → "+ Add Player" opens a search modal that takes player NAMES (not DUPR IDs). Type, pick, add.
How to try it: /matchup as signed-in (any role)
Open /matchup. Click "+ Add player" on Team 1. Type a name → autocomplete results → click to add.

👥 Role-by-role walk — every committee function verified end-to-end 33/33 VERIFIED

We personally drove every role through its core journeys on the live site. Click any screenshot to see exactly what should appear. Open the URL to follow the same route yourself.

Anonymous / Spectator 12/12 ✓

home
Homepage loads with hero, schedule + sponsors
standings
Standings page loads with division tabs
results-history
Results history page loads + division tabs work
clubs
Clubs page loads with map + club list
club-detail
Club detail page (212 HK) with clickable players
topten
Top Players with division pills
players-default-div
/players defaults to Division A (BUG-037-FIX-V1)
faq
FAQ page loads
sign-in
Sign-in page has magic-link, OAuth hidden
matchup
Matchup page with + Add Player name picker (bug-047)
rules
Rules & Regulations page
chat-widget
Public AI chatbot widget present + opens (bug-058)

Player 2/2 ✓

app-lands
Player lands on /app.html with profile
profile
Player can view own profile

Captain 5/5 ✓

app-lands
Captain lands on /app.html — My Team panel
my-team-api
Captain /api/v1/captain/teams returns team list
matches
Captain /api/v1/captain/matches returns matches
ai-assistant
AI assistant replies in same language (bug-019 BUG-018/020)
submit-score-form
Scoresheet page loads for a captain match (BUG-024/025)

Judge / Referee 2/2 ✓

referee-page
Judge lands on /referee.html with venue picker
judge-console
Judge console / live-score page loads

Registrar 1/1 ✓

registrar-queue
Registrar approval queue loads

Finance 1/1 ✓

finance-receipts
Finance landing — receipt verification surface

Division Rep 1/1 ✓

divrep-landing
Division Rep landing page

Editorial 1/1 ✓

editorial-admin
Editorial /admin.html — allowed tabs visible

Tenant Admin 4/4 ✓

admin-shell
Tenant Admin /admin.html — full sidebar loads
admin-clubs
Admin Clubs tab — list loads
admin-teams
Admin Teams tab — list loads
club-managers-tab
Club Managers — Invoices&Receipts panel present (BUG-012)

Super Admin 4/4 ✓

super-page
Super Admin /super.html — cross-tenant ops
super-tenants-api
GET /api/v1/super/tenants returns tenant list
super-users-search
GET /api/v1/super/users-search returns results (BUG-013 helpful error path)
admin-gallery-upload
Gallery editor has per-row 📤 Upload (BUG-029)

For a larger view of each journey (with sign-in steps + the "what we checked" detail panel), open the standalone role walkthrough page.

📥 Committee bug reports — this batch 22 CLOSEDclick any screenshot to see it full-size

Bug · fix marker · date Problem What you reported Screenshot How we fixed it How to test
bug-010
renderTeamSearchPanel
2026-06 (prior)
"Find your Team" went to wrong page
Filed: 2026-05-25
"Find your Team" goes to Player Database page
EN: "Find your Team" goes to Player Database page
(no screenshot) Removed link to /players. Replaced with in-page "Find a team to join" panel + #team-q search input.
Verify: /app.html
As role: spectator
Sign in as Spectator. Land on /app.html. Look for the "Find a team to join" panel — no Player Database redirect.
bug-013
BUG-013-FIX-V1
2026-06-29
/admin "Search failed (403)" with no explanation
Filed: 2026-05-26
stand in real users shoes. search error
EN: stand in real users shoes. search error
Frontend now reads j.detail from the 403 response and shows the helpful sentence. requireAuth() returns your_role + required_roles.
As role: a non-SUPER_ADMIN role
Sign in as Captain. Hit the impersonate search. Expect a clear "This action needs role SUPER_ADMIN, but your account is X..." message.
bug-017
BUG-017-FIX-V1
2026-06-29
/club.html — players not clickable, lost profile link
Filed: 2026-05-30
而家我哋有時間 player,但係個 player 揀唔到 team,又冇咗 profile,要睇吓係咩回事。
EN: Now we have time player, but that player cannot choose team, also lost profile, need to look what is matter.
(no screenshot) Wrapped every .player-row in an anchor → /profile/{dupr_id} when DUPR present. Captain/co-captain names also wrapped.
As role: anonymous
Open /club.html?id=1. Click any player row — lands on /profile/<dupr_id> with the player's page.
bug-018
BUG-018-FIX-V1
2026-06-29
AI said "find the reschedule button" — no such button
Filed: 2026-05-30
嗱 我呢就 login as 一個 captain, 我嘗試呢就 reschedule 一個比賽, 但呢 根據個 AI 就話 你去個 match card 度 有個 reschedule button, 但我都搵唔到個 reschedule button.
EN: 嗱 [particle] I [particle] then login as one [measure word] captain, I try [particle] then reschedule one [measure word] match, but [particle] according-to [measure word] AI then say you go [measure word] match card [location particle] have one [measure word] reschedule button, but I also cannot find…
(no screenshot) AI system prompt forbids referencing UI elements — the chat IS the action UX, emits ACTION_REQUEST + confirm button in-chat.
Verify: /app.html
As role: captain
Sign in as captain → open AI assistant → type "I want to reschedule." Reply does NOT tell you to click a button; asks which match by team+date.
bug-019
LANG-PIN-V1
2026-05-31
AI replied Chinese to English input
Filed: 2026-05-30
啦, captain page, 我用 AI assistant, 我都, swap player, 我明明打英文, 中文, consistent.
EN: [laa particle], captain page, I use AI assistant, I also, swap player, I clearly type English, Chinese, consistent.
(no screenshot) lib/help-desk-agent.js — CJK vs Latin char ratio hard-pins reply language to the latest message.
Verify: /app.html
As role: captain
Sign in as captain. Type English question → English reply. Type Chinese question → Chinese reply.
bug-020
BUG-020-FIX-V1
2026-06-29
AI asked for "match number 406" — captains don't memorise IDs
Filed: 2026-05-30
我呢都 page 啦,佢有個 AI assistant 啦,有一個 reschedule。啦, reschedule, 佢話 reschedule 一個一個 match, 300 number 406, 問題 user 或者 captain 都知 406 number, 所以我覺得要要改,應該要 list out,你係想 reschedule match 啊,可以我,我對對 stack,我先知道嘛。
EN: I [particle] also page [particle], it has an AI assistant [particle], has a reschedule. [particle], reschedule, it says reschedule one one match, 300 number 406, problem user or captain all know 406 number, so I feel need need change, should need list out, you are want reschedule match [particle], c…
(no screenshot) AI prompt: list matches as "{teamA} vs {teamB} on {date}" — never ask for a numeric ID.
Verify: /app.html
As role: captain
Sign in as captain → AI assistant → "I want to reschedule" without naming a match. AI lists matches by team+date, not by number.
bug-021
IN-APP-CONSENT-V1
2026-06 (prior)
Captain "added" a player who never accepted
Filed: 2026-05-30
(none)
(no screenshot) Captain POST /captain/players → creates TeamPlayer with is_active=false (PENDING). Player must accept via in-app banner.
Verify: /app.html
As role: captain → then the added player
Captain adds a player. Player sees in-app pending banner. Until accepted, /club.html doesn't list them as active.
bug-022
A4 + §3.1 guards
2026-06 (prior)
Same player both slots + repeated MIX pairs
Filed: 2026-05-30
(none)
(no screenshot) captain.js:1765 hard-errors if p1_dupr === p2_dupr same game. lib/match-format.repeatedMixedPairs catches reused MIX pairs.
As role: captain
Lineup wizard: set both slots of one game to the same player → hard error. Reuse a MIX pair → §3.1 error.
bug-023
BUG-023-FIX-V1
2026-06-29
All-female team accepted on MIX game
Filed: 2026-05-30
我依家我都係 as a team captain,我就 嘗試 submit 個 score 啦。 咁 你知道啦,女雙男雙混雙㗎嘛。 咁對方呢, 我幫對方入埋,但對方呢係冇男仔嘅,我全部都有返 全部女師。 咁我發現呢其實個 logic 係有啲問題嘅,因為佢後面冇 check 到個其實,喂,你呢個係唔可以有 男仔嘅,因為呢個係混雙, 女雙或者係 男雙 for example。 咁後面係冇 check 到一樣嘢,但個 score 都係 submit 到成功嘅。
(no screenshot) captain.js:1770 — partial lineups (one slot blank) now fail with incomplete_lineup before gender check is skipped.
As role: captain
On lineup save, fill ONE slot of a MIX game and leave the other blank → 422 with "incomplete_lineup".
bug-024
BUG-024-FIX-V1
2026-06-29
Co-sign button → bare "Failed: 403 Forbidden"
Filed: 2026-05-30
好,第三個問題呢,就我依家都係 team captain。咁明明我已經係 team captain 㗎嘛,咁我唔知點解下邊呢,submit score 嗰陣時呢,仲要我 sign in as a team captain。但撳掣呢,撳落去呢,有 error message 嘅,嗰個係 forbidden,但唔知係 forbidden 啲乜嘢。
EN: Okay, third one problem [particle], then I now still am team captain. So obviously I already am team captain [particle] [particle], so I don't know how why below [particle], submit score that time [particle], still need me sign in as a team captain. But press button [particle], press down-go [partic…
(no screenshot) middleware/session.js requireAuth() returns detail + your_role + required_roles. signSide() prefers j.detail.
As role: captain (of a different team)
Open a scoresheet for someone else's match → click "Sign as Captain" → get the helpful sentence, not "Failed: 403".
bug-025
BUG-025-FIX-V1
2026-06-29
Score save intermittent — "didn't work, then worked"
Filed: 2026-05-30
好奇怪喎。頭先呢,我而家喺個 submit 個 score 度呢, as a captain 呢, save 唔到喎。唔知點解咗一咗下呢,跟住又 save 到,唔知係咪呢個係 bug。
EN: 好 [very] 奇怪 [strange] 喎 [particle]. 頭先 [just now] 呢 [particle], 我 [I] 而家 [now] 喺 [at] 個 [classifier] submit [submit] 個 [classifier] score [score] 度 [location] 呢 [particle], as a captain [as a captain] 呢 [particle], save [save] 唔 [not] 到 [able] 喎 [particle]. 唔知 [don't know] 點解 [how/why] 咗 [completed …
(no screenshot) submitScores() catches network errors, auto-retries once on transient failure with toast feedback, surfaces j.detail on 4xx.
As role: captain
Submit a score. Transient blip → auto-retry toast. Hard failure → clear reason instead of silent.
bug-028
CONTENT-STUDIO-HUB-V1
2026-05-31
Content Studio → Content Library button unresponsive
Filed: 2026-05-30
我 as admin, content studio,好多個, content library,反應。我 day one 都反應。
EN: I as admin, content studio, many [classifier], content library, reaction/responsive. I day one also reaction/responsive.
(no screenshot) 13 dead placeholder tiles replaced with 11 real working tools (Homepage Video, Gallery, Asset Library, Posts, Mission Cards, etc.).
As role: tenant admin
Open Content Studio. Every tile leads to a working tool.
bug-029
BUG-029-FIX-V1
2026-06-29
Gallery editor missing upload button per row
Filed: 2026-05-30
我 login as admin, gallery page 嗰度呢, 要加返我 drop down menu. So that 係可以啲人可以揀返啲上去。 其他版又做,但呢版係留, 唔見咗個掣。
(no screenshot) Each gallery row has 📤 Upload button calling _inlineUpload helper. + Add Image Row uses the same template.
As role: tenant admin
Open Gallery tab. Each row has 📤 Upload + Remove. Pick a file → URL fills in.
bug-034
magic-link + H7 hide OAuth
2026-06 (prior)
sign-in.html "no login method working"
Filed: 2026-06-09
i cannot test this page, as no login method is working.
EN: i cannot test this page, as no login method is working.
(no screenshot) Magic-link verified 200. OAuth hidden until providers set up (task #175 H7).
As role: anonymous
Enter email → Send Magic Link → green confirmation. No misleading OAuth buttons.
bug-035
AUTH-AWARE-SEARCH-V1
2026-06 (prior)
/matchup — after remove, search returned nothing
Filed: 2026-06-09
i am doing the team comparison between team A and B, after i remove the players in team A, i should be able to choose back in the drop down list, but there is no this option. even i type the player name, nothing shown
(no screenshot) Logged-out users now see clear sign-in CTA instead of silent "no results". Remove→re-pick flow works.
Verify: /matchup
As role: signed-in (any role)
Fill 4 players, × to remove one. Click + Add Player → search returns 12+ results.
bug-037
BUG-037-FIX-V1
2026-06-29
/players should default sort by Division
Filed: 2026-06-09
Players need to be sorted by Division first.
EN: [Cannot be generated as the input is not Cantonese.]
Division dropdown auto-selects first division on page load. Page opens grouped by Division A.
Verify: /players
As role: signed-in
Open /players. Division dropdown shows "Division A" pre-selected.
bug-038
BUG-038-FIX-V1
2026-06-29
/clubs.html grammar: "We Are Clubs." + "Where the league plays"
Filed: 2026-06-09
"We Are Clubs." Poor Grammar. Change to "We are Hong Kong Pickleball League" "Where the league plays" Change to "Find a Team:"
Direct prisma update of clubs_hero_brand → "Hong Kong Pickleball League" + clubs_map_title → "Find a Team" across en/zh_Hant/zh_Hans.
Verify: /clubs.html
As role: anonymous
Open /clubs.html. Hero reads "We are Hong Kong Pickleball League". Map title reads "Find a Team".
bug-040
task #118 uat-cage
2026-06 (prior)
Homepage showed "UAT SANDBOX" tab next to Div A/B/C
Filed: 2026-06-12
(none)
URL: /
UAT-tenant cage cleanup removed all UAT sandbox leakage from live hkpl. Divisions API returns only A/B/C.
Verify: /
As role: anonymous
Open homepage → Match Schedule section. Tabs are only Division A/B/C.
bug-043
BUG-038-FIX-V1
2026-06-29
Same as bug-038 (clubs hero + map title)
Filed: 2026-06-12
(none)
Duplicate of bug-038 — same fix.
Verify: /clubs.html
As role: anonymous
See bug-038.
bug-051
TOPTEN-DIVISION-TABS-V1
2026-06-24
/topten should split by division (A/B/C separately)
Filed: 2026-06-12
你 top 10 players, 麻煩你分 division A top 10 players, division B division C, 可以全部, 但有分 division.
EN: You top 10 players, please you divide division A top 10 players, division B division C, can all, but have division.
/topten.html grew 4 division pills (All / A / B / C). Each filters to that division's top-10.
Verify: /topten.html
As role: anonymous
Open /topten.html. 4 pills present. Click Division A → only Div A players.
bug-055
DIVISION-TABS-DYNAMIC-V1
2026-06-22
/results-history division filter dead
Filed: 2026-06-12
呢一版呢, 揀唔同 division 呢, 係出唔到唔同嘅球隊喎。 哎呀, 全部都係 All Season All Teams 㗎呢。 有 bug 喺度。
EN: This one page [呢], choose different division [呢], is come out not able different [嘅] teams [喎]. Aiyaa, all also is All Season All Teams [㗎] [呢]. Have bug at here.
Division tabs re-wired to re-fetch with the chosen division. Each shows distinct teams (A=50, B=153, C=163).
As role: anonymous
Open /results-history.html. Click Div A, B, C — list visibly changes.
bug-060
task #118 uat-cage
2026-06 (prior)
Same as bug-040 (UAT SANDBOX tab on homepage)
Filed: 2026-06-12
(none)
URL: /#
Duplicate of bug-040 — same fix.
Verify: /
As role: anonymous
See bug-040.

🎥 Video-reported bug 1 ADDRESSED

VideoPageOriginal askStatusHow to test
v0
video 0.mp4
/docs/rules
A+ button should scale the rules CONTENT not just the TOC; every page should have a bug-report function
FIXED — site-wide font-zoom widget shipped (public/js/font-zoom.js + font-zoom-pill.js), bug-report widget on every page
Verify: /docs/rules
As role: anonymous
Open /docs/rules. Find the A+ font-zoom pill (top-right). Click + → text scales bigger. Find the bug-report widget (bottom-left) on every page.

🔧 Round 1–5 audit bugs — full history 37 fixedfrom the canonical docs/UAT_BUG_LOG.md

These were caught during deep audits before the committee batch — naive-user agents, role walks, security hats, multi-tenant integrity checks. Most have shipped fixes; a few are documented as "by design" (intentional choices) or "enhancement" (improvements queued for prioritisation).

ID · reporter Symptom Root cause How we fixed it Status
A1
Player (QA)
"Find your Team" went to the player database, not clubs wrong link target repointed `/players.html` → `/clubs.html` FIXED
A2
Captain Alice
Couldn't **sign** the scoresheet — "Forbidden" frontend POSTed a non-existent route (`/sign`), swallowed by an admin-only catch-all → bare 403 added a real **each-captain-signs-own-side** route (side derived from team membership) + shared finalizer FIXED
A3
Captain Alice
Could submit a **gender-illegal** lineup; "it let me save" `?force=1` bypass was **un-gated** for captains; submit-score also dropped the (validated) lineup `?force` now **admin-only**; submit-score **preserves the validated lineup** FIXED
A4
Captain Alice
Could add the **same player twice** duplicate-in-one-game not checked on any path gender/roster now enforced + non-bypassable; *same-person-both-slots still permitted* — see B-list PARTIAL
A5
Captain Alice
Score save "failed then worked" rules engine correctly 400s **partial** (<5 games) submissions while filling the sheet behaviour is correct; error now shows a clear reason; the wizard issue was the sign-403 (A2) FIXED
A6
Captain Alice
AI assistant replied in **Chinese to English** input reply language was 100% delegated to the model; Chinese-heavy roster context biased it reply language **pinned to the user's message** FIXED
A7
Captain Alice
Reschedule asks for a **match number**; "no reschedule button" button shows only when there's an upcoming scheduled match (test data had none); AI help-desk asks for a match id data-starvation (sandbox now fully seeded); AI-UX noted ?
A8
Captain Alice
Could add a player **without email verification** no verified-contact gate on roster-add intentional — HKPL identifies players by **DUPR id**, not email BY DESIGN
A9
Captain Alice
"Plan / request" function not needed **kept** (industry-standard pre-list/post-game flow); admin fast-path noted for future BY DESIGN
A10
Captain Alice
No **division** shown on captain's team cards (confusing w/ multiple teams) missing label UX label ENHANCEMENT
A11
Tenant-Admin Ursula
**Content Studio / "content library" unresponsive** "since day one" the 13 modules are a roadmap placeholder — never built, but styled clickable tiles now clearly **"Coming soon"** + a working pointer to **Settings → Asset Library** (real uploader) FIXED
A12
Tenant-Admin Ursula
**Editorial: can view but can't change title/words** saving a post with **no cover image** was rejected (`cover_url` required a URL) blank cover/logo URLs now accepted; editing title/body **saves + persists** (verified) FIXED
A13
Tenant-Admin Ursula
Homepage **video** not editable in admin homepage video was **hardcoded** (never-built TODO) **Homepage Video editor** added (Settings → video URL + title + description; no schema change); also fixed relative `/cdn/` asset URLs being wrongly rejected as covers/logos FIXED
A14
Tenant-Admin Ursula
Gallery tab: dropdown / upload button missing upload lives in Settings → Asset Library, not the gallery tab pointer added via Content Studio (A11); gallery-tab pointer pending PARTIAL
A15
Tenant-Admin Ursula
**Create match**: teams not filtered by division → unclear error UI lists all teams; server correctly rejects cross-division but the UI hid the detail server error now honest; client division→team filter pending ?
A16
Tenant-Admin Ursula
Rulebook spacing display formatting formatting polish ENHANCEMENT
A17
Captain (QA)
`super/users-search` 403 ("search error") the "sign in as any user" tool is **SUPER_ADMIN-only**; a captain session hit it works as intended (admin-only); the QA test surface is now sandbox-only anyway BY DESIGN
A18
Tenant-Admin (QA)
"Add a Generate Invoice + Receipt button" valid request ENHANCEMENT
B1
Unknown `/api/*` routes returned a misleading **403**
a last-mounted admin-only catch-all swallowed every typo honest **404** + per-route admin gate (kills the wrong-URL bug class) **FIXED** FIXED
B2
Many handlers **500'd** on a blank field / stale id
global error handler defaulted everything to 500 maps **ZodError→400, Prisma P2025→404, P2002/3→409** **FIXED** FIXED
B3 `findFirst({id:NaN})` threw outside a try → no response bad-id guard → clean 400 (**caught by the test harness**) **FIXED** FIXED
B4 frontend called the wrong path → `/api/v1/admin/clubs` **FIXED** FIXED
B5
Referee "Start Live Scoring" dead
wrong URL (`/live/start` vs `/matches/:id/live/start`) corrected **FIXED** FIXED
B6
Judge 401 → `/login.html` (doesn't exist)
wrong redirect → `/sign-in.html` **FIXED** FIXED
B7 **Cross-tenant** rule write (admin could target another tenant) forced to own tenant **FIXED** FIXED
B8
**Cross-tenant** club join
unscoped club lookup scoped to request tenant **FIXED** FIXED
B9
Eligibility rules **skipped** on join-request approval
engine wired only to the captain "add player" path approval now enforces the same rules (registrar override = the exception) **FIXED** FIXED
B10
New divisions/tenants had **no DUPR-band / NR** rules
rules seeded only for 3 hardcoded division ids `scripts/sync-division-rules.js` derives them for every division **FIXED** FIXED
B11
Dead social-media links (`href="#"`) on 5 public pages
populating script only on the homepage shared `social-links.js` populates or hides them **FIXED** FIXED
WS1
Live updates dead on uat (naive-agent: `/ws` → 403)
`WS_ALLOWED_ORIGINS` listed hkpl/szpb/macau/gba but **not `uat.silkvo.com`** → every WS upgrade from the uat host was origin-rejected added `uat.silkvo.com` to the allowlist (`lib/ws-server.js`) **FIXED** FIXED
A4
Same player in both slots of one game
no per-game duplicate check on any lineup path hard, **non-bypassable** `same_player_both_slots` guard on **both** lineup paths (captain `my-lineup` + judge-console); even admin `?force` can't override (it would double-submit one DUPR id). Harness test added (red→green) **FIXED** FIXED
DISC1 Admin couldn't find the homepage-video / post editors (naive-agent rated tenantadmin 1/10) dashboard **Common tasks** now has "News, posts & announcements" + a "Homepage video" shortcut that jumps to and scrolls to the editor **FIXED** FIXED
A10
No division on captain team cards
label only shown as a skewed badge explicit "Division: … · season" subline under the team name **FIXED** FIXED
A14
Gallery tab had no upload affordance
uploads live in Settings → Asset Library added a "📤 Upload images (Asset Library)" button that jumps to and scrolls to the uploader **FIXED** FIXED
A15 Create-match listed all teams → confusing cross-division reject + stale "endpoint not wired" note team dropdowns now **filtered by the selected division**, default B≠A, client A=B guard, server `detail` surfaced, stale note removed **FIXED** FIXED
JUDGE1
Judge lands on an empty state (naive-agent rated 6/10)
venue must be picked manually; bare "pick a venue" hint empty state is now actionable ("no matches on this date — pick another"), and a date with exactly one venue **auto-selects + loads** so the judge lands on the match list **FIXED** FIXED
PLAYER1 Player landing had no link to their own profile / DUPR (naive-agent rated 5/10) added a "My profile & DUPR" shortcut (→ `/profile.html`) in all 3 languages **FIXED** FIXED
SEED1 Registrar / division-rep cards showed a raw slug (`uat-pending-…`) in quotes seed now writes a human-readable note (still unique → still idempotent); the two live uat rows were updated in place **FIXED** FIXED
A18
"Generate invoice + receipt" button
New route `GET /api/v1/registrar/registrations/:id/invoice` renders a print-ready, self-contained **Invoice / Official Receipt** (browser Print → Save as PDF; no server Chrome dependency). Pulls real amount from `Tenant.registration_fee` + `currency`, presents as **PAID Official Receipt** once `rece… New route `GET /api/v1/registrar/registrations/:id/invoice` renders a print-ready, self-contained **Invoice / Official Receipt** (browser Print → Save as PDF; no server Chrome dependency). Pulls real amount from `Tenant.registration_fee` + `currency`… FIXED
A16
Rulebook spacing
Reader-facing rulebook is `/docs/rules` (docs.js). Each section now has a top divider + 40px top margin (clear separation) and the body reads at line-height 1.75 / 15px instead of the cramped 24px gap. `/docs/rules` 200 verified. **FIXED** Reader-facing rulebook is `/docs/rules` (docs.js). Each section now has a top divider + 40px top margin (clear separation) and the body reads at line-height 1.75 / 15px instead of the cramped 24px gap. `/docs/rules` 200 verified. **FIXED** FIXED
RCPT1
Admin "View receipt" link was broken
The link hrefed the raw `receipt:<file>` token (un-openable). Now points at the authenticated streaming route `/api/v1/registrar/receipt/:id`. **FIXED** (found while building A18) The link hrefed the raw `receipt:<file>` token (un-openable). Now points at the authenticated streaming route `/api/v1/registrar/receipt/:id`. **FIXED** (found while building A18) FIXED
JUDGE2
"Referee Console" vs "Judge" perception
No change warranted: the page says **Referee** consistently (HKPL's term for an on-court official); the "Judge" the agent saw top-right is the **QA persona's display name** ("Judge Jordan"), not a role label. Real users aren't named that. **NO CHANGE** No change warranted: the page says **Referee** consistently (HKPL's term for an on-court official); the "Judge" the agent saw top-right is the **QA persona's display name** ("Judge Jordan"), not a role label. Real users aren't named that. **NO CHANGE… NO CHANGE
C1 `GET /api/v1/public/teams?division=` (team-stats picker) had no route built in public.js **FIXED** FIXED
C2 `GET /api/v1/public/teams/:id/stats` (team-stats record) had no route built (reuses computeStandings) **FIXED** FIXED
C3 `GET /api/v1/results/history?division=` (Results History page) had no route built in public.js; tier letter resolves off division NAME (slugs are `division-a`) **FIXED** FIXED
C4
admin-roles.html "Help" → `/help.html` (nonexistent)
real dead link → `/overview.html` **FIXED** FIXED
F1
Content Studio: 13 dead "coming soon" IG/Canva tiles
real (placeholder) rebuilt as a **working hub** launching the 9 real content tools (video, gallery, asset library, posts, mission cards, organization, sponsors, rulebook, translations). Zero dead tiles. **FIXED** FIXED
R1
Reports tab deferred "PDF/ledger/DUPR sync log to Phase 4"
real (deferral) built **two real CSV exports** — full-season standings + registration/payment ledger (`/admin/reports/standings.csv` + `registrations.csv`). Deferral language removed. **FIXED** FIXED
X1
League Insights "12 cards spin forever, no JS"
**FALSE** — all 16 `/admin/analytics/*` endpoints exist and return real data; the agent saw the static "Loading…" placeholders and assumed they never populate none **WORKS** FALSE
X2 **FALSE** — it's in `EMBED_TABS`, iframes the real `admin-club-managers.html` none **WORKS** FALSE
X3
disputes tab "is dead/TODO"
**FALSE** — `renderDisputes` is a functional read view; the TODO was a dashboard *count* comment none **WORKS** FALSE

❓ Awaiting your input 3 items

bug-041: "Buttons smaller, table view too big" on the homepage. Too vague to act on — which buttons? which table?
→ Which specific page + which buttons / which table is the wrong size? A screenshot with the trouble area circled would let me fix it.
bug-057: Add a how-to video to /faq.html — needs a video file we don't have
→ Please provide a short MP4 walkthrough (or a YouTube/Vimeo link). We'll embed it as the first section of /faq.html.
bug-039: Proposed new role taxonomy (Club Manager / Captain / Players etc.)
→ Naming + permission split is your call. Share the final naming and we'll rename + re-wire the permission gates.

📋 Deliberately not done accidental snaps + dev-smoke pings

Reviewed and intentionally skipped. If any are real problems we missed, please re-report with a one-line description.

bug-042: Screenshot of homepage with a scrolled black area above hero — widget-screenshot artifact, page renders normally today.
bug-044/045: /club.html?id=1 snapped twice with no annotation — page renders normally today, no actionable signal.
bug-050/053: /matchup with different players — pages work, no annotation.
bug-052: /topten.html — same period as bug-051 fix, no annotation.
bug-056: /team-stats.html — renders normally, no annotation.
bug-061: Duplicate of bug-040 homepage view (UAT-leak), now fixed.
bug-004: "V2 widget smoke" — explicit dev smoke test.
bug-011: "club manager role" — context fragment, no screenshot, no clear ask.
bug-multiple: 12 dev-smoke pings (bug-001/002/003/005/006/007/008/009/014/015/016/062) — auto-pings during ship-gate runs.