Dead & Stale Register
Status: Active
The marked output of a three-lens investigation (dead code · orphaned routes · stale docs), every item grep-proven against the current code. Nothing here has been removed or fixed — this is the examination list. Verdict + recommended action are advisory; removal is the owner's call.
Two root causes account for most of it:
- Doc-move-without-backlink — files reclassified into
docs/history/leave staledocs/architecture/…citations behind. - Component-merge-without-doc-sweep — the 2026-07-20
ClubCardmerge + theclub-card.tsxrewrite invalidated the same descriptions in 4+ docs; onlyscreen-blueprint's Clubs section has been re-grounded so far.
A · Dead code
A1 · Dead files (owner call)
| File | Evidence | Verdict | Action |
|---|---|---|---|
packages/app/src/presentation/hooks/mutations/use-invites.ts (+ inviteKeys, query-keys.ts:255) | Zero importers; superseded by use-share-club-invite.ts (re-exported instead) | DEAD (high) | Remove |
packages/app/src/types/branded.ts | Zero consumers — all ~95 mutationKey: sites use plain arrays. CLAUDE.md's Enforcement Stack claims this shipped (P5) → also a stale claim (§C3) | DEAD (high) | Remove + fix CLAUDE.md, or revive adoption |
packages/features/clubs/src/shared/club-schedule-block.tsx | Zero JSX usage; club-card.tsx never imports it. canon/clubs.md documents it as a live card zone (§C2) — was live pre-rewrite (git 849fd276) | DEAD + DOC DRIFT (high) | Owner call: revive per canon, or delete + rewrite the clubs.md zone model |
A2 · Dead dependencies (remove)
@tamagui/animations-react-native(apps/mobile) — STYLE-2 forbids it, zero imports.nativewind(packages/app) — STYLE-1 forbids it, zero prod imports (+ orphaned jest mock).@tamagui/config·moti(redundant dup) ·@react-native-kakao/social·country-flag-icons·tamagui(features/activity + features/onboarding) ·@babel/preset-env+@babel/preset-typescript(covered bybabel-preset-expo).
A3 · Dead exports
formatMonthDaySlashWithWeekday(date-format.ts:94),formatMonthDayDot(date-format.ts:424) — remove.colors(config/colors.ts:154) — superseded by Tamagui$-tokens — investigate/remove.seasonKeys/seasonRecordKeys/clubEventKeys(query-keys.ts) — roadmap (Phase 11) scaffolding — investigate.
A4 · NOT dead — verified false positives (do not remove)
knip flagged ~1,368 export symbols; ~57% are internal barrel re-exports live via @twomore/app. Also false: scripts/**-hidden deps (@modelcontextprotocol/sdk, glob, gray-matter, minisearch), TYPE-3 *Schema exports (arch-test-mandated), native-module app deps (@shopify/flash-list, expo-image, react-native-mmkv, react-native-spotlight-tour… Expo autolinking), and app-link-association.ts helpers (load-bearing Universal Links). Verify per-symbol before deleting from any barrel.
B · Orphaned routes
| Route / component | Evidence | Verdict | Action |
|---|---|---|---|
apps/mobile/app/activity/sessions.tsx (+ web twin + activity-upcoming-sessions-screen.tsx + its index export) | No routes.ts key; 0 push/Link callers; the tab root already renders that same 내 세션 list inline — superseded | ORPHANED (high) | Delete the trio, or wire a real 더보기 CTA from ActivityScreen |
apps/mobile/app/clubs/[clubId]/sessions/[sessionId].tsx | Redirect stub, no mobile caller (routes.clubSession returns flat /sessions/id). Web serves the nested path | UNUSED on mobile (low) | Keep as external-link safety net, or delete |
apps/mobile/app/leaderboard.tsx, ranking.tsx | One-line redirect shims, 0 callers — but deliberate back-compat (web mirrors them) | KEEP | Cut only if history confirms no legacy links |
Not orphaned (corrected): (tabs)/(clubs)/discover.tsx is the real screen, reached via the intentional flat→nested <Redirect> pattern on all 5 tab roots. Earlier "may be orphaned" flag disproven.
Lead (inverse problem): ~12 routes.ts helpers point at nonexistent files (would 404 if called) — tournament, editSession, challenges, subscription, courtDetail, analysis*, seasonStandings, signalConsent, discoverPickups, partnerMatching — mostly unshipped roadmap. Also routes.ranking === /records (dup of routes.records).
C · Stale docs (~38 refs, grep-proven)
C1 · screen-blueprint.md (~24) — auto-fixed by the wireframe buildout
These are the sections the per-screen re-grounding pass hasn't reached yet (Home + Clubs already fixed). The buildout closes each as its screen is wireframed — no separate sweep needed, but tracked here:
- Systemic phantom
(app)route-group in 13+ headers (:37,215,259,297,624,821,851,914,977,981,985,989,993+ web) — no(app)group exists. :215(activity)→(sessions); entire §2.4 "Ranking Screens" (:914-993) keyed off a nonexistent(ranking)group +screens/ranking/dir — real routes are flatrecords/analysis/*.clubs/[id]→clubs/[clubId](:307,394,501,542,597,1082); Members/Dues/Attendance not under a[clubId]subfolder (:415,1198,1240).- Join/Create (
:559,578) → top-leveljoin-club.tsx/create-club.tsx; Session Edit (:805) →sessions/[sessionId]/edit.tsx; Settings (:1302), Notifications (:1356→home/notifications.tsx). - Whole sections describing nonexistent components — Profile tab (
:259-293), Match Board (:1483-1517), Weather Insight Sheet (:1534-1568), Challenges (:1041-1051). - Self-contradictions:
DiscoverClubCard(:601,633),validateName(:1034),TIER_BADGE_VARIANT/getTierColor(:267-268) — already-fixed elsewhere in the same doc.
C2 · Canon docs — need a dedicated doc sweep (the component-merge fallout)
| Doc:line | Stale ref | Should be |
|---|---|---|
canon/clubs.md:12 | MyClubCard / DiscoverClubCard | ClubCard (isMember-gated) |
canon/clubs.md:10 | ZONE 3 = ClubScheduleBlock (dead) | Re-ground zones from club-card.tsx (BannerCapacityCluster, GlyphFactRow×3, SectionEyebrow+Well) |
canon/components.md:14 | MyClubCard | ClubCard |
canon/components.md:51 | HomeLiveAlertBanner (nonexistent) | LiveSessionStack inside HomeTodayView |
canon/components.md:68 | MotionPressable (deleted 2026-05-09) | Pressable from @twomore/ui |
canon/sessions.md | session-actions-menu.tsx Popover (nonexistent) | header icon buttons + bottom 호스트 도구 SectionBlock |
canon/sessions.md | GPS check-in (retired by migration 00384) | attendance is match-derived/automatic |
canon/sessions.md | playability-info-sheet.tsx (nonexistent) | tap-to-explain sheet gone; score util still live |
canon/sessions.md | my-club-card.tsx / discover-club-card.tsx | club-card.tsx |
canon/status-and-recruitment.md:36 | sessionSummaryPolishMode dev flag (promoted + deleted) | remove — location-first is the unconditional default (contradicts sessions.md:10) |
canon/data-and-hooks.md:17 | validateName() (never existed) | inline validation |
canon/data-and-hooks.md:63 | tier-display.ts / getTierColor / TIER_BADGE_VARIANT | TIER_ICONS in trust.entity.ts; EloTierBadge/TrustTierBadge |
C3 · Hard-constraint / index fact drift
| Doc:line | Stale | Correct |
|---|---|---|
CLAUDE.md:209 | docs/architecture/solutions/ps11-guardrails.md | docs/history/ps11-guardrails.md (solutions/ is now empty) — same broken path in ci.yml:146-147 |
CLAUDE.md:209,213 | "22-file pgTAP / 222 assertions" | 30 files / ~283 assertions (CI says 19 — drifted 3×) |
CLAUDE.md:210 | "52 active ESLint rules" | 53 (matches current-doc-state.md) |
CLAUDE.md:210 | "87 waivers across 4 rules" | 75 (per eslint.ratchet.config.mjs:13) |
korean-market.md:10, AGENTS.md:97 (KR-1) | korean-phone.ts wrapping libphonenumber-js | file doesn't exist yet (built-ahead doc, or unbuilt feature) |
C4 · Doc-move backlinks (→ docs/history/)
agentic-project-foundation.md:76docs/architecture/networking-foundation-plan.md→docs/history/…agentic-project-foundation.md:78docs/architecture/drift-prevention.md→docs/history/…agentic-project-foundation.md:55,133"8 agent operating rules" → 9 (AOR-1..AOR-9).
Prevention (proposed, not yet built)
- Docs the tripwire could cover: the same
groundedInmechanism used for wireframes could mark canon/blueprint sections with the code they describe, warning on drift — closes C1/C2 mechanically. - Move-with-backlink lint: a
docs:checkrule that fails when an active doc cites a path now underdocs/history/— closes C4. - Generated counts: the CLAUDE.md numbers in C3 (rules/waivers/pgTAP) should be generated, not hand-typed.