# Phase 1a — Rename Per-Window Tables 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:** Rename the existing per-window tables (`participants`, `participant_expected_values`, `participant_qualifying_totals`, `participant_results`, `participant_surface_elos`) to `season_`-prefixed names, and rename `event_results.participant_id` to `season_participant_id`. Rename `app/models/participant.ts` to `app/models/season-participant.ts`. Ship a fully green build with zero behavior changes.

**Architecture:** Pure mechanical rename across ~100 files. No new tables, no new columns, no logic changes. This phase must land cleanly before Phase 1b can create the new canonical `participants` table (which reuses the freed name).

**Tech Stack:** Drizzle ORM, PostgreSQL, React Router 7, TypeScript, Vitest.

**Reference:** `docs/superpowers/specs/2026-05-01-canonical-tournament-layer-design.md` — Phase 1a section.

**Rename mapping (authoritative):**

| Old (table / column / symbol) | New |
|---|---|
| table `participants` | `season_participants` |
| table `participant_expected_values` | `season_participant_expected_values` |
| table `participant_qualifying_totals` | `season_participant_qualifying_totals` |
| table `participant_results` | `season_participant_results` |
| table `participant_surface_elos` | `season_participant_surface_elos` |
| column `event_results.participant_id` | `event_results.season_participant_id` |
| Drizzle export `participants` | `seasonParticipants` |
| Drizzle export `participantExpectedValues` | `seasonParticipantExpectedValues` |
| Drizzle export `participantQualifyingTotals` | `seasonParticipantQualifyingTotals` |
| Drizzle export `participantResults` | `seasonParticipantResults` |
| Drizzle export `participantSurfaceElos` | `seasonParticipantSurfaceElos` |
| Drizzle export `participantsRelations` | `seasonParticipantsRelations` |
| Drizzle export `participantExpectedValuesRelations` | `seasonParticipantExpectedValuesRelations` |
| Drizzle export `participantQualifyingTotalsRelations` | `seasonParticipantQualifyingTotalsRelations` |
| Drizzle export `participantResultsRelations` | `seasonParticipantResultsRelations` |
| Drizzle export `participantSurfaceElosRelations` | `seasonParticipantSurfaceElosRelations` |
| File `app/models/participant.ts` | `app/models/season-participant.ts` |
| Relation field `eventResults.participant` | `eventResults.seasonParticipant` |

**Files affected (counts from pre-flight audit):**
- `database/schema.ts` (1 — critical)
- `app/models/index.ts` (1)
- `app/models/` — 11 model files + 2 test files
- `app/routes/` — ~20 route files
- `app/services/` — probability-updater + 19 simulator files
- `app/utils/` — `sports-data-sync.server.ts`
- `server/` — `socket.ts`, test files
- `cypress/` — verify none reference these symbols by name

**Note on granularity:** Because this is a mechanical rename, tasks are batched by scope rather than broken into micro-TDD steps. Each task ends with typecheck + test run as the verification step.

---

### Task 0: Create baseline snapshot (one-time, before any code changes)

**Why:** Phase 2 verification depends on proving QP totals didn't drift. Capture now.

**Files:**
- Create: `scripts/capture-baseline.ts`

- [ ] **Step 1: Write the capture script**

