Club Growth Completion Slices
Status: Archived Last audited: 2026-06-11
This is a completed club-growth evidence packet from an earlier implementation batch. Current roadmap execution lives in Roadmap Implementation Plan.
This document records how the earlier Club Growth & Admin Overhaul gaps were closed. Treat it as evidence and history, not as the current queue of work.
Completion Ledger
| Slice | Status | Checkpoint |
|---|---|---|
| 1. Backend access proof | Complete | 8941de52 / OTA 6d2ee7a3-6505-4789-ba9e-47aa253d548a |
| 2. Shared card/filter/ranking contracts | Complete | 01cab953 / OTA 467e4164-d656-48f1-8511-b465e9a5257c |
| 3. Compact discovery filters | Complete | a64d8e53 / OTA 3049c233-0a4b-4f4f-b9bd-57c10cb9f4a4 |
| 4. Admin modal cleanup | Complete | 97dc3f97 / OTA 449e694d-06fb-42a7-80e4-3629864e9a70 |
| 5. Public profile/media smoke path | Complete | b28b65fb / OTA a1014d9b-9899-4585-a36a-4da1336c14d5 |
| 6. Scenario builder coverage | Complete | 4040c732 / OTA 03ac1823-a236-4298-867d-b7c8ee89f577 |
| 7. Hosted club smoke coverage | Complete | 08a9db61 / hosted run 019eb775-10a6-730e-8ff1-2ed44acce621 SUCCESS 2026-06-11 16:48 UTC — 3/3 flows PASSED on device (01-login 28s · 02-main-tabs 41s · 08-club-growth-media 80s), build 8b32e688 |
| 8. Final release evidence packet | Complete | This ledger + Evidence Ledger below IS the packet: migrations through 00258 on prod · yarn check 2,547 tests green · lint:pi-schema + lint:strict green · hosted scenario seeding proven in-run · latest app-affecting commit OTA'd (group d5128319) · hosted device smoke green (019eb775) |
Evidence Ledger
- Remote Supabase migration state was verified on 2026-06-11 with
yarn supabase migration list --linked; local and remote are aligned through00258. - Migration
00258_club_media_growth_access_contract.sqlwas applied to the linked remote project on 2026-06-11. It contains only access grants, RLS helper/policy refinements, and a PI exemption because it introduces no new personal-data fields or tables. - The
seed-scenarioSupabase function was deployed to projectllhvhhpbjnnrfwcczizcafter the scenario builder added pending application states and storage retry hardening. node scripts/run-scenario.mjs club_growthhas been run against the hosted backend after the final smoke-flow fix and seeded deterministic club growth data including media and pending join requests (users=29, clubs=8, media=10, joinRequests=7).- Preview OTA
d998a1e1-82af-4c8e-a0fa-a03cbc70b869was published forc7a9210fafter the stable card-selector fix. yarn check,yarn lint:pi-schema, targeted club/app/ui tests, and YAML parsing have passed for the relevant app-affecting slices before each checkpoint commit.- Hosted workflow
019eb640-9f51-71cd-97c9-1a47547d7bf0was canceled after hanging. - Hosted workflow
019eb65f-f38b-7a0e-9628-638dabb59123was started and then canceled as it reported no build progress updates after launch;8a5fca13-fd9a-4a73-919b-6ed5c66517c1never moved to finish state. - 2026-06-11/12 hosted-run arc (Claude session): hosted workflow
019eb6c7-bddd-7739-a0e9-d10b1170f932COMPLETED for the first time — build SUCCESS (build93876cc1, commit2414cfa4), flows01-login(28s) and02-main-tabs-smoke(42s) PASSED on the hosted device (first device-level proof for any flow),08-club-growth-mediaran 91s deep (seeding hook, discovery card selectors, admin navigation all worked) and failed only its final assertions. Failure 1 (run019eb6c7): the pending-photo caption sits below the fold on club settings and the flow asserted without scrolling — fixed ina53c637b(addscrollUntilVisible). Failure 2 (run019eb6ec, build93876cc1-equivalent SUCCESS, 01/02 PASSED again):assertVisible: '승인 대기'is unsatisfiable by construction — the status renders inside ONE composed meta line (승인 대기 · 갤러리 · …, gallery-section.tsx) and Maestro text matchers are full-string regexes, so the bare label never matches; this assertion had never passed on any run. Fixed in08a9db61(scroll to the meta line +'승인 대기 ·.*'regex). Verification run019eb775-10a6-730e-8ff1-2ed44acce621SUCCEEDED (2026-06-11 16:48 UTC): 3/3 flows PASSED on the hosted device —01-login28s,02-main-tabs-smoke41s,08-club-growth-media80s (build8b32e688, commit08a9db61). Slice 7's device-level proof obtained; slices 7+8 closed. Note: an intermediate trigger attempt for this run hung silently overnight during the CLI project upload without ever creating a run — triggereas workflow:runin the FOREGROUND with a timeout and confirm a run ID before polling (gotcha recorded in docs/maestro-e2e.md). For future flow-only iterations usemaestro-e2e-rerun.yml -F build_id=<id>(reuses an existing build, skips the ~28-min rebuild). - Lesson recorded: hosted-smoke text assertions must be authored against the RENDERED element tree (composed strings, full-string regex semantics), not the design intent; and a below-the-fold assert always needs its own
scrollUntilVisible. When the app is unchanged (test-YAML-only fix), the rebuild step is wasted ~25 min — pointing the Maestro job at the previous run'sbuild_idis a worthwhile workflow optimization. - Operational note (same session): the hosted backend had a 19-hour cron auth outage (2026-06-10 ~19:00 → 06-11 13:33 UTC;
app_config.service_role_keyheld a revoked API key → every cronnet.http_post401'd "Unregistered API key"; push + weather down). Repaired and verified during this session — see CLAUDE.md Operational State. The outage did NOT affect the hosted smoke runs (the seeding path authenticates separately), but any smoke flow asserting push/weather-derived UI would have flaked.
Known verification constraints:
- Local Maestro is unavailable in this environment (
maestro: command not found), so the device-level proof for Slice 7 is the hosted EAS Maestro run. yarn check:supabase-typesrequiresSUPABASE_PROJECT_IDandSUPABASE_ACCESS_TOKENor a local Supabase stack; it remains a type-sync check to run in an environment with those credentials.
Completion Point
The club overhaul is complete when all of these are true:
- Club data, media, discovery, admin, and analytics models are reachable from real screens without dead controls or hidden-only paths.
- Public discovery, My Clubs, public profile, club detail, settings, media manager, applications, and growth analytics have deterministic empty and rich scenario states.
- Media and growth analytics RLS/storage behavior is covered for public, member, admin, and outsider access.
- Shared discovery/card/filter behavior has focused tests, not only manual inspection.
- Hosted smoke coverage reaches the new club flows beyond login/main-tabs.
yarn check,yarn lint:pi-schema, targeted tests, scenario smoke, and OTA preview pass for the final app-affecting slice.
Slice 1: Backend Access Proof For Club Media And Growth Events
Current state:
club_media,club-gallery-mediastorage policies, andclub_growth_eventsexist in migrations00255and00257.- Existing pgTAP coverage in
supabase/tests/00010_rls_clubs.test.sqlcovers clubs and club members, but not media visibility, storage object access, or growth event aggregate access.
Done when:
- pgTAP coverage proves approved public media is readable by public discovery.
- pgTAP coverage proves members/admins can read member-only media.
- pgTAP coverage proves outsiders cannot read member-only, pending, rejected, or archived media.
- pgTAP coverage proves only admins can approve/reorder/archive media metadata.
- pgTAP coverage proves growth events can be recorded for visible clubs and only admins can read aggregate analytics.
Verification:
supabase test dbor the project-local Supabase test command.yarn lint:pi-schema.
Slice 2: Shared Club Card, Filter, And Ranking Contract Tests
Current state:
- Shared model ownership exists in
packages/features/clubs/src/shared/club-card-model.ts. - Discovery filter mapping exists in
packages/features/clubs/src/shared/discover-filters.tsx. - Viewer-aware membership exclusion exists in
packages/features/clubs/src/shared/use-viewer-discover-clubs.ts. - Feature packages currently run
test: "echo 'noop'", so these shared contracts are not covered by focused tests.
Done when:
buildClubCardModelis tested for media priority, profile completeness, next-session summary, capacity/open-slot signals, tags, focus, and join policy.sortClubCardModelsForDiscoveryis tested for deterministic score, immediacy, and stable fallback ordering.buildDiscoverClubsFilteris tested for search, region/district, tier, format, schedule, and join policy mapping.- The test path follows a repo-wide convention: either feature-package Jest is introduced deliberately or the pure contracts are promoted to an already tested package.
Verification:
- Targeted card/filter tests.
yarn check.
Slice 3: Discovery Filter UX Compactness
Current state:
- The search bar correctly owns the inline filter toggle.
- Region and district controls are connected.
- The expanded panel still presents many wrapping chips across format, region, district, tier min/max, day, time, and join policy.
Done when:
- Default collapsed state shows only search and the compact active-filter summary.
- Expanded state uses compact grouped controls appropriate to data type: region-to-district cascade, segmented format/join-policy controls, range-like tier control, and compact schedule controls.
- Active filters are readable without chip wrapping dominating the first viewport.
- All controls update the existing filter model without bottom sheets.
Verification:
yarn check.- Visual smoke on Clubs > Discover with empty, normal, and rich scenario data.
Slice 4: Admin Modal And Design-System Cleanup
Current state:
- Product bottom-sheet primitives are banned by
@twomore/no-bottom-sheet-outside-dev-panel, and current club "sheet" files useModalPanel. - Some component/file names still say "Sheet" even though the implementation is
ModalPanel. - Dues action modals use
StyledInput; no rawTextInputremains in that touched file.
Done when:
- Club modal components are named by behavior, not "Sheet", where touched.
- Dues action modals use design-system input primitives and no inline style drift.
- Modal panels have explicit close/cancel actions and no drag-handle/bottom sheet affordances.
Verification:
yarn check.- ESLint rule
no-bottom-sheet-outside-dev-panelremains green.
Slice 5: Public Profile And Media UX Evidence
Current state:
- Public profile uses approved public media, schedule, profile identity, description, join policy CTA, and inline application panel.
- Settings exposes gallery upload, caption, alt text, visibility, approval/rejection, feature, reorder, archive, and profile completeness.
- There is no dedicated visual smoke path proving those states render with rich scenario media.
Done when:
- Rich club scenario shows media on Discover cards, My Club cards, public profile, and settings gallery.
- Empty/bare club scenario shows clean fallbacks and useful admin completeness guidance.
- Approval-required club scenario shows the inline application path.
- Invite-only club scenario keeps invite code secondary and does not present a misleading open-join CTA.
Verification:
- Scenario smoke screenshots or Maestro flow for public profile/settings media.
yarn check.
Slice 6: Scenario Builder Coverage For Clubs
Current state:
- Scenario seeding includes club focus, tags, photo policy, join policy, rich media states, growth analytics events, and membership states.
- Dev panel scenario builder exists, but the club overhaul needs explicit preset coverage guarantees.
Done when:
- Configurable scenario builder can generate bare, rich social, competitive, beginner-friendly, invite-only, approval-required, full/no-slots, pending media, pending applications, member, non-member, and admin states.
- Each preset uses shared builders rather than one-off per-scenario data.
- Build progress and fresh/build-on-existing modes remain intact.
Verification:
- Targeted scenario-builder tests.
- Manual dev-panel scenario smoke for at least empty, rich, approval, invite, and admin-pending states.
Slice 7: Hosted Club Smoke Coverage
Current state:
- Maestro coverage exists for login, tabs, RSVP, scoring, dispute, sharing, and onboarding.
- Club media/discovery/admin growth flows are not covered by hosted smoke.
Done when:
- A deterministic smoke flow covers Clubs > Discover filters, club card media, public profile, join/application CTA state, My Clubs card, and club settings media manager entry.
- The flow uses seeded deterministic scenario data, not incidental production data.
- The workflow remains affordable: daily/manual hosted run, local smoke command for targeted development.
Verification:
- Local Maestro flow command for the new club smoke.
- Hosted/manual EAS Maestro run when actions quota is available.
Slice 8: Final Release Evidence Packet
Current state:
- Code-level app checks pass, and recent slices have preview OTA commits.
- The club overhaul is still not release-complete until backend access, UI smoke, and scenario proof are closed.
Done when:
- Slices 1-7 are complete.
- Remote Supabase migration status is verified.
- Worktree is clean and branch has a final checkpoint commit.
- Preview OTA is published for the final app-affecting commit.
- Remaining risks are explicitly documented as post-release, not hidden gaps.
Verification:
git status --short --branchsupabase migration list --linkedor equivalent remote migration check.yarn checkyarn lint:pi-schema- Targeted Supabase/scenario/Maestro checks from slices 1-7.
yarn ota:preview