The app matches game names case/punctuation/spacing-insensitively (everything non-alphanumeric is squashed, so DIRECTORS CUT ≡ Director's Cut ≡ Directors-Cut). The CI validator doesn't apply the same rule when a new profile is submitted, so two PRs adding directors-cut.json ("Directors Cut") and directors-cut-2.json ("Director's Cut") would both merge — and both would show in everyone's in-app library as separate cards for the same game, with only one of them winning the name match.
Proposed check (in scripts/validate-profile.mts or the PR workflow): normalize the incoming profile's game field the same way the app does and fail validation if it collides with any existing profiles/library/*.json entry's normalized game — unless the file being validated is that entry (edits to an existing profile must still pass).
Notes:
- The README (as of 7476d28) documents the convention: official store spelling, matching is normalization-insensitive, editions are distinct games.
- native.json is maintainer-curated and out of scope; this is about contributor profile PRs.
- Multiple variants for the same game, if ever wanted (e.g. "soft" vs "heavy" feels), would need an explicit mechanism rather than name collisions — rejecting collisions now keeps that door consciously closed instead of accidentally open.
The app matches game names case/punctuation/spacing-insensitively (everything non-alphanumeric is squashed, so
DIRECTORS CUT≡Director's Cut≡Directors-Cut). The CI validator doesn't apply the same rule when a new profile is submitted, so two PRs addingdirectors-cut.json("Directors Cut") anddirectors-cut-2.json("Director's Cut") would both merge — and both would show in everyone's in-app library as separate cards for the same game, with only one of them winning the name match.Proposed check (in
scripts/validate-profile.mtsor the PR workflow): normalize the incoming profile'sgamefield the same way the app does and fail validation if it collides with any existingprofiles/library/*.jsonentry's normalizedgame— unless the file being validated is that entry (edits to an existing profile must still pass).Notes: