Skip to content

feature: nightly live releases behind an activity gate (design) #127

Description

@Jammy2211

Overview

Move from ad-hoc manual releases to unattended nightly live PyPI releases behind two gates: an activity gate (skip entirely on quiet days, loudly) and the unchanged Heart GREEN release gate (stop and page on anything not GREEN). Decided 2026-07-09: once the next manual release succeeds, nightly runs ship for real with no per-release human approval — the human's role becomes a kill switch, paging response, and the morning digest. This is phase 1 of two: a design note reviewed by the human plus the dated PyAutoBrain/AUTONOMY.md doctrine edit that scopes the standing grant. Phase 2 (implementation) gets its own prompt once the design is approved.

Plan

  • Write a design note settling the nightly-release architecture: orchestration shape, activity-gate definition, Heart-GREEN acquisition in CI, loud skip/stop notifications, kill switch, version scheme, rehearsal/live composition, and the arming checklist.
  • Draft the dated PyAutoBrain/AUTONOMY.md edit: the scheduled-nightly path (activity-gated, Heart-GREEN-gated, kill-switchable) becomes a human-pre-authorised standing grant; manual and agent-initiated releases stay human-required.
  • Ship both as docs-only PRs; the PyAutoBuild PR review is the phase-1 human design review.
  • Phase 2 implements the reviewed design in release.yml (gate jobs, notifications, kill switch) as a follow-up prompt.
Detailed implementation plan

Affected Repositories

  • PyAutoBuild (primary — design note)
  • PyAutoBrain (AUTONOMY.md doctrine edit)

Branch Survey

Repository Current Branch Dirty?
./PyAutoBuild main clean
./PyAutoBrain main clean
./PyAutoHeart main clean (not edited in phase 1)

Suggested branch: feature/nightly-release-activity-gate

