Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.git
.github
.mypy_cache
.pytest_cache
.ruff_cache
.venv
.repro-venv
.repro-v3-venv
__pycache__
*.egg-info
build
dist
output
reports
runtime
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ __pycache__/
.pytest_cache/
.ruff_cache/
.mypy_cache/
runtime/
output/
.playwright-cli/
*.egg-info/
build/
dist/
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Universal Sports Engine Rules
# Waterboy Engine Rules

- Keep the simulation truth independent from rendering.
- Preserve deterministic replay: identical versions, inputs, and seed must produce identical events.
Expand Down
36 changes: 34 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Architecture
# Waterboy Architecture

## Decision

Expand All @@ -17,7 +17,11 @@ Kimi build:
## Layers

```text
CLI / SDK / domain-neutral bridge
Web UI / versioned HTTP API / CLI / SDK / domain-neutral bridge
|
Projection service, weekly board, hypothetical-matchup orchestration
|
Normalized point-in-time games, SQLite provenance store, bounded feed clients
|
Champion governance, recursive calibration, adaptive weights, drift quarantine
|
Expand All @@ -32,6 +36,34 @@ League packs own scoring, timing, possession/inning/drive/shift semantics, and
reference anchors. The kernel contains no player, ball, puck, inning, possession,
or scoreboard type.

## Sports-data and projection boundary

The production application adds a domain adapter outside the neutral kernel:

1. Read-only source adapters normalize public scoreboards or a protected local
historical database into `GameRecord`.
2. `SportsDataStore` records every normalized observation together with source URL,
observation time, ingest run, and payload SHA-256.
3. `ProjectionEngine` estimates recency-weighted, opponent-adjusted attack and
defense ratings, shrinks them toward league priors, and derives score parameters.
4. The existing analytical F0 engine produces deterministic, reproducible score
distributions from those parameters.
5. `SportsEngineService` exposes scheduled weekly games and hypothetical pairings
without giving the web layer direct database or simulation-kernel access.

Final games are observations, not projections. In-progress games show their
observed score and intentionally withhold a pregame projection. Sparse or stale
history remains visible in the projection evidence status instead of being hidden.

## Application boundary

FastAPI validates and bounds all external inputs, emits a versioned `/api/v1`
surface, and serves a static no-build dashboard. The browser does not evaluate
server-provided HTML. Security headers are applied globally, API responses are
non-cacheable, and remote binding requires an explicit operator flag. A remote
deployment must add TLS, authentication, rate limiting, and network policy at the
reverse proxy as described in `PRODUCTION_RUNBOOK.md`.

## Fidelity

- F0: analytical/batch score distribution (implemented; no event path).
Expand Down
6 changes: 3 additions & 3 deletions AUTONOMOUS_IMPROVEMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ and an untouched test audit after the champion is frozen.
## Commands

```powershell
.\.venv\Scripts\sports-engine.exe auto-improve `
.\.venv\Scripts\waterboy.exe auto-improve `
--csv data\point-in-time\historical.csv `
--config AUTONOMY_CONFIG.json `
--output reports\improvement-run-001

.\.venv\Scripts\sports-engine.exe simulate-adaptive `
.\.venv\Scripts\waterboy.exe simulate-adaptive `
--bundle reports\improvement-run-001\champion_bundle.json `
--league nba --seed 42 --home-strength 1.0 --away-strength 1.0

.\.venv\Scripts\sports-engine.exe adapt-online `
.\.venv\Scripts\waterboy.exe adapt-online `
--csv data\point-in-time\shadow.csv `
--config AUTONOMY_CONFIG.json `
--bundle reports\improvement-run-001\champion_bundle.json `
Expand Down
59 changes: 59 additions & 0 deletions DATA_PIPELINE_LINEAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Data Pipeline Lineage

## Boundary

Dummy is a protected source. Waterboy never imports Dummy modules,
writes to Dummy's checkout, migrates its database, or controls its processes. The
only reuse is a clean-room implementation of the required sports-history flow and
a query-only copy of eligible game rows into a target-owned database.

## Component map

| Capability observed in Dummy | Waterboy implementation | Boundary |
|---|---|---|
| Normalized sports history | `data.models.GameRecord` | New target-owned contract |
| SQLite sports history | `data.store.SportsDataStore` | New schema and provenance columns |
| Historical league rows | `data.pipeline.DummyHistoryImporter` | Source opened `mode=ro` plus `query_only` |
| Public score refresh | `data.espn.EspnScoreboardClient` | Bounded GET, timeout, retry, cache, payload hash |
| Sports ingestion orchestration | `data.pipeline.SportsDataPipeline` | Target-owned league aliases and ingest runs |
| Board/model consumption | `projection.ProjectionEngine` and `service.SportsEngineService` | No Dummy runtime dependency |

## Copied records

The importer selects only sports-history fields needed to reconstruct completed
games: source record identifier, league, UTC start time, home/away team IDs and
names, scores, and final status. It normalizes league aliases and rejects malformed
or same-team records that violate the target contract.

Each copied observation receives an immutable provenance reference to the protected
source database and source row. The target database can be discarded and rebuilt
without altering the source.

## Explicit exclusions

The implementation does not copy or activate:

- prediction-market, portfolio, brokerage, order, or execution paths;
- credentials, tokens, user data, environment files, logs, or runtime settings;
- model claims, profitability artifacts, settled-market evidence, or readiness
labels;
- Dummy code imports, database migrations, background jobs, or process controls;
- odds feeds, betting lines, injury data, private providers, or restricted data.

## Current public refresh

Current-week schedules and scores are normalized from a public, read-only
scoreboard endpoint. The client records the exact request URL, retrieval timestamp,
and SHA-256 of the raw payload. Requests are bounded by timeout, retry count,
response size, date span, and a local cache. College endpoints that reject a date
range fall back to bounded daily requests.

Provider availability is not guaranteed, and provider terms govern use. A fetch
failure stays visible as an ingest error and never becomes synthetic current data.

## Verification

Automated tests create temporary source and destination databases, verify that the
source bytes remain unchanged, exercise normalization and aliases, and inspect the
HTTP/API projection contracts. Operationally, recheck `git status` in Dummy after
an import and confirm it is clean.
38 changes: 29 additions & 9 deletions DATA_RIGHTS_AND_PROVENANCE.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
# Data Rights and Provenance

## Local build inputs
## Waterboy runtime inputs

No licensed event feed, tracking feed, private injury feed, sportsbook feed, or
proprietary roster database is present in this repository.
No licensed tracking feed, private injury feed, sportsbook feed, brokerage feed,
or proprietary roster database is present in this repository.

The shipped engine uses:
The application can use:

- deterministic synthetic events generated by the versioned league packs;
- transparent league-level reference anchors for broad output sanity checks;
- official rule-source links as provenance pointers for the minimal rule manifests.
- official rule-source links as provenance pointers for the minimal rule manifests;
- keyless, unauthenticated, read-only ESPN public scoreboard responses for schedules,
team identities, game state, and final scores;
- an optional local copy of sports history from Dummy, opened with SQLite `mode=ro`
and `PRAGMA query_only=ON`.

The reference anchors are approximate research fixtures. They are not an ingested,
point-in-time dataset and are labeled `provisional_reference_anchor` everywhere.

## Runtime provenance contract

Every normalized game stores its source, source URL, receipt time, and a SHA-256
hash of the observed payload. Scheduled rows do not receive synthetic observed
scores. In-progress scores remain labeled as observations; the pregame-only model
is withheld on those cards.

The public HTTP cache and local SQLite database live under `runtime/`, which is
gitignored. The repository does not redistribute provider payloads or the local
Dummy history database.

The adapter sends bounded GET requests with a descriptive user agent, response-size
limit, timeout, retries, and a short local cache. It has no login, credential,
write, odds, wagering, or automation-bypass behavior. Operators remain responsible
for evaluating provider terms and data rights for their deployment.

## Prohibited promotion

These inputs cannot support a claim of held-out player, team, game, season, spatial,
or counterfactual accuracy. Such claims require separately licensed data manifests,
earliest-available timestamps, revisions, train/calibration/test boundaries, and
independent reproduction.
These inputs cannot by themselves support a claim of held-out player, game, spatial,
or counterfactual accuracy. Such claims require frozen point-in-time manifests,
earliest-available timestamps, revisions, chronological train/calibration/test
boundaries, prospective scoring, and independent reproduction.
25 changes: 25 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM python:3.12-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
WATERBOY_DATA_PATH=/data/sports.db \
WATERBOY_CACHE_DIR=/data/http_cache

WORKDIR /app

RUN groupadd --system sports && useradd --system --gid sports --home-dir /app sports

COPY pyproject.toml README.md LICENSE ./
COPY src ./src

RUN python -m pip install --no-cache-dir . && \
mkdir -p /data && chown -R sports:sports /app /data

USER sports
VOLUME ["/data"]
EXPOSE 8765

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD python -c "import json,urllib.request; data=json.load(urllib.request.urlopen('http://127.0.0.1:8765/api/v1/health',timeout=3)); raise SystemExit(0 if data['status']=='healthy' else 1)"

CMD ["waterboy", "serve", "--host", "0.0.0.0", "--port", "8765", "--allow-remote", "--data", "/data/sports.db", "--cache", "/data/http_cache"]
17 changes: 14 additions & 3 deletions KNOWN_LIMITATIONS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
# Known Limitations

