Architecture Overview
The repository is organized around transformations from immutable source documents to progressively stronger basketball semantics.
Boundary rule
Every layer strengthens basketball meaning without obscuring the source evidence needed to reproduce or challenge that interpretation.
Boundaries
Source access
nba_lineup_model.ingest owns direct game-feed access.
nba_lineup_model.season.schedule owns the season-addressable schedule client.
nba_lineup_model.players owns bulk historical player identity and season bio
access. All preserve raw response bytes before source-specific normalization.
Canonical events
nba_lineup_model.events converts source actions into ordered, typed events.
This layer standardizes clocks, score deltas, identifiers, and event metadata
while preserving source values that later algorithms may need.
Lineup reconstruction
nba_lineup_model.lineups combines boxscore starters with play-by-play
substitutions. It produces a lineup before and after every event, plus stable
lineup stints.
Possession reconstruction
nba_lineup_model.possessions applies basketball transition rules to canonical
events. It uses the source possession team as a strong signal while allowing
explicit outcomes such as turnovers and defensive rebounds to override it.
Auditing
nba_lineup_model.audit runs the same in-memory reconstruction pipeline over a
versioned game manifest. It records exact invariant failures separately from
diagnostic warnings.
Orchestration
nba_lineup_model.flows contains thin Prefect wrappers around project-owned
selection, fetching, validation, and storage functions. Prefect supplies local
concurrency, retries, and observable task state. Raw JSON and Parquet manifests
remain authoritative so orchestration can be changed without changing the data
contracts. Season compaction uses one task per table and season-type partition;
the underlying compactor remains independently callable and testable.
Modeling
nba_lineup_model.modeling owns modeling-table construction, chronological
splits, run manifests, and artifact publication. nba_lineup_model.models
owns estimators and sparse signed encodings; nba_lineup_model.evaluation
owns weighted and game-aggregated metrics.
The first boundary is a regular-season one-number RAPM benchmark. It compares an intercept-only mean, schedule-adjusted team strengths, and signed player ridge coefficients before any offensive/defensive split, player prior, or nonlinear interaction is introduced.
Core orchestration
reconstruct_game_payloads is the shared in-memory pipeline. The season
processor reconstructs once, evaluates the audit invariants, and only then
persists the six game tables. The single-game builder persists directly, while
the audit runner evaluates the same objects without writing every intermediate
table.
This separation prevents the validation path from drifting away from production processing.
Failure policy
- Invalid source structure raises an exception.
- Impossible lineup transitions raise a reconstruction exception.
- Recoverable feed anomalies become structured warning or error records.
- Audit execution isolates failures by game so one bad endpoint does not abort a multi-season run.
- Season fetching retries only transient network and source failures, then records every terminal game outcome.
- Season processing isolates deterministic reconstruction and quality failures by game and checkpoints terminal metadata through a single writer.
- Season compaction rejects missing or mismatched build and quality provenance, then atomically publishes only row-conserving partitions.
- Exact score and duration failures make an audit game fail.
- Approximate boxscore possession estimates remain diagnostics.