skills: add pi-devbox-firstboot, and point the managed AGENTS block at it

The fleet's first-boot acceptance round is now scoped by published state
(policy v2, artifact art_20261023T204306_b388e93c3d64): a booting container
reads two claim keys -- firstboot-release-<TAG> and
firstboot-image-<TAG>-<ARCH> -- and derives whether it owes the release tier,
the per-architecture image tier, or only the device tier.

Nothing delivered that procedure to a device that does not already have a
coordination chain. The gate deliberately needs no roster, because fleet
membership changes in both directions, so no message addresses a new device and
nothing enrolls it. The consequence is that a BRAND-NEW device -- empty
mailbox, no chain, and the mempalace skill correctly telling it that an empty
mailbox is a fine answer -- had no path to the round at all. Historically a
peer planted the newcomer's first ask cross-device, which is exactly the roster
dependency the state design removes. This skill is how a device learns to plant
its own.

The skill is a FINDER, not the policy: it locates the newest policy.update on
topic=firstboot-acceptance and fetches the artifact, and says plainly that the
artifact wins on disagreement. A policy baked into an image is pinned to that
image; keeping only the lookup here means a revision needs no release and a
device on an older image still reaches the current policy.

Baked canonical, like pi-devbox-environment, rather than skillset-owned. The
round verifies the image, so pinning it to the image is right -- and a
skillset-owned skill needs the vendoring machinery (ARG SKILLSET_SNAPSHOT_REF,
the manifest/label pair, a per-skill refresh script) that today exists only for
mempalace. No wiring was needed: entrypoint-user.sh and pi-devbox-version both
enumerate the baked skills directory.

smoke-test.sh asserts the AGENTS.md pointer BY PATH, not by prose. A new device
reaches the round only through that line, so rewording the paragraph must not
be able to cut it silently. Both skill-resolution loops gain the new name.
This commit is contained in:
pi@mbp-m1-2020
2026-10-24 00:31:15 +02:00
parent 779efbf4fe
commit 5d6ff537c4
6 changed files with 295 additions and 3 deletions
+38
View File
@@ -13,6 +13,44 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`).
## Unreleased
### Added
- **`pi-devbox-firstboot` skill + a managed-block pointer to it, so a new
device can find the fleet's first-boot acceptance round at all.** The round
is now *scoped by published state* (policy v2, artifact
`art_20261023T204306_b388e93c3d64`): a booting container reads two claim
keys — `firstboot-release-<TAG>` and `firstboot-image-<TAG>-<ARCH>` — and
derives whether it owes the release tier, the per-architecture image tier, or
only the device tier. Previously every device re-ran the entire sequence on
every release, which was drift rather than a decision: each device plants its
own successor ask carrying the previous round's checklist, so scope only grew
(4 checks at v1.10.2 → B1–B5 at v1.11.2 → B1–B7 at v1.12.2) while a peer's
PASS on *identical image bytes* was recorded as context rather than as grounds
to skip. The v1.8.10-era "image half — already settled, do not repeat" split
was never retired; it simply lapsed.
Two properties the skill exists to protect. First, **the gate needs no
roster**: fleet membership changes in both directions, so nothing addresses a
device and nothing enrolls it — state is read, not pushed. The case that
therefore has no delivery path at all is a *brand-new* device, whose mailbox
is legitimately empty and whose coordination chain does not exist yet; it must
plant its own first ask, and this skill is how it learns that. Second, the
skill is a **finder, not the policy**: it locates the current policy artifact
in the logstream instead of restating it, because a policy baked into an image
is pinned to that image — a device on an older release still reaches the
current policy, and a revision needs no release.
Baked canonical (like `pi-devbox-environment`), not skillset-owned: the round
verifies the image, so pinning it to the image is correct, and a skillset-owned
skill would need the vendoring machinery (`ARG SKILLSET_SNAPSHOT_REF`, the
manifest/label pair, a per-skill refresh script) that today exists only for
`mempalace`. `entrypoint-user.sh` and `pi-devbox-version` both enumerate the
baked skills directory, so no wiring change was needed for either to pick it
up. `scripts/smoke-test.sh` asserts the baked file, both resolution loops, and
the `AGENTS.md` pointer **by path rather than by prose** — a new device reaches
the round only through that line, so rewording the paragraph must not be able
to break the link silently.
### Fixed
- **CI: a smoke job's image could be deleted mid-test by another job's disk