- The stalled remote Kimi repository was not exported; this is an independent local reconstruction.
- Waterboy's current score projections use team scoring history, recency, opponent adjustment,
and league priors; they do not yet ingest rosters, injuries, starting lineups,
probable pitchers, coaching changes, travel, officials, or forecast weather.
- The public scoreboard is an operational schedule/final-score source, not a
licensed tracking feed or a predictive-accuracy certification dataset.
- Some imported historical leagues are stale. Those ratings decay toward league
priors and surface `sparse_or_stale_team_history` rather than silently presenting
old form as current.
- In-progress scores are displayed as observations. The current projection model is
pregame-only and is withheld rather than mislabeled as a live win-probability model.
- F1 event paths are calibrated only to broad reference anchors, not licensed held-out data.
- Player identities, rosters, coaching policies, officials, injuries, fatigue, venues, and weather are contract surfaces rather than calibrated models.
- Player identities, rosters, coaching policies, officials, injuries, fatigue, and
weather are contract surfaces rather than calibrated models.
- F2 spatial trajectories and F3 physics/rendering are intentionally not fabricated without tracking evidence.
- Rule manifests cover complete-game flow but are not a complete executable transcription of every official rulebook edge case.
- Generic F1 games resolve a winner; competition-specific regular-season tie and
Expand All @@ -19,4 +29,5 @@
- Windows multi-process calls require an importable script or CLI entrypoint; an
interactive/stdin caller receives an explicit error and should use F0 or one worker.
- Counterfactual pairing reduces simulation noise but does not by itself establish causality.
- No live feed, wagering, sportsbook, trading, or capital interface exists.
- A read-only public scoreboard adapter exists. No wagering, sportsbook, trading,
brokerage, or capital interface exists.
122 changes: 122 additions & 0 deletions PRODUCTION_RUNBOOK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Production Runbook

## Scope

This runbook operates Waterboy 0.4 as a read-only projection and
simulation service. It does not provide wagering, trading, or order execution.

## Bootstrap

Python 3.12 is the supported runtime.

```powershell
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
```

Create the target-owned history store without writing to Dummy:

```powershell
.\.venv\Scripts\waterboy.exe import-dummy-history
.\.venv\Scripts\waterboy.exe refresh-data --days 7
```

The importer opens Dummy with SQLite URI `mode=ro` and enables
`PRAGMA query_only=ON`. The destination defaults to
`runtime/universal_sports_engine/sports.db`.

## Local operation

```powershell
.\.venv\Scripts\waterboy.exe serve --host 127.0.0.1 --port 8765
```

Health check:

```powershell
Invoke-RestMethod http://127.0.0.1:8765/api/v1/health
```

Refresh and weekly projection checks:

```powershell
.\.venv\Scripts\waterboy.exe refresh-data --days 7
.\.venv\Scripts\waterboy.exe project-week --simulations 500
.\.venv\Scripts\waterboy.exe simulate-matchup --league nfl --away KC --home PHI
```

## Container

```powershell
docker build -t waterboy:0.4.0 .
docker run --read-only --tmpfs /tmp -p 127.0.0.1:8765:8765 `
-v waterboy-data:/data waterboy:0.4.0
```

The image runs as a non-root user and stores mutable state only below `/data`.

## Remote deployment controls

The application refuses a non-loopback bind unless `--allow-remote` is present.
That flag is an acknowledgement, not a security layer. Before remote exposure:

- terminate TLS at an authenticated reverse proxy;
- restrict refresh endpoints to an operator identity;
- apply request-size, request-rate, and concurrency limits;
- restrict egress to approved data-source hosts;
- persist `/data` on encrypted storage;
- collect access, application, refresh, and health logs;
- alert on failed refreshes, stale league data, elevated latency, and disk growth;
- keep at least one tested database backup outside the serving host.

Do not expose the Uvicorn process directly to the public internet.

## Data refresh

Refresh is idempotent at the normalized game identifier and records an ingest run
for auditability. A partial source failure is explicit in the command/API result;
previously stored observations remain available.

Recommended cadence:

- in season: every 15 minutes while games are active, hourly otherwise;
- out of season: daily;
- after deploy: one forced refresh followed by `/api/v1/health`.

Respect provider terms, cache controls, rate limits, and permitted-use boundaries.
This repository does not grant data redistribution rights.

## Backup and restore

Stop the serving process or use SQLite's online backup API before copying the
database. Preserve the database, its checksum, UTC timestamp, application version,
and configuration together. After restoration:

1. start on a non-production port;
2. call `/api/v1/health`;
3. run `PRAGMA integrity_check` through an approved SQLite operator tool;
4. compare row counts and latest observation times;
5. run one deterministic hypothetical matchup twice and compare results.

## Incident behavior

If a feed fails, retain the last valid observations, surface stale evidence, and
investigate; never manufacture a current score. If integrity checks fail, remove
the instance from service and restore a verified backup. If forecasts behave
unexpectedly, preserve the database and seed, reproduce locally, and keep the
software/evidence boundary explicit.

## Release gate

Before deployment, require:

```powershell
.\.venv\Scripts\ruff.exe check .
.\.venv\Scripts\mypy.exe src scripts
.\.venv\Scripts\pytest.exe -q
git diff --check
```

Also build and inspect a wheel, exercise the browser at desktop and mobile widths,
and validate the container when Docker is available.
Loading
Loading