---
title: Resolve the Schema Conformance Ratchet Failure on the New Projection Tables
type: task
status: completed
description: >-
  League master CI is red on the schema conformance ratchet because two new projection tables carry
  year rather than season_year, which blocks every session's push and any deploy. The parent table's
  year is already baselined, so the fix is a judgment call between conforming the children now and
  baselining them with the family.
base_uri: user:task/league/resolve-projection-tables-schema-ratchet-failure.md
created_at: '2026-07-30T07:08:20.328Z'
entity_id: ea6a0b58-b0d5-488d-8516-e903722b1ebe
finished_at: '2026-08-04T06:10:44.975Z'
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: High
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-08-04T06:10:44.975Z'
visibility_analyzed_at: '2026-11-05T23:50:12.818Z'
---

# Resolve the Schema Conformance Ratchet Failure on the New Projection Tables

## Problem

`mistakia/league` master CI has been RED since `c4dacc74f` (2026-07-30 05:47Z). The failing step is
**Schema conformance ratchet**, not the test suite — `yarn test` never runs, so the suite's CI state at
that commit is unknown. Locally the full suite passes (2404 passing at `818aaaed5`).

```
schema conformance ratchet -- 2 violation(s) not in the baseline:
  [season_grain] league_player_rest_of_season_projection_values.year
  [season_grain] league_player_season_projection_values.year
```

Both tables were introduced by `0b7a866e0` ("db: add league_player period projection tables and migrate
the sentinels"), the additive half of hoisting the `'0'` and `'ros'` period sentinels out of
`league_player_projection_values.week`. That commit's message states the drops, sentinel deletes and week
narrowing "follow in a companion adhoc once the sweep is deployed" — so this cluster is mid-migration.
The authoring session is no longer running.

**This blocks every session's push.** `cli/sync/sync-all.sh` defers all pushes to a repo whose main is
red, and it never clears on retry. As of 2026-07-30 there are unpushed commits from at least three
sessions sitting behind it, and no league deploy is possible while it holds.

## The judgment call

The two new tables carry `year`, inherited from the table they were split out of. That parent,
`league_player_projection_values.year`, **is already accepted baseline debt** — as are
`league_format_player_projection_values.year` and `league_format_player_projection_values_history.year`.
The ratchet flags the two new tables only because they are new, not because they are inconsistent with
their family.

So there are two defensible resolutions, and they point in opposite directions:

1. **Conform the two new tables to `season_year`.** Standards-correct in isolation. But it leaves the
   children conformed while the parent and two siblings stay on `year`, which is exactly the per-
   `(table, column)` split the league `CLAUDE.md` warns produces joins that are correct on one side and
   stale on the other. It is also a real rename cluster: 15 call sites across
   `scripts/process-projections.mjs`, `libs-server/get-players.mjs` and
   `libs-server/data-views-column-definitions/player-projected-column-definitions.mjs` — the sweep is
   already written against `year` — plus a production DDL rename, a `physical-season-columns.mjs`
   registration, and data-view golden regeneration.
2. **Add the two entries to the ratchet baseline**, deferring the conform until the whole
   `*_projection_values` family is conformed in one cluster. Consistent with the family as it stands.
   Note the ratchet's own guidance reserves `--rebaseline` for "a deliberate audit widening", which this
   is not — so taking this path means accepting new debt knowingly, and should be recorded as such.

Option 2 unblocks the fleet in minutes; option 1 is the eventual end state either way. They are not
mutually exclusive: baseline now, conform the whole family as its own task.

## Plan

- [ ] Operator/domain decision between conform-now and baseline-now
- [ ] If baseline: add both entries, record why, and open a follow-up for the family-wide conform
- [ ] If conform: DDL rename, register both tables in `libs-server/data-views/physical-season-columns.mjs`,
      sweep all 15 call sites, regenerate affected goldens, run the EXPLAIN validity gate
- [ ] Confirm the ratchet passes and master goes green
- [ ] Verify the deferred pushes flow on the next `cli/sync/sync-all.sh` cycle
- [ ] Coordinate with the pending companion adhoc from `0b7a866e0` so the two do not collide

## Notes

- Do NOT clear this with a bare `PUSH_TO_RED_MAIN=1` — that un-gates every repo in the sync run. The
  scoped form is `PUSH_TO_RED_MAIN=mistakia/league`, and it is meant for carrying the repair through.
- The ratchet is a naming gate with no runtime meaning; production is not at risk from the red itself.
  The cost is purely that the fleet cannot push or deploy.