```typescript
// scripts/capture-baseline.ts
import { db } from "~/db/context";
import { sql } from "drizzle-orm";
import { writeFileSync, mkdirSync } from "fs";
import { join } from "path";

const OUT_DIR = join(process.cwd(), "test-fixtures", "baselines");

async function main() {
  mkdirSync(OUT_DIR, { recursive: true });

  const qpTotals = await db.execute(sql`
    SELECT pqt.*, ss.id as sports_season_id, s.name as sport_name
    FROM participant_qualifying_totals pqt
    JOIN sports_seasons ss ON ss.id = pqt.sports_season_id
    JOIN sports s ON s.id = ss.sport_id
    WHERE ss.scoring_pattern = 'qualifying_points'
    ORDER BY ss.id, pqt.participant_id
  `);

  const eventResults = await db.execute(sql`
    SELECT er.*, se.sports_season_id
    FROM event_results er
    JOIN scoring_events se ON se.id = er.scoring_event_id
    JOIN sports_seasons ss ON ss.id = se.sports_season_id
    WHERE ss.scoring_pattern = 'qualifying_points'
      AND er.qualifying_points_awarded IS NOT NULL
    ORDER BY se.sports_season_id, er.scoring_event_id, er.participant_id
  `);

  const surfaceElos = await db.execute(sql`
    SELECT pse.*, ss.sport_id
    FROM participant_surface_elos pse
    JOIN sports_seasons ss ON ss.id = pse.sports_season_id
    ORDER BY ss.id, pse.participant_id
  `);

  writeFileSync(join(OUT_DIR, "qp-totals-pre-phase1.json"), JSON.stringify(qpTotals.rows, null, 2));
  writeFileSync(join(OUT_DIR, "event-results-pre-phase1.json"), JSON.stringify(eventResults.rows, null, 2));
  writeFileSync(join(OUT_DIR, "surface-elos-pre-phase1.json"), JSON.stringify(surfaceElos.rows, null, 2));

  console.log(`Wrote baselines: ${qpTotals.rows.length} QP totals, ${eventResults.rows.length} event results, ${surfaceElos.rows.length} surface elo rows.`);
}

main().then(() => process.exit(0)).catch(e => { console.error(e); process.exit(1); });
```

- [ ] **Step 2: Run against production data read replica (or local dev DB loaded from `npm run db:sync-prod`)**

Run: `npx tsx scripts/capture-baseline.ts`
Expected: three JSON files created under `test-fixtures/baselines/`; non-zero row counts for QP totals and surface elos; Masters 2026 results visible in `event-results-pre-phase1.json`.

- [ ] **Step 3: Also capture Monte Carlo simulator output baselines**

Extend `scripts/capture-baseline.ts` to, for each in-flight qualifying-points `sports_seasons` row, run the matching simulator with a **fixed random seed** and save its output. This JSON is what Phase 3 Task 6's tennis-simulator regression test reads.

Pattern:

```typescript
// Pseudocode appended to scripts/capture-baseline.ts main():
import { getSimulator } from "~/services/simulations/registry";
// ... for each ss in qualifying-points seasons:
const sim = getSimulator(ss.simulatorType!);
const output = await sim.run(ss.id, { seed: 42, iterations: 10000 });
writeFileSync(join(OUT_DIR, `sim-output-${ss.simulatorType}-${ss.id}.json`), JSON.stringify(output, null, 2));
```

Check the existing `Simulator` interface in `app/services/simulations/types.ts` for the actual method signature; adapt accordingly. If a simulator does not currently accept a `seed`, add one as a non-breaking optional param in this task — it's needed for reproducible baselines.

- [ ] **Step 4: Commit the baseline fixtures**

```bash
git add scripts/capture-baseline.ts test-fixtures/baselines/
git commit -m "chore: capture pre-rename baselines for qualifying-points data and simulator output"
```

---

### Task 1: Rename schema exports and table names in `database/schema.ts`

**Why first:** Schema is the source of truth; the whole codebase compiles against its exports. Easiest to do in one sweep.

**Files:**
- Modify: `database/schema.ts`

- [ ] **Step 1: Rename table definitions and string names**

