Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agents/conductors/feature/MIND_TAXONOMY.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ context when memory has material. Sub-wikis (source: `PyAutoMemory/index.md`):
| `wiki/galaxies/` | galaxy formation & evolution | bulge/disk, MGE, morphology, IFU, kinematics |

Library targets also pull a default sub-wiki (`autolens`→lensing,
`autogalaxy`→galaxies, `autofit`/`autoarray`/`autoconf`→methods). PyAutoMemory is
`autogalaxy`→galaxies, `autofit`/`autoarray`/`autonerves`→methods). PyAutoMemory is
**optional**: if the checkout is absent the agent still names the sub-wikis to
read, degrading gracefully rather than failing.

Expand Down
2 changes: 1 addition & 1 deletion agents/conductors/health/health.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ REFRESH_CMD = {
}

def repo_of(reason):
# "PyAutoConf: on branch ..." -> "PyAutoConf"; else None.
# "PyAutoNerves: on branch ..." -> "PyAutoNerves"; else None.
m = re.match(r"\s*([A-Za-z0-9_\-]+)\s*:", reason)
return m.group(1) if m else None

Expand Down
2 changes: 1 addition & 1 deletion agents/conductors/hygiene/hygiene.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ CONDEMN_TRANSIT_DAYS="${HYGIENE_CONDEMN_TRANSIT_DAYS:-30}"
# fast stdlib modules); HYGIENE_PERF_THRESHOLD (s) is the slow cutoff.
PERF_PY="${HYGIENE_PYTHON:-python3}"
PERF_THRESHOLD="${HYGIENE_PERF_THRESHOLD:-3.0}"
read -r -a PERF_LIBS <<< "${HYGIENE_PERF_LIBS:-autoconf autofit autoarray autogalaxy autolens}"
read -r -a PERF_LIBS <<< "${HYGIENE_PERF_LIBS:-autonerves autofit autoarray autogalaxy autolens}"

