Vendors ~/utils/file_length into scripts/file_length so the gate is
reachable in CI: pre-commit's `entry:` is not shell-expanded and GitHub
runners have no ~/utils, so an external reference would pass locally and
silently skip on push. The existing pre-commit/action all-files job picks
the hook up with no workflow change.
The vendored copy is excluded from ruff/ruff-format/mypy/pylint and must
stay byte-identical to upstream -- ruff --unsafe-fixes otherwise rewrites
its print() calls to `pass` (T201/F841), which leaves the gate exiting 1
while reporting nothing.
Also:
- name-tests-test now exempts tests/_*.py, so the 35 test-file splits have
a landing zone for shared helpers (it rejects any non-test_*.py module
under tests/).
- pylint max-module-lines 1000 -> 250, so both limits agree.
Note: .git/hooks/pre-commit was never installed in this repo (only
pre-push), so no commit-stage hook had ever run. Installed via
`pre-commit install`.
55 files are currently over the cap; they are split in following commits.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPpmMpTSkp8UziRc5u8B7P
mcp 2.0.0 removed the mcp.server.fastmcp module that _mcp.py imports, so the
unbounded `mcp>=1.9` let a fresh CI runner resolve to 2.0.0 and fail
collection with ModuleNotFoundError.
This did not reproduce locally: this machine has mcp 1.28.1 installed, and
ci_mirror.sh caches its clean venv on the hash of requirements.txt, so it
reused an environment resolved back when >=1.9 still meant 1.x. The mirror
validates the resolution you already have, not the one a new runner gets.
Verified against the CI interpreter: a fresh python 3.11 venv built from the
pinned requirements resolves mcp 1.29.0, imports FastMCP, and runs the full
suite -- 1322 passed at 100.00% branch coverage.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbEaXapjMSkxyzgvbdkUFb
Expose the backlog enforcer's read surface and two gated write actions as
typed MCP tools (steam_backlog_enforcer._mcp) so Claude Code and its
subagents can query and drive the backlog without shelling out.
- _mcp.py: FastMCP stdio server. Read tools get_dataset/get_status/
get_stats/list_backlog; gated writes pick_manual/block_gaming (preview
unless confirm=True). Logs to stderr; never exposes Config/the API key.
- _actions.py: stdout-free, state-only cores shared by CLI and MCP
(apply_manual_pick, status_payload, is_manual_pick_locked). cmd_pick_manual
now delegates its state mutation here.
- .mcp.json + scripts/setup_mcp.sh: project-scoped registration via a
dedicated ~/.venvs/steam-backlog-mcp interpreter; mcp is an optional-dep,
kept out of the systemd/CLI system-python path.
- pyproject: fix setuptools flat-layout discovery and declare the previously
undeclared direct deps aiohttp + websockets, un-breaking the editable install.
- 100% coverage of the new modules; server verified end-to-end over stdio.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LQGQj8Ne6TriBExv91nG8v