feat(hygiene): detect orphan config files by reachability (#155) - #156
Merged
Conversation
`/hygiene config` could not see orphan config FILES: `_hygiene_config.py`
iterated only LIBRARY yamls and skipped any without a workspace counterpart, so
a workspace file the libraries never shipped was structurally invisible. That
blind spot let a dead `config/grids.yaml` survive in 10 repos for ~a year
(autolens_workspace#317).
Add an orphan-file pass beside the existing key-mirror diff. A workspace
`config/**/*.yaml` with no library counterpart at the same relative path is an
orphan. The right test of a config file is REACHABILITY (does anything read
it), not filename similarity — a pure filename check is ~120 hits, nearly all
legitimate, because whole subtrees are owned by something other than the
libraries. Those owners are named in an explicit ORPHAN_OWNERS map and
suppressed: `build/*` (PyAutoHands release tooling) and `priors/*`
(JSONPriorConfig class-path resolution). Deliberately an in-checker map, NOT a
per-repo `.hygieneignore` — 20 new files and a config surface that can itself
go stale is the exact failure mode being fixed.
The library's own shipped set encodes the verdict: it ships
`non_linear/GridSearch.yaml` (live) but not `non_linear/{nest,mle,mcmc}.yaml`
(dead), so the pass keeps the first and surfaces the rest with no per-file rule.
Only repos whose config/ MIRRORS the library tree (share >=1 file) are scanned,
which self-scopes to the workspace/test/assistant repos and excludes organ
repos without a hardcoded list.
Acceptance (all verified): flags the real pre-#317 `grids.yaml` blob, flags
`non_linear/*` on today's tree, stays silent on `build/*` and `priors/*`. A
check that cannot re-find the bug that motivated it is not validated.
Folded into the same `count|summary` prescan line; stdlib+PyYAML only; the
PyYAML-absent `sys.exit(1)` fallback is preserved.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 1 of PyAutoBrain#155 — the detector
/hygiene configcould not see orphan config files._hygiene_config.pyiterated only library yamls and skipped any without a workspace counterpart, so a workspace file the libraries never shipped was structurally invisible — how a deadconfig/grids.yamlsurvived in 10 repos for ~a year (autolens_workspace#317).What this adds
An orphan-file pass beside the existing key-mirror diff. A workspace
config/**/*.yamlwith no library counterpart at the same relative path is an orphan.The signal is reachability, not filename similarity — a pure filename check is ~120 hits, nearly all legitimate, because whole subtrees are owned by something other than the libraries. Those owners are named in an explicit
ORPHAN_OWNERSmap and suppressed:build/*→ PyAutoHands release toolingpriors/*→JSONPriorConfigclass-path resolutionDeliberately an in-checker map, not a per-repo
.hygieneignore— 20 new files and a config surface that can itself go stale is the exact failure mode being fixed.The library's own shipped set encodes the verdict: it ships
non_linear/GridSearch.yaml(live) but notnon_linear/{nest,mle,mcmc}.yaml(dead), so the pass keeps the first and surfaces the rest with no per-file rule. Only repos whoseconfig/mirrors the library tree (share ≥1 file) are scanned, self-scoping to workspace/test/assistant repos and excluding organ repos — no hardcoded list.Acceptance (all verified)
grids.yamlblobnon_linear/{nest,mle,mcmc}.yamltodaybuild/*priors/*A check that cannot re-find the bug that motivated it is not validated — the grids.yaml retrospective runs against the real blob at
ce99ca12b^.What it found
Running it surfaced 26 dead
non_linearfiles across 9 repos and a third cluster the ticket did not name —visualize/include.yamlin 2 test repos (no library ships it, nothing readsconf.instance["visualize"]["include"], noInclude2Dclass, user-facing workspaces already dropped it). Both are removed in the Part-2 PRs below.Tests
tests/test_hygiene_conductor.py: a suppressed-vs-flagged orphan fixture (the owner map is the part most likely to rot) and a non-mirror-repo skip.16 passed. Stdlib+PyYAML only; the PyYAML-absentsys.exit(1)fallback preserved; folded into the samecount|summaryprescan line.Part 2 — cleanup PRs (the dead config this found)
autocti_assistant, autocti_workspace, autocti_workspace_test, autofit_workspace_developer, autofit_workspace_test, autogalaxy_workspace_test, autolens_assistant, autolens_workspace_test, euclid_strong_lens_modeling_pipeline — all on
feature/hygiene-orphan-config-files.Closes #155.