Something went wrong. Try again.
personal memory agent
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209#!/usr/bin/env bash# SPDX-License-Identifier: AGPL-3.0-only# Copyright (c) 2026 sol pbc## solstone release-candidate rail.## This script is only the candidate rail dispatcher. It can finalize a# provider-neutral release candidate, revalidate retained candidate evidence, or# run the narrowed Linux structural dry-run. Publication lives in the aggregate# publisher: make publish-release RELEASE_DIR=dist/release-candidate/<version>/# or make publish-release-test RELEASE_DIR=dist/release-candidate/<version>/.## DESTRUCTIVE: --candidate is fresh construction. If retained# dist/release-candidate/<version> or target/release-evidence/<version> bytes# already exist, it refuses before cleanup unless the matching discard# authorization is set. Once authorized, it deletes prior raw build/dist outputs# and that version's stale payload/evidence before policy or build work.## Candidate flow:# 1. Run the serial release test and release-host tool rail.# 2. Verify the expected source commit, clean source tree, and core lock.# 3. Delete prior raw outputs and stale retained payload/evidence for the# version being constructed.# 4. Build local artifacts and receive macOS artifacts through the externally# configured build-host channel.# 5. Generate a fresh proof challenge, extract the nvattest authority from the# candidate's own root wheels and require every target to agree, and# materialize the locked support-wheel set, verifying it against uv.lock.# All of this happens before the ledger is written and before any proof# host is contacted.# 6. Collect a per-target receipt pair through configured proof-host channels# -- the install/smoke proof and a challenge-bound nvattest proof -- then# pair-promote payload and evidence.# 7. Revalidate payload, manifests, ledger, retained support wheels, and both# receipt classes, then print canonical local readiness JSON. This is not# publication authorization.## Recovery flow:# `--recover <version> <source-commit>` is retained-byte-only, read-only# validation. It preserves retained payload, ledger, retained support wheels,# and both receipt classes, and never rebuilds, refreshes advisories, contacts# hosts, installs wheels, reads authentication, or uses the network. It# re-derives the nvattest authority from the retained candidate wheel bytes# rather than trusting the ledger, so a ledger and receipt set forged to agree# with itself is still rejected. It reads no release lock: lock agreement is# enforced when the candidate is cut.## Dry-run flow:# `--dry-run-linux` is structural only. It emits no ready payload, manifest,# ledger, proof, or clean-source claim.
set -euo pipefail
echo "scripts/release.sh: frozen for the Rust-conversion effort (development gate is Rust-only; see docs/PORTING.md)" >&2exit 1
PUBLISH_LOCKOUT_MESSAGE="publishing is handled by scripts/release_publish.py; run make publish-release RELEASE_DIR=dist/release-candidate/<version>/ or make publish-release-test RELEASE_DIR=dist/release-candidate/<version>/"
usage() { cat <<'EOF'Usage: scripts/release.sh [--candidate|--recover <version> <source-commit>|--dry-run-linux]
Modes: --candidate Finalize a non-publishing all-host release candidate, write retained local evidence, and report readiness digests. Each attempt generates a fresh proof challenge and requires a per-target receipt pair: the install/smoke proof and a challenge-bound nvattest proof. DESTRUCTIVE: fresh construction refuses when retained payload/evidence already exists unless the matching optional discard authorization is set. Once authorized, it deletes prior raw build/dist outputs and that version's stale payload/evidence before policy or build work begins. --recover VERSION SOURCE_COMMIT Retained-byte-only, read-only validation of payload, ledger, retained support wheels, and both per-target receipt classes (install/smoke and nvattest). Re-derives the nvattest authority from the retained wheel bytes. Preserves retained bytes and never rebuilds, refreshes, or reads the network. --dry-run-linux Structural Linux-only dry-run. Emits no ready payload, manifest, ledger, proof, or clean-source claim. -h, --help Show this help.
Required environment: --candidate: EXPECTED_RELEASE_COMMIT expected lowercase source commit RELEASE_MODEL_PACKAGES include or exclude RELEASE_ADVISORY_SOURCE_NAME public advisory source id RELEASE_ADVISORY_DB_URL explicit non-GitHub advisory DB source RELEASE_ADVISORY_DB_ROOT cargo-deny advisory db parent; see scripts/release_advisory_policy.py RELEASE_BUILD_HOST_CHANNEL external build-host adapter command RELEASE_PROOF_HOST_LINUX_X86_64_MUSL_CHANNEL external proof-host adapter command RELEASE_PROOF_HOST_LINUX_AARCH64_MUSL_CHANNEL external proof-host adapter command RELEASE_PROOF_HOST_MACOS_ARM64_CHANNEL external proof-host adapter command
--recover: VERSION and SOURCE_COMMIT are required positional selectors. Recovery does not read current source metadata to decide what retained bytes to validate.
--dry-run-linux: RELEASE_MODEL_PACKAGES include or exclude
Optional environment: --candidate: RELEASE_CANDIDATE_DISCARD_RETAINED <version>; discard retained payload/evidence when no v<version> tag exists RELEASE_CANDIDATE_DISCARD_PUBLISHED_TAG <version>+<tag>; discard retained payload/evidence even when tag exists
Publication entry points: Running with no args, --test, make release, or make release-test fails closed before any external seam. Publish a retained candidate with: make publish-release RELEASE_DIR=dist/release-candidate/<version>/ or rehearse against TestPyPI only with: make publish-release-test RELEASE_DIR=dist/release-candidate/<version>/EOF}
fail_closed_publish() { echo "$PUBLISH_LOCKOUT_MESSAGE" >&2 exit 1}
MODE=""RECOVER_VERSION=""RECOVER_SOURCE_COMMIT=""
if [[ $# -eq 0 ]]; then fail_closed_publishfi
set_mode() { local next_mode="$1" if [[ -n "$MODE" ]]; then echo "only one release mode may be selected" >&2 usage >&2 exit 2 fi MODE="$next_mode"}
while [[ $# -gt 0 ]]; do case "$1" in --candidate) set_mode "candidate" shift ;; --recover) set_mode "recover" if [[ $# -lt 3 ]]; then echo "--recover requires VERSION and SOURCE_COMMIT" >&2 usage >&2 exit 2 fi RECOVER_VERSION="$2" RECOVER_SOURCE_COMMIT="$3" shift 3 ;; --dry-run-linux) set_mode "dry-run-linux" shift ;; --test) fail_closed_publish ;; -h|--help) usage exit 0 ;; *) echo "unknown argument: $1" >&2 usage >&2 exit 2 ;; esacdone
if [[ -z "$MODE" ]]; then fail_closed_publishfi
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"cd "$REPO_ROOT"
if [[ "$MODE" == "candidate" ]]; then if [[ "${SOLSTONE_RELEASE_TEST_RAIL:-}" == "1" ]]; then if [[ -z "${PYTEST_CURRENT_TEST:-}" ]]; then echo "SOLSTONE_RELEASE_TEST_RAIL is reserved for pytest release-entrypoint probes" >&2 exit 2 fi else make release-checks fifi
if [[ "$MODE" == "recover" ]]; then exec python3 scripts/release_candidate_driver.py recover \ --version "$RECOVER_VERSION" \ --source-commit "$RECOVER_SOURCE_COMMIT"fi
exec python3 scripts/release_candidate_driver.py "$MODE"