Skip to content

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 ​

SourceMethodResult
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 #10Every item checked against code before listing32 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-run4 unresolved: 3 "verify on device", 1 sign-up (external)
Owner questionsLive 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 gapsCode researchVenue-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 captured2 P1 and 4 P2 regressions and a seed defect (§2)

2. Found on the device today ​

IDSevFindingEvidence
DQ-1P1멤버 관리 shows no names in role sections: avatar, badge and kebab onlymember-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-2P1회비 관리 rows touch both screen edges; the 미납 title sits off the railadmin-roster-section.tsx:121 uses SCROLL_CONTENT.list around PersonRows, which own no rail (COMP-9)
DQ-3P2Several people render as empty grey circles (friends, participants): no photo, no initialsTheir 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-4P2DM inbox titles start at three different x positionsGroup rows lead with AvatarStacks of different widths; single rows lead with one avatar
DQ-5P2회비 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-6P2The dev account's 1:1 threads show previews ("서브 폼 많이 늘었어요!") and open emptyThe 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
—okVerified: DM header shows the counterpart (board item); 테니스장 carries 없는 장소 추가 + 제안 내역; 설정 five sections; 신고 관리 rows; 출석 rows; 알림 kind rows with row-counting chips; session detail roster on PersonRowScreenshots 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) ​

IDDecisionEvidence
RSVP-DEADLINEThe 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-HERONot 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-REVIEWPlatform 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.

IDQuestionEvidenceRecommendationAnswer
CLUB-ELO-POOLRetire 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 조 modelRetire the ladder: club ranks become the global ELO filtered to members; keep the per-club match count for home-club calibration. Until answered: nothing changesAnswered 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 photoClub cards without a photo keep the full default band?Screen audit D3; design-queue itemWireframe firstAnswered 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.
friendsGoingShow "친구 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.

Markdown remains the source of truth. Run yarn docs:check before handoff.