Grounding (what already exists)

  • PyAutoBuild/.github/workflows/release.yml already has the cron (0 2 * * 1-5); scheduled runs rehearse (TestPyPI-only) until repo var RELEASE_MODE=live (resolve_mode job). Scheduled versions auto-derive YYYY.M.D.1; run_attempt suffixes re-runs; live releases no longer commit version stamps back to library repos (research: version-pinning design review — exact pins vs daily release #118/feat: release stamping slim — wheels+tags only, no daily bump commits (R3-core) #120 fix), so pipeline self-commits on main are limited to notebook-regen / Colab-bump / API-baseline commits, all authored GitHub Actions bot with Release <version>: prefixes.
  • announce_release already posts live success/failure to Slack via PYAUTO_RELEASE_WEBHOOK_URL.
  • PyAutoHeart/heart/readiness.py is the authoritative gate; releases require GREEN, which requires a fresh passing release-validation report matching current main — how a 2 AM CI run obtains that verdict is the central design question. Heart is observer-only (no foreign dispatch), so the gate cannot live in heart-health.yml.
  • Known blocker to arming live: PyAutoBuild#126 (pipeline commits smoke-regenerated workspace datasets) is open.

Implementation Steps

  1. PyAutoBuild/docs/nightly_release_design.md (new) — sections:
    • Orchestration shape — recommended: gate jobs (activity_gate, heart_gate) at the head of release.yml's scheduled path; rejected alternative (external Brain-driven dispatcher) documented with rationale.
    • Activity gate — merged-to-main commits in the last 24 h across the 11 release-relevant repos (5 libraries, autofit/autogalaxy/autolens workspaces, HowToFit/Galaxy/Lens) via GitHub API; exclude pipeline self-commits (bot author + Release *: prefix) so a release never triggers the next; quiet night → skip downstream, report "no activity, skipped".
    • Heart GREEN gate — verdict acquisition design (evaluate pyauto-heart readiness --json over Heart's published state snapshot with an explicit freshness rule, vs rehearsal→validation-first); non-GREEN → stop + page; covers known-red items like bug: release pipeline force-commits simulated workspace datasets (git add -f) #126.
    • Notifications — three scheduled-run outcomes through the existing webhook: shipped / skipped—no activity / stopped—not GREEN (paging). Silence always means the pipeline broke.
    • Kill switch — repo var NIGHTLY_RELEASES, independent of RELEASE_MODE.
    • Version scheme — date-derived YYYY.M.D.1 on schedule (already implemented), same-day re-run semantics, pre_build minor-version ask automated on this path only.
    • Rehearsal/live composition + arming checklist — next manual live release succeeds → bug: release pipeline force-commits simulated workspace datasets (git add -f) #126 fixed → RELEASE_MODE=live + NIGHTLY_RELEASES=true.
    • Phase 2 sketch — concrete release.yml job diffs so implementation is mechanical.
  2. PyAutoBrain/AUTONOMY.md — dated edit to the caps table release row + hard invariants: the scheduled-nightly path is a scoped, human-pre-authorised standing grant; everything else stays human-required; cross-reference the design note.

Key Files

  • PyAutoBuild/.github/workflows/release.yml — existing cron/rehearsal/announce plumbing the design extends (read-only in phase 1)
  • PyAutoBuild/docs/nightly_release_design.md — new design note (the deliverable)
  • PyAutoBrain/AUTONOMY.md — caps table + hard invariants doctrine edit
  • PyAutoHeart/heart/readiness.py — verdict semantics the design consumes (read-only)

Verification

Docs-only: markdown renders, AUTONOMY.md caps table stays consistent with its consumers, cross-links resolve. No workflow/code behaviour changes in phase 1.

Original Prompt

Click to expand starting prompt

Nightly releases with an activity gate

Type: feature
Target: pyautobuild
Difficulty: large
Autonomy: human-required
Priority: high
Status: formalised

Nightly/routine releases with an activity gate: switch from ad-hoc manual
releases to a scheduled dispatch of the release pipeline (cron in
release.yml or a Heart/Brain-driven routine). The nightly run must first
judge whether any work merged in the past 24h (commits/merged PRs across the
release-relevant repos — libraries, workspaces, HowTo) and bypass the release
entirely on quiet days, reporting "no activity, skipped" rather than cutting
an identical version. Releases still require Heart GREEN, and a scheduled
release that would ship a known-red item should stop and page the human
instead. Design first, then implement behind human review.

Design constraints (from the 2026-07-09 session that conceived this)

  • DECIDED endpoint (user, 2026-07-09): once the next manual release
    succeeds, nightly runs perform FULL LIVE PyPI RELEASES unattended
    — no
    per-release human approval. This is a deliberate, scoped exception to the
    autonomy contract's "release is always human-required" invariant, so phase 1
    must include the dated doctrine edit to PyAutoBrain/AUTONOMY.md: the
    scheduled-nightly path (activity-gated, Heart-GREEN-gated) is
    human-pre-authorised as a standing grant; manual and agent-initiated
    releases stay human-required. The human's role moves to: a kill switch
    (e.g. a NIGHTLY_RELEASES repo var to pause the schedule), paging on any
    red/anomaly, and reviewing the morning digest of what shipped. pre_build's
    human minor-version ask must be automated on this path (date scheme derives
    it).
  • Activity gate: "work merged in the past 24h" needs a concrete definition
    — merged PRs / pushed commits to main across the 5 libraries, 3
    workspaces, 3 HowTo repos (the release-relevant set from repos.yaml).
    Version-stamp/notebook-regeneration commits made by the release pipeline
    itself must not count as activity (else every release triggers the next).
  • Heart GREEN is the gate, unchanged — the nightly path must call the same
    pyauto-heart readiness release gate as a manual release; STALE/YELLOW do
    not pass for releases. A known-red item (e.g. an open release-blocking
    issue like PyAutoBuild#126) stops the run and notifies (reuse the morning
    Slack webhook plumbing for paging).
  • Skip must be loud: a bypassed night reports "no activity, skipped"
    through the same notification channel, so silence always means something
    broke.
  • Version scheme: nightly cadence fits the date-based YYYY.M.D.B scheme;
    the design should cover the build-number choice and what happens on
    same-day re-runs.
  • Interactions to cover: rehearsal vs live (RELEASE_MODE, rehearsal
    input), TestPyPI rehearsal as the nightly's dry-run mode option, and how
    this composes with pre_build (which currently asks a human for the minor
    version).

Phase 1 = design note reviewed by the human (this prompt's deliverable);
phase 2 = implementation behind that reviewed design.

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