Editions and upgrades
Single-page view · as markdown
Editions
Peios / Peiso / Editions and upgrades
Peios has no channels and no release cadence. It is a rolling release with a full archive: every version of every package ever published stays installable. What it has instead of a channel is an edition — a package that says what a Peios is.
The edition package #
dev.peios.peios-experimental is the edition today. It retains
peios-experimental as a compatibility capability for image composition and
as the bounded name of pre-qualification installations. It is an ordinary
peipkg package with an unusual job:
- Its version is the OS version.
dev.peios.peios-experimental 2026.8-12is Peios 2026.8. The package writes/usr/lib/os-release(VERSION_ID="2026.8",VARIANT_ID=experimental,PRETTY_NAME="Peios 2026.8 Experimental") and the/usr/etc/os-releasecompatibility symlink, so a system's identity and its release are one fact, tracked in the package database. - Its dependencies are the base system. Kernel, modules and firmware; the initramfs —
prelude, its hooks, the module subset and its own base tree, each placedIN initramfsexplicitly; the service manager, registry, identity and networking daemons; the installer. Installing the package into an empty root yields a bootable Peios. - It provides
peios-release. Depend on that virtual name to mean "some Peios"; depend on the edition to mean that edition. - It ships
release.toml: what the release asks of a system beyond its packages, as data. - It declares an alternate upgrade path. peipkg refuses to install or upgrade it by name, holds it back from an upgrade of everything, and prints the message it carries: To upgrade Peios use the
upgrade-peioscommand. The reasons are below.
"Experimental" is a name, not a channel. It marks that Peios is not yet production-ready and says nothing about cadence. When enough exists for the split to make sense it is replaced by peios-pro, peios-minimal, peios-desktop and so on — each its own package, each providing peios-release, each shipping its own os-release.
What the edition deliberately does not contain #
Three things a live medium needs are absent from the edition, because they are properties of the medium:
live-bootanddisk-boot. Which boot packages a system carries depends on what it boots from. The installer swaps one for the other on the target; an edition that named either would be installable on only one kind of medium.peios-dwe. The Developer Workstation Environment makes a machine ownable. It is added by peiso for a development medium and could never be a thing that arrives by installing a package.- Anything the installer is not.
peios-installis in the edition: an installed system can install another.
Pinning #
Experimental's dependencies are >= floors — a floor lets a package move without republishing the edition on every change, which is right for a pre-alpha. A production edition pins exact versions, and then something useful follows: peipkg upgrade cannot move a pinned dependency past what the edition allows, so a real release upgrades as a unit, through upgrade-peios, never piecemeal.
Why the package manager will not move it #
Installing a package on Peios cannot change system policy. A package delivers files; which services run and which policies apply is decided by registry seeds that a package can only offer. That is the deliberate weakness that lets packages be installed freely.
Moving from one release to the next is more than a package upgrade: the new release's seeds have to be reconciled, and that is precisely the thing peipkg must not do. So the edition declares, in its manifest, alternate_upgrade = { message = "To upgrade Peios use the upgrade-peios command." } (PSPU §5.18). The declaration grants nothing — a package cannot name a command for the consumer to run, let alone run one. Its whole effect is that peipkg stops and shows the message, with a warning that whatever the message names sits outside the package manager's protections. The person runs upgrade-peios, which drives peipkg with --bypass-alternate-upgrade and then does the reconciling itself.
Where an edition lives #
The recipe is pkgs/dev.peios.peios-experimental/ in the Peios tree: a
pekit.toml whose build writes os-release and release.toml, and a
package.pekit.toml with the dependency table. Changing what Peios contains is
a change there, followed by a republish. peiso and its spec do not change.
release.toml
Peios / Peiso / Editions and upgrades
An edition package ships /usr/share/peios/release.toml. It states what the release asks of a system beyond its packages. peipkg never reads it; two tools do:
- peiso, when composing an image, to stage the seeds into the medium.
upgrade-peios, to stage and apply the installed release'sautoapplyseeds, including when an ordinary CLI package request is a no-op or declined. Read the upgrade warning and preview procedure before invoking it.
Both act as the operator, deliberately; the package manager acts as neither.
Contents #
This example shows the three queues, including the GXWI desktop seeds
listed in the Experimental quick start.
It is not an exhaustive release manifest: inspect the selected edition's
/usr/share/peios/release.toml for its complete lists.
# Example registry queues. Read by peiso and upgrade-peios.
[]
= [
"port-reservations",
"eudev-service",
"authd-service",
"authd-policy",
"lpsd-service",
"lpsd-authd-registration",
"login-console",
"eventd-config",
"eventd-service",
"netd-service",
"netd-default-profile",
"resolvd-service",
"resolvd-port",
"gxwid-service",
"gxwi-config",
"gxwi-network",
"fenestra-config",
"fenesh-config",
]
# The boot medium applies these and an installed machine does not.
= [
"lpsd-first-account",
]
# Only an installed machine applies these.
= [
"oobe-service",
]
Three lists, because a seed has a place #
A seed can belong to the medium, to the machine an installer writes, or to both. The distinction exists because an installer copies the shipped image verbatim: whatever is staged onto the medium arrives on the disk too, unless something takes it off again.
Two opposite cases make that matter, and before the split neither could be said:
lpsd-first-accountprovisions the development account whose password ships in the image and is therefore public. Right on a live medium; a hole on an installed machine — which used to get it, and then crash the provisioner against its own account on every subsequent boot.oobe-serviceruns first-boot setup, which asks for a real account. Right on an installed machine; on the medium it would take the console away from the installer.
| Key | Staged into | Applied by |
|---|---|---|
autoapply | lcl/policy/autoapply.d/ | every system, on first boot |
live_autoapply | lcl/policy/autoapply.live.d/ | the boot medium only |
install_autoapply | lcl/policy/autoapply.install.d/ | the installed machine only |
Each names a master a package in the edition's closure ships at /usr/share/regim/<name>.reg; listing it is what opts it in. A reader treats a name nothing ships as an error, and a name in two lists as an error too — it would be staged and drained twice, and in every case it means the release said something it did not mean.
peinit's drain applies the first two, base before live, so a live seed can override a value the base one set: the medium is the special case, and the special case goes last. It never touches the third. The installer is what promotes autoapply.install.d/ into the target's autoapply.d/ and deletes autoapply.live.d/ — the act that turns a copy of a medium into a system.
Nothing else is defined yet. Unknown keys are rejected by both readers, so the file can grow without silently meaning nothing to an older tool.
What is not here #
dwed-service. The DWE seed is peiso's to add, for a development medium only; a release never applies it. peiso stages it into the live queue, on the same reasoning that puts the development account there: a machine installed from a DWE medium is a machine, and a vsock control channel into it is not something the operator asked for.- Anything a medium adds.
live-bootand the medium repository are the image's, not the release's. - Seeds that were removed between releases. A seed present in 2026.8 and absent in 2026.9 is not un-applied by anything today; the registry keeps its history and that is where the record lives. This is the same limitation an edition has with packages it stops depending on, and it is deferred to the same future mechanism.
Why a file, and not a package field #
peipkg's manifest is the wrong place for this, on purpose. A field the package manager acted on — "apply these seeds when I am installed" — would let any package change system policy by being installed, which is the one thing Peios packages must not be able to do. As a file that only deliberate tools read, the list is inert until someone who has chosen to build an image or upgrade a system acts on it.
Upgrading Peios
Peios / Peiso / Editions and upgrades
Use upgrade-peios to move the edition package and reconcile the release's
registry seeds. First inspect the installed release and preview the package
plan:
--check does not apply the package plan or stage or apply registry seeds.
Planning can still refresh repository metadata for peipkg's trust-freshness
checks. It is a preview against the inputs available then, not a reserved
plan for a later invocation.
When you intend both the package update and seed reconciliation, run:
Re-running can finish seed work left by an interruption, but it also copies the installed release's seed masters into the queue again. Review the release's policy changes and preserve important local configuration before reapplying them. A failed package transaction needs the package recovery procedure, not an assumption that every interrupted step completed.
What happens #
- Find the edition.
upgrade-peiosreadsIDandVARIANT_IDfrom/usr/lib/os-release— the file the edition package itself wrote — and derives the edition package's name from them:VARIANT_ID=experimentalisdev.peios.peios-experimental. A system whoseIDis notpeios, or that has no variant, is refused (exit 2). - Move the edition package. It runs
peipkg upgrade dev.peios.peios-experimental --bypass-alternate-upgrade, passing--yesand--allow-stalethrough when given. The upgrade pulls the release closure with it. A peipkg failure is exit 3, and the updater stops before its seed steps. In ordinary CLI mode, peipkg exit 0 also includes a no-op or a declined prompt; those outcomes still reach the next step. - Stage the installed release's seeds. The installed
release.tomlis read, whether or not the package version changed; each seed it names is copied from/usr/share/regim/into/lcl/policy/autoapply.d/, and the drain script is placed in/lcl/policy/autorun.d/if it is missing. A seed the release names that nothing ships is exit 4. - Apply the queue. Unless staging for boot,
reg apply --dir /lcl/policy/autoapply.d --once-delete --yesapplies the queued seeds and removes successfully applied files. This command is run when the release names seeds and targets the whole directory, including other seeds already queued there. Registry policy and service definitions can change; verify their intended effects separately. Failure is exit 5, and is not a rollback of package changes or already-applied seeds.
upgrade-peios never elevates. peipkg and reg run with the caller's token, exactly as they would if you typed the two commands yourself; KACS decides what each may do.
An installation whose upgrade-peios itself predates the qualified package
name is covered too. Its old concrete request for peios-experimental selects
the final 2026.8-10 legacy migration release. That dependency-only release
requires dev.peios.peios-experimental; the successor's bounded replaces
edge removes the legacy package in the same transaction. The migration release
therefore never enters the installed result. The successor also conflicts with
the legacy name, so trying to install the trampoline into an empty system fails
rather than leaving two edition identities behind.
Options #
--on-reboot | Stop after staging. This still writes the seed queue, including after a plain-CLI no-op or declined package prompt. The seeds apply on the next boot, when peinit runs the drain script before planning its services. Use this when a seed changes something you would rather not change under a running session — the console login, say. |
--seeds-only | Skip the package upgrade and only reconcile the installed release's seeds. This is the re-run: after an interrupted upgrade, or to re-apply a release's policy. |
--yes, -y | Pass --yes to peipkg. |
--allow-stale | Pass --allow-stale to peipkg: carry on with a repository's out-of-date information when refreshing it brought nothing newer. |
--check | Preview peipkg's package plan with --dry-run; do not apply that plan or stage or apply seeds. Trust-freshness checks can still refresh repository metadata. |
--status | Show the installed release, the edition package's version, the seeds waiting for the next boot, and whether you may upgrade. |
--root DIR | Operate on the Peios rooted at DIR rather than /. A non-live root implies --on-reboot: seeds are still staged there, but reg is not run against the live registry. peipkg is run with --root DIR. |
To do it on the desktop, use Upgrade Peios.
It uses driven mode: a cancelled result stops before seed staging and
application. This cancellation handling differs from the ordinary CLI's
exit-status check. A driven done result with no package operations is not
cancelled; without --check, it can still reach seed reconciliation.
Check the outcome #
Separate the package result, the seed result, and the running system:
- Read the package result and warnings. peipkg exit 0 alone does not establish that an upgrade was performed or approved.
- Run
upgrade-peios --statusagain, using the same--root DIRfor an alternate root. Compare the installed edition version and queued seeds. An unreadable queue is unknown, not empty. After--on-reboot, staged seeds are expected to remain until boot applies them. - If staging or application failed, read the failed step before retrying.
Earlier seeds may already be staged or applied.
--seeds-onlystages the installed release's completeautoapplylist again; it is not a read-only check or a reversal of the failed attempt. - Verify affected registry policy and the software that uses it. An empty
queue does not by itself prove every intended service or policy is
working. Package
undodoes not restore registry state or undo a feature's setup; see recovery limits.
--status reads installed release/package metadata and the queue. It does
not identify the currently running kernel or mapped service binaries. This
updater invokes peipkg and reg; that path does not itself run a reboot or
boot-image regeneration command. Do not use its successful exit or status
as proof that all installed code is active or that every kernel update's
boot artifacts are ready. Upgrading from the medium is
a separate path with explicit boot-file regeneration.
Check what an update has activated #
Use these inspection steps after reviewing the package and seed results above. They do not regenerate boot files, start services or restart the machine. If a step cannot be verified, record boot activation not yet verified rather than treating the update as ready to boot.
Compare installed and running code #
For a kernel update on the live system, record:
uname -r identifies the running kernel release. Compare it with the intended
release in the installed kernel's payload paths, not directly with the edition
or package version: those are different identifiers. A difference before
restart is not proof that a restart will select the new kernel. For alternate
roots, select the intended package root separately; uname still describes
the running system.
Service status gives state, job, PID and start information, not an executing
binary's build identity. svctl --version is the client version. Use the
affected service's own reload/restart requirements and functional checks;
package installation or a registry-definition reload does not prove it has
adopted new code.
Inspect Dynamic Boot's actual state #
The located live regeneration mechanism is the optional Dynamic Boot
feature, whose scripts define mkirf-watch and mkuki-watch. Package delivery,
feature setup, enablement and running services are separate states:
The reviewed feature initially creates disabled services. Enabling it after boot clears that flag but does not retroactively start them; disabling it does not stop an already-running watcher. Image setup before boot-time service enumeration can differ. Check the actual services rather than inferring their state from the feature record. This section supplies no automatic start or restart sequence.
In the packaged definitions, mkirf-watch writes
/system/boot/initramfs.cpio.zst, and mkuki-watch writes
/boot/efi/EFI/BOOT/BOOTX64.EFI. Verify the definitions on your machine. The
UKI launcher chooses its command-line input at startup: a nonempty
/lcl/etc/boot/cmdline, otherwise /usr/share/live-boot/cmdline. Creating the
preferred file later does not prove an existing watcher switched to it.
Verify the destination and rebuild evidence #
Before relying on watcher output, use storage inspection
to identify the intended EFI System Partition and the filesystem at the output
path. Plain mount lists mounts visible in the caller's namespace; that is not
proof of firmware selection or another namespace's view.
In Services Manager, inspect Logs… for each watcher over the update's
job/time interval. Both can report rebuild failed and remain running; an
Active/Alive state or watching message is not build success. mkuki also
rejects zero or multiple regular vmlinuz-* candidates rather than selecting
the newest one.
Look for successful cpio replacement and a subsequent successful UKI rebuild using the final settled inputs, retaining all rebuild/watch errors. A wrote message follows output replacement, but the watchers run independently of the package transaction: it is not an all-input generation or bootability attestation. Intermediate builds can observe different update stages. Missing logs or timestamps alone cannot establish success; log visibility and delivery limits still apply.
Check after a separately planned restart #
Only follow the machine's supported restart procedure once its prerequisites
and recovery access are established. After it actually boots, run uname -r
again and compare the intended release. Check queued-seed state, affected
service jobs/status and their functional behavior separately. An accepted
restart request, installed edition name or old successful build message does
not replace these observations.
The installer-medium upgrade is a separate path that mounts its selected ESP and explicitly rebuilds boot files. It is not evidence that the live watcher destination is configured, nor a harmless generic repair.
Activation evidence and scope #
This checklist follows pinned static source, not a deployed-system test:
- Dynamic Boot setup, enable, disable, and launcher paths.
- mkirf failure handling and mkuki watch/build behavior.
- Kernel payload naming and running-kernel readback.
- Installer boot-file generation.
Check applicability to your image. These sources establish separate stages, not a complete live ESP setup, combined artifact verifier or successful boot.
For a program #
upgrade-peios --status --json answers with one object:
| Member | Is |
|---|---|
edition | The edition package's name. |
name, version_id, variant | PRETTY_NAME, VERSION_ID and VARIANT from os-release. |
version | The edition package's installed version, or null where peipkg's records can't be read. |
queued_seeds | The seeds waiting in /lcl/policy/autoapply.d/ for the next boot, by name, or null where the queue can't be read. |
may_upgrade | Whether you may upgrade: asked by opening peipkg's lock and database for writing and checking the seed queue is writable. Nothing is written. |
upgrade-peios --driven upgrades, or with --check looks, and reports it
as JSON Lines events on standard output. Its first part is
peipkg's driven mode: peipkg is
run with upgrade-peios's standard input, so the program answers peipkg's
questions as it would answer peipkg's own, and every event peipkg writes is
passed on except its terminal one. Then upgrade-peios adds:
| Event | Members | Means |
|---|---|---|
progress | phase, step, steps | phase is release-stage (the seeds are copied into the queue) or release-apply (they are applied). |
message | text | What upgrade-peios is doing, or a line reg wrote. |
done | summary, edition, seeds_queued | Finished; seeds_queued is true when the seeds were left for the next boot. |
cancelled | reason | peipkg's plan wasn't approved; the updater stops before staging or applying seeds. |
error | code, message | Failed. The code is peipkg's own for its part (stale, busy, denied, unresolvable, untrusted, failed…), or usage, no-release, seeds or apply. |
Exactly one done, cancelled or error ends the run. --yes is refused
with --driven. A program that goes away mid-upgrade doesn't stop it.
From the medium #
A machine with no reachable repository is upgraded from an image instead: boot it from the new medium with its disk attached and choose Upgrade an installation in the installer. That runs the same procedure against the mounted disk — the edition with the bypass, --seeds-only for the seeds, then everything else the medium carries — and rewrites the boot files. The medium's repository index is fixed at manufacture, so the installer always passes peipkg --allow-stale, which this command does only when asked.
Why not peipkg upgrade #
peipkg upgrade upgrades every package it can and holds the edition back, printing the edition's message:
The package "dev.peios.peios-experimental" has an alternate upgrade path.
To upgrade Peios use the `upgrade-peios` command.
Warning: Alternate upgrade paths may bypass normal peipkg protections; ensure you fully trust the authors of the package before running.
held back: dev.peios.peios-experimental 2026.8-12 -> 2026.9-1
peipkg upgrade dev.peios.peios-experimental refuses outright with the same
text. peipkg upgrade peios-experimental cannot name the installed qualified
package at all: named upgrades intentionally do not resolve through
provides. This is not peipkg being unable to move the edition; it is peipkg
declining to do only half the job. Moving a release also means reconciling its
seeds, and applying registry seeds is exactly what the package manager must
never do on a package's behalf. The refusal keeps that line where it is, and
the bypass used by upgrade-peios is the deliberate act that crosses it.
Once editions pin their dependencies exactly, this becomes the only way a release moves: peipkg upgrade cannot carry any pinned package past what the installed edition allows, so the system upgrades as a unit or not at all.
What it does not do #
- It does not upgrade packages outside the edition's closure that the edition merely floors. With
>=floors,peipkg upgradeafterwards brings the rest current; with pins there is no "rest". - It does not un-apply seeds the new release dropped. See
release.toml. - It does not reboot or verify runtime activation. Check the running system separately from the installed package version.
Source and release scope #
The CLI/driven distinction above follows
peiosutils 3344d469's upgrade path,
its seed-copying step,
and peipkg 8b588ae8's plan/approval return path.
Peipkg performs trust-freshness checks before its dry-run boundary.
The status implementation
establishes the limits of the inspection command. These are source-backed
behaviours, not a live cancellation/upgrade test or proof that a particular
released image includes these revisions. Check the tool versions supplied
by the image you operate.
Upgrade Peios
Peios / Peiso / Editions and upgrades
Upgrade Peios is the desktop's window on
upgrade-peios.
Open it from the launcher (type upgrade). It has no authority of its
own: it runs upgrade-peios --driven as you, with the same package and
seed operations. Driven mode handles an explicit cancellation separately:
a cancelled result stops before release seeds are staged or applied.
Do not apply the ordinary CLI's declined-prompt warning
to that driven cancellation result.
The release #
At the top is the release installed on this machine, as its name (Peios 2026.8 Experimental) and its edition package with that package's version. Beside it, once Upgrade Peios has looked: Up to Date, a newer release Available, or Not Checked when the look was refused.
Looking for a newer release #
Upgrade Peios looks as it opens, and again with Check Now or Check Again. A look refreshes the repositories this machine trusts, updating cached metadata, then previews the package plan without applying it or staging or applying release seeds.
It refreshes only repositories already trusted: a repository set up but never confirmed is confirmed in Package Manager, under Repositories, never as a side effect of looking.
When a newer release is offered, the page shows every change upgrading makes — the edition package and whatever of its release comes with it — with what it downloads and takes once installed.
Upgrading #
Apply Its Settings at the Next Restart chooses when the release's settings (its registry seeds: which services run, which policies apply) take effect. Off, as it starts, they are applied as soon as the release is installed. On, they wait for the next restart; use it when a setting would change something under the people signed in now.
Upgrade to … makes the upgrade. The changes it makes are the ones just shown; if they differ by the time it starts, because a repository changed in between, the new changes are shown and asked about again. Anything peipkg needs your specific approval for, such as a package moving back to an older version, is asked on its own, as in Package Manager.
The page then shows how far it has got: downloading and checking, putting the release in place, recording it, then gathering and applying the release's settings. Once the upgrade is approved it is made to the end even if you close the window, which stays, saying so, until it is done.
The upgrade doesn't restart the machine. Its displayed release and completed package/seed steps do not establish which kernel or service binaries are running. Follow the outcome checks, and follow the activation inspection checklist before relying on a kernel update.
When something stops it #
- A repository's information is out of date, and refreshing it brought
nothing newer. Continue Anyway carries on with what this machine
already has, as
--allow-staledoes, and is recorded. Upgrade Peios remembers it until you close it. - A repository isn't trusted yet. Confirm it, or remove it, in Package Manager.
- Another change is being made. Try Again once it has finished.
- The release's settings couldn't all be applied. The release is installed; its settings wait for the next restart, which tries them again.
Settings waiting for the next restart #
When some of the release's settings are waiting for the next restart —
left by an upgrade made that way, or by one that stopped part-way — the
page says so, with Apply Now to apply them at once, as
upgrade-peios --seeds-only does.
What you may do #
Whether you may upgrade is asked of the system, by upgrade-peios. As
shipped, only Administrators may. Anyone else sees the release, with the
reason said once, and nothing to press.
Software other than Peios itself is updated in Package Manager, which holds the edition back and points here.
The driven invocation is established by
gxwi-upgrade-peios f40e8d8b.
The release updater's source scope
also applies; a source revision is not proof of the version in an installed image.