Packaging-only patch. No runtime code changed. v2.0.0 → v2.0.1 fixes two latent defects that have been present since v1.0.0 but only surface when installing from PyPI (not from git clone, which is how this repo is normally deployed).
What was broken in v2.0.0
pip install player-coach-core==2.0.0 produced a package where:
player_coach/artifacts/was missing entirely from the wheel. Anyfrom player_coach.loop.coach_loop import CoachLoopchained throughplayer_coach.artifacts.writer.ArtifactWriterand crashed withModuleNotFoundError.yfinancewasn't declared in any extra. Evenpip install player-coach-core[market](which had numpy, hmmlearn, arch) couldn't importBacktestRunner— yfinance is needed for OHLCV fetching at module level.
Neither bug was caught by the existing 513-test suite because development happens from git clone where requirements.txt covers everything. They were caught during the post-publish smoke test on a clean venv.
Fixes
| Defect | Cause | Fix |
|---|---|---|
D1 — player_coach/artifacts/ missing from wheel |
.gitignore:12 had unanchored artifacts/ — hatchling's pathspec parser matched the Python sub-module too, even though git check-ignore correctly said it wasn't ignored |
.gitignore: artifacts/ → /artifacts/ (anchor to repo root) |
D2 — yfinance not declared |
[project.optional-dependencies.market] listed numpy, hmmlearn, arch — yfinance was missed |
pyproject.toml [market]: add yfinance>=0.2.40 |
TDD coverage added
Two new tests in tests/unit/test_packaging.py pin both defects so they cannot regress:
test_no_tracked_player_coach_file_matches_gitignore— walksgit ls-files player_coach/and asserts no path is matched by any.gitignorepattern under hatchling-equivalent semantics. Would have failed on v2.0.0.test_declared_dependencies_cover_runtime_imports— AST-parses everyplayer_coach/**/*.py, asserts every non-stdlib top-level import is in[dependencies]or an[optional-dependencies]table. Would have failed on v2.0.0.
Plus two guardrail tests that were already passing and remain unchanged:
test_pyproject_declares_llm_extra_for_anthropic— pins the CLAUDE.md install laddertest_tomllib_available— pins the Python 3.11+ floor needed for the static analysis above
Stale test removed
test_python_version_pinned_for_streamlit_cloud (in tests/unit/test_requirements.py) was pinning the .python-version file we removed in ee586d5. That file turned out to be a pyenv-only convention that Streamlit Cloud ignores (Cloud reads its Python version from the per-app Settings UI, not from any repo file). The test was pinning a contract that no longer applies; the deploy-mechanism docs moved to CLAUDE.md's "Deploy environment" section.
Verification
# clean venv, install from PyPI
python3 -m venv /tmp/v
/tmp/v/bin/pip install 'player-coach-core[market,llm]==2.0.1'
# the v2.0.0-broken import chain
/tmp/v/bin/python -c "
from player_coach.loop.coach_loop import CoachLoop
from player_coach.backtest.runner import BacktestRunner
from player_coach.artifacts.writer import ArtifactWriter # was missing in v2.0.0
print('all imports OK')
"
Test count
513 → 516 (+4 new packaging tests, –1 stale .python-version test = +3 net), 1 skipped, lint clean.
Who needs to upgrade
pip install player-coach-core users — yes, upgrade. v2.0.0 is fundamentally broken on import.
Streamlit Cloud users (this app's actual deploy path) — no change needed. Cloud reads from git, not PyPI.
git clone developers — no change needed; requirements.txt was always covering this.
Installation
pip install --upgrade 'player-coach-core[market,llm]==2.0.1'
---
## Why this body is shorter than v2.0.0's
v2.0.0 shipped features. v2.0.1 ships a packaging correction. The body reflects that — single section per defect, the TDD evidence, verification recipe, and a clear "who needs to upgrade" guide. ~50 lines instead of 100.
Ping me when the GitHub Release is published. The background install will notify me when it finishes (~2 min from when I started it).