From f661fa5a49465e8f0cab96ba96a8d2f836469bed Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 11:11:45 +0000 Subject: [PATCH 1/3] prompt: file issue for health-conductor-stale-verdict (PyAutoBrain#198) --- active.md | 9 +++++++++ active/health_conductor_stale_verdict.md | 15 +++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 active/health_conductor_stale_verdict.md diff --git a/active.md b/active.md index 3b4dcb22..8c5c82ac 100644 --- a/active.md +++ b/active.md @@ -1,5 +1,14 @@ # Active Tasks +## health-conductor-stale-verdict +- issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/198 +- status: library-dev — starting. Cloud session (web-github): no worktree, no `gh` CLI; working in the canonical /home/user/PyAutoBrain checkout on the mandated branch `claude/health-conductor-stale-verdict-6ve1sl`. Issue filed via the GitHub MCP surface. +- what: the health conductor has no STALE branch. `agents/conductors/health/health.sh` drops `stale_reasons` from triage (the classifier walks only red + yellow), so a stale-only verdict renders the UNKNOWN recommendation with 0/0/0 counts and exits 4 — indistinguishable from "Heart unreachable" for a machine caller, even though `AUTONOMY.md` leg 4 treats STALE as PASSING the dev-ship gate. +- exit-code decision: STALE gets **6**, not the free slot 1. Bash's own generic failure is 1 (missing `_common.sh`, failed `readlink`), and STALE is a *passing* tier for the ship gate — a crash must never read as a pass. Same reasoning the header already applies to usage errors (5, "so misuse is never read as a real YELLOW"). Existing codes are untouched: 0 green / 2 yellow / 3 red / 4 unknown / 5 usage. +- prompt: active/health_conductor_stale_verdict.md +- worktree: (none — cloud session, canonical checkout) +- repos-single-claim: PyAutoBrain is the only affected repo, named on this one line deliberately and NOT as a 2-space bullet, because worktree_check_conflict reads any such bullet as a live claim. PyAutoHeart is referenced only (its readiness.py already emits the tier correctly and needs no change). + ## covariance-interpolator-rng-seed - issue: https://github.com/PyAutoLabs/PyAutoFit/issues/1450 - status: library-dev — fix COMMITTED AND PUSHED to `claude/covariance-interpolator-rng-seed-8zexp3` (PyAutoFit 68a8b391). NO PR opened (not requested). Cloud session, no worktree and no `gh` CLI; issue filed via the GitHub MCP surface. diff --git a/active/health_conductor_stale_verdict.md b/active/health_conductor_stale_verdict.md new file mode 100644 index 00000000..1ae0e2ce --- /dev/null +++ b/active/health_conductor_stale_verdict.md @@ -0,0 +1,15 @@ +# Bug: the health conductor mis-reports a STALE verdict as UNKNOWN. + +Type: bug +Target: PyAutoBrain +Repos: +- PyAutoBrain +- PyAutoHeart +Difficulty: small +Autonomy: supervised +Priority: high +Status: formalised + +Bug: the health conductor mis-reports a STALE verdict as UNKNOWN. In PyAutoBrain agents/conductors/health/health.sh the recommendation chain branches on green / blockers / real-warnings / (gaps or yellow) and otherwise falls through to an UNKNOWN branch, and _exit_code_for maps only green/yellow/red with a catch-all 4. When PyAutoHeart returns STALE the card correctly prints 'adopted verdict = stale' with a score, then the recommendation incorrectly prints 'UNKNOWN - could not obtain a verdict from the vitals faculty' and the script exits 4. The triage item classifier only walks the red and yellow reason lists, so stale reasons are dropped and the counts wrongly read 0 blockers / 0 warnings / 0 gaps. PyAutoHeart AGENTS.md makes STALE a first-class freshness tier that the dev-ship gate treats as passing, so a caller cannot distinguish 'Heart says STALE' from 'Heart unreachable'. Reproduced on a live health run 2026-08-05. + + From 43f2117a292bf832d302cfa5494b23541225972d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 11:18:25 +0000 Subject: [PATCH 2/3] prompt: health-conductor-stale-verdict fix pushed (PyAutoBrain#198) Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FbLrcRCmUvhRQdtZbDWMDD --- active.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/active.md b/active.md index 8c5c82ac..c4f0aec8 100644 --- a/active.md +++ b/active.md @@ -2,7 +2,12 @@ ## health-conductor-stale-verdict - issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/198 -- status: library-dev — starting. Cloud session (web-github): no worktree, no `gh` CLI; working in the canonical /home/user/PyAutoBrain checkout on the mandated branch `claude/health-conductor-stale-verdict-6ve1sl`. Issue filed via the GitHub MCP surface. +- status: library-dev — fix COMMITTED AND PUSHED to `claude/health-conductor-stale-verdict-6ve1sl` (PyAutoBrain 1afae0a). NO PR opened (not requested). Cloud session (web-github): no worktree, no `gh` CLI; worked in the canonical /home/user/PyAutoBrain checkout. Issue filed via the GitHub MCP surface. +- validation: full Brain suite 222 passed = 204 pre-existing + 18 new. Conductor driven end-to-end against a stubbed Heart for all five verdicts: green 0, yellow 2, red 3, unknown 4, stale 6, usage 5. +- kind taxonomy: stale reasons get a NEW `evidence-gap` kind, deliberately NOT the existing `baseline-gap`. A baseline gap is rendered as "accept, not action items"; a stale reason is the opposite — its remedy is re-running the named check. Forcing the kind by severity mirrors the pre-existing red override in the same loop. +- refresh commands are grounded, never invented: `pyauto-brain release validate` (validate — the hard gate, preferred when present), `pyauto-heart verify_install`, `pyauto-heart tick` for anything the <30s tick measures. `test_run` / `url_check` have no known entry point → command None, named in prose. Same discipline the file already applied to `pyauto-heart fix` topics. +- docs updated in the same diff: health.sh header table AND agents/conductors/health/AGENTS.md (its second copy of the table, the triage taxonomy "three kinds"→"four", and the recommended-action table). A test pins both against `_exit_code_for` so they cannot drift. +- FOLLOW-UP FOUND, deliberately NOT folded in (one prompt = one task): `agents/faculties/vitals/AGENTS.md` has the same class of omission. Its step 1 documents the tier correctly, but step 3 ("Reason about significance") groups only Blocking/Warnings and step 4 ("Determine overall readiness") reads "any red_reasons -> RED, else any yellow_reasons -> YELLOW, else GREEN" — no stale rung. Docs-only, in the faculty the conductor consults; worth an intake. - what: the health conductor has no STALE branch. `agents/conductors/health/health.sh` drops `stale_reasons` from triage (the classifier walks only red + yellow), so a stale-only verdict renders the UNKNOWN recommendation with 0/0/0 counts and exits 4 — indistinguishable from "Heart unreachable" for a machine caller, even though `AUTONOMY.md` leg 4 treats STALE as PASSING the dev-ship gate. - exit-code decision: STALE gets **6**, not the free slot 1. Bash's own generic failure is 1 (missing `_common.sh`, failed `readlink`), and STALE is a *passing* tier for the ship gate — a crash must never read as a pass. Same reasoning the header already applies to usage errors (5, "so misuse is never read as a real YELLOW"). Existing codes are untouched: 0 green / 2 yellow / 3 red / 4 unknown / 5 usage. - prompt: active/health_conductor_stale_verdict.md From 56cfa62c42b1ab065f2b00b31d2a21251c784dc3 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 11:40:43 +0000 Subject: [PATCH 3/3] record: health-conductor-stale-verdict shipped (PyAutoBrain#199) Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FbLrcRCmUvhRQdtZbDWMDD --- active.md | 14 --- active/health_conductor_stale_verdict.md | 15 --- .../2026/08/health-conductor-stale-verdict.md | 97 +++++++++++++++++++ complete/index.md | 3 +- 4 files changed, 99 insertions(+), 30 deletions(-) delete mode 100644 active/health_conductor_stale_verdict.md create mode 100644 complete/2026/08/health-conductor-stale-verdict.md diff --git a/active.md b/active.md index c4f0aec8..3b4dcb22 100644 --- a/active.md +++ b/active.md @@ -1,19 +1,5 @@ # Active Tasks -## health-conductor-stale-verdict -- issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/198 -- status: library-dev — fix COMMITTED AND PUSHED to `claude/health-conductor-stale-verdict-6ve1sl` (PyAutoBrain 1afae0a). NO PR opened (not requested). Cloud session (web-github): no worktree, no `gh` CLI; worked in the canonical /home/user/PyAutoBrain checkout. Issue filed via the GitHub MCP surface. -- validation: full Brain suite 222 passed = 204 pre-existing + 18 new. Conductor driven end-to-end against a stubbed Heart for all five verdicts: green 0, yellow 2, red 3, unknown 4, stale 6, usage 5. -- kind taxonomy: stale reasons get a NEW `evidence-gap` kind, deliberately NOT the existing `baseline-gap`. A baseline gap is rendered as "accept, not action items"; a stale reason is the opposite — its remedy is re-running the named check. Forcing the kind by severity mirrors the pre-existing red override in the same loop. -- refresh commands are grounded, never invented: `pyauto-brain release validate` (validate — the hard gate, preferred when present), `pyauto-heart verify_install`, `pyauto-heart tick` for anything the <30s tick measures. `test_run` / `url_check` have no known entry point → command None, named in prose. Same discipline the file already applied to `pyauto-heart fix` topics. -- docs updated in the same diff: health.sh header table AND agents/conductors/health/AGENTS.md (its second copy of the table, the triage taxonomy "three kinds"→"four", and the recommended-action table). A test pins both against `_exit_code_for` so they cannot drift. -- FOLLOW-UP FOUND, deliberately NOT folded in (one prompt = one task): `agents/faculties/vitals/AGENTS.md` has the same class of omission. Its step 1 documents the tier correctly, but step 3 ("Reason about significance") groups only Blocking/Warnings and step 4 ("Determine overall readiness") reads "any red_reasons -> RED, else any yellow_reasons -> YELLOW, else GREEN" — no stale rung. Docs-only, in the faculty the conductor consults; worth an intake. -- what: the health conductor has no STALE branch. `agents/conductors/health/health.sh` drops `stale_reasons` from triage (the classifier walks only red + yellow), so a stale-only verdict renders the UNKNOWN recommendation with 0/0/0 counts and exits 4 — indistinguishable from "Heart unreachable" for a machine caller, even though `AUTONOMY.md` leg 4 treats STALE as PASSING the dev-ship gate. -- exit-code decision: STALE gets **6**, not the free slot 1. Bash's own generic failure is 1 (missing `_common.sh`, failed `readlink`), and STALE is a *passing* tier for the ship gate — a crash must never read as a pass. Same reasoning the header already applies to usage errors (5, "so misuse is never read as a real YELLOW"). Existing codes are untouched: 0 green / 2 yellow / 3 red / 4 unknown / 5 usage. -- prompt: active/health_conductor_stale_verdict.md -- worktree: (none — cloud session, canonical checkout) -- repos-single-claim: PyAutoBrain is the only affected repo, named on this one line deliberately and NOT as a 2-space bullet, because worktree_check_conflict reads any such bullet as a live claim. PyAutoHeart is referenced only (its readiness.py already emits the tier correctly and needs no change). - ## covariance-interpolator-rng-seed - issue: https://github.com/PyAutoLabs/PyAutoFit/issues/1450 - status: library-dev — fix COMMITTED AND PUSHED to `claude/covariance-interpolator-rng-seed-8zexp3` (PyAutoFit 68a8b391). NO PR opened (not requested). Cloud session, no worktree and no `gh` CLI; issue filed via the GitHub MCP surface. diff --git a/active/health_conductor_stale_verdict.md b/active/health_conductor_stale_verdict.md deleted file mode 100644 index 1ae0e2ce..00000000 --- a/active/health_conductor_stale_verdict.md +++ /dev/null @@ -1,15 +0,0 @@ -# Bug: the health conductor mis-reports a STALE verdict as UNKNOWN. - -Type: bug -Target: PyAutoBrain -Repos: -- PyAutoBrain -- PyAutoHeart -Difficulty: small -Autonomy: supervised -Priority: high -Status: formalised - -Bug: the health conductor mis-reports a STALE verdict as UNKNOWN. In PyAutoBrain agents/conductors/health/health.sh the recommendation chain branches on green / blockers / real-warnings / (gaps or yellow) and otherwise falls through to an UNKNOWN branch, and _exit_code_for maps only green/yellow/red with a catch-all 4. When PyAutoHeart returns STALE the card correctly prints 'adopted verdict = stale' with a score, then the recommendation incorrectly prints 'UNKNOWN - could not obtain a verdict from the vitals faculty' and the script exits 4. The triage item classifier only walks the red and yellow reason lists, so stale reasons are dropped and the counts wrongly read 0 blockers / 0 warnings / 0 gaps. PyAutoHeart AGENTS.md makes STALE a first-class freshness tier that the dev-ship gate treats as passing, so a caller cannot distinguish 'Heart says STALE' from 'Heart unreachable'. Reproduced on a live health run 2026-08-05. - - diff --git a/complete/2026/08/health-conductor-stale-verdict.md b/complete/2026/08/health-conductor-stale-verdict.md new file mode 100644 index 00000000..9f46abf2 --- /dev/null +++ b/complete/2026/08/health-conductor-stale-verdict.md @@ -0,0 +1,97 @@ +The health conductor had no STALE branch, so a stale-only readiness verdict was +mis-reported as UNKNOWN. The card printed `adopted verdict = stale` with a score, +then the recommendation printed "UNKNOWN — could not obtain a verdict from the +vitals faculty", the triage counts read `0 blocker(s) · 0 real warning(s) · +0 expected first-run gap(s)`, and the script exited 4 — the same code as "Heart +unreachable". PyAutoHeart makes STALE a first-class freshness tier and +`AUTONOMY.md` leg 4 treats it as PASSING the dev-ship gate, so collapsing it onto +unknown left a machine caller unable to tell an evidence gap from a dead sensor. + +**PR:** PyAutoBrain#199 (issue #198) — merged 2026-08-05, branch +`claude/health-conductor-stale-verdict-6ve1sl`. + +## What changed + +Three sites, all in `agents/conductors/health/health.sh`: + +- **Triage item classifier** — walked only `(red, yellow)`, so stale reasons never + became items. Now walks `stale_reasons` too and, mirroring the pre-existing + "severity wins over the keyword class" rule for red, forces them to a new + `evidence-gap` kind. +- **Recommendation chain** — a STALE branch ahead of the baseline-gap one, naming + the top evidence gap and preferring the release-validation gap when present. +- **`_exit_code_for`** — STALE maps to 6. + +Docs updated in the same diff: the header's exit-code table and +`agents/conductors/health/AGENTS.md` (its second copy of that table, the triage +taxonomy "three kinds" → "four", the recommended-action table). + +## Findings worth keeping + +- **The exit code is 6, not the free slot 1 — and the reason generalises.** `1` is + the shell's own generic failure (a missing `_common.sh`, a failed `readlink`), + and STALE is a *passing* tier for the ship gate, so a crash exiting 1 would have + been readable as a pass. Fail-safe direction: an accidental exit must never + resemble a passing verdict. This is the same reasoning the file already applied + to usage errors ("exits 5 — kept distinct from the verdict codes so misuse is + never read as a real YELLOW"). Full ladder now: 0 green / 2 yellow / 3 red / + 4 unknown / 5 usage / 6 stale. +- **A stale reason is NOT a baseline gap.** The tempting one-line fix — file stale + reasons into the existing `baseline-gap` kind — is wrong: that bucket renders as + "accept, not action items", while a stale reason's whole point is that re-running + the named check IS the action. Hence the new `evidence-gap` kind, and + `blocks_green: true` on it. +- **Refresh commands must be grounded like fix topics.** The conductor already + refused to invent `pyauto-heart fix` topics; the same discipline now governs + refresh entry points. Real ones only — `pyauto-brain release validate` (the hard + gate, delegated because the release conductor owns the MCP boundary), + `pyauto-heart verify_install`, `pyauto-heart tick` for anything the <30s tick + measures. `test_run` and `url_check` have no known entry point, so they get + `command: None` and prose naming the check. +- **Heart needed no change.** `heart/readiness.py` already computed and exported + `stale_reasons` correctly; this was purely a Brain-side consumer bug. Worth + remembering when a tier is added to Heart: the consumers are the risk surface, + not the producer. + +## Validation + +`tests/test_health_conductor.py` (new, 18 tests) stubs `pyauto-heart` on `PATH` +and drives the conductor end-to-end through the vitals faculty. It pins the three +fixed sites, that every verdict maps to a distinct exit code, that the documented +tables do not drift from `_exit_code_for`, that refresh commands are never +invented, and — as regression guards — that red still dominates a stale reason and +that a Heart with no `stale_reasons` key behaves exactly as before (the tier is +additive). Full suite 222 passed (204 pre-existing + 18); CI green on 3.12 + 3.13. + +## Follow-up filed as a finding, not folded in + +`agents/faculties/vitals/AGENTS.md` has the same class of omission: step 1 +documents the tier correctly, but step 3 ("Reason about significance") groups only +Blocking/Warnings and step 4 ("Determine overall readiness") reads "any +`red_reasons` → RED, else any `yellow_reasons` → YELLOW, else GREEN" — no stale +rung, in the very faculty this conductor consults. Docs-only; kept separate under +"one prompt = one task". + +## Environment + +Cloud session (web-github): no worktree, no `gh` CLI. Worked in the canonical +`/home/user/PyAutoBrain` checkout on the mandated branch; issue and PR via the +GitHub MCP surface. + +## Original prompt + +# Bug: the health conductor mis-reports a STALE verdict as UNKNOWN. + +Type: bug +Target: PyAutoBrain +Repos: +- PyAutoBrain +- PyAutoHeart +Difficulty: small +Autonomy: supervised +Priority: high +Status: formalised + +Bug: the health conductor mis-reports a STALE verdict as UNKNOWN. In PyAutoBrain agents/conductors/health/health.sh the recommendation chain branches on green / blockers / real-warnings / (gaps or yellow) and otherwise falls through to an UNKNOWN branch, and _exit_code_for maps only green/yellow/red with a catch-all 4. When PyAutoHeart returns STALE the card correctly prints 'adopted verdict = stale' with a score, then the recommendation incorrectly prints 'UNKNOWN - could not obtain a verdict from the vitals faculty' and the script exits 4. The triage item classifier only walks the red and yellow reason lists, so stale reasons are dropped and the counts wrongly read 0 blockers / 0 warnings / 0 gaps. PyAutoHeart AGENTS.md makes STALE a first-class freshness tier that the dev-ship gate treats as passing, so a caller cannot distinguish 'Heart says STALE' from 'Heart unreachable'. Reproduced on a live health run 2026-08-05. + + diff --git a/complete/index.md b/complete/index.md index 4e813bcc..0693aa29 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. -891 records across 7 buckets. +892 records across 7 buckets. ## Highlights @@ -23,6 +23,7 @@ _(curate hard-won records here — survives regeneration.)_ - [dep-floors-source-chain-ci](2026/08/dep-floors-source-chain-ci.md) - [ep-initializer-exception-should-not-abort](2026/08/ep-initializer-exception-should-not-abort.md) - [group-data-preparation-readme](2026/08/group-data-preparation-readme.md) +- [health-conductor-stale-verdict](2026/08/health-conductor-stale-verdict.md) - [howto-smoke-all-tutorials](2026/08/howto-smoke-all-tutorials.md) - [interferometer-start-here-integrate-oom](2026/08/interferometer-start-here-integrate-oom.md) - [intra-family-dep-floors](2026/08/intra-family-dep-floors.md)