> ## Documentation Index
> Fetch the complete documentation index at: https://hyperframes-deepwork-builder-hf-release-publish-ssot-guard.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Release channels

> How HyperFrames keeps alpha-only work out of stable releases.

HyperFrames publishes two release channels:

* Stable releases use versions like `0.4.24` and publish to the npm `latest` dist-tag.
* Prereleases use versions like `0.4.24-alpha.1` and publish to the npm dist-tag named by the prerelease suffix, such as `alpha`.

## Branch policy

Use branch separation to decide what code is eligible for each release channel.
Dist-tags only control npm install defaults; they do not remove code from a package.

* `main` is stable/releasable. Anything merged to `main` is eligible for `latest`.
* `release/v*` branches are for stable patch releases and hotfixes.
* `next`, `alpha`, `beta`, `rc`, `canary`, and `prerelease/*` branches are for prerelease integration.

If a feature should ship in alpha only, merge or retarget that PR to a prerelease branch instead of `main`.

## Stable release

Stable releases publish only when a reviewed `release/vX.Y.Z` PR merges into protected `main`.
Prepare and review release notes before creating the release commit:

```bash theme={null}
bun run release:prepare <version>
```

On the first run, `release:prepare` drafts missing changelog artifacts and exits non-zero for review so chained release commands stop before tagging. After the generated TODO summary is rewritten, rerun the same command to create the release commit and tag.

See [Changelog process](/contributing/changelog-process) for the full workflow. For stable releases, `bun run set-version <version>` still enforces this checkpoint when maintainers run the lower-level release command directly.

Push the release branch without its local tag, open a PR to `main`, and merge it after approval and CI. The publish workflow checks out the exact PR merge SHA, verifies it before publishing, creates the stable tag at that commit, publishes npm packages, and creates the GitHub release.

If that workflow needs recovery, rerun its original merged-PR event. Stable tag pushes and manual dispatches do not publish, so recovery cannot select a different commit.

For hotfixes, branch from the last stable tag, cherry-pick only the fix, publish the patch release, then merge or cherry-pick the same fix back into the prerelease branch.

## Alpha release

Alpha releases must be reachable from a prerelease branch such as `origin/next` or `origin/alpha`.
Use the same changelog draft workflow when the prerelease contains changes that users should know about.

```bash theme={null}
git checkout next
bun run set-version 0.4.25-alpha.1
git push origin next
git push origin v0.4.25-alpha.1
```

Consumers can install alpha builds explicitly:

```bash theme={null}
npm install hyperframes@alpha
npm install @hyperframes/core@alpha
```

## CI guardrails

The publish workflow validates release channel boundaries before publishing:

* Stable versions must publish with `latest`.
* Prerelease versions must publish with the prerelease dist-tag, such as `alpha`.
* Stable releases must come from a merged, reviewed `release/vX.Y.Z` PR.
* Prerelease tags must be reachable from a prerelease branch.
* Merged `release/vX.Y.Z` PRs publish stable releases only.
* Every publish job verifies that its checkout matches the immutable event SHA.

This prevents an alpha-only feature from being included in a stable hotfix by accident.

### Stable guard maintenance

Stable publishing requires the environment-scoped secret `RELEASE_GUARD_TOKEN`. Its named owner must
provision and rotate a dedicated fine-grained personal access token with an explicit expiry and only
these repository permissions: Administration (read-only) and Pull requests (read-only). Metadata read
access is added automatically by GitHub. Scope the token to this repository only; do not grant
Contents, Packages, Workflows, or organization write access. Store the credential under the same name
in both the `release-guard-health` and `npm-publish` environments; never create it as a repository or
organization secret. The publish workflow passes this credential only to the read-only stable guard;
checkout, tag creation, npm provenance, and GitHub Release writes continue to use their existing
credentials.

Before the initial upload and before every rotation, run this read-only API verification. It fails
unless the exact environment has a non-bypassable required-reviewer boundary with self-review
prevention and at least one reviewer. Do not upload either environment-secret copy unless it exits 0.

