Overview
The hygiene conductor's config prescan (agents/conductors/hygiene/_hygiene_config.py) emits a single count|summary line naming how many library config keys are absent downstream and a per-target tally, and its main() accepts only --root. The hygiene skill tells the operator to route config findings onward for repair, but the mode hands over nothing routable — recovering the actual key paths today means importing the module and re-running diff() by hand.
This adds a --detail flag that prints each drifted key path grouped by the config file it is missing from, and does the same for the orphan_files signal the module already computes. The existing single-line output stays the default, so the conductor's summary table is unchanged.
Plan
- Split each of the two signals into a detail-producing core plus the existing count/tally wrapper, so the paths the module already computes internally become returnable instead of being discarded at the
len().
- Add
--detail to main(): drifted key paths grouped by the workspace config file that is missing them, and orphan config files grouped by their repo.
- Keep the default
count|summary line byte-identical — prescan_config in hygiene.sh calls the helper with --root only and parses ${out%%|*}, so the default scan's summary table must not move.
- Wire the
hygiene config single-mode branch in hygiene.sh to render the detail block, mirroring the existing refs / optdeps / extras single-mode branches, so the findings are reachable through the documented command surface rather than only by calling the helper directly.
- Add contract tests: default output unchanged,
--detail grouping for both signals, and --detail on a clean tree.
Detailed implementation plan
Affected Repositories
- PyAutoBrain (primary, only)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoBrain |
claude/hygiene-detail-flag-n1fgdq |
clean |
| ./PyAutoMind |
claude/hygiene-detail-flag-n1fgdq |
clean (prompt staged) |
Branch: claude/hygiene-detail-flag-n1fgdq (harness-designated; overrides the usual feature/<task-name> convention for this session)
Implementation Steps
-
agents/conductors/hygiene/_hygiene_config.py — key-mirror signal:
- Add
diff_detail(root, pairs=PAIRS) -> list[tuple[str, str, list[str]]], one record per (workspace repo, config filename, sorted missing dotted key paths). It walks the same library↔workspace pairs and applies the same skip rules (isdir pair check, missing workspace counterpart, unparseable YAML) as diff(), but keeps key_paths(lib) - key_paths(ws) instead of only its length.
- Re-express
diff() over diff_detail() so there is one traversal and the count can never disagree with the listing. Its (total, ["repo:N", ...]) return stays exactly as-is — tests/test_hygiene_conductor.py::test_config_helper_recursive_key_diff asserts it.
-
Same file — orphan signal:
- Add
orphan_detail(root, libraries=LIBRARIES, lib_relpaths=None, owners=ORPHAN_OWNERS) -> list[tuple[str, list[str]]], one record per (repo, sorted orphan relpaths), carrying the existing mirror self-scoping and ORPHAN_OWNERS suppression.
- Re-express
orphan_files() over it; its (total, ["repo:N", ...]) return is asserted by test_orphan_files_flags_unmirrored_and_suppresses_owned / test_orphan_files_skips_non_mirror_repos and stays unchanged.
-
Same file — main():
ap.add_argument("--detail", action="store_true").
- Default (no flag): print
f"{total}|{summary}" exactly as today.
- With
--detail: print the human summary sentence plus the grouped listing — each drifted key path under a <repo> config/<file> heading, each orphan file under its repo heading — and a closing routing pointer. A clean tree prints the in-sync line and no groups.
-
agents/conductors/hygiene/hygiene.sh:
- Add a
config branch to the human-footing if/elif chain (next to refs / optdeps / extras) that runs the helper with --detail and prints the /refactor routing line.
- Leave
prescan_config() untouched — it is what the default summary table and the --json row read.
-
tests/test_hygiene_conductor.py — extend the existing config block:
--detail names the drifted key paths, grouped under the file they are missing from (fixture: nested + top-level key drift).
--detail names orphan files grouped by repo, still suppressing build/ and priors/.
- Default output (no flag) is still exactly one
count|summary line, so the conductor's table cannot regress.
hygiene config single-mode output contains the drifted key paths.
Verification against the live checkouts
The scan currently reports 19 drifted keys (autofit_workspace:3 autogalaxy_workspace:15 autolens_workspace:1). --detail must resolve those to: autofit_workspace general.yaml (output.search_internal, test.check_likelihood_function) and logging.yaml (total_files_open); autogalaxy_workspace general.yaml (test.exception_override) plus 14 notation.yaml labels (multipoles, virial mass/overdensity, GRF and InputPotential superscripts); autolens_workspace general.yaml (output.fit_dill).
Key Files
agents/conductors/hygiene/_hygiene_config.py — the prescan helper; both signals and main().
agents/conductors/hygiene/hygiene.sh — prescan_config() (unchanged) and the single-mode human branch (new).
tests/test_hygiene_conductor.py — contract tests for the CLI footing.
Original Prompt
Click to expand starting prompt
# Add a --detail flag to the hygiene config scan so
Type: feature
Target: PyAutoBrain
Repos:
- PyAutoBrain
Difficulty: small
Autonomy: safe
Priority: normal
Status: formalised
Add a --detail flag to the hygiene config scan so its findings are routable. The config scan in PyAutoBrain agents/conductors/hygiene/_hygiene_config.py emits only a 'count|summary' line naming how many library config keys are absent downstream and a per-target tally. Its main() accepts only --root and prints that one line, so there is no way to see which key paths actually drifted. The hygiene skill tells the operator to route config findings onward for repair, but the mode hands over nothing routable: recovering the key paths currently means importing the module and re-running its diff() internals by hand. Add a --detail flag that prints each drifted key path grouped by the config file it is missing from, keeping the existing single-line output as the default so the conductor's summary table is unchanged. Extend the same treatment to the orphan_files signal the module already computes.
<!-- formalised by the Intake (Conception) Agent on 2026-08-05 -->
Overview
The hygiene conductor's
configprescan (agents/conductors/hygiene/_hygiene_config.py) emits a singlecount|summaryline naming how many library config keys are absent downstream and a per-target tally, and itsmain()accepts only--root. The hygiene skill tells the operator to route config findings onward for repair, but the mode hands over nothing routable — recovering the actual key paths today means importing the module and re-runningdiff()by hand.This adds a
--detailflag that prints each drifted key path grouped by the config file it is missing from, and does the same for theorphan_filessignal the module already computes. The existing single-line output stays the default, so the conductor's summary table is unchanged.Plan
len().--detailtomain(): drifted key paths grouped by the workspace config file that is missing them, and orphan config files grouped by their repo.count|summaryline byte-identical —prescan_configinhygiene.shcalls the helper with--rootonly and parses${out%%|*}, so the default scan's summary table must not move.hygiene configsingle-mode branch inhygiene.shto render the detail block, mirroring the existingrefs/optdeps/extrassingle-mode branches, so the findings are reachable through the documented command surface rather than only by calling the helper directly.--detailgrouping for both signals, and--detailon a clean tree.Detailed implementation plan
Affected Repositories
Branch Survey
Branch:
claude/hygiene-detail-flag-n1fgdq(harness-designated; overrides the usualfeature/<task-name>convention for this session)Implementation Steps
agents/conductors/hygiene/_hygiene_config.py— key-mirror signal:diff_detail(root, pairs=PAIRS) -> list[tuple[str, str, list[str]]], one record per(workspace repo, config filename, sorted missing dotted key paths). It walks the same library↔workspace pairs and applies the same skip rules (isdirpair check, missing workspace counterpart, unparseable YAML) asdiff(), but keepskey_paths(lib) - key_paths(ws)instead of only its length.diff()overdiff_detail()so there is one traversal and the count can never disagree with the listing. Its(total, ["repo:N", ...])return stays exactly as-is —tests/test_hygiene_conductor.py::test_config_helper_recursive_key_diffasserts it.Same file — orphan signal:
orphan_detail(root, libraries=LIBRARIES, lib_relpaths=None, owners=ORPHAN_OWNERS) -> list[tuple[str, list[str]]], one record per(repo, sorted orphan relpaths), carrying the existing mirror self-scoping andORPHAN_OWNERSsuppression.orphan_files()over it; its(total, ["repo:N", ...])return is asserted bytest_orphan_files_flags_unmirrored_and_suppresses_owned/test_orphan_files_skips_non_mirror_reposand stays unchanged.Same file —
main():ap.add_argument("--detail", action="store_true").f"{total}|{summary}"exactly as today.--detail: print the human summary sentence plus the grouped listing — each drifted key path under a<repo> config/<file>heading, each orphan file under its repo heading — and a closing routing pointer. A clean tree prints the in-sync line and no groups.agents/conductors/hygiene/hygiene.sh:configbranch to the human-footingif/elifchain (next torefs/optdeps/extras) that runs the helper with--detailand prints the/refactorrouting line.prescan_config()untouched — it is what the default summary table and the--jsonrow read.tests/test_hygiene_conductor.py— extend the existing config block:--detailnames the drifted key paths, grouped under the file they are missing from (fixture: nested + top-level key drift).--detailnames orphan files grouped by repo, still suppressingbuild/andpriors/.count|summaryline, so the conductor's table cannot regress.hygiene configsingle-mode output contains the drifted key paths.Verification against the live checkouts
The scan currently reports 19 drifted keys (
autofit_workspace:3 autogalaxy_workspace:15 autolens_workspace:1).--detailmust resolve those to: autofit_workspacegeneral.yaml(output.search_internal,test.check_likelihood_function) andlogging.yaml(total_files_open); autogalaxy_workspacegeneral.yaml(test.exception_override) plus 14notation.yamllabels (multipoles, virial mass/overdensity, GRF andInputPotentialsuperscripts); autolens_workspacegeneral.yaml(output.fit_dill).Key Files
agents/conductors/hygiene/_hygiene_config.py— the prescan helper; both signals andmain().agents/conductors/hygiene/hygiene.sh—prescan_config()(unchanged) and the single-mode human branch (new).tests/test_hygiene_conductor.py— contract tests for the CLI footing.Original Prompt
Click to expand starting prompt