Skip to content

Router doesn't dispatch pre-game API exchanges (EventJoin, EventGetCoursesV2, EventSetDeckV3, EventOpenedNonAggregate) #203

Description

@timc-enthrall

Summary

Pre-game corpus sessions (sealed-entry, deck-build) show artificially low parser router coverage because the router does not currently dispatch the HTTP-style API exchanges that dominate those phases. Surfaced by the sealed-flow capture in manasight-corpus#31.

Evidence

Session Phase Routed/Total Coverage
session_2026-05-01_1657_sealed-purchase Sealed entry + pack opening 4/47 8.5%
session_2026-05-01_1715_sealed-deckbuild 40-card sealed deck submission 3/52 5.8%
session_2026-05-01_1751_sealed-matches Bo1 match play 1546/1636 94.5%

Match-phase coverage (94.5%) is healthy. Pre-game coverage drops to single digits because the relevant data is in API exchanges the router treats as Unknown rather than dispatching to event handlers.

Specific events seen but unrouted

From the sealed-purchase + sealed-deckbuild logs:

  • ==> EventJoin / <== EventJoin — the entry that produces the course, archetype choice, and currency cost (SealedToken, gems, gold)
  • ==> EventGetCoursesV2 / <== EventGetCoursesV2 — full course list including the active sealed course's CardPoolByCollation (the 6-pack pool reveal)
  • ==> EventSetDeckV3 / <== EventSetDeckV3 — sealed deck submission
  • ==> DeckUpsertDeckV3 / <== DeckUpsertDeckV3 — deck save (40-card MainDeck, format DirectGameLimited)
  • ==> EventOpenedNonAggregate (if present) — pack-opening reveal
  • EventPayEntry InventoryInfo.Changes — currency consumption (e.g., SealedToken: -1)

Today these all flow into the Unknown bucket of the smoke test report.

Why this matters

  1. Misleading corpus metrics. Coverage thresholds and ratchets misrepresent parser health because pre-game phases dilute the routed % even when the phase is fully captured.
  2. Future feature dependencies. Sealed-pool–aware features (full pool render in sealed deck-build, archetype-choice persistence, currency-spend telemetry, deck-tracker "starting deck" hints) need these events typed.
  3. Bo3 sideboard recovery. G2/G3 sideboarded-deck recovery currently leans on SubmitDeckResp from the GRE side; having the typed client-API path would reduce the parsing burden on consumers.

Proposed parser additions

(LOC budget TBD; ~50–80 each based on existing parsers/event_lifecycle.rs precedent.)

  • New parser: parsers/event_join.rs — typed EventJoin{Request,Response} with event_name, entry_currency_type, entry_currency_paid, event_choice
  • New parser: parsers/event_get_courses.rs — typed EventGetCoursesV2Response with course_id, card_pool_by_collation (Vec<CollationEntry { collation_id, card_pool: Vec }>), archetype, event_name
  • New parser: parsers/event_set_deck.rs — typed EventSetDeckV3{Request,Response} with event_name, deck_summary (name, main_deck, sideboard, format, sleeve_grp_id)
  • New parser: parsers/deck_upsert.rs — typed DeckUpsertDeckV3 with deck CRUD payload (some reuse from existing deck_collection.rs?)
  • Optional: parsers/inventory.rs extension for EventPayEntry source detection on inventory deltas

Test plan

  • Add round-trip fixture tests for each new parser using corpus snippets from manasight-corpus/session_2026-05-01_1657_sealed-purchase.log and session_2026-05-01_1715_sealed-deckbuild.log
  • Re-run smoke_test_router_real_logs against the corpus; expect routed/total to jump from 4/47 + 3/52 to >70% on both pre-game sessions
  • Smoke-baseline ratchet update once parsers land

References

  • Corpus PR: manasight-corpus#31
  • Existing parser modules for reference: src/parsers/event_lifecycle.rs, src/parsers/deck_collection.rs, src/parsers/inventory.rs

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions