diff --git a/active.md b/active.md index 6d4cf305..fb25a165 100644 --- a/active.md +++ b/active.md @@ -13,36 +13,3 @@ - registered: 2026-08-19 by the wake_up session — the issuing session (claude/autofit-priors-messages-audit-ylvenv) filed the prompt + issue but not this entry, tripping Lifecycle Drift on main. - repos-none-claimed: this entry claims NO repos — one line deliberately, not 2-space bullets. - -## organ-repo-spelling-splits -- issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/287 -- issued: 2026-08-26 -- prompt: active/organ_repo_spellings_split_across_keys.md -- status: ready-to-ship — implemented and pushed on both branches; no PR opened - yet (PyAutoMind e160d40b, PyAutoBrain 6329db8). 515 Brain tests pass, - repos_sync --check all 13 legs OK, Heart NOT EVALUATED (web-github). -- worktree: n/a — web-github session; the session's own PyAutoBrain + PyAutoMind - clones are the checkout, on the designated branch below (no - ~/Code/PyAutoLabs-wt/ worktree exists in this environment). -- repos: - - PyAutoBrain: claude/organ-repo-spelling-splits-hbbms0 - - PyAutoMind: claude/organ-repo-spelling-splits-hbbms0 -- summary: | - Infrastructure task (organism repos only). Fourth instance of the - hand-maintained-aliases vs derived-target-set defect class (#267, #269); - this one closes the class. Keying decision taken up front per the prompt: - organs key PREFIXED (`pyautobrain`), extending #271's rule — canonical key - is the bare package name where the repo ships one, the repo name where it - does not. Fix derives the bare/prefixed/package alias join from the body - map (new `package:` identity key in repos.yaml) and adds three coverage - guards to test_policy_seams.py. Sweep also covers PyAutoScientist and - pyautolabs.github.io, both split/unresolvable and not named in the prompt. - Heart unreachable from this environment — ship gate leg 4 records NOT - EVALUATED. - - DEVIATION from the answered scope question: `pyautolabs.github.io` was - deliberately DE-REGISTERED rather than joined. Joining it means aliasing its - truncated head `pyautolabs`, which is the ORG name — `@PyAutoLabs/PyAutoFit` - would then resolve to the static site instead of PyAutoFit. The acceptance - criterion's other branch ("or is deliberately not registered") covers it, and - a guard pins both halves. Raised for review at ship time. diff --git a/active/organ_repo_spellings_split_across_keys.md b/active/organ_repo_spellings_split_across_keys.md deleted file mode 100644 index 45c40534..00000000 --- a/active/organ_repo_spellings_split_across_keys.md +++ /dev/null @@ -1,72 +0,0 @@ -# Organ repo spellings split across two normalised keys - -Type: bug -Target: pyautobrain -Repos: -- PyAutoBrain -Difficulty: large -Autonomy: supervised -Priority: normal -Status: formalised -Filed: 2026-08-24 -Issued: 2026-08-26 - -Found while shipping the refactor witness-map audit (@PyAutoBrain#269 / PR #271). - -## The defect - -The bare spellings of the organ repos do not normalise to the same key as their -repo spellings, so a policy map keyed on one is invisible to the other. - -@PyAutoBrain/agents/faculties/sizing/_sizing.py (`_target_sets.names_for`) -registers BOTH spellings of every `PyAuto*` repo as known targets -(`name.lower()` and `name.lower()[2:]`), but the `repo_aliases` table in -@PyAutoBrain/config/policy.yaml only joins them for the libraries: - -| mention | normalises to | resolves? | -|---|---|---| -| `@PyAutoBrain` | `pyautobrain` | yes | -| `@autobrain` | `autobrain` | no — a known target with nothing filed under it | - -Same for the bare Heart, Memory, Mind and Gut spellings. `@autohands` was joined -in PR #271 because `extra_organism_targets` declares it explicitly and it -reaches real code today; the rest are latent — no prompt in the Mind history -uses them yet. - -## Decide before fixing - -This is NOT a blind alias sweep. Should organs key on the bare form -(`autobrain`) or the prefixed form (`pyautobrain`)? `target_signals` keys the -prefixed form (`pyautobrain`, `pyautomind`, `pyautoheart`, `pyautobuild`), and -after #271 `test_witness` keys organs prefixed but libraries bare. Whichever way -it goes has to hold across both maps at once, so answer the question first and -let the edit follow. - -## The wider question this raises - -Three separate repos have now hit this same defect class — PyAutoNerves -(#267), PyAutoCTI and PyAutoReduce (#269). The shared cause is that -`repo_aliases` is HAND-MAINTAINED while the known-target set is DERIVED from the -body map, so the two drift silently and the gap only ever surfaces as a -wrong-but-plausible conductor message ("strengthen tests first" for a -well-tested repo). - -Guard 2 added in #271 — a witness-map key must be what its repo normalises to — -closes the witness-map instance only. An alias gap in a map with no coverage -guard is still invisible. Consider deriving `repo_aliases` from the body map so -the class closes rather than its fourth instance. - -## Notes on this prompt's header - -`pyauto-brain intake classify` scored this `bug` at high confidence (kept), but -proposed `Target: autocti` — it read the prior-instance history above as the -subject — and `Difficulty: too-large` (score 10), inflated by the repo names and -the design-decision keywords. Corrected to `pyautobrain` / `large` on review. -An alternative classification is `refactor`: the fix is behaviour-preserving for -every spelling that resolves today. `bug` was kept because the Bug Agent's -investigate-first strategy matches the "decide before fixing" requirement above. - -Acceptance: every spelling of every body-map repo that `_target_sets` registers -as a known target resolves to a key the policy maps are actually filed under, or -is deliberately not registered; a guard makes a future alias gap fail loudly -rather than degrade a conductor's advice. diff --git a/complete/2026/08/organ-repo-spelling-splits.md b/complete/2026/08/organ-repo-spelling-splits.md new file mode 100644 index 00000000..d966109f --- /dev/null +++ b/complete/2026/08/organ-repo-spelling-splits.md @@ -0,0 +1,180 @@ +- issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/287 (closed on ship) +- shipped: 2026-08-26 — PyAutoBrain PR https://github.com/PyAutoLabs/PyAutoBrain/pull/288 + and PyAutoMind PR https://github.com/PyAutoLabs/PyAutoMind/pull/333 (Mind merged first) +- classification: bug (PyAutoBrain + PyAutoMind; organism infrastructure — neither + library nor workspace) +- summary: The bare and prefixed spellings of seven repos normalised to two different + keys, so a policy map filed under one was invisible to the other. The keying question + the prompt demanded be answered first was answered — **organs key PREFIXED** — and + then the class was closed rather than its fourth instance: the bare/prefixed/package + alias join now DERIVES from the body map's new `package:` field, and five guards make + the next gap fail loudly. + +## The decision, taken before the edit + +Organs key on the prefixed form (`pyautobrain`). Not a new rule — #269's rule made +executable: *the canonical key is the package the repo SHIPS where it ships one, the +repo name where it does not.* Organs ship no package; Nerves is the one that does and +already keyed bare (`autonerves`). Everything downstream was already filed prefixed for +organs — `test_witness`, `target_signals`, `REPO_DISPLAY`, `target_default_wiki`, and +the Mind's own `draft/*/pyautobrain/` target folders — so keying bare would have rekeyed +five maps for no gain. + +## Shipped changes + +- `PyAutoMind/repos.yaml`: `package:` on the seven repos that ship one (six libraries + + Nerves), documented in the header as identity — the other name a repo is known by. +- `PyAutoBrain/agents/faculties/sizing/_sizing.py`: `_body_map_specs`, `canonical_key`, + `spellings_of`, `unreachable_repos`, `_derived_aliases`, `_repo_aliases`; the alias + table is now derived ∪ hand, with a conflict between them raising rather than one + quietly winning. +- `PyAutoBrain/config/policy.yaml`: `repo_aliases` trimmed to what a body map cannot + know, with the canonical-key rule written where the maps live. + `extra_organism_targets` emptied — `autohands` is derived now. +- `PyAutoBrain/agents/conductors/intake/_intake.py`: `REPO_DISPLAY` derived too. +- `PyAutoBrain/tests/test_policy_seams.py`: five guards (below). + +## What the reproduction found beyond the prompt + +The prompt named five organs. Sweeping every body-map repo found seven splits — the five +organs, PyAutoHands (joined only by a policy literal), and **PyAutoScientist** — plus one +repo that could never resolve at all. + +**`pyautolabs.github.io` was DE-REGISTERED, not joined.** This is a deliberate deviation +from the scope answered at plan time ("join both"). `normalise_repo` truncates at the +first `.`/`/`, so no mention can reach a dotted repo name. The obvious fix — alias the +truncated head — is *worse* than the gap: that head is `pyautolabs`, the ORG name, so +`@PyAutoLabs/PyAutoFit` would have started resolving to the static site instead of +PyAutoFit. The acceptance criterion's other branch ("or is deliberately not registered") +covers it. The exclusion derives from the names themselves (any name carrying a +separator), not a hand-kept list, and a guard pins both halves: the repo is out of the +known targets AND its truncated head still resolves to nothing. + +## Guards, each mutation-tested + +| Guard | Mutation that proves it | +|---|---| +| no repo splits across two keys | removing the derived join names all seven affected repos | +| no alias points at a key nothing is filed under | — | +| body map `package:` agrees with the witness map | mis-keying one `package:` value raises at import | +| unreachable repos excluded, and their head resolves to nothing | forcing the dotted repo back into the set | +| canonical keys survive a body map with no `package:` | deleting the pre-package fallback rows | + +## Traps and findings + +- **The cross-repo CI pinning is the trap this task turns on.** `tests.yml` checks the + sibling Mind out at `main`, pinned, so a Brain half that REQUIRED the Mind half would + sit red until Mind merged. `canonical_key` falls back to the hand table's library rows + when no `package:` is declared, giving identical keys either way — and a test pins that + property so the fallback is not an unexercised path. The corroboration guard did NOT + have that tolerance on first push and **failed CI for exactly this reason**; the fix + made it all-or-nothing (a map declaring no package has nothing to corroborate; one + declaring *some* must declare all), which is a stronger guard than the one it replaced, + not a weakened one. +- **The tenant firewall rejected two drafts of the prose**, for naming PyAutoCTI, + PyAutoReduce, PyAutoScientist and PyAutoLabs in comments — the third consecutive task + where it caught the agent's own drift (cf. #267, #269). The comments read generically + because of it. +- **Behaviour preservation was measured, not asserted.** An A/B over every spelling in + the alias table and target sets shows exactly six resolutions changed, all intended + joins; libraries, short forms, renames, workspaces and org-qualified paths byte-identical. +- **`REPO_DISPLAY` had the beginnings of the same drift** — reachable keys (`pyautohands`, + the CTI/Reduce libraries, the HowTos) carried no row, so a header rendered + `Target: pyautohands`. Newly-reachable keys would have inherited it, so it was derived + in the same pass rather than special-cased. +- **A `git checkout --` during the mutation sweep clobbered the implementation** and it + had to be reapplied. Worth naming: mutation-testing a file you are also editing needs a + file backup, not a git restore. + +## Gate + +Brain tests 515 pass (510 baseline + 5 guards), on both matrix legs in CI, and locally +against BOTH body-map states — the branch's Mind with all seven packages declared, and a +Mind checkout at `origin/main` with none. `repos_sync --check` all 13 legs OK. Smoke n/a +(organism repos). **Heart NOT EVALUATED** — `pyauto-heart` is unreachable from a +web-github session, so leg 4 of the ship gate never ran; recorded that way rather than +claimed clean. Effective autonomy `supervised`; the run took its plan checkpoint (two +scope questions put to the human) and proceeded on the answers. + +## Follow-ups + +- The seven pre-package library rows in `repo_aliases` are the fallback for a body map + without `package:`. Now that PyAutoMind#333 has merged they are dead weight and can be + deleted, which also fully arms the corroboration guard's strict path. +- `normalise_repo` still passes `maxsplit` positionally (a DeprecationWarning on 3.13). + The copy this task introduced was fixed; the pre-existing one was left alone. + +## Original prompt + +# Organ repo spellings split across two normalised keys + +Type: bug +Target: pyautobrain +Repos: +- PyAutoBrain +Difficulty: large +Autonomy: supervised +Priority: normal +Status: formalised +Filed: 2026-08-24 +Issued: 2026-08-26 + +Found while shipping the refactor witness-map audit (@PyAutoBrain#269 / PR #271). + +## The defect + +The bare spellings of the organ repos do not normalise to the same key as their +repo spellings, so a policy map keyed on one is invisible to the other. + +@PyAutoBrain/agents/faculties/sizing/_sizing.py (`_target_sets.names_for`) +registers BOTH spellings of every `PyAuto*` repo as known targets +(`name.lower()` and `name.lower()[2:]`), but the `repo_aliases` table in +@PyAutoBrain/config/policy.yaml only joins them for the libraries: + +| mention | normalises to | resolves? | +|---|---|---| +| `@PyAutoBrain` | `pyautobrain` | yes | +| `@autobrain` | `autobrain` | no — a known target with nothing filed under it | + +Same for the bare Heart, Memory, Mind and Gut spellings. `@autohands` was joined +in PR #271 because `extra_organism_targets` declares it explicitly and it +reaches real code today; the rest are latent — no prompt in the Mind history +uses them yet. + +## Decide before fixing + +This is NOT a blind alias sweep. Should organs key on the bare form +(`autobrain`) or the prefixed form (`pyautobrain`)? `target_signals` keys the +prefixed form (`pyautobrain`, `pyautomind`, `pyautoheart`, `pyautobuild`), and +after #271 `test_witness` keys organs prefixed but libraries bare. Whichever way +it goes has to hold across both maps at once, so answer the question first and +let the edit follow. + +## The wider question this raises + +Three separate repos have now hit this same defect class — PyAutoNerves +(#267), PyAutoCTI and PyAutoReduce (#269). The shared cause is that +`repo_aliases` is HAND-MAINTAINED while the known-target set is DERIVED from the +body map, so the two drift silently and the gap only ever surfaces as a +wrong-but-plausible conductor message ("strengthen tests first" for a +well-tested repo). + +Guard 2 added in #271 — a witness-map key must be what its repo normalises to — +closes the witness-map instance only. An alias gap in a map with no coverage +guard is still invisible. Consider deriving `repo_aliases` from the body map so +the class closes rather than its fourth instance. + +## Notes on this prompt's header + +`pyauto-brain intake classify` scored this `bug` at high confidence (kept), but +proposed `Target: autocti` — it read the prior-instance history above as the +subject — and `Difficulty: too-large` (score 10), inflated by the repo names and +the design-decision keywords. Corrected to `pyautobrain` / `large` on review. +An alternative classification is `refactor`: the fix is behaviour-preserving for +every spelling that resolves today. `bug` was kept because the Bug Agent's +investigate-first strategy matches the "decide before fixing" requirement above. + +Acceptance: every spelling of every body-map repo that `_target_sets` registers +as a known target resolves to a key the policy maps are actually filed under, or +is deliberately not registered; a guard makes a future alias gap fail loudly +rather than degrade a conductor's advice. diff --git a/complete/index.md b/complete/index.md index bfad2dbe..84c66e86 100644 --- a/complete/index.md +++ b/complete/index.md @@ -6,7 +6,7 @@ Token-light navigation over the finished-work records (schema: only then grep a dated bucket. Curators: edit the band between the CURATED markers; everything below GENERATED is rebuilt. -1141 records across 7 buckets. +1142 records across 7 buckets. ## Highlights @@ -159,6 +159,7 @@ _(curate hard-won records here — survives regeneration.)_ - [numerical-inversion-failures](2026/08/numerical-inversion-failures.md) - [one-tap-dashboard-rollout](2026/08/one-tap-dashboard-rollout.md) — the pattern (a generated page + one-tap 📋 copy-for-Claude payloads, phone - [optional-dependency-skip-guards](2026/08/optional-dependency-skip-guards.md) — `test_nautilus.py::test__single_core_builds_no_pool` had no skip guard +- [organ-repo-spelling-splits](2026/08/organ-repo-spelling-splits.md) — closed on ship - [organism-board-final-readmes](2026/08/organism-board-final-readmes.md) — close on record - [paper-management-pipeline](2026/08/paper-management-pipeline.md) — auto-closed on merge - [per-parameter-step-scaling](2026/08/per-parameter-step-scaling.md) diff --git a/dashboard.html b/dashboard.html index f3e997ba..f1fa40b3 100644 --- a/dashboard.html +++ b/dashboard.html @@ -185,7 +185,7 @@
Intent. Priority. Flow.
Every task the Mind is holding. Tap a task's 📋 and its /start_dev command is on your clipboard — paste it into a Claude Code chat to route Claude straight to that task. Recent is the same work by date — what has been happening rather than what to do next.
Last updated 2026-08-26. This page is generated from active/, draft/ and the registry files, so it is only as current as they are. dashboard_refresh.yml re-renders it on every push to main — that heals a stale page, but not a stale prompt: a task that shipped without its prompt advancing to complete/ keeps rendering here as pickable backlog. Reconciling those is the refresh below.