Deterministic engine-backed chess reviews with automated Telegram delivery, trait tracking, and a hardened polling pipeline.
Built for players ~800–1600 who want practical feedback after every game — not 40 lines of engine noise.
v0.3.0 focuses on stability, determinism, and queue correctness.
- No duplicate Telegram sends
- No false “already processed” skips
- Deterministic retry + cooldown logic
- Oldest-first queue processing
- Markdown file + Telegram message always aligned
- Single-shot processing mode (
--once) - Host-editable prompts with runtime verification
This release restores full pipeline integrity:
Chess.com → Engine → LLM → Markdown → Telegram → Database state
- Stockfish (configurable depth)
- Generates structured evaluation signals
- No narrative generation here
- Fully deterministic
- Ollama or GPT-compatible provider
- Receives structured engine-derived signals
- Produces coaching narrative
- Format validation + retry logic
- SQLite → authoritative local state (dedupe + cadence)
- Postgres → long-term game tracking, queue state, flags
- Host-mounted
/data→ Markdown + PGN + stats
- Docker + Docker Compose
- Chess.com account
- Ollama running (or OpenAI-compatible endpoint)
Example:
ollama serve
ollama pull qwen2.5:14b-instructgit clone <repo-url>
cd chess-coach
cp .env.example .envMinimum required:
CHESS_USERNAME=your_usernameOptional Telegram:
TG_BOT_TOKEN=...
TG_CHAT_ID=...mkdir -p "${HOME}/chess"Bind-mounted into container as /data.
docker compose up -d --build
docker compose logs -f chess-coachPoll interval defaults to 300 seconds.
Games are processed only if:
success_notified = FALSEengine_failed = FALSEattempt_count < POLL_MAX_ATTEMPTS- cooldown elapsed
- PGN present
Processing order:
- Oldest
played_at - Oldest
created_at - Lowest
id
Batch size controlled by:
POLL_BATCH_SIZE=5
POLL_MAX_ATTEMPTS=5
POLL_COOLDOWN_SECONDS=600Process exactly one eligible game and exit:
docker compose run --rm chess-coach python chess_review.py --onceProperties:
- Forces batch size = 1
- Does not start Telegram command loop
- Exits immediately
- Deterministic return codes
On success:
- Sends formatted summary message (URL last line for preview)
- Attaches Markdown file
- Only then marks:
success_notified = TRUEreview_notified = TRUE
If Telegram fails:
- Success flags are NOT written
- Send-only retry will occur next cycle
- Analysis is not rerun
Prompts live in:
/app/prompts
On first run:
- Seeded automatically if empty
At runtime:
- SHA256 and mtime logged for each prompt
- No rebuild required to edit prompts
Modify:
review_system.mdreview_user_strict.md
Restart container to reload.
On first run with empty Postgres:
- Fetches last
CHESS_BOOTSTRAP_GAMES(default 100) - Seeds DB
- Skips LLM narrative during bootstrap
- Generates initial stats/summary
Bootstrap is idempotent.
python3 chess_review.py --username your_username --backfill 50Constraints:
- Max 200 games
- No Telegram
- No LLM
- Deterministic trait recompute
- Exit 0 on success
python -m src.main status
python -m src.main stats
python -m src.main summary
python -m src.main health
python -m src.main helpTelegram (if enabled):
/status
/stats
/summary
/health
/help
chess/
├── md/
├── pgn/
├── player_stats.md
├── player_summary.md
├── state.sqlite
CHESS_USERNAME=
DATABASE_URL=postgresql://chess:chess@postgres:5432/chesscoach
STATE_DB=/data/state.sqlite
ENABLE_ENGINE=true
ENGINE_DEPTH=15
STOCKFISH_PATH=/usr/bin/stockfish
OLLAMA_URL=http://host.docker.internal:11434
OLLAMA_MODEL=qwen2.5:14b-instruct
POLL_BATCH_SIZE=5
POLL_MAX_ATTEMPTS=5
POLL_COOLDOWN_SECONDS=600Enable poll execution audit:
ENABLE_POLL_EXEC_AUDIT=1Logs include:
- candidate list
- skip reasons
- attempt results
- retry outcomes
v0.3.0 prioritizes:
- Deterministic state transitions
- Explicit terminal flags
- No hidden ingest-based skips
- Strict success-write semantics
- Controlled retry behavior
Coaching quality improvements will build on this stable core in v0.4.0.
MIT