# Phase 4 — Cleanup Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Remove the per-window surface-Elo admin UI + backing table, remove the old batch-add-results wrapper route (keeping the canonical route as the only path), and strip compatibility shims. Leaves the canonical layer as the sole source of truth. **Architecture:** Pure removal. No new behavior. Each removal is preceded by a verification step proving the removed code is no longer reachable. **Tech Stack:** Drizzle migration, Vitest, Cypress. **Prerequisite:** Phase 3 complete and green in production for at least 7 days with active draft activity. Tag `phase-3-complete` exists. **Reference:** `docs/superpowers/specs/2026-05-01-canonical-tournament-layer-design.md` — Phase 4 section. --- ### Task 1: Verify `season_participant_surface_elos` is no longer read **Why:** Before dropping the table, prove nothing reads from it. - [ ] **Step 1: Grep for reads** Run: ```bash grep -rn "seasonParticipantSurfaceElos\|season_participant_surface_elos" app/ server/ scripts/ database/ ``` Expected: only hits in `database/schema.ts` (the Drizzle export and relation). No app/service reads, no queries. If any live read remains — stop. Phase 3 was incomplete; fix the read path to go canonical, redeploy, wait 24h, then return here. - [ ] **Step 2: Production observability check** Check production logs and/or `pg_stat_user_tables` for activity on `season_participant_surface_elos`: ```sql SELECT seq_scan, seq_tup_read, idx_scan, idx_tup_fetch, n_tup_upd, n_tup_del FROM pg_stat_user_tables WHERE relname = 'season_participant_surface_elos'; ``` Check `pg_stat_reset()` was not called recently. If the table has seen reads/writes in the past 7 days (compared against a baseline), investigate before dropping. - [ ] **Step 3: Commit a note in the plan** Paste the output of Steps 1 and 2 into a short PR description for the drop migration, documenting verification. --- ### Task 2: Drop `season_participant_surface_elos` **Files:** - Modify: `database/schema.ts` (remove export + relations) - Create: `drizzle/XXXX_drop_season_participant_surface_elos.sql` - [ ] **Step 1: Remove the table from schema** In `database/schema.ts`, delete: - The `seasonParticipantSurfaceElos` `pgTable(...)` export. - The `seasonParticipantSurfaceElosRelations` export. - Any references in other `*Relations` exports (e.g., in `seasonParticipantsRelations` or `sportsSeasonsRelations` that include `seasonParticipantSurfaceElos` via `many()`). - [ ] **Step 2: Generate migration** Run: `npm run db:generate -- --name=drop_season_participant_surface_elos` Expected: Migration with a single `DROP TABLE "season_participant_surface_elos"` statement. - [ ] **Step 3: Verify snapshot chain** Run: `npm run db:generate` Expected: "No schema changes". - [ ] **Step 4: Apply migration on staging and re-run tests** Run: `npm run db:migrate` Run: `npm run test:all` Expected: Green. - [ ] **Step 5: Apply migration on production** Follow your normal deploy flow. After deploy, re-verify: ```sql SELECT tablename FROM pg_tables WHERE tablename = 'season_participant_surface_elos'; ``` Expected: no row returned. - [ ] **Step 6: Commit** ```bash git add database/schema.ts drizzle/ git commit -m "migration: drop season_participant_surface_elos table Canonical participant_surface_elos is the sole source of surface Elo since Phase 3. No reads or writes observed in the past 7 days. Part of Phase 4 canonical tournament layer cleanup." ``` --- ### Task 3: Remove per-window surface-Elo admin UI **Files:** - Remove: `app/routes/admin.sports-seasons.$id.surface-elo.tsx` - Modify: `app/routes.ts` (remove the route registration) - Modify: any navigation links pointing at the removed page - [ ] **Step 1: Find references to the removed route** Run: ```bash grep -rn "surface-elo" app/ | grep -v "^\.\/app/routes/admin\.sports-seasons\.\\\$id\.surface-elo\.tsx" ``` Expected: admin navigation links + possibly dashboard; update them to point at `/admin/participants/:id/surface-elo` or the canonical participant list. - [ ] **Step 2: Delete the route file** ```bash git rm app/routes/admin.sports-seasons.$id.surface-elo.tsx ``` - [ ] **Step 3: Remove route registration** In `app/routes.ts`, delete the line registering `admin.sports-seasons.$id.surface-elo.tsx`. - [ ] **Step 4: Update any links** Edit each file found in Step 1 to redirect or remove the per-window link. - [ ] **Step 5: Run full test suite** Run: `npm run test:all` Expected: Green. Any failing tests that specifically asserted on the old route should be updated or removed. - [ ] **Step 6: Commit** ```bash git add app/routes.ts app/ git commit -m "remove: per-window surface-elo admin UI Canonical participant surface-elo edit page (/admin/participants/:id/surface-elo) is now the only path. Part of Phase 4 cleanup." ``` --- ### Task 4: Remove the batch-add-results wrapper from per-window route **Goal:** The per-window scoring-event admin route still has a `batch-add-results` intent (added in Phase 3 as a wrapper that writes to canonical). Remove the intent so the route no longer accepts per-window result entry. Admins must use `/admin/tournaments/:id` instead. **Files:** - Modify: the per-window route handling qualifying result entry (the one edited in Phase 3 Task 11; find via `grep -l "batch-add-results" app/routes/`) - Modify: any UI component that still posts to `batch-add-results` on that route - [ ] **Step 1: Grep for usages of the wrapper** Run: ```bash grep -rn "batch-add-results" app/ ``` Cross-reference with Phase 3 changes — confirm the only live callers are UI components on per-window pages (which should have been deprecated in Phase 3 release notes). - [ ] **Step 2: Remove the `batch-add-results` intent branch** In the per-window route action handler, delete the `if (intent === "batch-add-results") { ... }` branch. Other intents stay. - [ ] **Step 3: Remove the Batch Result Entry UI from the per-window event page** Find the component that rendered the "Enter Results" form on per-window pages. Replace with a banner: ```tsx
Result entry has moved.
Enter results for {event.name} here.