Release supply chain
AI-DLC uses .github/workflows/promote-release.yml to select a published
preview's source, .github/workflows/release.yml to build and publish its stable
release, and .github/workflows/preview-release.yml to produce nightly previews.
Publication uses the repository's GITHUB_TOKEN; no additional credential is
needed. Only the preview's Full Suite uses the live model environment.
Release trigger
Run Promote preview on main. An empty dispatch lists all published previews
with their source, manifest compatibility and warnings. A promotion supplies preview, version and
reviewed release notes; DEVELOPERS.md
has the commands. Preview publication may have succeeded despite test failures;
selection is the maintainer's decision, with those failures still recorded.
scripts/release-promotion.ts checks that the selected release is a published
prerelease, its annotated tag's source trailer agrees with its commit and
repository, and that commit is on main. Before creating a release commit or
reserving a tag, it downloads the preview's version.json and applies the same
manifest contract as the final asset verifier, bound to that preview and source.
An incompatible historical preview stays in the list with its rejection reason;
the maintainer must select a compatible preview. It prepares one child commit with:
- the chosen stable version in
core/tools/aidlc-version.tsand README; - the new CHANGELOG entry, preserving all previous entries;
- the complete workflow tree, promotion script, preview tag parser and shared manifest verifier from the immutable main snapshot checked out during preparation;
.github/release-promotion.json, binding the preview, source, controls, version, notes, date and recorded warnings.
The workflow tree is copied in full, including deletions, so its files match
reviewed main content and do not require an additional workflow-writing token.
The product source, dependencies, build scripts and harnesses otherwise remain
those of the preview. Carrying publication controls lets an older preview use
the current release process. The candidate's source and controls commits must
both be ancestors of main; the release commit itself need not be on main.
Validation checks its single parent, the complete changed-file set, exact
metadata contents, file modes and the exact control blobs. It runs again before
signing and publication. An arbitrary tag on main cannot release.
Preparation pushes the stable tag without force and dispatches release.yml
explicitly on that tag, because a GITHUB_TOKEN push does not trigger another
push workflow. The tagged workflow checks the event ref, checkout and tag SHA.
The source identity seen by provenance remains the actual stable tag and commit.
Preparation serializes independently from stable builds. Retries reuse only a
matching verified reservation; another preview or notes cannot claim its tag.
Stable promotion does not repeat CI or Full Suite. Previous results remain
associated with the selected preview and are linked from the stable notes;
recorded warnings are retained. Failed tests are not relabeled as passing.
The existing release environment still controls final publication.
An explicit manual full-suite.yml dispatch may set live_verification=true
to validate a candidate's live jobs before merge, or full_verification=true to
run every credential-free job on it. The two are mutually exclusive, and both
inputs are unavailable to reusable callers. The plan requires workflow_dispatch and an exact match
between the checked-out source and the manually selected workflow head
(github.sha). Ordinary runs accept the requested ref, including an unmerged
branch, and run all required jobs using its resolved immutable SHA. A dispatch
from a candidate branch does not qualify as trusted stable-release evidence.
There is no automatic privileged branch-push or PR trigger.
Live verification uses the same isolated live preparation, environment-owned role
and low-privilege broker clients. It intentionally omits the native,
deterministic and production-guard jobs. Its artifact is named
full-suite-live-verification-result and records purpose: "live-verification"
and complete: false; a successful result requires the live jobs to succeed
and the omissions to be explicitly skipped. The stable release workflow does
not consume this artifact, including for a verification run on main.
Full verification runs the native, deterministic, production-guard and Windows
release-contract jobs on the candidate, and never the jobs that receive
credentials: it skips the three live_prepare_* jobs and live_linux,
live_macos and live_windows, so unmerged code never runs where those
credentials are reachable. Every Full Suite checkout sets
persist-credentials: false, so candidate code does not find the repository
token on disk either. It refuses verification_family and verification_test
filters. Its artifact is named full-suite-verification-result and records
purpose: "full-verification", complete: false, and exactly seven jobs in
omittedLegs: those six and scope_runs, whose tests the deterministic job
already runs; a successful result requires every other job to succeed and the
seven to be skipped. No release workflow consumes it, even after the
candidate merges.
Manual verification can additionally select verification_family as
claude-sdk, claude-tui, codex, copilot, or opencode; its default is all.
Scoped runs keep the same exact-head authorization, run only the chosen
family's existing shards, and require Windows release-contract coverage to be
explicitly skipped. The result records verificationFamily and its omissions.
Release-purpose runs refuse scoped selections and require
verificationFamily: "all" independently of passed and the job statuses.
For a specific family, verification_test can select an exact repository file.
Discovery rejects unknown or mismatched files and retains their original shard
identities and declared platforms. Preparation runs only on those platforms.
The result records verificationTest, verificationPlatforms and any omitted
hosted job; the reducer requires those omissions to be skipped and the selected
jobs to succeed. Both the source gate and result reducer refuse this selection
for release-purpose runs.
POSIX preparation obtains a pinned official Node distribution and transports its complete prefix with the validated dependency archive. Credentialed jobs only unpack and copy those prepared bytes; they do not execute dependency installers. Node and CLI startup run under the low-privilege identity after runner directories are protected. Collection retires that macOS account's launchd domains and refuses to copy while executable processes remain.
Live matrices assign one file per supported platform to each job. Linux, macOS and Windows live jobs have separate concurrency caps of 4, 2 and 3. Each role session requests 3,600 seconds just before its run step; jobs allow 80 minutes, test steps 70 minutes, and live files and runs 3,600 seconds. Model work stops at the five-minute cleanup reserve, so it always ends while the session is valid, and evidence collection follows. Timeouts fail coverage. The existing IAM role duration and credential-separation boundary are unchanged.
Feature, fix, documentation, refactor, and test PRs do not update release
metadata. Promotion updates it on the selected source. After publication a
metadata-only branch and PR link synchronize the version, badge and changelog
with current main, without changing its product code or downgrading a newer
version.
Build and validation
After validating the promotion, the stable workflow:
- regenerates the preview source's harness distributions and checks determinism;
- builds native binaries for Linux, macOS, and Windows with the stable version;
- runs native and installer smoke tests, ShellCheck and PSScriptAnalyzer;
- packages the native and manual-copy runtime archives, installers, manifest and checksums;
- checks installation, lifecycle and updates from the previous stable release;
- verifies and attests the staged release inventory before publication.
The update journey and final asset verifier use the pinned publication-control commit's tooling; the build and packager use the selected preview's source. No PR test matrix or live suite runs during promotion. Required PR checks provide Linux smoke, unit, and deterministic integration coverage for product changes; nightly previews provide the broader harness coverage. Lifecycle and upgrade failures in the newly built stable candidate still block publication.
The release manifest records the stable tag ref and exact release commit. Native
installers select aidlc-runtime-X.Y.Z.tar.gz; manual-copy users download
aidlc-copy-runtime-X.Y.Z.tar.gz. The copy archive and its checksum sidecar stay
outside the manifest and main checksum inventory for older client compatibility.
Provenance authenticates them independently. No installer trust rule changes.
Provenance
The publish job receives id-token: write and attestations: write only
after the build, lifecycle and update-from-the-last-release jobs pass
(a preview's publish does not wait for the update job, which only reports there). GitHub generates build provenance for
the staged assets. The exported provenance bundle is included as
aidlc-release.intoto.jsonl.
The preview workflow schedules main daily at 22:00 in Europe/Lisbon and
accepts manual dispatch. Scheduled and manual runs serialize through the
release-preview workflow concurrency group without cancelling the active run.
Each later run re-reads the release list: the planner skips the publication build
chain if the source commit is unchanged since the latest published preview, or
if that preview was built from a newer commit that descends from this run's
source (an older run, retried or queued), so the channel never moves backwards.
Contract checks and Full Suite still run for that source. The final result
requires validation and the release tests (which report the Full Suite result)
to succeed, and publication to succeed or be skipped as intended; a failed Full
Suite does not fail it, deduplicated or not. If main advances again on the
same UTC date, another preview can publish with the next build counter.
A run tests and publishes the commit it was started on. main receives merges
constantly, and a runner can pick a run up long after its trigger (22 minutes
for Preview Release 36485041152), so planning, publication and release require
only that the commit is still on main (an ancestor of its current tip), not
that it is the tip. The run's provenance names that commit, so it cannot switch
to a newer one. A revert does not remove a commit from main's history, so a
commit reverted after its preview was triggered is still tested with the Full
Suite's credentials and can publish as a prerelease: to withdraw it, cancel that
Preview Release run, or delete the prerelease after it publishes. This is a
maintainer decision (2026-09-29).
The planner reads the current stable x.y.z from
core/tools/aidlc-version.ts and allocates
<x.y.(z+1)>-preview.<YYYYMMDD>.<N> using the UTC date at planning and ids
occupied by existing tags or release records. It calculates the next patch in
memory and never edits release metadata. Drafts and orphan tags reserve their
ids, so retry planning and later same-day publications advance N past their
occupied ids. Leftover aidlc-staging-* drafts still require inspection and
removal before the publisher stages another candidate.
The planner renders notes from changes since the previous preview. Contract
checks gate the authorized commit, then the release build chain and Full Suite
run in parallel. Publication waits for validated artifacts and the completed
test report. A failing suite still permits publication; the preview notes open
with a warning and end with the Full Suite failure report. Full Suite runs
separately and retains its failed status
without failing Preview Release. Only the preview's Full Suite dispatch job adds
actions: write, to start and watch that run; the Release tests job adds
actions: read to download its evidence and list its jobs. Preview does not repeat the
PR CI test matrix.
PR CI and Full Suite use the same deterministic-tests.yml workflow definition
with different matrices: ten Linux unit shards and integration for PRs, and
Linux/macOS/Windows smoke/sixteen unit shards/integration/E2E for a manual full
verification. PR CI runs Linux smoke in its combined contract and production-guard
check job. The nightly (release purpose) Full Suite runs no deterministic
tier: its scope runs and guard matrix run in a job of their own on every OS,
beside the live jobs.
Integration and isolated E2E run in separate jobs with fresh runner processes. Each call
tests a fresh checkout of the supplied commit and retains sanitized evidence;
no previous test result is substituted for a run.
AIDLC_BUILD_VERSION stamps the preview id into projections, binaries,
version.json, both versioned runtime archives, and the packaged installers
while the source tree keeps its stable x.y.z version. A packaged installer
therefore defaults to the release that carried it instead of rediscovering
latest. The preview publisher verifies a staging draft,
creates an annotated tag that records the source repository and commit, then
publishes the draft as a prerelease with make_latest: false; stable
latest/download discovery therefore remains unchanged.
Stable and preview publication use the protected release and unattended
preview environments respectively. The preview environment must keep the
same main deployment policy but no required reviewers; merge approval plus
contract checks are its human and deterministic gates, and Full Suite failures
are reported in the preview notes rather than blocking it. Stable
runs use a separate concurrency group. The preview publisher stages and
byte-verifies the complete
candidate before publication and works with either mutable or immutable
repository releases.
When a compatible GitHub CLI is available, installers verify checksums.txt
against that bundle and bind verification to:
awslabs/aidlc-workflows;.github/workflows/release.ymlfor stable versions or.github/workflows/preview-release.ymlfor preview versions;- the version tag for stable releases or
refs/heads/mainfor previews; - the exact source commit from
version.json.
Missing or older GitHub CLI versions do not block installation. In that mode, online transport remains HTTPS-only, and source identity validation plus SHA-256 checks remain mandatory, but the client does not authenticate the Sigstore bundle.
Publication
The final release job runs in the protected release environment and receives
contents: write. Configure required reviewers on that environment when
releases need human approval. After approval, the job downloads the attested
candidate, rechecks the tag and checksums, and creates the GitHub Release:
bun scripts/release-promotion.ts notes \
--repository "$GITHUB_REPOSITORY" \
--tag "$RELEASE_TAG" \
--out "$RUNNER_TEMP/release-notes.md"
gh release create "$RELEASE_TAG" build/release/* \
--verify-tag \
--title "AI-DLC ${RELEASE_TAG#v}" \
--notes-file "$RUNNER_TEMP/release-notes.md"
The body contains the reviewed notes from the verified promotion record, which
also supplies this version's CHANGELOG.md entry, followed by the selected
preview/source reference and its recorded validation warnings. The helper
rechecks the promotion before writing the notes. GitHub's own generated notes
are not used: their "What's Changed" list names every contributing account by handle.
The job then compares the local asset names with the asset names returned by the GitHub Release API. A missing or extra upload fails the workflow.
Stable build and validation jobs retain contents: read; no Full Suite is
called during promotion. The separate preparation job has contents: write
to reserve the tag and actions: write to dispatch its build. After publication,
metadata synchronization has contents: write to push the metadata branch.
These jobs use GITHUB_TOKEN; final publication remains in the protected
release environment.
Creating a release
Use Promote a preview to production.
Select the published preview's tag, choose the final stable version and supply
its release notes. Follow the dispatched stable build, then open the generated
metadata-only PR to record the version on main.
If the build fails before publication, rerun the failed jobs or dispatch Release on the same prepared tag. A retry never moves an existing tag to another commit. If a release already exists, inspect it before retrying; never replace published assets silently. Corrections ship in a new version. Metadata synchronization has its own retry and cannot undo a published release.