Let a line generate itself #357

Open
PerishFire wants to merge 1 commit from task/a-line-generates-itself into main
Owner

A release that repairs the release mechanism is built by the mechanism it repairs.

v0.26.0 met this and answered with a one-time bootstrap bound to one beta, retired a commit later as an exception that had served its purpose. The next version needed it again — and this time on every dispatch rather than only the stable one:

本地构建   → plumb requires a sibling this release has not published yet   ✅ skipped
装着的 v0.26.0 → Packaging plumb → error: failed to select `plumb-macro = "=0.27.0-beta.4"`  ❌

v0.27.0 teaches the Cargo rehearsal to skip a package pinned to an unpublished sibling; v0.26.0, which does the release, does not know that yet. So v0.27.0 cannot publish itself.

An exception that recurs is not an exception

Every exact publication now points its channel at what that run published, and the install step reads that pointer:

v1/channels/beta.json → newest exact plumb → install it
absent                → canonical stable

This needs an exact run to move its own channel pointer, which it could not do: publish credentials are create-only by design, and only stable lanes carried the activation pair. Exact lanes carry it now. That widens what a beta run can touch, and the boundary is narrower than ones a beta already crosses — a beta publishes irreversibly to cargo, npm, oci and chart before it reaches this.

The generator stops claiming what it is not

It recorded stable provenance whatever produced it. A prerelease binary now seals exact-release provenance naming its own published seal and digest, and the audit requires that provenance to name a point on the line being released rather than forbidding it outright.

The one-time constants go with it — including BETA_VERSION = "v0.26.0-beta.5", a release point that was never cut: the same falsehood the frozen changelog carried.

This does not repair the release in flight

No channel pointer stands yet, so the next beta still installs stable and still fails at the Cargo rehearsal — but its seal publishes the pointer on the way past, and the beta after it is built by a Plumb that knows.

**A release that repairs the release mechanism is built by the mechanism it repairs.** v0.26.0 met this and answered with a one-time bootstrap bound to one beta, retired a commit later as an exception that had served its purpose. The next version needed it again — and this time on *every* dispatch rather than only the stable one: ``` 本地构建 → plumb requires a sibling this release has not published yet ✅ skipped 装着的 v0.26.0 → Packaging plumb → error: failed to select `plumb-macro = "=0.27.0-beta.4"` ❌ ``` v0.27.0 teaches the Cargo rehearsal to skip a package pinned to an unpublished sibling; v0.26.0, which does the release, does not know that yet. **So v0.27.0 cannot publish itself.** ## An exception that recurs is not an exception Every exact publication now points its channel at what that run published, and the install step reads that pointer: ``` v1/channels/beta.json → newest exact plumb → install it absent → canonical stable ``` This needs an exact run to move its own channel pointer, which it could not do: publish credentials are create-only by design, and only stable lanes carried the activation pair. **Exact lanes carry it now.** That widens what a beta run can touch, and the boundary is narrower than ones a beta already crosses — a beta publishes irreversibly to cargo, npm, oci and chart before it reaches this. ## The generator stops claiming what it is not It recorded `stable` provenance whatever produced it. A prerelease binary now seals `exact-release` provenance naming its own published seal and digest, and the audit **requires** that provenance to name a point on the line being released rather than forbidding it outright. The one-time constants go with it — including `BETA_VERSION = "v0.26.0-beta.5"`, **a release point that was never cut**: the same falsehood the frozen changelog carried. ## This does not repair the release in flight No channel pointer stands yet, so the next beta still installs stable and still fails at the Cargo rehearsal — **but its seal publishes the pointer on the way past**, and the beta after it is built by a Plumb that knows.
Let a line generate itself
All checks were successful
guard / guard (pull_request) Successful in 2m46s
1d2a4b066b
A release that repairs the release mechanism is built by the mechanism it
repairs. v0.26.0 met this and answered with a one-time bootstrap bound to one
beta, retired a commit later as an exception that had served its purpose. The
next version needed it again, and this time on every dispatch rather than only
the stable one: v0.27.0 teaches the Cargo rehearsal to skip a package pinned to
an unpublished sibling, and v0.26.0 — which does the release — does not know
that yet, so v0.27.0 cannot publish itself.

An exception that recurs is not an exception. Every exact publication now points
its channel at what that run published, and the install step reads that pointer,
so a run installs the newest exact Plumb and falls back to canonical stable only
when none stands. This needs an exact run to move its own channel pointer, which
it could not do: publish credentials are create-only by design, and only stable
lanes carried the activation pair. Exact lanes carry it now. That widens what a
beta run can touch, and the boundary it crosses is narrower than the ones a beta
already crosses — a beta publishes irreversibly to cargo, npm, oci and chart
before it reaches this.

The generator stops claiming what it is not. It recorded `stable` provenance
whatever produced it; a prerelease binary now seals `exact-release` provenance
naming its own published seal and digest, and the audit requires that provenance
to name a point on the line being released rather than forbidding it outright.
The one-time constants go with it, including a `BETA_VERSION` naming
`v0.26.0-beta.5` — a release point that was never cut, the same falsehood the
frozen changelog carried.

This does not repair the release in flight. No channel pointer stands yet, so
the next beta still installs stable and still fails at the Cargo rehearsal — but
its seal publishes the pointer on the way past, and the beta after it is built
by a Plumb that knows.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
All checks were successful
guard / guard (pull_request) Successful in 2m46s
This pull request has changes conflicting with the target branch.
  • .forgejo/workflows/exact.release.yml
  • .forgejo/workflows/ship.yml
  • AGENTS.md
  • crates/cli/assets/release/exact.yml.in
  • crates/cli/assets/ship/binary.yml.in
  • crates/cli/assets/ship/install.yml.in
  • crates/cli/src/command/release/output/capsule.rs
  • crates/cli/src/command/release/truth/storage.rs
  • crates/cli/src/command/release/truth/verify.rs
  • crates/cli/src/dispatch/release/generator.rs
  • crates/cli/tests/operator/lane.rs
  • docs/CHANGELOG/v0.27.0/en/INDEX.md
  • docs/CHANGELOG/v0.27.0/zh/INDEX.md
  • plumb.toml
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin task/a-line-generates-itself:task/a-line-generates-itself
git switch task/a-line-generates-itself
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
PerishLab/plumb!357
No description provided.