Skip to content

Rename the PRINTING_TAG_* symbols: they govern CardPrintingTag, not the retired PrintingTagVote #659

Description

@WilfordGrimley

PrintingTagVote was retired by PR #615 — 0 rows, no resolver, no reader, no consumer ever built. But a family of symbols named after it still exists and governs something else entirely.

They all operate on CardPrintingTag — the printing identification vote, 167,229 rows, the whole Stage D printing channel:

  • _split_new_printing_tag_votes — signature is literally (votes_batch: list[CardPrintingTag]) -> tuple[list[CardPrintingTag], int]. A CardPrintingTag collision guard.
  • PRINTING_TAG_MIN_VOTES — the app-wide consensus threshold (read by printing_consensus, tag_consensus, artist_consensus, question_feed, consensus_recompute).
  • PRINTING_TAG_IMPLICIT_CAP — read only inside resolve_weighted_consensus.
  • PRINTING_TAG_MACHINE_WEIGHT.

This has now misled three readers in a week

  1. An orchestrator briefed a worker that these symbols governed PrintingTagVote. They do not — the grain investigation (PR Decision doc: should PrintingTagVote exist? Printing-tag vs illustration-tag grain #599) had to trace every one to its call sites to establish it.
  2. The retirement PR (Retire PrintingTagVote: the vote channel that had no resolver, no reader and no rows #615) needed an explicit "do not touch these" section in its brief, and left a RETIRED comment block in models.py naming the two load-bearing look-alikes (CardPrintingTag, CardTagVote) specifically so the next reader could not repeat the conflation.
  3. The owner, reading a design discussion on 2026-07-30: "_split_new_printing_tag_votes... didn't we scrap printing tags???"

The confusion was survivable while PrintingTagVote existed, because both readings pointed at something real. Now that it is gone, the names point at a model that does not exist, which is worse — a reader who greps for PrintingTagVote finds nothing and reasonably concludes the symbols are dead code.

This is the same class as corrections/OPS-CORR-0008, where an identity was purged when a channel was meant and 53,966 vote rows were destroyed. Similar names, different scopes, and the distinction lived only in people's heads.

Why now is the right moment

PR #585 landed constant_rename_equivalence — a CI check that proves a rename changed no behaviour. This is exactly what it was built for, and it has not yet had a real subject. Doing the rename now both removes a live hazard and exercises the guard on something that matters.

What would close this

Rename to say what they govern — CARD_PRINTING_TAG_* / _split_new_card_printing_tag_votes, or PRINTING_IDENTIFICATION_* if that reads better — verified behaviour-preserving by #585's check. Update the RETIRED comment block in models.py to stop needing to warn about the collision.

Sequencing note: hold until the monolith wiring lands. These symbols sit in vote_consensus and local_calculate_verdicts, which that work touches, and a rename mid-build would create conflicts for no benefit.

Related: #615 (the retirement), #599 (the disambiguation), #652 (recurring naming/scope traps), #585 (the equivalence check).

Metadata

Metadata

Assignees

No one assigned

    Labels

    housekeepingBranch/PR cleanup, no product change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions