WP-203 — gate, CI and test infrastructure¶
Engineering log · Phase 19 — Codebase audit remediation
WP-203 — the gate, the workflows and the test scaffolding, consolidated in one commit¶
Batch 3 of the codebase-audit roadmap. The audit of 2026-10-21 found a gate target that could skip its own check, the same helpers copied across the repo-content checkers and the test tree, and workflows that spent the critical path on serial pytest. Nothing here changes shipped behaviour except the declared jsonargparse floor. The gate is make gate, as for every package (AGENTS.md sec. 1, D30); it will be run before the commit is made, and this page claims no result for it.
Gate and lint tooling. make golden runs scripts/check_goldens.py unguarded, so a missing harness fails instead of printing a skip line. make test takes COV (default --cov=lucid_yolo --cov-report=term; a CI cell that measures nothing passes COV=) and PYTEST_XARGS (default -n auto). Shared helpers replace per-checker copies: REPO_ROOT, the --repo-root argument, sorted_rglob and the failure printer in scripts/lint/_common.py, and REPO_ROOT and one digest in scripts/_common.py; ten checkers plus check_goldens.py and freeze_goldens.py use them, and the _load_audit copies in the checker tests are one load_script in scripts/_tests/script_loader.py. Checker output and exit codes were diffed against HEAD over 25 invocations and are identical. The no-ipynb-tracked hook is now a stock language: fail hook on \.ipynb$, so audit_no_notebooks_tracked.py and its test are deleted and the hook runs on pre-commit.ci. Three hooks are new: test-name-filler-adverbs (the five padding adverbs of AGENTS.md sec. 2 in test names), tqdm-auto-only (over tests/, scripts/ and notebooks/, which ruff's per-file ignores exempt) and model-card-figures (scripts/lint/audit_model_card_figures.py, the wiring-gate figure on each model card against the golden it cites). tqdm.tqdm joins ruff's banned-api table for src/. The .pre-commit-config.yaml comment that counted twelve local hooks no longer counts.
Test tree. The 45 autouse seed fixtures that only called torch.manual_seed(0) are deleted; tests/conftest.py already seeds every test at the same scope and value, and tests/ptl/test_compile.py::isolate_dynamo, which also resets dynamo, stays. tests/fixtures/ gains markers.py (requires_cuda, requires_accelerator, the BF16 replay expectation), determinism.py (deterministic_algorithms, with two fixtures in tests/ptl/conftest.py), training.py (LogRecorder, has_gradient, tiny_module, collate_unpacked) and tensors.py (assert_bytes, seeded_generator), each replacing the copies the audit listed. Every in-body pytest.skip() became a per-case mark, so none is left under tests/, and the one cuda case of test_module.py that ran nowhere now carries requires_cuda. 91 sites in 18 files use the two markers. 39 test names lose a filler adverb; the one node id cited in a doc, in docs/ROADMAP.md, is updated, and two parametrized dtype tests change their ids (dtypeN to float32 and so on). No assertion changed. On the final tree the offline selection reads 4668 of 5029 collected with 361 deselected, against 4671 of 5031 and 360 at the start of the batch. Helper consolidation alone accounts for 12 fewer selected items (19 doctest items of deleted duplicates, less 8 doctest items of the new helpers, plus the one cuda case that moved to the deselected side) and adds or removes no test function; the rest of the delta is the batch's own test changes: the model-card figure checker's tests and the fixture-cache race and lock tests are added, and the notebook checker's tests are deleted with the checker.
Parallel suite. pytest-xdist>=3.5 joins the dev group and make test runs -n auto; PYTEST_XARGS= runs serially, which is how a failure is read, since xdist interleaves output. The synthetic fixture cache under tests/fixtures/_generated is rebuilt under one fcntl.flock per set and published by atomic rename, so a worker never reads a half-written set and a set any worker has returned is never moved away; a current set is read without taking the lock. The lock makes the test suite POSIX-only, which matches the Linux and macOS CI matrix. Wall time of make test on the 16-core development Mac, same tree and same 4612 passed / 47 skipped: 739 s serial (PYTEST_XARGS=), 207 s with -n auto on a warm cache, 228 s cold, 461 s at -n 4 (the width of a hosted runner); coverage stays 96.52% under xdist. No GitHub-side timing exists yet.
Workflows. The test matrix is ubuntu on 3.11, 3.12 and 3.13 plus one macOS cell on 3.13 (the principal's decision), with coverage measured only on ubuntu 3.11 through COV_ARGS; goldens are their own goldens job and testing-guardian needs the testing, goldens, wheel and workflows jobs. A composite action, .github/actions/wheel-smoke, builds the check shared by ci-tests.yml and release.yml: twine check, a wheel install into a venv outside the checkout, the four --help calls and one packaged config loaded through importlib.resources. Every checkout drops credentials except the docs publish step; docs.yml splits into a read-only build and a publish job that installs only ghp-import; every job has a timeout-minutes set from the recent run history; cache: pip is gone from all five places. ci-tests.yml gains a workflows job running actionlint and zizmor at pinned versions through uvx, so a workflow-audit failure turns the required testing-guardian context red. New: links.yml (weekly lychee run over the README and docs/, not a required check) and .github/dependabot.yml (github-actions, monthly, one group, seven-day cooldown). pyproject.toml raises jsonargparse[signatures] from >=4.28 to >=4.36, the first release that exports auto_cli, which lucid-eval and lucid-predict import; WP-202 had left that floor for this batch. A wheel built from this tree installed against jsonargparse 4.36.0 in a scratch venv printed usage for all four commands.
Left deliberately.
- Lint helpers, partial. Fence tracking is not unified:
audit_doctest_fencesfollows language-aware fences with offsets andaudit_wp_linkstoggles on three-backtick and tilde fences with a quote prefix, and merging them risks different output for no line saved.REPO_ROOTstays local inaudit_frozen_manifest,check_commit_trailers,absolutize_readme,golden_producers,overfit_micro,release_guardandshapes_regression, where the bootstrap needed to import the helper costs more than it removes;audit_frozen_manifestandcheck_commit_trailerskeep their own failure wording.audit_frozen_manifest._loadand theaudit_licensesfixture keep their own loaders. - Cross-task test stories are not merged:
tiny_moduletakes the task and its keyword arguments, and the obb, segment and keypoint files keep a thin binding of their own gains. - Skip gaps. The four
test_overfit_micro.pytests aregpuanddatawith no skip, the notebooks full run (test_runs_in_full) is the same, and the mps case intest_module.pyis a skip with nogpumark; all three are outside what this batch scoped and stay as they were. - Kept after review. The
img_sizedefault pinned intests/predict/test_predict_obb.py, the signature-bound spy intests/eval/test_eval_obb.pyand thebackenddefault intests/eval/test_coco_eval.pyassert documented public constants or library-boundary defaults and were not rewritten as behaviour tests; the principal may revisit the first. - CI proof is local.
actionlintandzizmorare clean and the wheel-smoke steps ran by hand, but no GitHub-side run exists: the matrixinclude, the composite action, theCOV_ARGSexpression, the docs artifact hop and lychee are untested live. The dropped macOS 3.11 and 3.12 cells must not be required checks in branch protection;testing-guardianis the documented required one.
No frozen golden is touched.