sports-impact-core
v0.79.0
Published
Deterministic sports roster-impact simulation core for injury, trade, and draft analysis.
Readme
sports-impact-core
Reusable TypeScript library and CLI for sports roster-impact simulations.
MVP support:
- normalized NBA/WNBA basketball baseline ingestion from CSV/JSON rows
- NBA injury-impact scenarios
- NBA trade-impact scenarios with outgoing/incoming player deltas
- shared player availability constraints for simulations and lineup matchup ranking
- WNBA roster-impact scenarios from approved roster/minutes exports or BALLDONTLIE WNBA API pulls using
league: "WNBA",sport: "wnba", 40-minute regulation assumptions, header templates, andimport-baseline-dataset --validate-only - deterministic NBA-like trade-feasibility guardrails for salary matching, luxury-tax/apron thresholds, hard caps, salary aggregation, roster-count checks, and optional required salary/payroll/apron source-license provenance
- deterministic minutes redistribution and retained-rotation compression
- player stat/fantasy deltas
- transparent team rating heuristic
- markdown report rendering
- historical absence fixture generation
- fixture-backed injury and trade backtest metrics
- multi-suite injury and trade calibration reports
- deterministic trade model parameter tuning and profile comparison
- trade fixture quality validation, case-level provenance, historical fixture-pack manifests, input-hash evidence, reproducibility and deterministic rerun verification with drift grouping, configurable regression gates, maturity-aware benchmarks, benchmark comparisons, train/validation/test splitting, readiness gates, holdout scoring, unified audits, and model diagnostics
- deterministic analysis of precomputed NBA game-footage tracking/detection outputs (player/ball tracks, quality audit warnings, possession segments/estimates, and court-zone summaries) without raw video inference
- deterministic external handoff validation reports for schema/version, metadata, pixel-scale, raw-video boundary, coordinate completeness, detection completeness, and confidence checks
- deterministic external handoff normalization into
sports-impact-core/game-footage-analysis-input/v1, including directcourt_feetcoordinates and explicit-scale pixel/bbox-center conversion - downstream external handoff fixture-gate CI adoption plans, adoption verification, and adoption registries that generate/verify deterministic GitHub Actions YAML for both valid fixture-pack gates and invalid-fixture gates across projects
- deterministic SVG/Markdown court visualizations for selected precomputed frames and player/ball track paths
- dependency-free normalization for precomputed Roboflow/YOLO-style JSON, CSV detection rows, ByteTrack/Supervision-style tracking JSON, and validated external handoff JSON into the game-footage input schema
- game-footage fixture-pack manifests with adapter source files including external handoffs, input hashes, validation evidence, deterministic visualization artifact hashes, reusable baseline lifecycle policy scaffolds/conformance reports/run audits/CI adoption generators/adoption verifiers/trend reports/CI-hardened trend gates/trend registries/dashboard aggregation/dashboard adoption verification/dashboard adoption registries, materialized/verifiable/comparable/gated/baseline-checked/promotable/promotion-verifiable/suite-checkable/ledger-verifiable/ledger-registry-verifiable/ledger-registry-gated/ledger-registry-comparable/ledger-registry-comparison-gated SVG/Markdown artifact bundles, golden expectation checks, and deterministic rerun verification
- file-backed run bundle summaries with
run-manifest.jsonandEXECUTIVE_SUMMARY.md - manifest-driven scenario bundles that run existing trade, draft, and lineup steps before summarizing
- coaches lineup matchup ranking from precomputed game-footage reports, candidate lineups, and availability constraints
Trade feasibility can require financial provenance via embedded financialProvenance.sources or CLI/API ingestion of salary ledger, team payroll, and apron-threshold CSV/JSON fixtures with source, license, retrieval timestamp, and rule-profile version/effective-season metadata.
The repository includes an optional BALLDONTLIE-primary internal demo importer, npm run generate:balldontlie-nba-demo-pack -- --out-dir /tmp/sports-impact-balldontlie-nba-demo-pack --team-abbreviations LAL,BKN --contract-season 2025 --stats-season 2024 --effective-season 2025-26 --include-player-averages (or --all-current-teams for all 30 current NBA teams). It reads BALLDONTLIE_API_KEY from the environment, never writes the key to artifacts, and emits salary-ledger, contract-detail, derived known-payroll, NBA PR/NBPA apron-threshold, optional player-baseline, provenance, source-fit, summary, and hash files. BALLDONTLIE is third-party aggregated/best-effort data and not official league data; generated payroll is not official NBA cap payroll.
For WNBA roster-impact baselines, use BALLDONTLIE_API_KEY=... sports-impact import-balldontlie-wnba-baseline --season 2026 --team-abbreviations NY,CON --out-dir runs/wnba-balldontlie. It fetches WNBA teams, active players, season averages, and advanced stats; writes teams.csv, players.csv, baseline-dataset.json, and summary.json; and never writes the API key. BALLDONTLIE WNBA stats endpoints require the appropriate WNBA/ALL-ACCESS tier. Generated WNBA data is third-party aggregated best-effort data, not official league data or roster advice.
Use npm run summarize:run -- --run-dir runs/<trade-draft-or-lineup-run> or exported summarizeRun to index run artifacts and write run-manifest.json plus EXECUTIVE_SUMMARY.md. Use npm run run:scenario-bundle -- --manifest path/to/scenario-bundle.json or exported runScenarioBundleFromFile when one manifest should run supported trade/draft/lineup steps first, then summarize the run. Summaries are deterministic decision-support evidence for trade, draft, and coaches lineup artifacts, not recommendations.
Use rankCoachesLineupMatchupsFromFiles with a precomputed game-footage analysis report, modeled players, opponent lineup, candidate lineups, and optional availability constraints to write coaches lineup matchup JSON/Markdown artifacts. This is coaching decision support only, not an authoritative coaching decision.
Use npm run generate:balldontlie-demo-trade -- --pack-dir /tmp/sports-impact-balldontlie-nba-demo-pack --out-dir /tmp/sports-impact-balldontlie-demo-trade --target-team LAL --partner-team BKN --season 2025-26 to turn an existing BALLDONTLIE demo pack into ready-to-run trade-feasibility.json and trade-simulation-input.json files with embedded financial provenance and internal-demo caveats. Add --outgoing-player <playerId-or-exact-name> and --incoming-player <playerId-or-exact-name> to override deterministic picks. The generated trade is a deterministic demo scenario, not an official transaction recommendation or CBA ruling.
Use npm run optimize:balldontlie-demo-trades -- --pack-dir /tmp/sports-impact-balldontlie-nba-demo-pack --out-dir /tmp/sports-impact-balldontlie-trade-search --target-team LAL --partner-teams BKN,ATL,DAL --max-outgoing 8 --max-incoming-per-team 8 --trade-families 1-for-1,1-for-2,2-for-1,2-for-2 --max-candidate-count 500 --top 10 --objective-preset production_preserving --salary-relief-weight 1 --fantasy-delta-weight 1 --net-rating-weight 10 --protect-top-n-minutes 2 --max-outgoing-salary 20000000 --min-fantasy-delta -12 --exclude-player "LeBron James" to run multistep deterministic scenario search over many candidate single- or multi-player trades. Presets include salary_relief, production_preserving, apron_escape, bench_upgrade, and star_protected; explicit weights/constraints override preset defaults. If --trade-families is omitted, the optimizer preserves the original 1-for-1 search behavior. The optimizer enumerates candidates, applies constraints and aggregate outgoing-salary caps, runs feasibility and impact simulation for each remaining candidate, ranks by explicit objective weights, explains top-candidate scores, and emits JSON/Markdown plus top-candidate runnable artifacts. Use npm run evaluate:balldontlie-multi-team-demo-trade -- --pack-dir /tmp/sports-impact-balldontlie-nba-demo-pack --out-dir /tmp/sports-impact-balldontlie-multi-team-trade --trade-legs-path /tmp/sports-impact-balldontlie-multi-team-legs.json to evaluate an explicit multi-team transaction from every participating team's perspective; the legs file is a JSON array of { fromTeam, toTeam, player } objects. The shared implementations are exported as optimizeBalldontlieDemoTrades and evaluateBalldontlieMultiTeamDemoTrade for package and Pi/autocontext integrations. These workflows are internal demo/source-fit optimization/evaluation, not official recommendations.
Use npm run optimize:balldontlie-three-team-demo-trades -- --pack-dir /tmp/sports-impact-balldontlie-nba-demo-pack --out-dir /tmp/sports-impact-balldontlie-three-team-trade-search --target-team LAL --partner-teams BKN,ATL,DAL --max-players-per-team 4 --max-candidate-count 250 --top 10 --objective-preset balanced_multi_team --three-team-trade-families 1-for-1-for-1,2-for-1-for-1 --protect-top-n-minutes 3 --max-target-outgoing-salary 30000000 --min-target-fantasy-delta -15 --min-all-team-fantasy-delta 0 --min-team-fantasy-delta -8 --max-team-net-salary-increase 5000000 --max-team-incoming-salary 30000000 --require-no-team-fantasy-loss-below -12 --require-all-teams-feasible true --dedupe-by-target-swap true --max-candidates-per-target-outgoing-player 3 --max-candidates-per-target-incoming-player 3 --exclude-player "LeBron James" --exclude-player "Luka Doncic" --generate-candidate-comparison --candidate-comparison-retained-limit 5 --candidate-comparison-alternatives 3 to generate deterministic bounded three-team cycles (target → partner A → partner B → target), including optional multi-player leg families (1-for-1-for-1, 2-for-1-for-1, 1-for-2-for-1, 1-for-1-for-2), protect top-minute players from every participating team's outgoing pool, evaluate each participating team, enforce target/all-team and partner-team fantasy/salary guardrails, de-duplicate near-identical target swaps, and rank candidates with transparent target/all-team objective weights. The run also writes three-team-guardrail-audit.json / .md with protected players by team, excluded-player matches, filter reason counts, fairness filter details, and a pass/fail verification of returned candidates; sourceFit confidence summaries; and per-top-candidate candidate-explanation.json / .md artifacts explaining survival, guardrail/diversity impact, source-fit warnings, and nearby filtered alternatives grouped by failure reason with closest guardrail-boundary details; and filtered-candidates/ near-miss artifacts (index.json, filtered-candidates.md, and by-reason/*.json) with failed guardrails, actual/limit/gap-to-pass boundaries, affected teams, phases, and trade legs. Presets include salary_relief, production_preserving, apron_escape, star_protected, and balanced_multi_team; explicit weights/constraints/diversity controls override preset defaults. balanced_multi_team defaults to minAllTeamFantasyDelta: 0, apron_escape defaults to minTargetSalaryReliefUsd: 5000000, and star_protected defaults to top-minute protection plus target-swap diversity caps; override the new floors with --min-all-team-fantasy-delta and --min-target-salary-relief. The shared implementation is exported as optimizeBalldontlieThreeTeamDemoTrades and exposed through Pi as optimize_balldontlie_three_team_demo_trades; guardrail and source-fit/explanation gates are exposed through Pi as gate_balldontlie_three_team_guardrail_audit and gate_balldontlie_three_team_source_fit_explanations, and reusable source-fit/explanation gates are exported as gateBalldontlieThreeTeamSourceFitExplanations. Use npm run inspect:balldontlie-three-team-filtered-candidates -- --summary /tmp/sports-impact-balldontlie-three-team-trade-search/summary.json --out /tmp/sports-impact-balldontlie-three-team-trade-search/filtered-candidates/filtered-candidate-inspection.json --report /tmp/sports-impact-balldontlie-three-team-trade-search/filtered-candidates/filtered-candidate-inspection.md --reason maxTeamNetSalaryIncrease --team BKN --limit 10 or Pi action inspect_balldontlie_three_team_filtered_candidates to summarize top failure reasons, closest near misses, and by-team guardrail gaps without hand-reading JSON. Add --generate-candidate-comparison to the optimizer, or set Pi generateCandidateComparison: true, to write retained-vs-filtered candidate-comparison.json / .md artifacts during search without changing ranking. Use npm run compare:balldontlie-three-team-candidates -- --summary /tmp/sports-impact-balldontlie-three-team-trade-search/summary.json --out /tmp/sports-impact-balldontlie-three-team-trade-search/candidate-comparison.json --report /tmp/sports-impact-balldontlie-three-team-trade-search/candidate-comparison.md --reason maxTeamNetSalaryIncrease --alternatives 3 --retained-limit 5 or Pi action compare_balldontlie_three_team_candidates to pair retained top candidates with nearest filtered alternatives by target-swap similarity and guardrail gap. Use npm run gate:balldontlie-three-team-candidate-comparison -- --comparison /tmp/sports-impact-balldontlie-three-team-trade-search/candidate-comparison.json --comparison-report /tmp/sports-impact-balldontlie-three-team-trade-search/candidate-comparison.md --out /tmp/sports-impact-balldontlie-three-team-candidate-comparison-gate.json --report /tmp/sports-impact-balldontlie-three-team-candidate-comparison-gate.md or Pi action gate_balldontlie_three_team_candidate_comparison to fail on comparison schema/content drift. Output remains source-fit scenario search, not a recommendation or CBA ruling. Use npm run gate:balldontlie-three-team-guardrail-audit -- --audit /tmp/sports-impact-balldontlie-three-team-trade-search/three-team-guardrail-audit.json --out /tmp/sports-impact-balldontlie-three-team-guardrail-gate.json --report /tmp/sports-impact-balldontlie-three-team-guardrail-gate.md in CI to fail on non-pass returned-candidate verification, positive violations, or missing required constraint/filter-count audit fields. Use npm run gate:balldontlie-three-team-source-fit-explanations -- --summary /tmp/sports-impact-balldontlie-three-team-trade-search/summary.json --out /tmp/sports-impact-balldontlie-three-team-source-fit-explanation-gate.json --report /tmp/sports-impact-balldontlie-three-team-source-fit-explanation-gate.md --minimum-confidence 0 to fail when retained top candidates lose sourceFit fields, candidate-explanation JSON/Markdown artifacts drift/disappear, or filtered-candidate near-miss artifacts disappear/schema-drift. CI/release preflight also runs npm run gate:balldontlie-three-team-guardrail-audit:smoke, which now emits one combined guardrail + source-fit + candidate-comparison gate smoke summary/report with candidate counts, explanation/comparison and filtered-near-miss artifact counts, source-fit confidence, and paths/hashes for gate and near-miss artifacts.
Use npm run evaluate:draft-candidate-fit -- --prospects /tmp/sports-impact-draft/prospects.json --team-needs /tmp/sports-impact-draft/team-needs.json --target-team LAL --top 10 --out /tmp/sports-impact-draft/draft-candidate-fit.json --report /tmp/sports-impact-draft/draft-candidate-fit.md to rank fixture-backed draft prospects against a target team's modeled needs. The shared implementation is exported as evaluateDraftCandidateFitFromFiles and exposed through Pi as evaluate_draft_candidate_fit. Inputs are source-agnostic JSON/CSV fixtures for prospects and team needs; outputs include roster-need alignment, skill fit, minutes pathway, risk/timeline fit, source-fit warnings, and deterministic score breakdowns. Use npm run analyze:draft-board-sensitivity -- --fit-report /tmp/sports-impact-draft/draft-candidate-fit.json --top 10 --out /tmp/sports-impact-draft/draft-board-sensitivity.json --report /tmp/sports-impact-draft/draft-board-sensitivity.md to test robustness across preset boards (default, win_now_readiness, upside_swing, low_risk, minutes_pathway, skill_need_heavy, and source_confidence_penalty) and report consensus, volatile, upside, win-now, risk-sensitive, source-sensitive, and tier-stability evidence. The shared implementation is exported as analyzeDraftBoardSensitivityFromFile and exposed through Pi as analyze_draft_board_sensitivity. Use npm run reconcile:draft-board -- --fit-report /tmp/sports-impact-draft/draft-candidate-fit.json --sensitivity /tmp/sports-impact-draft/draft-board-sensitivity.json --scout-board /tmp/sports-impact-draft/scout-board.json --out /tmp/sports-impact-draft/draft-board-reconciliation.json --report /tmp/sports-impact-draft/draft-board-reconciliation.md to compare model rankings with scout rankings/notes and emit consensus, model-high/scouts-low, scouts-high/model-low, high-upside disagreement, source/data-gap disagreement, film-review, provenance-blocker, and meeting-agenda evidence. The shared implementation is exported as reconcileDraftBoardFromFiles and exposed through Pi as reconcile_draft_board. Use npm run plan:draft-availability -- --fit-report /tmp/sports-impact-draft/draft-candidate-fit.json --sensitivity /tmp/sports-impact-draft/draft-board-sensitivity.json --reconciliation /tmp/sports-impact-draft/draft-board-reconciliation.json --market-board /tmp/sports-impact-draft/market-board.json --pick-slots 17,47 --out /tmp/sports-impact-draft/draft-availability-plan.json --report /tmp/sports-impact-draft/draft-availability-plan.md to turn fit, sensitivity/reconciliation, market/mock-board, and team pick slots into likely/maybe/unlikely availability bands, reach/value flags, contingency paths, and trade-up/down evidence. The shared implementation is exported as planDraftAvailabilityFromFiles and exposed through Pi as plan_draft_availability. Use npm run update:draft-war-room-state -- --availability /tmp/sports-impact-draft/draft-availability-plan.json --selected-picks /tmp/sports-impact-draft/selected-picks.json --current-pick 14 --pick-slots 17,47 --out /tmp/sports-impact-draft/draft-war-room-state.json --report /tmp/sports-impact-draft/draft-war-room-state.md during live draft-room updates to remove selected prospects, refresh remaining board and target stacks, activate/archive trade-up/down evidence, compute decision pressure, and render a clock-ready briefing. The shared implementation is exported as updateDraftWarRoomStateFromFiles and exposed through Pi as update_draft_war_room_state. Use npm run run:draft-workflow -- --manifest /tmp/sports-impact-draft/draft-workflow-manifest.json --out /tmp/sports-impact-draft/draft-workflow-run.json --report /tmp/sports-impact-draft/draft-workflow-run.md --gate for a manifest-driven actual/demo workflow that runs fit → sensitivity → reconciliation → availability → war-room → brief from supplied fixture paths and optionally gates the produced artifact bundle. The manifest uses sports-impact-core/draft-workflow-manifest/v1 with inputs.prospects, inputs.teamNeeds, inputs.scoutBoard, inputs.marketBoard, inputs.selectedPicks, targetTeam, currentPick, and pickSlots. The shared implementation is exported as runDraftWorkflow and exposed through Pi as run_draft_workflow. Use npm run smoke:draft-workflow -- --work-dir /tmp/sports-impact-draft-workflow-ci-smoke --current-pick 14 --pick-slots 17,47 for a synthetic CI smoke that runs fit → sensitivity → reconciliation → availability → war-room → brief and writes a summary artifact bundle with output paths and hashes. The shared implementation is exported as runDraftWorkflowCiSmoke and exposed through Pi as run_draft_workflow_smoke. Use npm run gate:draft-workflow -- --fit-report /tmp/sports-impact-draft-workflow-ci-smoke/draft/draft-candidate-fit.json --sensitivity /tmp/sports-impact-draft-workflow-ci-smoke/draft/draft-board-sensitivity.json --reconciliation /tmp/sports-impact-draft-workflow-ci-smoke/draft/draft-board-reconciliation.json --availability /tmp/sports-impact-draft-workflow-ci-smoke/draft/draft-availability-plan.json --war-room /tmp/sports-impact-draft-workflow-ci-smoke/draft/draft-war-room-state.json --brief /tmp/sports-impact-draft-workflow-ci-smoke/draft/front-office-draft-decision-brief.json --out /tmp/sports-impact-draft-workflow-ci-smoke/draft-workflow-gate.json --report /tmp/sports-impact-draft-workflow-ci-smoke/draft-workflow-gate.md to gate actual/demo workflow artifacts for schema drift, linked source path/hash drift, candidate/team consistency, Markdown caveats, and not-a-draft-recommendation language. The shared implementation is exported as gateDraftWorkflowArtifacts and exposed through Pi as gate_draft_workflow. Use npm run build:draft-decision-brief -- --fit-report /tmp/sports-impact-draft/draft-candidate-fit.json --top 10 --out /tmp/sports-impact-draft/front-office-draft-decision-brief.json --report /tmp/sports-impact-draft/front-office-draft-decision-brief.md to convert the fit report into a GM/data-analyst brief with draft board tiers, archetype picks (best fit, safest fit, highest upside, best value), risk register, opportunity costs, analyst appendix, and next-review questions. The shared implementation is exported as buildDraftDecisionBriefFromFile and exposed through Pi as build_draft_decision_brief. Output is internal demo/source-fit evidence only, not a draft recommendation.
Use npm run compare:nba-contract-source-packs -- --primary-salary-ledger /tmp/sports-impact-balldontlie-nba-demo-pack/salary-ledger.json --espn-salary-ledger /tmp/sports-impact-espn-contract-prototype/salary-ledger.json --sportradar-salary-ledger /tmp/sports-impact-sportradar-financial-pack/salary-ledger.json --out-dir /tmp/sports-impact-nba-contract-source-comparison to compare BALLDONTLIE primary salary-ledger rows against optional ESPN/Sportradar ledgers by normalized player name + team alias. The report is deterministic source-fit evidence only, not an official NBA/CBA determination or front-office cap-sheet ruling.
The repository also includes an optional internal-evaluation importer, npm run generate:sportradar-financial-pack -- --out-dir /tmp/sports-impact-sportradar-financial-pack, for account-permitted Sportradar NBA v8 Team Profile salary data. It reads SPORTRADAR_API_KEY from the environment, sends it only as an x-api-key header, never writes the key to artifacts, and emits uncommitted salary-ledger, derived known-salary payroll, apron-threshold, provenance, summary, and hash files. Treat generated outputs as internal evaluation unless your Sportradar account/order-form terms permit broader use; derived payroll is not an official cap-payroll determination.
For ESPN source-fit exploration, npm run generate:espn-contract-prototype -- --players /tmp/espn-nba-contract-players.json --out-dir /tmp/sports-impact-espn-contract-prototype --espn-season 2026 --effective-season 2025-26 reads a JSON player list containing espnAthleteId values and fetches ESPN Sports Core contract rows. It emits salary-ledger, contract-detail, derived known-salary payroll, provenance, source-fit report, summary, and hash files. The ESPN endpoint is undocumented web infrastructure, not a licensed public developer feed discovered for this project; use generated outputs for internal evaluation/source-fit comparison only unless ESPN grants permission. Derived payroll covers only requested players and is not official NBA cap payroll.
Boundaries and external handoff
See the package-local boundary document BOUNDARIES.md, the machine-readable handoff schema schemas/game-footage-external-handoff.schema.json, and the canonical repository boundary contract at docs/BOUNDARIES.md. Game-footage APIs start from precomputed court-coordinate tracking/detection outputs. Use validateGameFootageExternalHandoffFromFile or the validate-game-footage-external-handoff CLI command to produce deterministic JSON/Markdown contract reports for schema/runtime provenance, bbox format, pixel-scale, and raw-video boundary alignment, then normalizeExternalHandoffGameFootageInputFromFile or normalize-external-handoff-game-footage to bridge valid handoffs into the existing analysis input schema before analyzeGameFootageFromFile. Fixture-pack manifests can also use normalization.adapter: "external_handoff" plus files.externalHandoffInput to audit validation, normalization, input hashes, normalized-input comparison, and rerun drift in CI; gateGameFootageExternalHandoffFixturePackFromManifest / gate-game-footage-external-handoff-fixture-pack turns positive fixture-pack evidence into a hard pass/fail gate, gateGameFootageExternalHandoffInvalidFixturesFromManifest / gate-game-footage-external-handoff-invalid-fixtures gate reusable invalid-fixture manifests so invalid checked-in handoffs fail with stable validation check IDs and are rejected before normalization, generateGameFootageExternalHandoffFixtureGateCiPlanFromManifest / generate-game-footage-external-handoff-gate-ci emits downstream GitHub Actions YAML that runs both gates together, verifyGameFootageExternalHandoffFixtureGateCiAdoptionFromFiles / verify-game-footage-external-handoff-gate-ci verifies adopted YAML still matches the deterministic generator, verifyGameFootageExternalHandoffFixtureGateCiAdoptionRegistryFromManifest / verify-game-footage-external-handoff-gate-ci-registry verifies a manifest-backed registry of downstream adopted workflows across projects, and gateGameFootageExternalHandoffFixtureGateCiAdoptionRegistryFromFiles / gate-game-footage-external-handoff-gate-ci-registry enforces required-project, package-version, YAML-match, command-coverage, valid+invalid fixture-gate, boundary, and optional previous/current drift policy over registry reports. generateGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiPlanFromManifest / generate-game-footage-external-handoff-gate-ci-registry-gate emit downstream registry-gate CI YAML, verifyGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiAdoptionFromFiles / verify-game-footage-external-handoff-gate-ci-registry-gate verify adopted registry-gate CI YAML still matches the deterministic generator, and verifyGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiAdoptionRegistryFromManifest / verify-game-footage-external-handoff-gate-ci-registry-gate-registry verify registries of downstream registry-gate CI adoptions, and gateGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiAdoptionRegistryFromFiles / gate-game-footage-external-handoff-gate-ci-registry-gate-registry enforce required-project, minimum-package-version, command-coverage, YAML-match, previous-registry, and optional previous/current drift policy over those registry reports. generateGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiAdoptionRegistryGateCiPlanFromManifest / generate-game-footage-external-handoff-gate-ci-registry-gate-registry-gate emit downstream CI YAML for that verifier+gate pair, verifyGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiAdoptionRegistryGateCiAdoptionFromFiles / verify-game-footage-external-handoff-gate-ci-registry-gate-registry-gate verify adopted YAML still matches the deterministic generator, and verifyGameFootageExternalHandoffFixtureGateCiAdoptionRegistryGateCiAdoptionRegistryGateCiAdoptionRegistryFromManifest / verify-game-footage-external-handoff-gate-ci-registry-gate-registry-gate-registry verify registries of downstream adoption for that generated workflow. The package does not perform raw video inference, object detection, segmentation, homography estimation, or jersey OCR, and it does not provide betting/gambling recommendations, medical advice, or guaranteed-performance claims.
import {
analyzeGameFootageFromFile,
validateGameFootageExternalHandoffFromFile,
normalizeExternalHandoffGameFootageInputFromFile,
renderGameFootageExternalHandoffValidationMarkdownReport,
appendGameFootageVisualizationArtifactBundleBaselinePromotionLedgerEntry,
auditGameFootageVisualizationBaselineLifecycleRun,
auditGameFootageFixturePackFromManifest,
normalizeCsvGameFootageInput,
checkGameFootageVisualizationArtifactBundleBaselineFromFiles,
checkGameFootageVisualizationArtifactBundleBaselineSuite,
compareGameFootageVisualizationArtifactBundlesFromFiles,
promoteGameFootageVisualizationArtifactBundleBaselineFromFiles,
verifyGameFootageVisualizationArtifactBundleBaselinePromotion,
verifyGameFootageVisualizationArtifactBundleBaselinePromotionLedger,
verifyGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistry,
gateGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistry,
compareGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistries,
createGameFootageVisualizationBaselineLifecycleDashboard,
verifyGameFootageVisualizationBaselineLifecycleDashboardAdoption,
createGameFootageVisualizationBaselineLifecycleTemplate,
generateGameFootageVisualizationBaselineLifecycleCiPlan,
verifyGameFootageVisualizationBaselineLifecycleCiAdoption,
compareGameFootageVisualizationBaselineLifecycleRuns,
gateGameFootageVisualizationBaselineLifecycleTrend,
verifyGameFootageVisualizationBaselineLifecycleTemplateConformance,
gateGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistryComparison,
gateGameFootageVisualizationArtifactBundleComparisonFromFile,
materializeGameFootageFixturePackVisualizationsFromManifest,
normalizeRoboflowGameFootageInput,
verifyGameFootageVisualizationArtifactBundleFromManifest,
renderGameFootageCourtVisualizationFromFile,
normalizeTrackingGameFootageInput,
auditTradeFixturePackFromManifest,
auditTradeFixtures,
benchmarkTradeFixturePackFromManifest,
buildTradeSimulationInput,
compareTradeFixturePackBenchmarks,
calibrateInjuryBacktests,
calibrateTradeBacktests,
generateInjuryBacktestSuiteFromFixtures,
calibrateTradeModel,
diagnoseTradeModel,
evaluateTradeModelHoldout,
evaluateTradeModelReadiness,
generateTradeBacktestSuiteFromFixtures,
importNbaBaselineDataset,
splitTradeBacktestSuite,
simulateImpact,
validateTradeBacktestFixtures,
verifyGameFootageExternalHandoffFixtureGateCiAdoptionRegistryFromManifest,
verifyGameFootageFixturePackRerun,
verifyTradeFixturePackBenchmarkReproducibility,
verifyNbaTradeFeasibility,
renderNbaTradeFeasibilityMarkdownReport,
verifyTradeFixturePackBenchmarkRerun,
} from "sports-impact-core";
const dataset = importNbaBaselineDataset({ season, teams, players });
const tradeInput = buildTradeSimulationInput(dataset, {
teamId: "LAL",
outgoingPlayerIds: ["star_forward"],
incomingPlayerIds: ["incoming_shooter"],
});
const salaryByPlayerId: Record<string, number> = {
star_forward: 20_000_000,
incoming_shooter: 25_000_000,
};
const feasibility = verifyNbaTradeFeasibility({
schema: "sports-impact-core/nba-trade-feasibility-input/v1",
schemaVersion: 1,
team: tradeInput.team,
players: tradeInput.players.map((player) => ({ ...player, salaryUsd: salaryByPlayerId[player.playerId] })),
scenario: { ...tradeInput.scenario, assumeLegal: false },
teamFinancialContext: {
teamId: "LAL",
salaryBeforeTradeUsd: 149_000_000,
rosterCountBeforeTrade: 15,
salaryCapUsd: 141_000_000,
luxuryTaxLineUsd: 171_315_000,
firstApronUsd: 178_132_000,
secondApronUsd: 188_931_000,
},
financialProvenance: {
sources: [
{
sourceId: "salary-ledger",
label: "Salary/payroll source label",
dataKind: "synthetic",
retrievedAt: "2026-06-15T00:00:00.000Z",
license: { name: "Synthetic fixture license" },
covers: ["player_salaries", "team_payroll"],
},
{
sourceId: "apron-thresholds",
label: "Apron threshold source label",
dataKind: "synthetic",
version: "synthetic-2025-26-v1",
effectiveSeason: "2025-26",
retrievedAt: "2026-06-15T00:00:00.000Z",
license: { name: "Synthetic fixture license" },
covers: ["salary_cap", "luxury_tax_line", "first_apron", "second_apron", "rule_profile"],
},
],
},
rules: { requireFinancialProvenance: true },
});
const feasibilityMarkdown = renderNbaTradeFeasibilityMarkdownReport(feasibility);
const tradeResult = simulateImpact(tradeInput);
const suite = generateInjuryBacktestSuiteFromFixtures({ dataset, absences, teamOutcomes, playerOutcomes });
const calibration = calibrateInjuryBacktests({ inputs: [{ suiteId: "injury-history", value: suite }] });
const tradeSuite = generateTradeBacktestSuiteFromFixtures({ dataset, trades, teamOutcomes, playerOutcomes });
const tradeCalibration = calibrateTradeBacktests({ inputs: [{ suiteId: "trade-history", value: tradeSuite }] });
const quality = validateTradeBacktestFixtures(tradeSuite);
const split = splitTradeBacktestSuite(tradeSuite, { trainFraction: 0.7, validationFraction: 0.15, testFraction: 0.15 });
const tradeModelCalibration = calibrateTradeModel({
suite: tradeSuite,
parameterGrid: { incomingMinutesCap: [28, 30, 36] },
trainCaseIds: split.splits.train.caseIds,
validationCaseIds: split.splits.validation.caseIds,
});
const readiness = evaluateTradeModelReadiness({ split, calibration: tradeModelCalibration });
const holdout = evaluateTradeModelHoldout({ split, calibration: tradeModelCalibration });
const audit = auditTradeFixtures({ suite: tradeSuite, split, calibration: tradeModelCalibration });
const diagnostics = diagnoseTradeModel({ suite: tradeSuite, calibration: tradeModelCalibration });
const fixturePackAudit = await auditTradeFixturePackFromManifest({ manifestPath: "examples/nba-trade-historical-template/trade-fixture-pack.json" });
const fixturePackBenchmark = await benchmarkTradeFixturePackFromManifest({ manifestPath: "examples/nba-trade-historical-template/trade-fixture-pack.json" });
const fixturePackReproducibility = await verifyTradeFixturePackBenchmarkReproducibility({ report: fixturePackBenchmark });
const fixturePackRerunVerification = await verifyTradeFixturePackBenchmarkRerun({ report: fixturePackBenchmark });
const fixturePackBenchmarkComparison = compareTradeFixturePackBenchmarks({ reports: [fixturePackBenchmark] });
const roboflowInput = normalizeRoboflowGameFootageInput(roboflowDetections, {
gameId: "demo-game",
sourceLabel: "Precomputed Roboflow/YOLO detections",
fps: 5,
pixelsPerFootX: 10,
pixelsPerFootY: 10,
});
const csvInput = normalizeCsvGameFootageInput(csvDetectionRows, {
gameId: "demo-game-csv",
sourceLabel: "CSV precomputed detections",
pixelsPerFootX: 10,
pixelsPerFootY: 10,
});
const trackingInput = normalizeTrackingGameFootageInput(trackingJson, {
gameId: "demo-game-tracking",
sourceLabel: "ByteTrack/Supervision precomputed tracks",
pixelsPerFootX: 10,
pixelsPerFootY: 10,
bboxFormat: "xyxy",
sourceKind: "bytetrack",
});
const gameFootageAnalysis = await analyzeGameFootageFromFile({ inputPath: "examples/nba-game-footage/footage-analysis-input.json" });
const courtVisualization = await renderGameFootageCourtVisualizationFromFile({ inputPath: "examples/nba-game-footage/footage-analysis-input.json", frameIndex: 1 });
const gameFootageFixturePackAudit = await auditGameFootageFixturePackFromManifest({ manifestPath: "examples/nba-game-footage/game-footage-fixture-pack.json" });
const gameFootageVisualizationArtifacts = await materializeGameFootageFixturePackVisualizationsFromManifest({
manifestPath: "examples/nba-game-footage/game-footage-fixture-pack.json",
outputDir: "runs/demo-game-footage/visualizations",
});
const gameFootageVisualizationArtifactVerification = await verifyGameFootageVisualizationArtifactBundleFromManifest({
manifestPath: gameFootageVisualizationArtifacts.artifactManifestPath,
artifactDir: gameFootageVisualizationArtifacts.outputDir,
});
const gameFootageVisualizationArtifactComparison = await compareGameFootageVisualizationArtifactBundlesFromFiles({
inputPaths: [gameFootageVisualizationArtifacts.artifactManifestPath, gameFootageVisualizationArtifacts.artifactManifestPath],
});
const gameFootageVisualizationDriftGate = await gateGameFootageVisualizationArtifactBundleComparisonFromFile({
comparisonPath: "runs/demo-game-footage/game_footage_visualization_artifacts_comparison.json",
policyPath: "examples/nba-game-footage/visualization-drift-gate-policy.json",
});
const gameFootageVisualizationBaselineCheck = await checkGameFootageVisualizationArtifactBundleBaselineFromFiles({
baselinePath: gameFootageVisualizationArtifacts.artifactManifestPath,
currentPath: gameFootageVisualizationArtifacts.artifactManifestPath,
policyPath: "examples/nba-game-footage/visualization-drift-gate-policy.json",
});
const gameFootageVisualizationBaselinePromotion = await promoteGameFootageVisualizationArtifactBundleBaselineFromFiles({
baselinePath: gameFootageVisualizationArtifacts.artifactManifestPath,
currentPath: gameFootageVisualizationArtifacts.artifactManifestPath,
policyPath: "examples/nba-game-footage/visualization-drift-gate-policy.json",
reason: "Reviewed deterministic SVG/Markdown diffs.",
reviewer: "qa-reviewer",
changeId: "VIS-29",
});
const gameFootageVisualizationBaselinePromotionVerification = verifyGameFootageVisualizationArtifactBundleBaselinePromotion({
promotion: gameFootageVisualizationBaselinePromotion,
baselineBundle: gameFootageVisualizationArtifacts,
currentBundle: gameFootageVisualizationArtifacts,
policy: { schema: "sports-impact-core/game-footage-visualization-artifact-bundle-drift-gate-policy/v1", schemaVersion: 1 },
requireReviewer: true,
requireChangeId: true,
});
const gameFootageVisualizationBaselineSuite = await checkGameFootageVisualizationArtifactBundleBaselineSuite({
manifest: {
schema: "sports-impact-core/game-footage-visualization-artifact-bundle-baseline-suite-manifest/v1",
schemaVersion: 1,
suiteId: "demo-game-footage-visualization-baselines",
entries: [
{
entryId: "demo-baseline",
baselinePath: gameFootageVisualizationArtifacts.artifactManifestPath,
currentPath: gameFootageVisualizationArtifacts.artifactManifestPath,
policyPath: "examples/nba-game-footage/visualization-drift-gate-policy.json",
},
],
},
});
const gameFootageVisualizationBaselinePromotionLedger = appendGameFootageVisualizationArtifactBundleBaselinePromotionLedgerEntry({
ledgerId: "demo-game-footage-visualization-baseline-promotions",
promotionVerification: gameFootageVisualizationBaselinePromotionVerification,
entryId: "VIS-30",
sourceCommit: "example-source-commit",
ciRunId: 1,
});
const gameFootageVisualizationBaselinePromotionLedgerVerification = verifyGameFootageVisualizationArtifactBundleBaselinePromotionLedger({
ledger: gameFootageVisualizationBaselinePromotionLedger,
requireReviewer: true,
requireChangeId: true,
requireSourceCommit: true,
requireCiRunId: true,
});
const gameFootageVisualizationBaselinePromotionLedgerRegistry = await verifyGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistry({
manifest: {
schema: "sports-impact-core/game-footage-visualization-artifact-bundle-baseline-promotion-ledger-registry-manifest/v1",
schemaVersion: 1,
registryId: "demo-game-footage-visualization-baseline-promotion-ledger-registry",
entries: [
{
entryId: "demo-ledger",
ledgerPath: "runs/demo-game-footage/game_footage_visualization_baseline_promotion_ledger.json",
requireReviewer: true,
requireChangeId: true,
requireSourceCommit: true,
requireCiRunId: true,
},
],
},
});
const gameFootageVisualizationBaselinePromotionLedgerRegistryGate = gateGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistry({
registry: gameFootageVisualizationBaselinePromotionLedgerRegistry,
policy: {
schema: "sports-impact-core/game-footage-visualization-artifact-bundle-baseline-promotion-ledger-registry-gate-policy/v1",
schemaVersion: 1,
requiredLedgerIds: ["demo-game-footage-visualization-baseline-promotions"],
minVerifiedLedgerEntryCount: 1,
maxWarnings: 0,
},
});
const gameFootageVisualizationBaselinePromotionLedgerRegistryComparison = compareGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistries({
previous: gameFootageVisualizationBaselinePromotionLedgerRegistry,
current: gameFootageVisualizationBaselinePromotionLedgerRegistry,
previousGate: gameFootageVisualizationBaselinePromotionLedgerRegistryGate,
currentGate: gameFootageVisualizationBaselinePromotionLedgerRegistryGate,
});
const gameFootageVisualizationBaselinePromotionLedgerRegistryComparisonGate = gateGameFootageVisualizationArtifactBundleBaselinePromotionLedgerRegistryComparison({
comparison: gameFootageVisualizationBaselinePromotionLedgerRegistryComparison,
policy: {
schema: "sports-impact-core/game-footage-visualization-artifact-bundle-baseline-promotion-ledger-registry-comparison-gate-policy/v1",
schemaVersion: 1,
maxAddedLedgerCount: 0,
maxRemovedLedgerCount: 0,
maxChangedLedgerCount: 0,
maxLatestEntryHashChangedCount: 0,
maxFailedCheckCountDelta: 0,
maxWarningCountDelta: 0,
minVerifiedEntryCountDelta: 0,
},
});
const lifecycleTemplate = createGameFootageVisualizationBaselineLifecycleTemplate({
preset: "strict-ci",
packId: "demo-game-footage-pack",
baselineId: "demo-baseline",
registryId: "demo-registry",
});
const lifecycleConformance = verifyGameFootageVisualizationBaselineLifecycleTemplateConformance({
template: lifecycleTemplate,
preset: "strict-ci",
});
const lifecycleCiPlan = generateGameFootageVisualizationBaselineLifecycleCiPlan({
template: lifecycleTemplate,
rootDir: "runs/demo-game-footage/lifecycle",
format: "github-actions-workflow",
});
const lifecycleCiAdoption = verifyGameFootageVisualizationBaselineLifecycleCiAdoption({
template: lifecycleTemplate,
adoptedYaml: lifecycleCiPlan.generatedYaml,
rootDir: "runs/demo-game-footage/lifecycle",
format: "github-actions-workflow",
});
const lifecycleRunAudit = await auditGameFootageVisualizationBaselineLifecycleRun({
template: lifecycleTemplate,
rootDir: "runs/demo-game-footage/lifecycle",
preset: "strict-ci",
});
const lifecycleTrend = compareGameFootageVisualizationBaselineLifecycleRuns({
audits: [lifecycleRunAudit, lifecycleRunAudit],
ciAdoptions: [lifecycleCiAdoption, lifecycleCiAdoption],
labels: ["previous", "current"],
});
const lifecycleTrendGate = gateGameFootageVisualizationBaselineLifecycleTrend({ trend: lifecycleTrend });
const gameFootageFixturePackRerun = await verifyGameFootageFixturePackRerun({ report: gameFootageFixturePackAudit });
const result = simulateImpact(input);The library intentionally keeps projection math deterministic and inspectable. Use LLM/autocontext layers only for context gathering and narrative explanation.
