---
title: Prove absence by enumeration, not by probing a guessed name
type: task
status: completed
description: >-
  Close the failure shape that produced at least seven wrong readings across three league lanes on
  2026-09-16: searching for an identifier spelled from memory and reading the empty result as proof
  the thing does not exist.
base_uri: user:task/prove-absence-by-enumeration.md
created_at: '2026-09-16T18:19:37.440Z'
entity_id: 858361f3-5abe-45fd-b288-0d9be497ba11
finished_at: '2026-09-16T18:27:57.316Z'
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: High
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-09-16T21:05:26.812Z'
visibility_analyzed_at: '2026-11-05T23:50:40.346Z'
---

A session asks "does constant X exist?", greps for `X`, gets nothing, and records that X is missing. The grep was correct, the corpus was correct, and the answer was wrong — because `X` was never the real spelling. No control at the pattern level can catch this, which is why it survived several that were run in good faith.

On 2026-09-16 this produced at least seven false claims across three concurrent league lanes in a single afternoon, each one written into shipped code or a task document as a measured finding.

## The evidence

All from the betting-market feed chain, same day.

- The FanDuel lane reported four missing shared constants — `GAME_PLAYER_SACKS`, `GAME_PLAYER_TACKLES`, `GAME_PLAYER_ASSISTS`, `GAME_PLAYER_DEFENSIVE_INTERCEPTIONS`. All four names are fictional. Three exist under different spellings (`GAME_PLAYER_DEFENSE_SACKS`, `GAME_PLAYER_SOLO_TACKLES`, `GAME_PLAYER_TACKLE_ASSISTS`) and the fourth exists only as an ALT (`GAME_PLAYER_ALT_DEFENSE_INTERCEPTIONS`). It is `DEFENSE`, never `DEFENSIVE`, on every one.
- A second session repeated the claim after running a control, then on audit found three more of its own: `SEASON_PLAYER_LEADER_SACKS`, `_INTERCEPTIONS` and `_RECEPTIONS` all exist and had been named as absent, and the 3+ and 4+ touchdown rungs had been parked as "above the highest rung that exists" hours after their constants were coined.
- The DraftKings lane reported two further wrong readings the same day from adjacent shapes — a truncating regex, and a query whose two booleans were both false for an unconsidered reason.

**The reassuring part is what makes it dangerous.** Every one of these entries landed in a surface whose whole value is that it carries a REASON — a declared-exotic allow-list entry, a parked finding, a "deliberately null" task section. A one-line reason per entry is what turns an absence into an assertion. A false reason inverts that: it reads as decided, so nobody re-examines it, and the real constant sits unused indefinitely.

## Why the existing controls did not fire

`guideline/silent-search-failures.md` already carries the closest section, "A control that proves the SUBJECT exists does not prove the PATTERN can fire" (line 201). That one covers a pattern that cannot match because of regex mechanics. This is a third variant and the guideline does not yet name it:

- The pattern mechanics were fine.
- The corpus was the right file.
- The control was run, on a token genuinely present, and it passed.

The control proved the search MECHANISM worked. It could not prove the searched-for token was spelled the way the searcher guessed, because the searcher's spelling is the one thing the control does not test. A control on the mechanism is not a control on the predicate.

## The fix, which two lanes converged on independently

Invert the question. Do not ask "does `X` exist" against a name you recalled; ask "what exists" and read the answer. Enumerate the authoritative list once — the constants export, the schema's column list, the registry's check ids — then search WITHIN that enumeration, and validate the enumeration itself against known-positive controls. The enumeration is cheap, it is usually one command, and it answers the question you actually had rather than the one your spelling implied.

## Plan

- [x] Add the new section to `guideline/silent-search-failures.md`, sited beside line 201 since it is the third variant of that control failure. Name the shape, carry the seven-claim evidence, and state the enumerate-then-search rule with a worked example against `libs-shared/bookmaker-constants.mjs`
- [x] Decide whether the rule generalizes past identifiers to any closed vocabulary — schema columns, registry check ids, market types, tab slugs — and say so explicitly rather than leaving it implied by one example. It does; the section says so, with the enumerability of the set as the discriminator
- [x] Sweep the league allow-list reason comments for surviving false reasons. The two audits so far were each triggered by an external correction rather than by a check, so the population is unbounded — `is_recognized_*` across all five books, plus `parked.json` entries and any "no constant exists" comment. Enumerate the constants once and grep that list against every named absence
- [x] Decide whether this warrants a gate. Recommendation: not a blocking one. See the `[recommendation]` observations
- [x] Confirm the FanDuel and DraftKings lanes' corrected entries actually landed, rather than trusting the reports

## Sweep result

The scanner is `cli/monitoring/check-false-absence-reasons.mjs`, run daily by
[[██████████████-████████████████████-█████-███████-██████████]]. The scratch directory the sweep was
developed in has been retired — everything in it was superseded by that script and its baseline.

The enumeration comes from IMPORTING `bookmaker-constants.mjs` — the file composes exports by spread
and wraps long entries onto a second line, so a `NAME: 'NAME'` grep of its source misses real members.

Controlled in both directions before anything was read from it. The enumeration was required to
contain the seven real spellings from the evidence and to exclude the four invented ones. The
scanner was run against a corpus carrying four reintroduced false reasons across all three surface
shapes (comment, JSON reason field, prose) and reported all four, plus a true-negative it correctly
did not report. That control now ships as the script's `--self-test`, which runs on every production
invocation and was verified to go red on a rotted marker list.

**The one live false reason is closed.** `libs-server/pinnacle.mjs` asserted
`GAME_PLAYER_THREE_PLUS_TOUCHDOWNS does not exist` while it did. It went false by ageing rather than
by an invented name — honest at 10:42, falsified by the coining at 12:46 the same day. Reported to
the Pinnacle lane, which corrected it in league `0afebe8a6` and kept the map short on a MEASUREMENT
(both readable Pinnacle populations carry only the 0.5 rung) rather than on the false claim.

The remaining candidates are co-occurrence — the absence claim is about a different subject than the
constant named in the same sentence, which is how a correct contrastive reason reads. They are
adjudicated in `cli/monitoring/check-false-absence-reasons.baseline.json`, each with a one-line
reason. One lower-severity item was fixed outright: `test/libs-server.prizepicks.spec.mjs` opened
with a sentence its own paragraph corrected (league `b88341b15`).

Do not cite a constant count from this document. Re-enumerate — the export grew from 340 to 359
during the session that wrote this.

Re-enumerate before citing any of this. A sibling lane is coining period-scoped constants today.

## Verification bar

The guideline change is prose and needs no gate, but the sweep does: a scan reporting zero surviving false reasons is exactly the reading this task exists to distrust. Run it against a known-positive control — reintroduce one of the corrected entries in a scratch copy and require the scan to report it — before recording any clean result.

## Out of scope

Do not edit any book's market-type mappings or coin any constant. This task reports false REASONS; acting on one is the owning book lane's call. Book lanes were live and concurrent on 2026-09-16 and own their own directories.