```bash theme={null}
ENVIRONMENT_JSON="$(gh api repos/heygen-com/hyperframes/environments/release-guard-health)"
jq -e '
  .can_admins_bypass == false and
  any(
    .protection_rules[]?;
    .type == "required_reviewers" and
    .prevent_self_review == true and
    ((.reviewers // []) | length >= 1)
  )
' <<<"$ENVIRONMENT_JSON" >/dev/null || {
  echo "release-guard-health is not protected; do not upload RELEASE_GUARD_TOKEN." >&2
  exit 1
}
echo "release-guard-health protection verified; environment secret upload may proceed."
```

After provisioning or rotation, an administrator must run the read-only capability check from a
protected environment that injects the secret without putting its value on the command line:

```bash theme={null}
GITHUB_REPOSITORY=heygen-com/hyperframes \
  RELEASE_GUARD_PROBE_PR=<existing-pr-number> \
  RELEASE_GUARD_PROBE_SHA=<existing-commit-sha> \
  node scripts/stable-release-guard.mjs --preflight
```

The protected environment must supply `RELEASE_GUARD_TOKEN`. The check reads effective `main`
rules, repository rule suites, reviews for the probe PR, and check runs for the probe SHA. Public
check-run reads may not expose a separate fine-grained permission in GitHub's PAT UI, so this
same-client capability proof is authoritative. It reports only endpoint/status/request-ID
classification on failure and never prints response bodies, headers, or the credential. Record a
successful check before merge. If the secret is missing, expired, incorrectly scoped, or the
capability check does not pass, this PR must not merge and the stable workflow will fail before
creating a tag.

The separate release-guard credential health workflow repeats these reads on same-repository pull
requests, every Monday, and through a safe manual run after provisioning or rotation. The pull-request
trigger is the bootstrap path before the workflow exists on the default branch (GitHub does not
register `workflow_dispatch` there until after merge): each PR run pins checkout to the exact head SHA
and refuses fork pull requests. Because that source is still mutable PR code, the credential-bearing
job references the `release-guard-health` environment and cannot start until a required reviewer
approves that exact run. Configure the environment with required reviewers (at least one), prevent
self-review enabled, and administrator bypass disabled **before** uploading its environment secret.
An unconfigured environment or missing environment secret is a fail-closed blocker, not a reason to
fall back to a repository secret. Scheduled and manual runs are restricted to the repository's default
branch. The check discovers a recent merged `main` pull request and verifies effective rules, its exact
month-window rule suite, reviews, and check runs. It has only `contents: read` on the built-in token,
passes `RELEASE_GUARD_TOKEN` only to the health step, and has no release, tag, package, or publish path.

Required checks remain dynamically sourced from effective rules, but each must identify a concrete
GitHub App integration so the guard can reduce actual check runs. A new required context without a
positive integration ID is unsupported and fails closed; the guard never falls back to legacy commit
statuses. Configured stable-guard timeouts must be 15–40 minutes, with a 25-minute default.

The stable guard intentionally fails closed when GitHub adds a rule type it does not recognize.
If a release reports `Unsupported effective repository rule`, inspect the effective rules for
`main` and decide whether the new rule needs an explicit check or is already enforced by the
exact update rule-suite result. Add a rule to `NON_CHECK_RULES` only when a `pass` rule suite
fully covers it; never soften the unknown-rule failure into a warning.

After updating and reviewing the guard, rerun the original merged-PR workflow for recovery.
Do not push a stable tag, select a different SHA, or introduce a manual publish path.

Bypass rejection is intentional: a ruleset result of `bypass` permanently blocks that merge SHA
from publishing. Release PRs must merge normally with their required approval and checks. If a
release PR was bypass-merged, prepare a fresh release PR and merge it normally; rerunning the
bypassed event cannot turn its historical rule-suite result into `pass`.
