--channel canary already worked, but only on a box with nothing installed: the guided installer skips its whole install block once the three binaries are on PATH, so re-running it with --channel on an existing host printed "already installed" and changed nothing at all. Switching was a docs page of sed one-liners you ran by hand.
Now --channel means the same thing on a fresh box and an installed one, and it means it in both directions.
The switch
A repo rewrite plus a re-resolve that is allowed to go down. Canary is always a minor ahead of stable by construction, so canary→stable is a downgrade and every package manager refuses one unless told:
family
how it walks back down
apt
explicit version pins from apt-cache madison — apt will not step to a lower candidate on its own
pacman
-Sy then -S, never -Syu (which looks at the lower stable version and does nothing)
dnf
distro-sync behind the install
sysext
already moved both ways on its own per-feed rollback floor
Three things that were quietly wrong
pacman left both repos enabled. The canary path appended [punktfunk-canary] while leaving [punktfunk] in place, so a canary install let repo order decide which build you got. This one was live on the install path, not just the switch. The switch drops whichever section is there first, reusing --uninstall's own delete.
The stable default was a footgun.--channel defaults to stable, so lifting the early-exit would have let a bare re-run — to fix a group, to open a firewall port — silently drag a canary box back a channel. With no explicit --channel the script now follows whatever the box is on.
A switch has to move every punktfunk package on the box, not the three the script installs, or a hand-installed punktfunk-gamescope is stranded on the channel the machine just left. That set comes from --uninstall's existing query.
Verification
A downgrade path touches packages people already have, so it gets two gates rather than a claim.
check-docs-drift.sh gains gate 8: six --dry-run cases over the four families, with the repo config and the installed binaries faked (PUNKTFUNK_INSTALL_ETC joins PUNKTFUNK_INSTALL_OS_RELEASE as a testing override). The case that matters is a canary box missing a package, re-run bare.
That case was earned rather than assumed. The first version of it passed against deliberately broken code — it asserted on a message that reads from $CUR and so stayed correct while $CHANNEL was wrong. Rewritten around the partial-install shape, mutating the follow-the-box rule now turns it red, which is how it was checked.
installer-smoke.yml adds the round trip against the real registries, where the version has to move and then come back. The textual gate proves the commands are emitted; only that one proves the downgrade happens — so this is unproven until CI runs it. A red there can also mean a family's canary channel is empty rather than a bug in the script; the step says so.
Also checked locally: sh -n parses, shellcheck shows no new findings, all eight drift gates green, ten dry-run switch cases across the four families in both directions, and a stub dpkg-query confirming punktfunk-gamescope joins the switch while a removed-but-not-purged punktfunk-client does not.
Docs
channels.md's "Migrating an existing box to canary" becomes a both-directions "Switch an installed box between channels" — no inbound links to the old anchor — and picks up the by-hand pacman and sysext recipes it never had, plus the flags each manager needs to come back down.
`--channel canary` already worked, but only on a box with nothing installed: the guided installer skips its whole install block once the three binaries are on PATH, so re-running it with `--channel` on an existing host printed "already installed" and changed nothing at all. Switching was a docs page of `sed` one-liners you ran by hand.
Now `--channel` means the same thing on a fresh box and an installed one, and it means it in both directions.
## The switch
A repo rewrite plus a re-resolve that is allowed to go **down**. Canary is always a minor ahead of stable by construction, so canary→stable is a downgrade and every package manager refuses one unless told:
| family | how it walks back down |
|---|---|
| **apt** | explicit version pins from `apt-cache madison` — apt will not step to a lower candidate on its own |
| **pacman** | `-Sy` then `-S`, never `-Syu` (which looks at the lower stable version and does nothing) |
| **dnf** | `distro-sync` behind the `install` |
| **sysext** | already moved both ways on its own per-feed rollback floor |
## Three things that were quietly wrong
- **pacman left both repos enabled.** The canary path appended `[punktfunk-canary]` while leaving `[punktfunk]` in place, so a canary install let repo order decide which build you got. This one was live on the *install* path, not just the switch. The switch drops whichever section is there first, reusing `--uninstall`'s own delete.
- **The stable default was a footgun.** `--channel` defaults to stable, so lifting the early-exit would have let a bare re-run — to fix a group, to open a firewall port — silently drag a canary box back a channel. With no explicit `--channel` the script now follows whatever the box is on.
- **A switch has to move every punktfunk package on the box**, not the three the script installs, or a hand-installed `punktfunk-gamescope` is stranded on the channel the machine just left. That set comes from `--uninstall`'s existing query.
## Verification
A downgrade path touches packages people already have, so it gets two gates rather than a claim.
`check-docs-drift.sh` gains **gate 8**: six `--dry-run` cases over the four families, with the repo config and the installed binaries faked (`PUNKTFUNK_INSTALL_ETC` joins `PUNKTFUNK_INSTALL_OS_RELEASE` as a testing override). The case that matters is a canary box missing a package, re-run bare.
That case was earned rather than assumed. The first version of it **passed against deliberately broken code** — it asserted on a message that reads from `$CUR` and so stayed correct while `$CHANNEL` was wrong. Rewritten around the partial-install shape, mutating the follow-the-box rule now turns it red, which is how it was checked.
`installer-smoke.yml` adds the round trip against the real registries, where the version has to move and then come back. The textual gate proves the commands are emitted; only that one proves the downgrade happens — **so this is unproven until CI runs it.** A red there can also mean a family's canary channel is empty rather than a bug in the script; the step says so.
Also checked locally: `sh -n` parses, shellcheck shows no new findings, all eight drift gates green, ten dry-run switch cases across the four families in both directions, and a stub `dpkg-query` confirming `punktfunk-gamescope` joins the switch while a removed-but-not-purged `punktfunk-client` does not.
## Docs
`channels.md`'s "Migrating an existing box to canary" becomes a both-directions "Switch an installed box between channels" — no inbound links to the old anchor — and picks up the by-hand pacman and sysext recipes it never had, plus the flags each manager needs to come back down.
`--channel canary` already worked, but only on a box with nothing installed:
the guided installer skips its whole install block once the three binaries are
on PATH, so re-running it with `--channel` on an existing host printed
"already installed" and changed nothing at all. Switching was a docs page of
`sed` one-liners you ran by hand.
Now `--channel` means the same thing on a fresh box and an installed one, and
it means it in both directions. A switch is a repo rewrite plus a re-resolve
that is allowed to go DOWN — canary is always a minor ahead of stable by
construction, so canary→stable is a downgrade and every package manager
refuses one unless told: apt gets explicit version pins from `madison`,
pacman `-Sy` then `-S` (never `-Syu`, which looks at the lower stable version
and does nothing), dnf a `distro-sync` behind the `install`, and the sysext
script already moved both ways on its own per-feed rollback floor.
Three things that were quietly wrong fall out of doing this properly:
- pacman appended `[punktfunk-canary]` while leaving `[punktfunk]` in place,
so a canary install left both repos enabled and let repo order decide which
build you got. The switch drops whichever section is there first, reusing
--uninstall's own delete.
- `--channel` defaults to stable, so lifting the early-exit would have let a
bare re-run — to fix a group, to open a firewall port — silently drag a
canary box back a channel. With no explicit `--channel` the script now
follows whatever the box is on. The gate below is built around this case.
- A switch moves every punktfunk package on the box, not the three the script
installs, or a hand-installed punktfunk-gamescope is stranded on the channel
the machine just left. That set comes from --uninstall's existing query.
Verification, since a downgrade path touches packages people already have:
check-docs-drift gains gate 8, six --dry-run cases over the four families with
the repo config and the installed binaries faked (`PUNKTFUNK_INSTALL_ETC`
joins `PUNKTFUNK_INSTALL_OS_RELEASE` as a testing override). The case that
matters is a canary box missing a package and re-run bare — mutating the
follow-the-box rule turns it red, which is how it was checked. installer-smoke
adds the round trip against the real registries, where the version has to move
and then come back; the textual gate proves the commands are emitted, only
that one proves the downgrade happens.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
--channel canaryalready worked, but only on a box with nothing installed: the guided installer skips its whole install block once the three binaries are on PATH, so re-running it with--channelon an existing host printed "already installed" and changed nothing at all. Switching was a docs page ofsedone-liners you ran by hand.Now
--channelmeans the same thing on a fresh box and an installed one, and it means it in both directions.The switch
A repo rewrite plus a re-resolve that is allowed to go down. Canary is always a minor ahead of stable by construction, so canary→stable is a downgrade and every package manager refuses one unless told:
apt-cache madison— apt will not step to a lower candidate on its own-Sythen-S, never-Syu(which looks at the lower stable version and does nothing)distro-syncbehind theinstallThree things that were quietly wrong
[punktfunk-canary]while leaving[punktfunk]in place, so a canary install let repo order decide which build you got. This one was live on the install path, not just the switch. The switch drops whichever section is there first, reusing--uninstall's own delete.--channeldefaults to stable, so lifting the early-exit would have let a bare re-run — to fix a group, to open a firewall port — silently drag a canary box back a channel. With no explicit--channelthe script now follows whatever the box is on.punktfunk-gamescopeis stranded on the channel the machine just left. That set comes from--uninstall's existing query.Verification
A downgrade path touches packages people already have, so it gets two gates rather than a claim.
check-docs-drift.shgains gate 8: six--dry-runcases over the four families, with the repo config and the installed binaries faked (PUNKTFUNK_INSTALL_ETCjoinsPUNKTFUNK_INSTALL_OS_RELEASEas a testing override). The case that matters is a canary box missing a package, re-run bare.That case was earned rather than assumed. The first version of it passed against deliberately broken code — it asserted on a message that reads from
$CURand so stayed correct while$CHANNELwas wrong. Rewritten around the partial-install shape, mutating the follow-the-box rule now turns it red, which is how it was checked.installer-smoke.ymladds the round trip against the real registries, where the version has to move and then come back. The textual gate proves the commands are emitted; only that one proves the downgrade happens — so this is unproven until CI runs it. A red there can also mean a family's canary channel is empty rather than a bug in the script; the step says so.Also checked locally:
sh -nparses, shellcheck shows no new findings, all eight drift gates green, ten dry-run switch cases across the four families in both directions, and a stubdpkg-queryconfirmingpunktfunk-gamescopejoins the switch while a removed-but-not-purgedpunktfunk-clientdoes not.Docs
channels.md's "Migrating an existing box to canary" becomes a both-directions "Switch an installed box between channels" — no inbound links to the old anchor — and picks up the by-hand pacman and sysext recipes it never had, plus the flags each manager needs to come back down.