Architecture and boundaries
Chess Analytics Lab uses one Python/SQL repository and local DuckDB files.
chesslab provides the foundation ingestion and two offline demos. The
analytical source command is python -m chess_analytics.corpus; the checked analyst is
python -m chess_analytics.analyst. These functional commands are the entry points while
historical package and report names remain stable for source hashes.
Lichess fixed complete archive / fixed byte prefix / synthetic PGN
→ chess_analytics.ingest: caps, parser, normalization, dedup, quarantine
→ chess_analytics.warehouse: checked immutable snapshots + current pointer
→ chess_analytics.marts: local dbt copy, tests, published marts + recovery ledger
→ chess_analytics.corpus: selected moves, opening and clock definitions
→ chess_analytics.dashboard: parameterized analysis and Streamlit views
→ chess_analytics.analyst: allowlisted read-only tools, bounded plan, evidence IDs
→ frozen references + scorer + preserved attempts and costs
The single writer lock protects data-changing CLI operations. A candidate is validated before its current pointer is replaced. Foundation source manifests bind normalized output to source bytes, code and lock hashes; the analytical move publication also binds its extracted receipt to the checked source hash. Source order, sampling selection, coverage and exclusions are in manifests. The partial compressed prefix is hashed as retained bytes; it is never marked as a fully verified publisher archive.
The optional Dagster assets and Prefect tasks call the same stage/publish/verify functions and optional dbt mart transform. Neither is a production scheduler or cloud dependency; the orchestration guide gives the exact local commands and comparison evidence. Airflow remains a later option.
The analyst can list definitions, read coverage, query named metrics, compare
openings and inspect clock buckets. query_metric reads the governed
draw-rate, opening-usage, and opening-score metrics from the published mart
when that mart's source snapshot and model hash match the analytical
snapshot; any mismatch or semantic failure keeps the reviewed SQL.
compare_openings calls query_metric, so it uses the same path. The
analytical snapshot is not modified. It cannot execute free-form SQL, files,
network access or extensions through its tool surface. Offline typed plans and
recorded fixture plans run without a key. A live provider path exists but
requires personal configuration, an explicit finite gross cap and named key;
its requests/results are logged separately. Evidence IDs bind tool name,
arguments, result and dataset ID. Scoring is external to the agent; historical
M5–M7 rubrics remain frozen, portfolio fixture checks use portfolio-1.0,
and engine-tool fixture checks use engine-1.0.
The dbt graph is drawn in dbt lineage. GitHub renders that Mermaid diagram from the committed manifest projection. The published catalog is the dbt docs for the tiny fixture. The Pages workflow generates it at deploy time. It is not the 2013 corpus.
The same allowlisted tools are available outside that planner through
chesslab mcp, a stdio-only MCP server described in MCP. Each call
is checked on its own. The planner's four-step limit and the M6/M7 scores
belong to this repository's planner; they do not transfer to an outside client.
Typed plans and that server can also score one position with a configured local
engine and read observed White continuations from local opening data. Those
scores are depth-limited evidence. The live provider prompt is unchanged.
See ENGINE.
The full demo copies only required code/contracts into an ignored project under
work/portfolio-demo/project, publishes a synthetic snapshot there and passes
that path to Streamlit with CHESSLAB_PROJECT. It never replaces the real
data/ pointers. The dashboard marks synthetic data on every view.