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 commits 15×15 smoke-regenerated workspace datasets (30/49 at 2026.7.6.649) #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 commits 15×15 smoke-regenerated workspace datasets (30/49 at 2026.7.6.649) #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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions