Skip to content

fix(readiness): ingest Stage 3's verify_install result into the install-verification leg #76

Description

@Jammy2211

Overview

Heart's release-fidelity Stage 3 (workspace-validation.yml, mode=release) already runs verify_install checks A–E against the TestPyPI wheels and they pass — but the readiness verdict still reports install verification not run. The evidence is produced in CI and then thrown away: heart/validate.py reads the --verify-install sidecar only in the failure direction, and nothing ever writes the verify_install.json sidecar that readiness.py reads. This is one of three legs holding Heart at YELLOW 70. Because the armed nightly release driver's step-5 gate requires GREEN and has deliberately no force input, Heart never reaching GREEN means the nightly can never ship unattended — 2026.7.15.1 shipped only because a human forced it with release --force.

Verified on main at 2026-07-15 (measured, not inherited):

  • pyauto-heart readinessYELLOW score 70, with ? install verification not run.
  • ~/.pyauto-heart/verify_install.json — the file heart/state.py:84 reads — does not exist.
  • ~/.pyauto-heart/validation_report.json from the real 2026-07-15 release run was ingested successfully (integrate stage pass, 543 passed / 0 failed) and contains zero trace of verify_install.

Discard point: heart/validate.py:563-569ready is False force-fails the stage; a PASS contributes nothing.

Plan

  • Record index (testpypi | pypi) in the verify_install.sh JSON sidecar so the result carries its own provenance.
  • Embed the sidecar in the Stage 3 stage report, instead of only consulting it to force a failure.
  • On validate --ingest, persist that embedded result to HEART_STATE_DIR/verify_install.json — the file the readiness leg already reads.
  • Surface the index in the readiness reason line, so a TestPyPI-wheel pass never reads as proof that a PyPI install works.
  • readiness.py needs no logic change: the leg starts receiving evidence through the path it already consumes.

Decided design question (human, 2026-07-15): a TestPyPI-wheel verify_install pass does satisfy this leg — the about-to-ship wheels are the right evidence for a release gate — but provenance is recorded so the verdict claims only what was verified. Precedent: the rehearse stage already records index: "testpypi".

Autonomy note (2026-07-15): launched with --auto, but work-type release caps at human-required (AUTONOMY.md:56), so effective level = human-required and --auto changed nothing. This is the cap working as intended: the change edits what makes Heart GREEN, which is the exact gate guarding the unattended nightly (AUTONOMY.md:85). Plan approved by the human; run ends at PR-open, merge stays human.

Detailed implementation plan

Affected Repositories

  • PyAutoHeart (primary, only)

Branch Survey

Repository Current Branch Dirty?
./PyAutoHeart main clean

Suggested branch: feature/wire-verify-install-leg (no worktree conflict)

Implementation Steps

  1. heart/checks/verify_install.sh — in the --report-json sidecar writer, add "index": "testpypi" when USE_TESTPYPI=1, else "pypi". Pass it through the existing VI_* env-var handoff to the inline python3 writer (alongside VI_READY/VI_VERSION).

  2. heart/validate.pyto_stage_report(...) — add a verify_install: dict | None param. When present, embed a normalized {ts, ready, version, index, checks} block under stage_report["verify_install"]. Keep force_fail/extra_failures behaviour exactly as-is (pure function, no I/O).

  3. heart/validate.py CLI (--verify-install) — keep the force-fail path; additionally pass the parsed sidecar into to_stage_report so a pass survives into the artifact. Update the --verify-install help text, which currently documents only the fail direction.

  4. heart/validate.py ingest (_Accumulator / run) — when an ingested stage report carries a verify_install block, persist it to state.HEART_STATE_DIR / "verify_install.json" via state.atomic_write_json. Idempotent on re-ingest; keep the newest ts. This is the one new write, and it stays inside ~/.pyauto-heart/ — the module boundary (no dispatch, no GitHub, no foreign repo) is preserved.

  5. heart/readiness.py — no gate-logic change. Only extend the existing pass/stale reason strings to name the index (e.g. install verification stale (testpypi, 16d old)), so the provenance decision is visible in the verdict.

  6. Teststests/test_validate.py: sidecar embeds into the stage report on pass; --ingest writes verify_install.json; re-ingest is idempotent; existing force-fail tests still green. tests/test_readiness.py: an ingested testpypi pass flips the leg off the stale tier; reason line carries the index. tests/test_verify_install_script.py: sidecar contains index.

  7. Verification — after ingest of a stage report carrying a pass, pyauto-heart readiness must drop install verification not run, leaving the two known follow-up legs (stale test_run re-run; 58 stale parked no_run scripts). Those are explicitly out of scope per the prompt.

Key Files

  • heart/validate.pyto_stage_report (:395), CLI --verify-install (:541-570), ingest accumulator
  • heart/checks/verify_install.sh — sidecar writer (--report-json block)
  • heart/readiness.py:365-386 — the install-verification leg (consumer; near-untouched)
  • heart/state.py:84verify_install.json → snapshot key
  • .github/workflows/workspace-validation.ymlverify_install_release + emit_release_report (already wired; expected to need no change)

Original Prompt

Click to expand starting prompt

Wire Stage 3's verify_install result into Heart's install-verification readiness leg. Heart's release-fidelity Stage 3 (workspace-validation mode=release) already runs verify_install checks A-E against the TestPyPI wheels and they pass, but the readiness verdict still reports 'install verification not run' because that result is a separate ingest the leg never receives. Evidence is produced and then thrown away. This is one of three legs holding Heart at YELLOW 70; because the armed nightly release driver's step-5 gate requires GREEN and has deliberately no force input, Heart never reaching GREEN means the nightly can never ship unattended - 2026.7.15.1 shipped only because a human forced it with 'release --force'. Fixing this leg is the durable half: the other two are an ops re-run of the weekly mode=smoke workspace-validation to refresh the stale test_run leg (its 3 failures from 2026-07-09 are already disproven by the fresh release run: autolens_test 90p/0f, 543p/0f/0t overall), and hygiene triage of 58 stale parked no_run scripts (all age_days=90, category slow). Those two are follow-ups, not this task.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions