Per-system bundles, and Android's start problem closed by narrowing it

Two gaps.

The bundle's contents are per system even though its mechanism is not, so there
are now three: substrate-arch.lock, substrate-alpine.lock and
substrate-android.lock. All three are embedded and a host reads only the one it
was built for. Arch and Alpine remain placeholders -- the closure for a one-node
mesh is still research 011/012's open question, and inventing it here would be
worse than an honest placeholder.

Android's is not a placeholder. It says a partial host cannot raise a mesh and
why: every step of a bootstrap is a package, a container, or an action against
one, and those are exactly the shapes it refuses. So a partial host can JOIN a
mesh and cannot BE the first node. That belongs where somebody looking for the
android bundle will find it.

Also separated two things that were being conflated: "this system has no
bundle" and "this system was never built". Loading a bundle for debian is not
ErrEmpty, and the test asserts they differ.

0062 -- a host may be episodic. There is no way to keep a process running on an
ordinary Android device: init needs root, a foreground service can be killed
for memory. The answer is not to fight that. It is that being killed IS
disconnection, which ADR 0036 already made an ordinary situation -- and
everything the design does for a laptop that closes is what an episodic host
needs, at a shorter period. An authoritative local store, reconcile on start,
last-heard-from reported without an alarm.

So the gap closes by requiring less rather than building something. No keep-
alive, no Android daemon, no fighting the platform's process management.

Two consequences recorded rather than glossed. Last-heard-from is a much weaker
signal on an episodic host, so a healthy phone reads as a dead server unless
the reader knows which kind it is looking at. And a declaration may take a long
time to land, which makes 0058's separation of outstanding from failed
load-bearing rather than tidy.

Left open deliberately: how an episodic host is actually started, and -- first --
what an Android node is for. Building the start mechanism before deciding that
would be building it for nobody.
This commit is contained in:
2026-08-28 01:24:06 +02:00
parent 02f1fcc865
commit ebba16ce4a
7 changed files with 111 additions and 27 deletions
+13 -5
View File
@@ -24,11 +24,19 @@ import (
// and an unlocked bootloader. On a normal device nothing can register with it.
// - **container** — no container runtime, and no kernel access to give one.
//
// **Being STARTED on Android is not solved by this file, and it is the real gap.** Everywhere
// else an init runs the launcher at boot. Here the equivalent is the app framework — a
// foreground service, or something under Termux — both of which the system may kill when it
// wants memory. That is a different mechanism from every other node rather than a variant of
// one, and nothing here designs it.
// **This host is EPISODIC** (novox/hq ADR 0062). Everywhere else an init runs the launcher at
// boot and the launcher supervises the host. Android grants neither: nothing to register with
// without root, and nothing worth supervising, because a supervisor would be killed alongside
// what it supervises.
//
// So it runs when the platform allows and is killed when the platform wants the memory — and
// that is **disconnection**, which ADR 0036 already made an ordinary situation rather than an
// exception. It needs no keep-alive and no new mechanism: the store is already authoritative
// while disconnected, reconcile already happens on start, and the mesh already reports *last
// heard from* rather than alarming on silence.
//
// It also **cannot be the first node** — every step of raising a substrate is a shape it
// refuses — and its bundle says so rather than being an empty placeholder.
type android struct{}
func (android) Name() string { return "android" }