The archive reached zero ruff findings this morning, so the standing rule in
.pre-commit-config.yaml -- a hook lands only once the thing it gates is clean
-- is finally satisfied for ruff. `ruff check` and `ruff format --check` are
hooks now, pinned at v0.16.5 per rules/dependency-freshness, plus
`no-suppressions`, which rejects `# noqa` and `# type: ignore`. CLAUDE.md has
always claimed a hook did that; until now the only thing stopping them was
whoever was reading ruff's output, and I typed `# noqa-free` three times in
this session by accident. mypy stays out: six of its errors are third-party
typing limits rather than our code.
The first attempt used `language: system`, which passed `pre-commit run
--all-files` and then failed the actual commit with "Executable `ruff` not
found" -- git hooks do not get ~/.local/bin on PATH. Taking the hooks from
astral-sh/ruff-pre-commit means pre-commit installs ruff itself, which is also
what makes the pin mean anything.
`ruff format --check` failed the moment it was wired up, on four TRAK files I
wrote today and never formatted. Formatted, and the ray_tracing0 render is
still 02484bdb6b6c1ddeff317d7e5566580f.
Then the run guard from f780d023 needed proving on more than TRAK, since it
now applies to every course kind. make, cpp and python courses pass it; node
and target and obj are all properly gitignored, so npm, maven and dotnet
builds cannot trip it either. But NotProgramming/MOM failed, and not because
of the guard:
`_first_file '*.tex'` used `find -print -quit`, which returns whatever readdir
hands back. After the 19 reports were split into sections, that was
`report_three/sections/02-model-dwukryterialny.tex`, and latexmk faithfully
tried to typeset a bare `\section` as a document. DOCS-runnability.md has
recorded MOM as runnable throughout. The tex branch now picks a file that
actually contains `\documentclass`.
Deliberately not sorted, and that is the interesting part. Sorting is the
obvious fix and it made things worse: it swapped ELAC's pick to projectA and
AIS's to report/final/ver1, both of which fail with latexmk exit 12. Those two
documents are broken independently, and sorting merely surfaced them; turning
two green courses red to fix a third is a bad trade. Recorded in
TODO-refactor-remaining.md instead. MOM, ELAC, AIS, SPD, ZPOB, SDM, DPZ and
ESOEN all exit 0 now.
`_works` also grew a `timeout 5`, because `unityhub --version` never returns
on this machine and a probe without one would hang the status sweep.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
494 ruff findings to 0, and mypy --strict is clean too -- the first course in
this campaign where that is true of both.
Two real bugs turned up on the way, neither of which ruff can see:
- `main.py` passed `args.environment_map` to `ray_trace`, and argparse only
ever defined `--environment`. Every `--algorithm ray_tracing0` run died with
AttributeError before rendering a pixel, so `rendering.py` -- the largest
file in the course -- had no way to be exercised at all.
- `mouse_button` in the environment-map viewer assigned `mouse_last_x/y`
without declaring them `global`, so the drag origin went to locals and was
thrown away. Measured against HEAD: a 10x5 px drag turned the camera by
11.0/20.5 degrees because it measured from (0, 0); it is 1.0/0.5 now, which
is what the 0.1 degrees-per-pixel constant says it should be.
Fixing the first one is what made the rest safe. `ray_tracing0` has no RNG
anywhere in it, so it renders byte-identically every time, and the whole
refactor of `rendering.py` is verified by one md5 comparison:
02484bdb6b6c1ddeff317d7e5566580f, 248619 rays, before and after. The
cornell_box path cannot do that -- its ray count drifts by ~20 between
identical runs.
Three files were over the 250-line cap and are now split, geometry away from
the algorithm that uses it: rendering.py 462 -> 137 + raytracer.py,
photon_mapping.py 261 -> 160 + photon_geometry.py, and
code/photonmapping/python/main.py 257 -> 203 + geometry.py. No TRAK source
file is over the cap now.
The two photon mappers do use numpy's legacy global RNG, so NPY002 could not
be bit-identical. Each was done in two steps: restructure first, verified
identical under an external seed (digests 7220370f60206a62 and
21b4771504ab2351, and an identical 828 photon traces), then the swap to
`default_rng` on its own, checked against the before/after distributions.
Verified by running, not by reading:
- cornell_box through `./run.sh run Programming/TRAK`: 24.27s, 13294 rays
- all five scenes build after `from sightpy import *` became explicit imports
- the standalone photon mapper end to end: 81.4s, 38742 photon traces
- the EXR loader byte for byte: a0c3890350ce6101247c6948, 6291456 bytes
- the GLUT viewer under xvfb-run, which drew a real 1024x512 frame
`pyproject.toml` gains a mypy override for Imath, OpenEXR, OpenGL and
matplotlib. Those four ship neither stubs nor py.typed, and without it mypy
cannot import them at all and so reports nothing else about the file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kuhy overruled the "do not fix coursework to be better than it was submitted"
rule: git history is the archive, so the working tree can be clean. This lands
the config and the mechanical half of the cleanup -- 9,281 ruff findings under
the fleet config down to 3,686, with no per-file-ignores anywhere.
What is in here:
- pyproject.toml, the first one in this repo. select = ["ALL"], mypy strict,
and the vendored list mirrored into ruff exclude and coverage omit. Five
rules are off and each says why; CPY001 is the only judgement call, because
stamping a copyright header onto 137 university assignments would assert a
licence that was never claimed. No hook is wired up yet -- a gate lands only
once its subject is clean.
- ruff format + the safe fixes, then a second pass over the docstring rules
ruff marks unsafe (they only edit docstring text). 108 files.
- TRAK/sightpy is vendored, not coursework: it is rafael-fuente/Python-Raytracer
(BSD 3-Clause). Verified against a fresh upstream clone with line endings
normalised -- 30 of 32 files byte-identical, ray.py and scene.py carrying a
12- and 13-line local patch that counts rays for the report. 35 files that
should never have been linted, now excluded and restored.
- WDWR, SPD, MOM and ECRYPT are fully clean, by hand and verified by running
them: WDWR's three plot scripts print the same statistics as before, MOM's
PuLP model solves to the same cost. WDWR's graph.py had a 342-character CSV
header embedded as a string literal, which cannot be wrapped -- the data
moved to data/pareto_front.csv. Two 0-byte .py stubs are deleted; an empty
file is not a deliverable and git still has it.
Three harness bugs found by actually running things:
- `run` now forces MPLBACKEND=Agg. TRAK finished its ray trace in 37 seconds
and then sat for 45 minutes: plt.show() had opened an image viewer and was
waiting for someone to close the window.
- TRAK's main.py only pops that viewer with --show now, and its runner writes
to a gitignored build/ via the new --entry-args. The default output path is
outputs/output.png, which is TRACKED -- a plain run overwrote a submitted
deliverable.
- course_lib.sh was 357 lines, over this repo's own cap. Split into
course_probe.sh and course_run.sh.
Verified: ECOTE 26 tests pass, ECRYPT_PROJECT 99 pass, TRAK renders
cornell_box in 37s and exits 0, every module compiles, and every import ruff
removed was checked to be genuinely unused.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE