---
title: Harden the rename-alias-residue gate oracle
type: task
status: completed
description: >-
  Fix nine defects an adversarial review found in db/gates/check-rename-alias-residue.mjs, three of
  which change its verdict: SPLIT PRODUCERS masked as UNIFORM for wholesale producers, the
  imperative-builder alias-back missed entirely, and a registry path filter excluding 21 real query
  emitters.
base_uri: user:task/league/harden-rename-alias-residue-gate-oracle.md
created_at: '2026-08-06T16:31:54.561Z'
entity_id: de5f5778-7301-4d37-b218-e2ead137a1b3
finished_at: '2026-08-06T17:38:49.718Z'
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: High
public_read: true
started_at: '2026-08-06T16:34:38.144Z'
tags:
  - user:tag/league-xo-football.md
  - ███████████████-██████-███████████
  - user:tag/software-task.md
updated_at: '2026-08-06T17:38:49.718Z'
visibility_analyzed_at: '2026-11-05T23:49:36.001Z'
---

## Context

`db/gates/check-rename-alias-residue.mjs` shipped 2026-08-06 as the third rename
gate, anchored on the alias-back site. An adversarial review the same day
falsified its oracle in three independent ways and found six smaller defects.
The gate is genuinely useful — it caught the `nfl_plays` residue in `20e4a31f6`
and its stale-adjudication rule survived a wholesale-blinding mutation — but its
verdict was not trustworthy in the shapes below.

**All nine are fixed.** The sections below are the brief as written, kept
because each states the falsification that produced a negative-control case;
see Outcome for what the repair changed.

Findings are recorded as observations on
[[user:task/league/collapse-column-alias-layer-and-gate-rename-residue.md]].

## The three that changed the verdict

1. **SPLIT PRODUCERS is reported as UNIFORM when the bare producer projects
   wholesale.** `collect_bare_projections` (`db/gates/check-rename-alias-residue.mjs:414`)
   matches only qualified `'table.column'` literals via `QUALIFIED_BARE_RE`
   (`:362`). A `select('*')` producer — the exact shape league `CLAUDE.md`
   documents as gate 2's silent defect — and an unqualified bare projection both
   contribute nothing to `bare_by_pair`, so the finding is classed UNIFORM
   ("correct today") with an empty `bare_producers` list. The alias side reads
   both anchor forms; the bare side reads one.

2. **The imperative knex builder is missed entirely.** `const query = db('widgets');
   query.select('widget_salary as salary')` reports nothing: `statement_span_at`
   ends at the `db()` chain, so the unqualified alias resolves to no table and is
   dropped by `run_scan` (`:535`). The declared blind spot covers only a FROM
   target that is not a `db('<table>')` literal, not a chain broken across
   statements.

3. **`REGISTRY_PATH_MARKERS` over-excludes.** `'data-view'` (`:170`) is a
   substring match over the whole relative path, excluding 141 files, 21 of them
   real `db('<table>')` emitters — `api/routes/data-views.mjs`, all of
   `libs-server/data-views/rate-type/`, and two scripts caught on filename alone.
   Live instance: `libs-server/data-views/add-defensive-play-by-play-with-statement.mjs:72-73`
   returns `'season_year as year'` / `'season_type as seas_type'`, genuine
   `nfl_plays` rename alias-backs, invisible twice over.

## The six smaller ones

4. `collect_alias_sites` tokenizes COMMENTS — `scripts/process-projections-for-league-format.mjs:113,205`
   are prose. Same trap `CLAUDE.md` records blinding `check-saved-view-param-coverage`.
   A commented-out `db('<table>')` can also mint a phantom statement span.
5. Negative control cases 5 and 6 assert only that alias literals exist, and their
   denominator counts comment prose (`save as new`, `bounded as designed`), so they
   can stay green over an extractor that stopped matching real code.
6. `:1063` runs `main()` bare at module scope, so importing the four exported
   functions runs the whole gate and sets `process.exitCode=1`. A harness or spec
   cannot import it cleanly. Note the header's reasoning for calling `main()` bare
   (`is_main` compares `argv[1]` verbatim) is correct and must be preserved — solve
   it without reintroducing the `is_main` guard.
