Skip to content

fix(statistics): F8 classification reads enveloped mission_name (was excluding all replays) - #14

Merged
Afgan0r merged 2 commits into
masterfrom
fix/f8-mission-name-envelope
Jun 14, 2026
Merged

Afgan0r merged 2 commits into
masterfrom
fix/f8-mission-name-envelope

Conversation

@Afgan0r

@Afgan0r Afgan0r commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Critical F8 fix

On real data, F8 game-type classification excluded every replay → replays.game_type NULL for all 23,556, all aggregates empty (parity-driver confirmed against the live DB after deploying #12).

Root cause: extractMissionName read replay[key] only when typeof === "string", and the candidate keys lacked the real snake_case mission_name. In the parser artifact the field is replay.mission_name wrapped in the present/value envelope {"state":"present","value":"mace@…"} (an object, not a string). So extraction returned null → classifyGameType returned null (excluded) for all.

Fix: read mission_name first (+ world_name/map_name) and unwrap the {state:"present",value} envelope (local unwrapMissionField, mirrors the existing presentValue helper; classifier stays dependency-free; plain strings still accepted). Classification spec otherwise unchanged.

Why the green tests missed it: the unit test fed a plain-string missionName, never the enveloped artifact shape. Now: unit tests add enveloped + {state:"absent"} cases (fail against old code, pass against fix); the real-pg seeds were converted to the faithful enveloped mission_name shape so the harness exercises the production extraction path end-to-end.

pnpm verify green: 807 tests, 100% coverage, OpenAPI contract diff empty.

Follow-up (not in this PR)

public-stats/replay-mapper.ts extractMapName has the identical envelope bug (the public replay map label is also empty on live data). Display-only, not parity-blocking — flagged for a separate fix.

🤖 Generated with Claude Code

Afgan0r and others added 2 commits June 14, 2026 19:12
extractMissionName read replay[key] only when typeof === 'string' and the
candidate keys lacked the real snake_case 'mission_name'. In the parser artifact
the field is at replay.mission_name wrapped in the present/value envelope
({state:'present',value:'mace@…'}), so classification returned null (excluded)
for every replay → game_type NULL for all 23556 → empty aggregates on real data.

Now reads mission_name (first) + world_name/map_name and unwraps the
{state:'present',value} envelope (local unwrapMissionField, mirrors presentValue),
still accepting plain strings. Unit tests add enveloped + absent cases (fail on
old, pass on new); real-pg seeds use the faithful enveloped mission_name shape so
the harness exercises the production extraction path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Afgan0r
Afgan0r merged commit 87e615e into master Jun 14, 2026
3 checks passed
@Afgan0r
Afgan0r deleted the fix/f8-mission-name-envelope branch June 14, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant