Open-Issues Plan — 2026-09-24
Status: Active Last reviewed: 2026-10-06
Owner request (2026-09-24): "perform research and plan for evidence-based fixes on all the open issues, and then implement."
1. How the list was built
| Source | Method | Result |
|---|---|---|
| Inventory lane: current state, external blockers, improvement plan, screen audit, usability audit, duplication audit, decision log, every blueprint's Gaps., roadmap, implementation plan, owner backlog, GitHub #10 | Every item checked against code before listing | 32 open items; 11 doc claims found stale (already fixed in code) |
Page QA board (feedback collection, 79 entries) | scripts/apply-qa-board-state.mjs --dry-run | 4 unresolved: 3 "verify on device", 1 sign-up (external) |
| Owner questions | Live SQL (\sf) + client trace + benchmarks (Spond, TeamSnap, Meetup, Band; Chess.com, Lichess, UTR, WTN, Matchi) | RSVP deadline decided below; club ELO pool is an owner question (§5) |
| Known gaps | Code research | Venue-finder actions, platform report review, person hero, pgTAP global asserts |
Device (Android emulator Medium_Phone_API_36.1, preview APK 6d8b72a7, OTA 0ce3160e) | Deep links into the hosted QA world, 15 routes captured | 2 P1 and 4 P2 regressions and a seed defect (§2) |
2. Found on the device today
| ID | Sev | Finding | Evidence |
|---|---|---|---|
| DQ-1 | P1 | 멤버 관리 shows no names in role sections: avatar, badge and kebab only | member-row.tsx:148 wraps PersonRow in <XStack paddingHorizontal="$4">; in a row-direction parent ListRow sizes to content and the name column (flex 1, minWidth 0) collapses to 0 wide |
| DQ-2 | P1 | 회비 관리 rows touch both screen edges; the 미납 title sits off the rail | admin-roster-section.tsx:121 uses SCROLL_CONTENT.list around PersonRows, which own no rail (COMP-9) |
| DQ-3 | P2 | Several people render as empty grey circles (friends, participants): no photo, no initials | Their photo URLs return 200 image/jpeg; AvatarBubble draws only a placeholder until onError, so a slow or throttled photo sits blank. The board's "verify on device" item was real |
| DQ-4 | P2 | DM inbox titles start at three different x positions | Group rows lead with AvatarStacks of different widths; single rows lead with one avatar |
| DQ-5 | P2 | 회비 rows carry a filled primary 납부 확인 pill each (eleven stacked CTAs) | dues-row.tsx:118 action="primary"; the sibling review screen's row action is secondary |
| DQ-6 | P2 | The dev account's 1:1 threads show previews ("서브 폼 많이 늘었어요!") and open empty | The dense seed inserts messages with the service role; private.dm_set_sender_id sets sender_id := auth.uid() and raises when it is NULL, so every seeded batch fails and the seed only warns |
| — | ok | Verified: DM header shows the counterpart (board item); 테니스장 carries 없는 장소 추가 + 제안 내역; 설정 five sections; 신고 관리 rows; 출석 rows; 알림 kind rows with row-counting chips; session detail roster on PersonRow | Screenshots in the session scratchpad |
3. Fixes (lanes of at most seven files; one reviewer pass per lane)
Lane A — rows and avatars (UI): DQ-1 (a column wrapper, or better, the members list rails itself); DQ-2 (railed list; the summary stops padding itself); DQ-5 (row action secondary); DQ-3 (AvatarBubble always draws initials under the photo, so loading and failure both read as initials); DQ-4 (a group avatar that keeps one avatar's footprint: two faces overlapped diagonally, the member count stays in the sub line).
Lane B — backend and QA bed (migration 00668): DQ-6: dm_set_sender_id accepts an explicit sender only for service-role writes (users stay forced to auth.uid()); a data fix clears previews on threads with no messages; the seed fails loudly on an insert error instead of warning. Platform report review: dev_read_content_reports / dev_resolve_content_report behind the existing DEV_USER_ID guard (the dev_read_telemetry pattern) plus scripts/review-reports.mjs — no client gains read access. pgTAP: five assertions in three files compare a global function's return value (00031 ×4, expire_unpaid_holds_promotion, venue_court_count_contract); they assert the fixture's own rows instead.
Lane C — RSVP deadline (decided, §4): stop presenting a passed deadline as closed.
Lane D — small screen fixes: edit-session's per-field modals say 적용, not a second 저장 (F8); partner-suggester value column stops wrapping "29/40" (G3); the mission card's typed › becomes the chevron icon (I4); the 경기-tab 테니스장 pane gets 없는 장소 추가 and 제안 내역 through one explore-only VenueFinder option (the directory screen's own chrome stays); VenueCard's dead map-overlay branch is deleted; venue-directory-content.tsx's stale comment is fixed.
Lane E — venue provenance (M): the club venues screen's free-text venue creation routes to the contribution flow (없는 장소 추가), per canon/clubs.md; the create-session wizard's free-text venueName gets the same treatment where the canon says it is queued.
Lane F — prevention: a layout audit on the web rung. ListRow marks itself for web (dataSet), and scripts/qa-layout-audit.mjs runs the existing screenshot-web probe over the route list: a row whose leading content is off the 16 px rail, or whose title collapsed to zero width, fails. DQ-1 and DQ-2 are its canaries.
Lane G — docs: refresh the roadmap and implementation plan (dated June, 0.6.1/69 screens), fix the eleven stale claims (EXT-1 CPO already named, usability §5, U-37, screen-audit A11 and I2, improvement-plan §3), reconcile duplication-audit D7 with the three shipped explainer sheets, reclassify EXT-9 as buildable, board replies for the three device items.
4. Decided here (logged for veto)
| ID | Decision | Evidence |
|---|---|---|
| RSVP-DEADLINE | The deadline is what the server already makes it: members answer by it for priority, and after it the open seats also go to guests (the ratified 00481 rule). No surface says 마감/모집 마감 once it passes — recruitment status follows capacity and session status; the fact row reads as an answer-by time and is omitted once passed; the reminder push asks for an answer instead of announcing a close. A real, optional hard close stays a future feature. | No server path rejects a member RSVP after the deadline (six readers, fifteen rsvps triggers traced); the CTA and server accept it; every benchmark that shows "closed" enforces it |
| PERSON-HERO | Not built. Four of the six sites already compose TypeHero + leading; the DM intro is a chat convention (centered), and edit-profile's avatar is an edit control, not an identity display. | Code research, file:line in the lane report |
| REPORT-REVIEW | Platform reports get an ops path, not an in-app screen: the owner reads and resolves them with scripts/review-reports.mjs through two dev-account-gated RPCs. | Same guard and risk profile as the shipped telemetry reader; no platform-admin role exists |
| PICKUP-HOST-RULES (2026-09-24) | Resolved — the §5 question below was premised on something false. Every pickup lives in a personal clubs.type='pickup' club its host OWNS (hostPickupGame → handle_new_club, 00011 seats the creator as 'owner'), so the host already passes update_session_rules' own owner/admin/match_director guard; nothing server-side singled a host out, and the UI already offered 경기 규칙 on open/locked sessions. Built the two REAL gaps instead: a rules change now notifies confirmed/waitlisted rsvps (signals_on_session_update widened to match_rules + is_friendly, reusing the same session_updated signal — no new type), and the server now refuses a rules edit on a completed or cancelled session (previously only an in_progress match blocked it). | Migration 00672_session_rules_change_notice.sql; live bodies of update_session_rules/signals_on_session_update; docs/canon/sessions.md |
5. Owner questions
All three answered (2026-10-06 review). Each row's Recommendation column is the question as asked; the answer and where it landed are in the Answer column.
| ID | Question | Evidence | Recommendation | Answer |
|---|---|---|---|---|
| CLUB-ELO-POOL | Retire the per-club rating pool? | club_elo_ratings applies the global match delta to a club total starting at 1000, so members do not start equal in any meaningful sense; it has no history table of its own; get_session_rating_impact ranks a player's GLOBAL rating against other members' CLUB ratings (a real bug either way); Chess.com, Lichess, UTR, WTN and Matchi all keep one rating and show club ranks as a filter. Retiring it reverses part of the ratified 조 model | Retire the ladder: club ranks become the global ELO filtered to members; keep the per-club match count for home-club calibration. Until answered: nothing changes | Answered 2026-09-24: retired (owner: "Yeap, I agree with your recommendation"). Migration 00670, club-rating-unification-plan, decision log CLUB-RATING-UNIFIED. |
| D3 club card photo | Club cards without a photo keep the full default band? | Screen audit D3; design-queue item | Wireframe first | Answered twice. 2026-09-24 CLUB-IDENTITY-BAND (own-colour band), then vetoed 2026-09-26 by the owner: COVER-ALWAYS, every club surface renders a photo (album, banner, or the club's assigned default cover via resolveClubCoverUrl). Decision log. |
| friendsGoing | Show "친구 N명" on session surfaces? | Plumbed in the model, never rendered (info-flow wave 3) | Wireframe first (a facepile, not a text line) | Answered 2026-09-24: yes, as a strip chip (`친구 참석 |
6. External (not fixable in the repo)
U-01 self-serve sign-up (verified-identity directive, EXT-11); EXT-2…8, EXT-10…16 as registered; U-11 native one-tap copy needs expo-clipboard in the next EAS build. EXT-9 (force update) is buildable and queued after this plan.
7. Verification and ship
Each lane runs the root gates (yarn typecheck, yarn test, i18n gates); the main thread runs yarn check, pushes 00668 to the hosted QA project, ships a preview OTA, and re-checks DQ-1…6 on the emulator before closing the board items.
8. Status (2026-09-24)
All lanes built and reviewed:
- A: DQ-1, DQ-2, DQ-5.
- A2: DQ-3, DQ-4.
- B: 00668, the report ops path, the five global pgTAP assertions.
- C: RSVP deadline.
- D: the finder contribution row, the fact merge, dead code.
- E: venue picks everywhere.
- F:
yarn qa:layout, 11 routes clean, non-blind. - G: docs.
- H/H2: seeds fail loudly and follow server rules.
- I: the version gate, 00669.
Two adversarial reviewers found:
- the seed completion flip firing the attendance trigger (fixed by H2);
- a false guest promise in the deadline caption (now answer-by only);
- a clock straddle in the deadline fact (the model's
computedAt); - a bare-name allowlist entry (now the exact signature).
GitHub #10 is closed as superseded. CLUB-ELO-POOL: the owner approved the recommendation (2026-09-24); built per club-rating-unification-plan-2026-09-24.md.