7. Run without `--base`, the default `origin/master` yields zero lost columns and
   all 15 adjudications stale — a guaranteed exit 1.
8. `parse_schema`'s `\n);` terminator does not match `)\nPARTITION BY RANGE(...);`,
   so 6 partitioned parents swallow their first partition child's body and 6 tables
   are absent from the parsed map (`nfl_plays_current_week`,
   `historical_injury_index_2009`, `nfl_snaps_year_2000`, `player_gamelogs_default`,
   `projections_history_default`, `projections_index_default`). Benign today because
   children carry identical columns; the failure direction is a silent miss.
9. The `!source.includes(' as ')` fast path (`:523`) is case-sensitive while the
   alias regexes are `/i`, so a file whose only alias literals use `AS` is skipped.
   3 in the corpus, all identity aliases in an already-excluded path — latent.

## Plan

- [x] Reproduce every finding before changing anything, with a synthetic
      `run_scan` and an injected `read_file`. Eleven cases went red at
      `23269028b`; the five that could not (the over-fire guards) assert
      behaviour that did not exist yet.
- [x] Fix 1 and 2. The bare side now reads the three shapes the alias side
      reads — qualified, unqualified, wholesale `'*'` — and a builder binding
      (`const query = db('t')`) carries its table onto later `query.<method>()`
      calls.
- [x] Fix 3 by dropping the `data-view` marker. It was never what removed the
      load-bearing `player-adp-column-definitions.mjs:107` exclusion (that path
      contains `column-definitions` too), so `column-definitions` alone is the
      whole filter and 13 real emitters return to the scan.
- [x] Fix 4-9: comments stripped before extraction on the alias, statement-span
      and key-read paths; denominator cases rebuilt; `main()` guarded by a
      realpath comparison rather than `is_main`; `--base` required; partition
      terminator widened; fast path made case-insensitive.
- [x] Negative control extended from 12 cases to 23, covering every fix
      including the wildcard case and both over-fire directions.
- [x] `yarn check:cluster --base 62ca45544` green (12 of 12), full suite green
      at 3314 passing in an isolated database, eslint and prettier clean.
- [x] Rewrite the CLAUDE.md distrust caveat a sibling added in `e779a313b`,
      in the same commit, so it does not outlive the defects it describes.

## Outcome

The gate's verdict changed on the real corpus in the predicted direction and
nowhere else. Same 15 findings, all still adjudicated, exit 0 — but SIX moved
from ORPHANED ALIAS to SPLIT PRODUCERS, naming four bare producers no run had
ever printed. Each was opened: all four read the PHYSICAL name, so none is a
live defect, and they are the divergent-vocabulary surface the tracked
`rosters_players` migration has to sweep.

Its named acceptance test at `782b78907^` is strictly stronger: 33 findings
against the previous 18, still reporting `transactions.player_salary as value`
at `libs-server/get-roster.mjs:52` as SPLIT PRODUCERS and still naming
`get-league-rosters-from-database.mjs:51` — now alongside eight further bare
producers, three of them wholesale.

Lost columns rose 222 to 243 across 66 to 67 tables (finding 8's six partitioned
parents), and unresolvable unqualified aliases fell 76 to 65 (the builder walk).

One thing the fix deliberately does NOT close: the `add-defensive-play-by-play-with-statement.mjs:72-73`
alias-backs the brief cites are still unreported. Removing the path exclusion
returned that FILE to the scan; it did not make those SITES resolvable, because
they are strings returned from a helper rather than literals inside a
`db('<table>')` statement. Recorded in the header's blind spots and in CLAUDE.md
rather than papered over.

## Constraints

- Do NOT touch [[user:task/league/migrate-roster-row-position-and-roster-id-to-physical-names.md]].
- Do not deploy. This is gate tooling; it ships by commit, not by deploy.
- Do not `--rebaseline` anything.
- No GitHub issues or PRs.
