Watch
1
0
Fork
You've already forked SouveraineOS
0

distribution: add ViewTop to the laptop body

Record update delivery as a per-body offer and local candidate activation after a live shell push killed an active conversation.
This commit is contained in:
Fimeg 2026-08-11 14:40:08 -04:00
commit d8820da557
4 changed files with 49 additions and 5 deletions

View file

@ -12,6 +12,10 @@ its release lands. Those decisions live here, once.
- `manifest.toml` is the canonical body, package, producer, and installer
profile graph.
- A package normally names one `producer`; when architecture-specific release
paths live in different repositories it names `producers` explicitly. This
records one package identity without pretending one workflow built both
bodies.
- The signed `edge` archive is one multi-producer archive. Its implementation
currently lives in `souveraine/packaging/arch/publish-edge.sh`; this manifest
names it so consumers do not grow their own publisher.

View file

@ -25,6 +25,11 @@ repository = "Fimeg/Pixel3Arch"
workflow = ".gitea/workflows/packages.yml"
architectures = ["aarch64"]
[producers.souveraine-viewtop]
repository = "Fimeg/souveraine-viewtop"
workflow = ".gitea/workflows/ci.yml"
architectures = ["x86_64"]
# Current packages. `managed` means a producer and shared archive path exist;
# it does not assert that the newest run is green. `blocked` and `planned` are
# intentionally visible to the installer gate.
@ -32,7 +37,7 @@ architectures = ["aarch64"]
souveraine = { producer = "souveraine", architectures = ["x86_64", "aarch64"], state = "managed" }
upower-souveraine = { producer = "souveraine", architectures = ["x86_64", "aarch64"], state = "managed" }
souveraine-updater = { producer = "souveraine-updater", architectures = ["x86_64", "aarch64"], state = "managed" }
souveraine-viewtop = { producer = "pixel3arch", architectures = ["aarch64"], state = "managed" }
souveraine-viewtop = { producers = ["pixel3arch", "souveraine-viewtop"], architectures = ["aarch64", "x86_64"], state = "managed" }
linux-blueline = { producer = "pixel3arch", architectures = ["aarch64"], state = "blocked", blocker = "kernel.yml does not publish into the shared archive" }
souveraine-callaudio = { producer = "pixel3arch", architectures = ["aarch64"], state = "managed" }
souveraine-callaudiod = { producer = "pixel3arch", architectures = ["aarch64"], state = "managed" }
@ -68,8 +73,8 @@ blockers = ["linux-blueline is not published to the shared archive", "rootfs ove
[profiles.x86-laptop]
status = "blocked"
architectures = ["x86_64"]
packages = ["souveraine", "upower-souveraine", "souveraine-updater"]
blockers = ["laptop installer and hardware profile are not implemented"]
packages = ["souveraine", "upower-souveraine", "souveraine-updater", "souveraine-viewtop"]
blockers = ["package-owned shell and ViewTop session are not implemented", "laptop installer and hardware profile are not implemented"]
[profiles.d10]
status = "blocked"

View file

@ -158,6 +158,34 @@ live sysfs + D-Bus backend, so a battery/charge page can be honest today.
So: package the surfaces → expose what already actuates (charge, existing
pages) → add state-machine controls as TASK-15/08 wire them up.
### 2026-08-11 — an update is offered to a body, not pushed through its glass
Observed on the Pixel daily driver: `deploy.sh --phone` passed its lock check,
snapshotted the tree, and still replaced the live QuickShell composition while
Casey was using it. The reload killed an active Souveraine conversation. A
rollback makes the files recoverable; it does not make destroying live session
state an acceptable delivery protocol.
Casey's required development shape is now explicit:
1. CI publishes a signed, immutable surface candidate. The laptop never rsyncs
that candidate directly over a live body's active tree.
2. A connected-device channel may announce that a development update is
available and safe to evaluate. USB Signaller is a possible transport for
that offer; it is not the update authority and attachment is not consent.
3. Each body answers independently. Its local updater acquires the durable
maintenance lease, verifies the package and target profile, stages beside
the running candidate, and reports what would change.
4. Activation is an explicit local transition with conversation/session state
preserved or deliberately quiesced, a health check, and an automatic return
to the last working candidate. One connected device accepting must not make
every connected device switch.
`deploy.sh --phone` remains a recovery/developer instrument for an explicitly
quiesced target. It is no longer the ordinary update path. TASK-08 owns the
lease and state projection; the updater owns retrieval and candidate
activation; USB Signaller can carry presence and offers only.
## The actual inventory (measured 2026-07-25)
379,153 files under `/usr /etc /opt /boot`; **5,624 owned by nothing**. The

View file

@ -40,8 +40,15 @@ def main() -> int:
for name, package in packages.items():
if package.get("state") not in PACKAGE_STATES:
error(f"package {name}: invalid state {package.get('state')!r}")
if package.get("producer") not in producers and package.get("state") != "planned":
error(f"package {name}: unknown producer {package.get('producer')!r}")
package_producers = package.get("producers")
if package_producers is None:
package_producers = [package.get("producer")]
if not package_producers:
error(f"package {name}: no producer declared")
elif package.get("state") != "planned":
for producer in package_producers:
if producer not in producers:
error(f"package {name}: unknown producer {producer!r}")
if not package.get("architectures"):
error(f"package {name}: no architecture declared")