tmt-release ยท diff

git:20261003.73e5f87 to git:20261003.4ea97a7

3 added, 2 removed. Audit A to A.

---
name: tmt-release
description: Maintain and promote tmux-team release lines, versions, and prerelease readiness without assuming publish authorization.
---
# tmux-team release management
Use this skill for release-line maintenance, v4 compatibility fixes, v5 promotion, version synchronization, or prerelease readiness in this repository.
## Long-lived branch policy
- `main` is the active v5 line after promotion.
- `v4` is the maintenance line rooted at commit `7056679dfa816a1acef8e7c978cf1733a578115b`.
- If remote `v4` does not exist, create it at that exact anchor only when the user has explicitly requested the maintenance line, then verify the remote ref before continuing.
- Before any branch mutation, verify the relevant remote refs and ancestry. Never force-push or repoint a long-lived line.
- A v4 maintenance fix requires a tracked issue, a dedicated branch and worktree, and a reviewable pull request. Keep the fix on the v4 line unless an explicitly scoped backport is requested.
- Use the checks available on the v4 line for maintenance pull requests; do not require contexts that the target branch cannot produce. Record any coverage gap in the issue.
- The CLI version is owned by `rust/Cargo.toml` and exposed through Cargo's package version; there is no TypeScript fallback. Keep any retained developer package version and public release instructions consistent when changing versions. The native skill ships with the CLI; there is no separately versioned plugin or marketplace.
- Follow `AGENTS.md` for GitHub issue state, branch and pull-request links, verification evidence, and safe worktree cleanup.
## Main cut authorization
The [architecture](../../../ARCHITECTURE.md#main-release-cuts) owns the release
model; the [main-cut reference](references/main-cuts.md) owns allocation, source
verification and pipeline procedures. The [CI reference](references/ci-selection.md)
owns selection, workers and cache policy.
Automatic cuts and publication cover only released products on their existing
alpha core version. Stable releases, major/minor changes, breaking releases and
any manual publication require the owner. An explicit version on a cut requests a
draft and native verification; it never overrides a publication gate.
A first alpha also needs the product owner's authorization and reviewed activation
under #1418. No existing-product authorization grants a new product activation. Keep hold,
retry and rerun authorization below, required merge checks, every publication
proof and immutable releases intact. Missing draft visibility or history requires
investigation, never an incomplete allocation catalog.
Independent tags never wait for a prior component draft or pipeline. Failed drafts
stay unpublished without holding later cuts; retries, hold releases and reruns
remain owner-authorized operations on one exact tag. Alpha publication requires a
unique unpublished tag/version; stable publication retains the existing monotonic
gate. CLI alphas keep `prerelease=false`: every CLI publication initially uses
`latest=false`, then bounded read/correct/readback rounds converge latest to the
highest published CLI version. A stale publisher corrects again to the current
maximum; disagreement after the bound fails visibly. Extensions remain prereleases
with `latest=false`. Public smoke proves `releases/latest/download/install.sh` for
the highest CLI, or the versioned installer for an older out-of-order cut. Managed
alpha discovery must still choose the highest eligible version. Upgrade proofs use the newest published version
**below** the candidate, preserve candidate > previous and downgrade rejection,
and retain every four-host artifact/installation/adapter proof. Notes, migration comparison and breaking authorization share one boundary: the
newest **published** ancestor release of the component. Failed or running drafts
reserve numbers but never advance that boundary. Concurrent cuts can therefore
repeat note items; inherited unpublished migrations remain counted and inherited
unapproved breaking changes stay held by the existing owner gate.
- Cut allocation runs hourly (minute 17 UTC) or by owner dispatch, never on every
- main push. The hourly schedule replaces the daily allocation safety net. New work
+ Cut allocation uses cadence-admitted main pushes, an hourly schedule backup and
+ owner dispatch. The [main-cut reference](references/main-cuts.md) owns cadence
+ admission and its fail-closed history checks. New work
eligibility uses the newest allocated ancestor cut, whether draft or published:
no releasable component commit after it means no new cut. Failed drafts reserve
their content and number without blocking subsequent new component work. Notes,
migration comparison and breaking authorization retain the published boundary
above. Allocation remains a short serialized critical section; each admitted run
captures current main and preserves unallocated work. Once allocated, tag-keyed
pipelines never displace another tag's pending pipeline.
Non-publishing `prepare` rehearsals and installation fixtures derive
`<committed major.minor.patch>-alpha.999999` through the single
`release-versions.syntheticAlphaVersion` helper. This deliberately synthetic
version is never a real cut or publication target. Preparation keeps the draft
tag empty, creates no Git tag, and runs every source, archive and installation
gate against the injected version. It adds no dispatch input and authorizes no
product activation. Follow the [installation-fixture procedure](references/installation-fixtures.md).
The private release tool's mechanical source/lock proof grants no publishing
permission. Do not commit injected versions back to main, create tags early,
replace public assets or replay publication to recover a smoke failure.
## Conventional PR titles
Merge groups report conventional squash-title syntax through `pr-title-check.mjs`. The report-only phase writes findings and unavailable evidence to job
output/summary and always exits zero; it does not enforce titles yet. Do not add
an `edited` trigger to full CI or compare ordinary queued subjects against mutable
REST titles. [The rollout notes](references/native-release.md#conventional-pr-title-rollout)
owns the observation day and the separate explicit UTC cutover, 24 hours after
the report-only PR merges. The cut planner owns release notes and attribution.
## Project release reconciliation
Keep delivery evidence separate from publication: the Project updater derives
closed-issue fields from merged closing PRs, changed-path product ownership and
the earliest published containing tag for every affected product. Use the existing
component map and release policy/version helpers, never notes or a recency window.
Every sweep is authoritative for eligible issues, including recovery from built-in
status workflow writes. Exclude epic trackers from both fields; their owning lead
retains the acceptance/dogfood gate, and the summary lists them as skipped. The post-publication dispatch waits for read-back and smoke completion;
authenticated acquisition errors remain failures, with the daily sweep retaining publication reconciliation.
Retain the daily safety net. Follow [Project release tracking
procedure](references/native-release.md#project-release-tracking) for full dry-run table
review, request and GraphQL point-cost reporting, exact verification commands and
activation evidence.
A tracking dispatch never authorizes publication or a publishing-workflow replay.
The component map distinguishes explicitly parked products from those awaiting
activation; `release:false` alone never means Done.
## Promotion and prerelease checks
Read the complete [native release verification reference](references/native-release.md)
before archive, installer, upgrade, bootstrap or publication work. It owns the
procedures referenced below; [DEVELOPMENT.md](../../../DEVELOPMENT.md) owns ordinary native checks.
For packed verifier process-runner changes, follow the
[packed cleanup checks](references/native-release.md#packed-verifier-cleanup).
Preserve its real absence and surviving-group controls; synthetic fixture success
does not authorize publication or replace artifact acceptance.
- For Rust archives, follow the guide's native Rust release archive procedure.
Generate the offline clarification config before calling cargo-about directly,
as documented there; keep its vendored-license checksum and version checks,
`--fail` and the archive verifier's placeholder rejection intact.
Keep cargo-dist's manifest as the artifact metadata owner; independently verify
bounded extraction, notices, linkage, skill installation and persisted state.
Raw PR runtime checks do not establish release archive correctness. Do not enable a
generated installer or publication workflow merely to obtain local archives.
- Follow the native runtime checks and the reference's archive verification for artifact changes.
For fixture-only archive-policy fixes, follow the reference's negative archive checks
for hard-link construction and rejection controls.
Reuse the shared runtime proof for linkage, exact embedded skills and SQLite
reopen behavior. Keep the independent archive inventory/checksum/notices and
installer failure/cleanup evidence; raw binaries are not release artifacts.
- For native binary publication changes, also follow the guide's offline
installer lifecycle procedure using actual separately versioned archives.
Keep ownership anchored in the installation prefix, not application-state
selectors; verify old executable preservation, pin policy, partial command-link
finalization and unchanged data. The internal preview entrypoint is not a
public bootstrap or permission to replace a user/package-manager installation.
- Promotion requires passing Code quality, Unit tests, and Docker E2E checks.
- For a public native alpha, follow the guide's explicit multi-platform
release preparation procedure. A `prepare` run of the manual artifact workflow never
publishes;
all four final native verifiers must pass on the recorded reviewed commit.
Keep cargo-dist as the merged manifest owner. Authorized publication uses an
immutable draft-to-published GitHub release and verifies its attestation and
public installer before promoting README instructions. Publish with the
bundle's `release-publication.json` flags: the CLI release is a normal release
whose latest selection follows the main cut authorization contract above;
Office, Squad, Remote, Colab and Herdr releases retain their product prerelease policy and never
become latest. After
a manual publication, run the [publication readback](references/main-cuts.md#manual-publication-readback) (the pipeline checks
its own publications). Do not equate a
downloadable CI bundle with a published or accepted release.
- Every CLI, extension or driver release also passes the guide's upgrade from the last
published release using the product-specific proof in the reference, not only a
fresh install. Old CLI/extension receipts must stay readable.
Synthetic extension-upgrade tests use the private native recording driver on
every platform. Follow the [fixture build contract](references/installation-fixtures.md#native-recording-driver)
before running them; preserve exact architecture admission and public-command
assertions rather than substituting a shell executable.
The pre-publication CLI proof requires installation, migration and real-archive
acceptance of the release's own adapter on all four hosts. Follow the guide's
distinction between injected acquisition, skipped differential skill coverage for identical text,
older-source rerun applicability and separate public installer/upgrade smoke.
A standalone driver uses previous/candidate archives and the current published
CLI's path approval surface. Herdr awaits activation; product activation and its first alpha belong to #1418
and require owner authorization.
- For curl bootstrap, follow the guide's native curl bootstrap verification.
Generate from final verified cargo-dist artifacts and invoke the existing
native publisher; do not enable a competing stock installer. Test an actual
matching-host archive without Node/Rust on runtime PATH, and distinguish
controlled-download evidence from an authorized public release smoke test.
npm/pnpm replacement is a fresh installation without data-transfer machinery,
not permission to delete old state or silently uninstall another manager.
- Tags, GitHub Releases, npm publishing, and npm dist-tags are separate operations that require explicit authorization; this skill never assumes permission for them. The one standing authorization is the release pipeline's alpha publication below.
- Update user-facing installation or channel documentation whenever a version change would make it inaccurate.
- The nested v5 TypeScript package is private developer tooling, not a product distribution.
Do not restore npm publishing or a download wrapper without a separately scoped
distribution decision. Historical v4 publishing uses that branch's own rules.
## Archive contents and install facts
Remote and Colab are activated native alpha products. Remote embeds its device SDK;
Colab embeds its app, including used `colab-client` code, through `TMT_COLAB_APP_DIR`
and appends frontend notices to Rust notices. Follow the
[product verification procedure](references/main-cuts.md#remote-and-colab-products).
Their first cuts require a published supporting CLI containing registration;
archive, installation and public-smoke gates still establish delivery.
- Every native product archive carries its executable, `LICENSE`,
`NATIVE-INSTALL.md` and `THIRD-PARTY-NOTICES.txt`. The installer enforces this
inventory (`tmt-core`'s `native_install/product.rs`), so adding, renaming or
dropping an entry is an installer-contract change with an upgrade proof, not a
documentation edit. The CLI release may also carry optional companion executables.
- The archive's `NATIVE-INSTALL.md` is sourced from `rust/archive/NATIVE-INSTALL.md`
through `dist-workspace.toml` and extension package includes. Keep it a short,
product-neutral offline note without version numbers: user guidance belongs to the
handbook, and the onboarding test runs the note's PATH block in Bash and Zsh.
- Release targets are macOS x64/arm64 (build deployment target 11.0) and Linux
x64/arm64 with a static musl runtime. macOS x64 follows the
[runtime acceptance policy](../tmt-e2e/references/runtime-smoke-matrix.md):
cross-build on arm64, complete Rosetta verifier process trees with exact
installed-byte architecture checks, plus weekly native Intel public
installation and upgrade coverage. A deployment target is not testing on every
macOS version; cite the release's verification evidence for tested hosts.
- The manifest's SHA-256 checksums detect corruption, not a compromised download
origin. Locally generated checksums are not signatures, and no local test artifact
carries a GitHub attestation. Only a published immutable release does
(`gh release verify`, `gh release verify-asset`).
- The generated `install.sh` fixes the initial version and channel (never a mutable
tag). It verifies the manifest and archive sizes and digests before it runs the
temporary binary, then delegates permanent writes to the native installer. It does
not edit shell profiles or touch SQLite, and it needs only a POSIX shell, curl,
tar/gzip, standard utilities and `sha256sum` or `shasum`. Its receipts record
local-archive verification, not independent attestation provenance.
- Successful human installer output names `<requested-prefix>/bin/tmt`, matching the
bootstrap summary even when a prefix ancestor is a symlink. Installation
validation, receipts and JSON reports keep canonical paths (#1098).
## Automated alpha publication
The owner chose a trunk-based alpha channel: there is no separate edge channel, and a merge to
`main` publishes an alpha release through the release pipeline once its publication gates pass
(the owner's decisions on #497). That choice is the owner's standing authorization for **the
pipeline** to publish alpha releases from `main`; it is recorded here so that the written rule
matches practice. The
[native release verification reference](references/native-release.md) owns the
gates, the markers and the procedures; this section owns who may publish what.
- Covered: an alpha draft of a released native product (a version `X.Y.Z-alpha.N`, enforced by
the `channel` gate and again by the publish command) that the pipeline built from `main`,
verified and attached, of a component that is released (`release: false` in the component map
parks one), and that passes every publication gate. A new SQLite migration does not hold an
alpha: migrations are forward-only, and the `migration` gate only reports the new entries in
its summary. The CLI alpha is published as a
normal release; its latest convergence follows the main cut contract above.
Extensions and drivers retain the bundle's prerelease policy and never become latest.
- Still the owner's explicit authorization: stable releases and anything outside the alpha
channel; a release from a branch line; a draft that any gate holds, and in particular a
breaking change (a `!` or `BREAKING CHANGE:` commit), which always pauses for the owner's
explicit OK;
README installer promotion; creating or rotating Project release App credentials,
changing the main-only `release` Environment (the owner's setup is in the guide's main-cut section);
enabling or changing release immutability; and this authorization itself.
- The authorization belongs to the pipeline, not to an agent. An agent still never tags,
creates, edits or publishes a release by hand, and never dispatches a run that publishes,
without the owner's explicit authorization for that release. A run of `native-release.yml`
with `prepare` off publishes every draft of the product that passes its gates, and so does
its `hold` input for the released draft; `prepare` on (one bundle, no draft), `release.yml`
with `dry_run` on and the upgrade proof are not publication.
- A held draft carries `publication-held.json` with the gate, the reason and the run. Read it,
then follow the guide: the owner publishes by hand, or releases the hold by dispatch, which
skips only the gate the marker names. An owner-authorized `rerun` instead re-proves
every gate with current main tooling against the draft's existing assets and its
release-source expectations and adapter code, preserving the marker on failure
and removing it only after all pass.
`rerun` requires the owner's explicit authorization, like `hold`.
- After it publishes, the pipeline reads the release back (public, immutable, the policy's
flags, the tag on the release commit, GitHub's attestation for the release and every asset).
A failed check opens an issue and fails the run; nothing is rolled back, and a repair is a new
reviewed version. A read-only smoke then installs the published release through the public
installer (and `tmt upgrade` for the CLI) in an isolated environment on the four hosts, and a
real failure there is reported on the same issue. The shared public-install-smoke
action uses the workflow's `contents: read` `GITHUB_TOKEN` for native API acquisition.
Pass it through env only, never argv or disk; redact output and verify isolated
installed state contains no credential. Asset downloads remain public and token-free.
Preserve the native bounded HTTPS retry and the bounded older-alpha latest-installer
lag retry. Exhausted rate limits are ordinary failed smoke checks; there is no
deferred rate-limit retry workflow. Use the PR-only four-host proof against existing
published releases for tooling changes, never a publishing dispatch. Keep the
post-publication Project dispatch gated on successful smoke and historical failure issues
visible to the release monitor. Never dispatch publication to recover a smoke failure.
## CLI upgrade proof
`native-release-policy.mjs::upgradeSupportFloor` declares the exact published CLI
floor (alpha.36). For candidates above it, `release-upgrade.mjs` stages both the
floor and last published source, deduplicating identical sources, and the candidate
`install.sh`; every archive, manifest and bootstrap must retain its recorded
GitHub digest. Candidates at or below the floor keep their historical single-source proof.
Candidate `native_install/handoff.rs::VERSION` owns probe applicability. Protocol-1
sources require the exact successful candidate probe in
[the handoff contract](../../../contracts/native-install-handoff-v1.md); malformed,
failed or unsupported probes cannot become legacy evidence. Each source creates
its own receipt and application state. An offline source installer that rejects
added inventory must emit its actual `NATIVE_INSTALL_FAILED` / `Unexpected native
archive asset inventory.` error and preserve the complete installation and SQLite.
The actual candidate bootstrap then recovers with only curl acquisition replaced
by the exact staged versioned assets, retaining old bytes and migrating state cleanly.
Offline installation remains strict and does not prove self-upgrade delegation.
Every distinct source also passes the existing managed lifecycle/migration checks
and actual-archive adapter acceptance. Compile the candidate's adapter lib tests
once per host; require exactly one discovered ignored test and one passing execution
per source. Acquisition is injected; production candidate delegation and real
candidate execution are exercised by the candidate adapter. Public downloads and
`tmt upgrade` remain the separate post-publication smoke.
Keep each prove job's ten-minute timeout, read-only dependency cache and per-source
bootstrap/adapter plus compile durations. For tooling changes, use a PR-only,
read-only/no-secrets four-host rehearsal against a pinned real main source and
actual cargo-dist archives; remove temporary rehearsal machinery before readiness.
Do not dispatch a publishing workflow to obtain proof.
Focused checks from the repository root:
```sh
(cd typescript && corepack pnpm exec vp test run --config vitest.config.ts test/tooling/release-upgrade.test.ts test/tooling/native-upgrade-proof.test.ts test/tooling/native-release-policy.test.ts test/tooling/native-bootstrap.test.ts test/tooling/intel-verification.test.ts test/tooling/xcrun-warmup.test.ts test/tooling/release-workflow.test.ts test/tooling/repository-layout.test.ts)
(cd typescript && corepack pnpm check:tooling)
actionlint .github/workflows/native-release-upgrade.yml
```