fix(readiness): ingest Stage 3's verify_install result into the install-verification leg#77
Merged
Merged
Conversation
…ll leg Stage 3 (workspace-validation, mode=release) has always run verify_install A-E against the TestPyPI wheels, but the sidecar was consulted only in the failure direction: ready==false forced the stage to fail, while a PASS contributed nothing and was discarded. Nothing ever wrote the verify_install.json that heart/state.py reads into the snapshot, so the readiness leg reported "install verification not run" no matter how many times the check passed. That is one of three legs holding Heart at YELLOW 70. The armed nightly release driver's gate requires GREEN and has deliberately no force input, so a leg that can never be satisfied means the nightly can never ship unattended -- 2026.7.15.1 shipped only because a human forced it. Carry the sidecar through as evidence and persist it on ingest: - verify_install.sh records `index` (testpypi|pypi) in the sidecar. - to_stage_report() embeds the sidecar in the stage report; the existing force-fail path is unchanged. - validate --ingest persists the block to HEART_STATE_DIR/verify_install.json (newest ts wins, so re-ingesting an older artifact cannot walk the leg backwards). It stays out of validation_report.json, which is schema v1 and does not describe it; ingest() is split into _fold/_distill so run() can reach the fold state without changing ingest's signature or purity. - readiness names the index in every reason line. A --testpypi run proves the wheels about to ship install -- the right evidence for a release gate (human decision, 2026-07-15) -- but must never silently read as proof that installing from PyPI works. readiness gate logic is otherwise untouched: the leg simply starts receiving evidence through the path it already read. workspace-validation.yml needs no change; it already passes --verify-install. Verified end to end by driving the real CI sequence (verify_install.sh -> --emit-stage-report -> --ingest, with the intermediate sidecar deleted before ingest to prove the result travels inside the stage report): the leg goes from "install verification not run" to satisfied, and reverts when the sidecar is removed. The 6 new validate tests and 3 new readiness tests were confirmed to fail against unfixed source. Refs #76
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.
Closes #76.
What was wrong
Stage 3 (
workspace-validation.yml,mode=release) has always runverify_installA–E against the TestPyPI wheels. The result was then thrown away:heart/validate.pyconsulted the sidecar only in the failure direction —ready is Falseforce-failed the stage, while a PASS contributed nothing. Nothing ever wrote theverify_install.jsonthatheart/state.py:84reads into the snapshot, so the readiness leg reportedinstall verification not runno matter how often the check passed.This is one of the three legs holding Heart at YELLOW 70. The armed nightly release driver's gate requires GREEN and deliberately has no force input, so a leg that can never be satisfied means the nightly can never ship unattended — 2026.7.15.1 shipped only because a human forced it with
release --force.Measured on
mainbefore the change (not inherited from the prompt):pyauto-heart readiness→YELLOW score 70,? install verification not run~/.pyauto-heart/verify_install.json→ absent~/.pyauto-heart/validation_report.jsonfrom the real 2026-07-15 release run → ingested fine (integratepass, 543p/0f), zeroverify_installtraceWhat this does
heart/checks/verify_install.sh— recordsindex(testpypi|pypi) in the sidecar.to_stage_report()— embeds the sidecar in the stage report as evidence. The existing force-fail path is untouched.validate --ingest— persists the block toHEART_STATE_DIR/verify_install.json, newesttswinning so re-ingesting an older artifact can't walk the leg backwards. It stays out ofvalidation_report.json(schema v1 doesn't describe it), soingest()is split into_fold/_distillandrun()reaches the fold state without changingingest's signature or purity.heart/readiness.py— no gate-logic change; reason lines now name the index.workspace-validation.ymlneeds no change — it already passes--verify-install(line 537). The CI side was always wired; only the Python side discarded the pass.The one judgment call
A
--testpypirun proves the wheels about to ship install; it says nothing about the current PyPI release. Wiring it up silently would let TestPyPI evidence satisfy a leg whose plain reading is "a new user canpip install autolens".Human decision (2026-07-15): accept it — the about-to-ship wheels are the right evidence for a release gate — but record provenance. So
indextravels with the result and appears in every reason line (install verification stale (testpypi, 16d old)). Precedent: therehearsestage already recordsindex: testpypi. A sidecar predating the field reportsindex unknownrather than being guessed at.Verification
Beyond the unit tests, I drove the real CI sequence end-to-end —
verify_install.sh→--emit-stage-report→--ingest— deleting the intermediate sidecar before ingest to prove the result travels inside the stage report rather than being re-read:test_validate.pyand 3 newtest_readiness.pytests were confirmed to fail against unfixed source — they aren't vacuous. (The 7th,..._leaves_sidecar_untouched, passes both ways by design: it guards a no-op.)Scope
Per the prompt, the other two YELLOW legs are follow-ups, not this PR: an ops re-run of the weekly
mode=smokeworkspace-validation to refresh the staletest_runleg (its 3 failures from 2026-07-09 are already disproven by the fresh release run), and hygiene triage of 58 stale parkedno_runscripts.This makes Heart GREEN-eligible on this leg; it does not by itself make Heart GREEN.
Autonomy note
Launched with
--auto, but work-typereleasecaps athuman-required(AUTONOMY.md:56), so effective level =min(safe, human-required)=human-requiredand--autochanged nothing. That's the cap working as designed: this edits what makes Heart GREEN, which is the exact gate guarding the unattended nightly. Plan was human-approved; this run ends at PR-open. Merge stays human.🤖 Generated with Claude Code
https://claude.ai/code/session_01VrVWvBMKQzxavj3VUokwAb