Apply these replacements in `database/schema.ts`. The safest order: string names first (they're unambiguous), then export names (which must be done with care to avoid breaking references in relations).

Table rename block 1 — `participants` (~ lines 376-390):
```typescript
// OLD:
export const participants = pgTable("participants", {
  // ...
});
// NEW:
export const seasonParticipants = pgTable("season_participants", {
  // ...
});
```

Table rename block 2 — `participant_expected_values` (~ lines 642-672):
```typescript
// OLD:
export const participantExpectedValues = pgTable("participant_expected_values", { ... });
// NEW:
export const seasonParticipantExpectedValues = pgTable("season_participant_expected_values", { ... });
```

Table rename block 3 — `participant_qualifying_totals` (~ lines 537-550):
```typescript
// OLD:
export const participantQualifyingTotals = pgTable("participant_qualifying_totals", { ... });
// NEW:
export const seasonParticipantQualifyingTotals = pgTable("season_participant_qualifying_totals", { ... });
```

Table rename block 4 — `participant_results` (~ lines 414-428):
```typescript
// OLD:
export const participantResults = pgTable("participant_results", { ... });
// NEW:
export const seasonParticipantResults = pgTable("season_participant_results", { ... });
```

Table rename block 5 — `participant_surface_elos` (~ lines 1219-1235):
```typescript
// OLD:
export const participantSurfaceElos = pgTable("participant_surface_elos", { ... });
// NEW:
export const seasonParticipantSurfaceElos = pgTable("season_participant_surface_elos", { ... });
```

Column rename in `eventResults` table (~ lines 458-476):
```typescript
// OLD:
participantId: uuid("participant_id").notNull().references(() => participants.id, { onDelete: "cascade" }),
// NEW:
seasonParticipantId: uuid("season_participant_id").notNull().references(() => seasonParticipants.id, { onDelete: "cascade" }),
```

- [ ] **Step 2: Rename relations exports and their field references**

In `database/schema.ts`, update each `*Relations` export and every `one()/many()` call that referenced the renamed tables. Replacements needed:
- `participantsRelations` → `seasonParticipantsRelations`
- `participantExpectedValuesRelations` → `seasonParticipantExpectedValuesRelations`
- `participantQualifyingTotalsRelations` → `seasonParticipantQualifyingTotalsRelations`
- `participantResultsRelations` → `seasonParticipantResultsRelations`
- `participantSurfaceElosRelations` → `seasonParticipantSurfaceElosRelations`

Within `eventResultsRelations` (~ lines 952-961):
```typescript
// OLD:
participant: one(participants, {
  fields: [eventResults.participantId],
  references: [participants.id],
}),
// NEW:
seasonParticipant: one(seasonParticipants, {
  fields: [eventResults.seasonParticipantId],
  references: [seasonParticipants.id],
}),
```

Update every other relation `one()`/`many()` that referenced `participants`, `participantResults`, `participantQualifyingTotals`, `participantSurfaceElos`, or `participantExpectedValues` to use the new table export names.

- [ ] **Step 3: Verify schema parses**

Run: `npm run typecheck`
Expected: Will fail with many errors in model/route files that still import old names. That's fine for now — schema.ts itself compiling is the win. Confirm the errors are only in files outside `database/schema.ts`.

- [ ] **Step 4: Commit schema rename alone**

```bash
git add database/schema.ts
git commit -m "refactor(schema): rename per-window tables to season_* prefix

Renames participants, participant_expected_values, participant_qualifying_totals,
participant_results, participant_surface_elos to season_* prefixed names.
Renames event_results.participant_id to season_participant_id.
Phase 1a of canonical tournament layer migration."
```

---

### Task 2: Generate and hand-edit the Drizzle rename migration

**Why:** `drizzle-kit generate` treats renames as drop+create by default; this loses data. For safe renames, we generate with `--custom` and hand-edit, OR use `drizzle-kit generate` and answer its interactive rename prompts. Using custom is safer here because multiple renames in one migration can confuse the prompt sequence.

**Files:**
- Create: `drizzle/0087_rename_per_window_tables.sql` (filename assigned by drizzle-kit; adjust to whatever it generates)
- Create: `drizzle/meta/0087_snapshot.json` (generated)

- [ ] **Step 1: Generate a custom migration scaffold**

Run: `npm run db:generate -- --custom --name=rename_per_window_tables`
Expected: Creates a new empty `.sql` file in `drizzle/` and a paired snapshot in `drizzle/meta/`.

- [ ] **Step 2: Write the rename SQL manually**

Open the new `drizzle/XXXX_rename_per_window_tables.sql` and replace its contents with:

```sql
-- Rename per-window tables to season_* prefix
-- Part of canonical tournament layer migration (Phase 1a)

-- Drop the FK on event_results.participant_id before renaming target
ALTER TABLE "event_results" DROP CONSTRAINT IF EXISTS "event_results_participant_id_participants_id_fk";

-- Rename tables
ALTER TABLE "participants" RENAME TO "season_participants";
ALTER TABLE "participant_expected_values" RENAME TO "season_participant_expected_values";
ALTER TABLE "participant_qualifying_totals" RENAME TO "season_participant_qualifying_totals";
ALTER TABLE "participant_results" RENAME TO "season_participant_results";
ALTER TABLE "participant_surface_elos" RENAME TO "season_participant_surface_elos";

-- Rename column on event_results
ALTER TABLE "event_results" RENAME COLUMN "participant_id" TO "season_participant_id";

-- Re-add the FK against the renamed table
ALTER TABLE "event_results"
  ADD CONSTRAINT "event_results_season_participant_id_season_participants_id_fk"
  FOREIGN KEY ("season_participant_id") REFERENCES "season_participants"("id")
  ON DELETE cascade ON UPDATE no action;

-- Rename any unique indexes that embed the old table names
ALTER INDEX IF EXISTS "participant_surface_elos_unique" RENAME TO "season_participant_surface_elos_unique";
-- (Add further ALTER INDEX ... RENAME TO for any other indexes whose names embed old table names.
--  Run `\d <new_table_name>` in psql against a fresh migrate to confirm nothing lingers.)
```

**Note:** FK and index constraint names are auto-generated based on table names. After the `ALTER TABLE ... RENAME TO`, Postgres does NOT auto-rename the FK constraint on `event_results` pointing at the old name — we drop and re-create explicitly above. Run the migration against a scratch DB and inspect `\d event_results` and `\d season_participants` to catch any leftover naming.

- [ ] **Step 3: Verify snapshot is consistent**

Run: `npm run db:generate`
Expected: "No schema changes" — confirms the snapshot chain is valid. If drizzle-kit wants to generate another migration, stop and diagnose; the snapshot is out of sync with the custom SQL.

- [ ] **Step 4: Run migration on local DB**

Run: `npm run db:migrate`
Expected: New migration applied; existing data intact (verify row counts match pre-rename via `psql ... -c "SELECT count(*) FROM season_participants;"` = prior `SELECT count(*) FROM participants;`).

- [ ] **Step 5: Commit migration**

```bash
git add drizzle/
git commit -m "migration: rename per-window tables to season_* prefix"
```

---

### Task 3: Rename and update `app/models/participant.ts` → `app/models/season-participant.ts`

**Files:**
- Rename: `app/models/participant.ts` → `app/models/season-participant.ts`
- Modify: `app/models/index.ts`

- [ ] **Step 1: Git-rename the file**

```bash
git mv app/models/participant.ts app/models/season-participant.ts
```

- [ ] **Step 2: Update the file's internal symbol references**

Open `app/models/season-participant.ts`. Replace all references to renamed Drizzle exports:
- `participants` → `seasonParticipants`
- `participantResults` → `seasonParticipantResults` (if referenced)
- `participantQualifyingTotals` → `seasonParticipantQualifyingTotals` (if referenced)

Update any exported function names that embed "participant" that logically should now be "seasonParticipant" — but **only if they are window-scoped**. E.g., a function `findParticipantsForSeason` likely stays named as-is since callers in routes don't distinguish; a function `createParticipant(sportsSeasonId, data)` likely stays named. Rename only if the name would be genuinely misleading. **Default: keep exported function names to minimize route-layer churn.**

- [ ] **Step 3: Update `app/models/index.ts`**

Change:
```typescript
export * from "./participant";
```
To:
```typescript
export * from "./season-participant";
```

- [ ] **Step 4: Verify file compiles in isolation**

Run: `npx tsc --noEmit app/models/season-participant.ts` (may still reference other unrenamed files — acceptable as long as the error is about imports, not the rename itself.)

- [ ] **Step 5: Commit**

```bash
git add app/models/season-participant.ts app/models/index.ts
git commit -m "refactor: rename participant.ts model file to season-participant.ts"
```

---

### Task 4: Update all model files referencing renamed schema exports

**Files (update each to use new export names):**
- `app/models/draft-pick.ts`
- `app/models/draft-utils.ts`
- `app/models/event-result.ts`
- `app/models/group-stage-match.ts`
- `app/models/participant-result.ts`
- `app/models/qualifying-points.ts`
- `app/models/scoring-calculator.ts`
- `app/models/scoring-event.ts`
- `app/models/sports-season.ts`
- `app/models/surface-elo.ts`
- `app/models/team-score-events.ts`

- [ ] **Step 1: In each file, replace imports and references**

Replacement map for imports and schema symbol references throughout the file body:

| Old symbol | New symbol |
|---|---|
| `participants` (Drizzle table) | `seasonParticipants` |
| `participantExpectedValues` | `seasonParticipantExpectedValues` |
| `participantQualifyingTotals` | `seasonParticipantQualifyingTotals` |
| `participantResults` | `seasonParticipantResults` |
| `participantSurfaceElos` | `seasonParticipantSurfaceElos` |
| `eventResults.participantId` | `eventResults.seasonParticipantId` |
| Relation access `.participant` on an `eventResults` row | `.seasonParticipant` |

**Keep unchanged:**
- Local variable names like `participant`, `participants`, `participantId` — these are runtime identifiers used by business logic; renaming them would cascade into hundreds of lines for zero benefit. Only the *schema symbol* and *Drizzle relation field* change.
- Function signatures and param names.
- JSDoc.

**Example `draft-pick.ts` update:**

```typescript
// BEFORE
import { participants, draftPicks } from "database/schema";
const [p] = await db.select().from(participants).where(eq(participants.id, participantId));

// AFTER
import { seasonParticipants, draftPicks } from "database/schema";
const [p] = await db.select().from(seasonParticipants).where(eq(seasonParticipants.id, participantId));
//                                   ^^^^^^^^^^^^^^^^^       ^^^^^^^^^^^^^^^^^ schema symbol only
// `participantId` param name stays.
```

- [ ] **Step 2: Run typecheck after each batch of 3 files**

Run: `npm run typecheck 2>&1 | head -40`
Expected: Errors shrink with each file updated. Stop and diagnose if error count grows.

- [ ] **Step 3: Update model test files**

Files:
- `app/models/__tests__/sports-season.clone.test.ts`
- `app/models/__tests__/auto-pick.test.ts`
- `app/models/__tests__/executeAutoPick.timer.test.ts`

Same replacement rules. Run affected tests after update:

Run: `npm run test:run -- app/models/__tests__`
Expected: PASS.

- [ ] **Step 4: Commit**

```bash
git add app/models/
git commit -m "refactor(models): update model layer to use renamed schema exports"
```

---

### Task 5: Update all route files referencing renamed schema exports

**Files:**
- `app/routes/admin.sports-seasons.$id.events.$eventId.bracket.server.ts`
- `app/routes/admin.sports-seasons.$id.events.$eventId.server.ts`
- `app/routes/admin.sports-seasons.$id.events.$eventId.cs2-setup.tsx`
- `app/routes/admin.sports-seasons.$id.expected-values.server.ts`
- `app/routes/admin.sports-seasons.$id.surface-elo.tsx`
- `app/routes/admin.sports-seasons.$id.simulate.tsx`
- `app/routes/admin.sports-seasons.$id.standings.tsx`
- `app/routes/admin.sports-seasons.$id.elo-ratings.tsx`
- `app/routes/admin.sports-seasons.$id.tsx`
- `app/routes/admin.sports-seasons.$id.golf-skills.tsx`
- `app/routes/admin.sports-seasons.$id.regular-standings.tsx`
- `app/routes/admin.sports-seasons.$id.futures-odds.tsx`
- `app/routes/admin.data-sync.tsx`
- `app/routes/api/draft.force-manual-pick.ts`
- `app/routes/api/draft.make-pick.ts`
- `app/routes/api/draft.replace-pick.ts`
- `app/routes/api/seasons.$seasonId.draft.ts`
- `app/routes/leagues/$leagueId.draft-board.$seasonId.tsx`
- `app/routes/leagues/$leagueId.draft.$seasonId.tsx`
- `app/routes/leagues/$leagueId.sports-seasons.$sportsSeasonId.server.ts`

- [ ] **Step 1: Apply replacement rules (same map as Task 4) to each file**

Use find-and-replace per-file. After every ~5 files, run:

Run: `npm run typecheck 2>&1 | wc -l`
(Track error count; should decrease monotonically.)

- [ ] **Step 2: Verify route tests still pass**

Run: `npm run test:run -- app/routes`
Expected: PASS (or same-as-before count; no new failures).

- [ ] **Step 3: Commit**

```bash
git add app/routes/
git commit -m "refactor(routes): update route layer to use renamed schema exports"
```

---

### Task 6: Update simulators and services

**Files:**
- `app/services/probability-updater.ts`
- `app/services/standings-sync/index.ts`
- `app/services/simulations/registry.ts`
- `app/services/simulations/simulator-config.ts`
- `app/services/simulations/types.ts`
- `app/services/simulations/afl-simulator.ts`
- `app/services/simulations/auto-racing-simulator.ts`
- `app/services/simulations/bracket-simulator.ts`
- `app/services/simulations/cs-major-simulator.ts`
- `app/services/simulations/darts-simulator.ts`
- `app/services/simulations/golf-simulator.ts`
- `app/services/simulations/llws-simulator.ts`
- `app/services/simulations/mlb-simulator.ts`
- `app/services/simulations/nba-simulator.ts`
- `app/services/simulations/ncaa-football-simulator.ts`
- `app/services/simulations/ncaam-simulator.ts`
- `app/services/simulations/ncaaw-simulator.ts`
- `app/services/simulations/nfl-simulator.ts`
- `app/services/simulations/nhl-simulator.ts`
- `app/services/simulations/snooker-simulator.ts`
- `app/services/simulations/tennis-simulator.ts`
- `app/services/simulations/ucl-simulator.ts`
- `app/services/simulations/wnba-simulator.ts`
- `app/services/simulations/world-cup-simulator.ts`
- `app/utils/sports-data-sync.server.ts`
- `server/socket.ts`
- `server/__tests__/timer-autodraft.test.ts`

- [ ] **Step 1: Apply replacement rules**

Same map as Task 4. Simulators are largely symmetric — one simulator's pattern will reveal all; batch 5 at a time and verify with typecheck.

- [ ] **Step 2: Run simulator unit tests**

Run: `npm run test:run -- app/services/simulations/__tests__`
Expected: PASS. These tests consume Drizzle types extensively — a good regression canary.

- [ ] **Step 3: Run full typecheck**

Run: `npm run typecheck`
Expected: PASS (0 errors). Any remaining errors indicate a file missed in earlier tasks.

- [ ] **Step 4: Commit**

```bash
git add app/services/ app/utils/ server/
git commit -m "refactor(services): update simulators and services for renamed schema"
```

---

### Task 7: Full test suite + Cypress verification

**Why:** Mechanical renames are easy to get 99% right and 1% broken in a way typecheck doesn't catch — especially relation-field renames (`.participant` → `.seasonParticipant`).

- [ ] **Step 1: Run full unit test suite**

Run: `npm run test:run`
Expected: PASS. If failures, inspect each: a common miss is a relation accessor like `result.participant.name` that needs to become `result.seasonParticipant.name`.

- [ ] **Step 2: Run a key E2E flow**

Run: `npx cypress run --spec "cypress/e2e/draft-room.cy.ts"` (or equivalent flagship flow)
Expected: PASS. E2E is the final guard — it exercises real relation loading.

- [ ] **Step 3: Manual smoke in dev**

Run: `npm run dev`
Manually:
1. Load the admin dashboard for an in-flight golf sports season — verify participant list renders.
2. Load a league's draft room — verify participant cards render.
3. Open admin surface-elo page for the tennis sports season — verify Elo values load.

Fix any broken UI before committing. (The rename may have missed a relation accessor somewhere.)

- [ ] **Step 4: Final commit if any fixups were needed**

```bash
git add -A
git commit -m "refactor: fix straggler relation accessors after rename"
```

---

### Task 8: Verify baselines still match

**Why:** The entire point of Phase 1a is zero data change. Verify.

- [ ] **Step 1: Re-capture and diff**

Run:
```bash
npx tsx scripts/capture-baseline.ts --out=/tmp/post-phase1a
```
(Update the script to accept `--out` or copy the baseline JSON files from `test-fixtures/baselines/` and re-run capture manually into `/tmp/post-phase1a/`.)

Run:
```bash
diff test-fixtures/baselines/qp-totals-pre-phase1.json /tmp/post-phase1a/qp-totals-pre-phase1.json
diff test-fixtures/baselines/event-results-pre-phase1.json /tmp/post-phase1a/event-results-pre-phase1.json
diff test-fixtures/baselines/surface-elos-pre-phase1.json /tmp/post-phase1a/surface-elos-pre-phase1.json
```
Expected: All three diffs empty.

- [ ] **Step 2: Tag the branch**

```bash
git tag phase-1a-complete
```

---

### Task 9: Update documentation

**Files:**
- Modify: `docs/agents/database.md` — if it references the old table names
- Modify: `docs/agents/domain-models.md` — if it describes these tables

- [ ] **Step 1: Scan docs for old names**

Run: `grep -l "participant_qualifying_totals\|participant_expected_values\|participant_results\|participant_surface_elos\|event_results.participant_id" docs/`
Expected: list of docs to update.

- [ ] **Step 2: Update each doc to use new names**

For each file found, apply the rename map. Keep prose clear; where it helps readers, note "renamed from `X` in 2026-05".

- [ ] **Step 3: Commit**

```bash
git add docs/
git commit -m "docs: update table names in agent guides"
```

---

## Self-Review Checklist

Before marking this plan complete, verify:

- [ ] `git log --oneline phase-1a-complete` shows ~8 commits corresponding to Tasks 0–9.
- [ ] `grep -rn "from \"./participant\"" app/` returns zero results.
- [ ] `grep -rn "participantExpectedValues\|participantQualifyingTotals\|participantSurfaceElos" app/ database/ server/ scripts/` returns zero results (excluding string literals in UI labels, which are fine).
- [ ] `grep -rn "participantResults\b" app/ database/ server/` returns zero results.
- [ ] `npm run test:all` is green.
- [ ] `psql` confirms the renamed tables exist and the old names do not:
  ```
  SELECT tablename FROM pg_tables WHERE tablename LIKE '%participant%' OR tablename LIKE '%season_participant%';
  ```
  Expected: `season_participants`, `season_participant_expected_values`, `season_participant_qualifying_totals`, `season_participant_results`, `season_participant_surface_elos`. None without the `season_` prefix.

## Rollback

If Phase 1a must be undone:

1. `git revert` the commits from Tasks 1–9 (skip Task 0 baseline capture — keep fixtures).
2. Create a reverse migration that renames all five tables back and the column back, re-creates the old FK constraint.
3. Run `npm run db:migrate`.

Phase 1b must not begin until Phase 1a is shipped, green in production for at least 24 hours, and the tag `phase-1a-complete` is on `main`.
