earned_time 0.4.0 only changes shutdown resolution and adds the workout
ledger reader; every gaming_minutes this daemon reads is identical for every
input, so no code change here. Also brings aiohttp 3.14.4 and types-requests
2.33.0.20261006 to newest stable, which the dependency-freshness gate needs
before any commit to these manifests can land.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrjUTo1yhgAsUUasdw4bpG
hltb, _cmd_done, _whitelist and _actions each kept a module __getattr__
that served names moved out in the 250-line split, via importlib to
dodge the resulting import cycle. pylint cannot see through that, and
graded every such import as no-name-in-module (26 of them). The 32
import statements now name the real module; with nothing left going
through the facades, they are gone.
Also the pylint hook on 4.0.8 with the source-only scope config, the
three implicit-booleaness disables the reference repos carry, the
http.server do_GET admission, and the third-party pins the hook was
missing (aiohttp, websockets, howlongtobeatpy). Gate still 8.0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHCbkJWXHjtTUaqvnHRAqA
Also bumps mcp 2.2.0, ruff 0.16.7, types-requests 2.33.0.20260906 and, in
web/, react 19.3.0, vitest 5.0.0 (+ coverage-v8), eslint 10.10.0,
typescript-eslint 8.70.0, vite 8.3.0 and the small ones, so the freshness
gate lets this through. Web lint/build/tests/coverage (100 %) unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AwtowrowDXx6ccmWVPkCaF
`requires-python` and the CI pin already said 3.14, but ruff, mypy and pylint
were still grading against 3.10 -- three tools judging an interpreter nothing
runs any more, and ruff withholding the pyupgrade fixes that only become safe
at the newer target. `pin_ci_python.py` rewrites exactly these three knobs.
What the stale target was hiding: `datetime.timezone.utc` where `datetime.UTC`
is now correct (UP017), `socket.timeout` where `TimeoutError` is (UP041),
deprecated `typing` imports (UP035), PEP 695 `type` aliases (UP040), and ruff's
stable formatter applying PEP 758 -- `except (A, B):` becomes `except A, B:`.
That last one makes the source 3.14-only at the syntax level, which is what
`requires-python = ">=3.14"` already promised; kuhy chose it deliberately over
holding ruff a release back (2026-08-29).
ruff, ruff-format, mypy --strict and pylint all clean at the new target. The
two modified web/ TypeScript files are another session's in-flight work and
are deliberately left unstaged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SfnJmxxsZ534AKk16rC2Gr
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