MODE_ORDER=(perf tidy crlf docstrings escapes refs optdeps extras artifacts packaging noise deps docs config)
declare -A MODE_DELEGATE=(
Expand Down
7 changes: 3 additions & 4 deletions bin/ensure_workspace_labels.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
#
# Exits 0 on success, 1 if any API call fails.
#
# Repos with non-PyAutoLabs orgs:
# - Jammy2211/euclid_strong_lens_modeling_pipeline
# - rhayes777/PyAutoConf, rhayes777/PyAutoFit
# All others are under PyAutoLabs/.
# Every repo below is under PyAutoLabs/ — the pre-migration rhayes777/ and
# Jammy2211/ homes are gone. Owners come from the body map's `github:` field
# (PyAutoMind/repos.yaml); never hardcode a legacy owner default.

set -euo pipefail

Expand Down
12 changes: 6 additions & 6 deletions config/policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ repo_aliases:
al: autolens
pyautoarray: autoarray
pyautofit: autofit
pyautoconf: autoconf
pyautogalaxy: autogalaxy
pyautolens: autolens
pyautonerves: autonerves
autoconf: autonerves # back-compat: the Nerves package was renamed autoconf → autonerves
pyautoconf: autonerves # back-compat: the Nerves repo was renamed PyAutoConf → PyAutoNerves
pyautobuild: pyautohands # back-compat: the Hands repo was renamed PyAutoBuild → PyAutoHands

# Which body-map categories mean "library-flow" / "workspace-flow" /
Expand Down Expand Up @@ -67,14 +69,12 @@ target_default_wiki:
autogalaxy: galaxies
autofit: methods
autoarray: methods
autoconf: methods # legacy name — the Nerves repo was PyAutoConf
autonerves: methods
pyautonerves: methods
autonerves: methods # the PyAutoConf/autoconf spellings alias here

# Refactor conductor: normalised repo -> the test dir that witnesses
# behaviour preservation.
test_witness:
autoconf: PyAutoConf/test_autoconf
autonerves: PyAutoNerves/test_autonerves
autofit: PyAutoFit/test_autofit
autoarray: PyAutoArray/test_autoarray
autogalaxy: PyAutoGalaxy/test_autogalaxy
Expand All @@ -84,7 +84,7 @@ test_witness:
# Release policy (NOT identity: the released set is a deliberate subset of
# the body map's libraries — e.g. PyAutoReduce is not in the nightly matrix).
release:
relevant_repos: [PyAutoConf, PyAutoFit, PyAutoArray, PyAutoGalaxy, PyAutoLens,
relevant_repos: [PyAutoNerves, PyAutoFit, PyAutoArray, PyAutoGalaxy, PyAutoLens,
autofit_workspace, autogalaxy_workspace, autolens_workspace,
HowToFit, HowToGalaxy, HowToLens]
tag_repo: PyAutoLabs/PyAutoLens
Expand Down
2 changes: 1 addition & 1 deletion skills/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ gets rediscovered twice, it belongs here.
- **`PYAUTO_TEST_MODE` namespaces output under `output/test_mode/`.** Any
manually composed output path must include that segment or asserts read the
wrong tree.
- **autoconf lowercases YAML dict keys** (`muJy` → `mujy`). Keep config keys
- **autonerves lowercases YAML dict keys** (`muJy` → `mujy`). Keep config keys
and the registries that read them snake-case-lowercase from the start.
- **New library `output.yaml` keys need mirroring** into each workspace's
config copy — workspace configs override library defaults, so a key added
Expand Down
7 changes: 5 additions & 2 deletions skills/repo_cleanup/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,8 @@ open PR that are merged to `main`
(`gh api repos/<owner>/<repo>/compare/main...<branch>` → `ahead_by == 0`) as
**candidates** only. Do not delete remotely; recommend running on a local-dev
checkout to complete the sweep (which re-audits against local state). Skip
stash/dirty sections. Owner mapping: PyAutoConf/PyAutoFit → `rhayes777`, else
`Jammy2211`.
stash/dirty sections. Resolve each repo's `<owner>/<repo>` from the `github:`
field in `PyAutoMind/repos.yaml` (the body map is the single source of repo
identity) — do not assume a default owner. Nearly every repo is under
`PyAutoLabs/`; the pre-migration `rhayes777/` and `Jammy2211/` homes are gone
bar the two the body map still records.
14 changes: 13 additions & 1 deletion tests/test_activity_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,17 @@ def test_anchor_validator():
def test_release_relevant_set_is_the_design_set():
# Design §4: 5 libraries + 3 workspaces + 3 HowTo repos.
assert len(activity_gate.RELEASE_RELEVANT_REPOS) == 11
for repo in ("PyAutoConf", "autolens_workspace", "HowToFit"):
for repo in ("PyAutoNerves", "autolens_workspace", "HowToFit"):
assert repo in activity_gate.RELEASE_RELEVANT_REPOS
# The pre-rename name must not linger: nightly.sh fetches
# `repos/<org>/$repo/commits` for each entry verbatim, so the gate must
# never depend on GitHub answering the old name via a rename redirect.
assert "PyAutoConf" not in activity_gate.RELEASE_RELEVANT_REPOS


def test_nerves_commit_qualifies_the_night():
# The rename acceptance criterion (PyAutoBrain#267): a commit on the Nerves
# repo must COUNT as qualifying activity under the name the driver fetches.
v = activity_gate.judge({"PyAutoNerves": [commit()]})
assert v["active"] is True
assert v["counts"]["PyAutoNerves"] == 1
92 changes: 92 additions & 0 deletions tests/test_nerves_rename_complete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""tests/test_nerves_rename_complete.py — the PyAutoConf → PyAutoNerves rename
stays finished.

PyAutoBrain#267: the repo/package rename (``PyAutoConf`` → ``PyAutoNerves``,
``autoconf`` → ``autonerves``) was completed in the reader-facing docs but left
live sites behind — a policy alias resolving to a key the body map does not
know, a refactor witness pointing at a deleted repo path, the nightly activity
gate polling the old repo name, and ``/hygiene`` timing an import that no longer
exists. Every one of those was silent: nothing failed, the surfaces just stopped
seeing the Nerves repo.

This test is the prompt's grep acceptance, enforced. The old spellings are
allowed to survive only where they are deliberately *about* the rename — the
history note, the back-compat aliases, and the tests that pin them.
"""

from __future__ import annotations

import re
import subprocess
from pathlib import Path

BRAIN_HOME = Path(__file__).resolve().parents[1]

# Paths where a pre-rename spelling is deliberate. Each entry is a reason, not a
# waiver: deleting the reason means deleting the entry.
DELIBERATE = {
# The organism's own record of the rename having happened.
"ORGANISM.md",
# The back-compat alias table — old @-mentions in ~150 archived Mind prompts
# must keep routing to the Nerves repo.
"config/policy.yaml",
# The intake conductor's own legacy alias, labelled as such.
"agents/conductors/intake/_intake.py",
# The tests that pin the aliases and the gate's repo set.
"tests/test_policy_seams.py",
"tests/test_activity_gate.py",
"tests/test_nerves_rename_complete.py",
}

# `autoconf` also appears inside unrelated words in third-party contexts (GNU
# autoconf, `auto_config`), so match the PyAuto spellings as whole tokens.
STALE = re.compile(r"(?<![A-Za-z0-9_])(PyAutoConf|autoconf)(?![A-Za-z0-9_])")


def _tracked_files() -> list[str]:
out = subprocess.run(
["git", "-C", str(BRAIN_HOME), "ls-files"],
capture_output=True, text=True, check=True,
)
return [line for line in out.stdout.splitlines() if line]


def test_no_undeclared_pyautoconf_references():
offenders: dict[str, list[str]] = {}
for rel in _tracked_files():
if rel in DELIBERATE:
continue
path = BRAIN_HOME / rel
try:
text = path.read_text(encoding="utf-8")
except (UnicodeDecodeError, FileNotFoundError, IsADirectoryError):
continue # binary or a submodule pointer — nothing to grep
hits = [
f"{rel}:{n}: {line.strip()}"
for n, line in enumerate(text.splitlines(), 1)
if STALE.search(line)
]
if hits:
offenders[rel] = hits

assert not offenders, (
"pre-rename PyAutoConf/autoconf spellings outside the deliberate set — "
"rename them, or add the path to DELIBERATE with the reason:\n"
+ "\n".join(h for hits in offenders.values() for h in hits)
)


def test_deliberate_set_has_no_dead_entries():
"""A path that no longer carries the old spelling must leave DELIBERATE.

Otherwise the allowlist silently grows into a blanket waiver.
"""
tracked = set(_tracked_files())
dead = []
for rel in sorted(DELIBERATE):
if rel not in tracked:
dead.append(f"{rel} (not tracked)")
continue
if not STALE.search((BRAIN_HOME / rel).read_text(encoding="utf-8")):
dead.append(f"{rel} (no longer mentions it)")
assert not dead, "stale DELIBERATE entries: " + ", ".join(dead)
36 changes: 35 additions & 1 deletion tests/test_policy_seams.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ def test_aliases_normalise_known_mentions():
assert _sizing.normalise_repo("PyAutoFit") == "autofit"


def test_nerves_spellings_share_one_canonical_key():
# PyAutoBrain#267: before the rename cleanup `@PyAutoConf` normalised to
# `autoconf` and `@PyAutoNerves` to `pyautonerves` — two dead keys for one
# repo, neither of them in the body map. All four spellings must land on the
# single key the policy maps are written against.
for mention in ("PyAutoNerves", "@autonerves", "PyAutoConf", "@autoconf"):
assert _sizing.normalise_repo(mention) == "autonerves", mention
# ...and that key must be a repo the organism actually knows about.
assert "autonerves" in _sizing.KNOWN_REPOS


def test_memory_wikis_route_science_vocabulary():
wikis = _sizing.MEMORY_WIKIS
# Keys are the wiki/<domain>/ names (the *_wiki root layout is retired).
Expand All @@ -68,7 +79,9 @@ def test_feature_default_wiki_loads():
import _feature

assert _feature.TARGET_DEFAULT_WIKI["autolens"] == "lensing"
# The Nerves rename is covered both ways (legacy autoconf + autonerves).
# The Nerves repo resolves under every spelling, via the alias table rather
# than duplicate wiki rows (PyAutoBrain#267).
assert _feature.TARGET_DEFAULT_WIKI[_sizing.normalise_repo("PyAutoConf")] == "methods"
assert _feature.TARGET_DEFAULT_WIKI["autonerves"] == "methods"


Expand All @@ -77,6 +90,11 @@ def test_refactor_test_witness_loads():
import _refactor

assert _refactor.TEST_WITNESS["autofit"] == "PyAutoFit/test_autofit"
# PyAutoBrain#267: the Nerves suite is real (test_autonerves, 157 tests), so
# a refactor touching it must not be reported `[unwitnessed: pyautonerves]`.
assert _refactor.TEST_WITNESS["autonerves"] == "PyAutoNerves/test_autonerves"
for mention in ("PyAutoNerves", "@autonerves", "PyAutoConf"):
assert _sizing.normalise_repo(mention) in _refactor.TEST_WITNESS, mention


def test_release_policy_loads():
Expand All @@ -87,6 +105,22 @@ def test_release_policy_loads():
assert "PyAutoMind" not in activity_gate.RELEASE_RELEVANT_REPOS


def test_release_relevant_repos_all_exist_in_the_body_map():
"""The drift guard PyAutoBrain#267 was missing.

``nightly.sh`` fetches ``repos/<org>/$repo/commits`` for every name in
this list verbatim. A repo renamed in the body map but not here leaves the
gate polling a name that only a GitHub rename redirect could answer — which
is how ``PyAutoConf`` survived the Nerves rename. Pin the set to identity.
"""
sys.path.insert(0, str(BRAIN_HOME / "agents" / "conductors" / "release"))
import activity_gate

known = set(_sizing._body_map_categories())
unknown = [r for r in activity_gate.RELEASE_RELEVANT_REPOS if r not in known]
assert not unknown, f"not in PyAutoMind/repos.yaml: {unknown}"


def test_nightly_tag_repo_resolves():
here = BRAIN_HOME / "agents" / "conductors" / "release"
out = subprocess.run(
Expand Down
Loading