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:
@@ -291,12 +291,19 @@ run "image-baked pi-devbox-environment skill" \
|
||||
"test -f /usr/local/share/pi-devbox/skills/pi-devbox-environment/SKILL.md"
|
||||
run "image-baked credential-incident-response skill" \
|
||||
"test -f /usr/local/share/pi-devbox/skills/credential-incident-response/SKILL.md"
|
||||
run "image-baked pi-devbox-firstboot skill" \
|
||||
"test -f /usr/local/share/pi-devbox/skills/pi-devbox-firstboot/SKILL.md"
|
||||
run "global-AGENTS append snippet present" \
|
||||
"test -f /usr/local/share/pi-devbox/pi-global-AGENTS.append.md"
|
||||
run "pi-devbox block merged into pi-global-AGENTS.md" \
|
||||
"grep -q 'pi-devbox:managed-block' /opt/pi-toolkit/pi-global-AGENTS.md"
|
||||
run "mempalace session-start pointer merged into global AGENTS.md" \
|
||||
"grep -q 'load the mempalace skill' /opt/pi-toolkit/pi-global-AGENTS.md"
|
||||
# The firstboot pointer is asserted by PATH, not prose: a brand-new device with
|
||||
# an empty mailbox reaches the acceptance round only through this line, and
|
||||
# rewording the paragraph must not be able to silently break the link.
|
||||
run "firstboot skill pointer merged into global AGENTS.md" \
|
||||
"grep -q 'pi-devbox-firstboot/SKILL.md' /opt/pi-toolkit/pi-global-AGENTS.md"
|
||||
# Vendored fallback skills (so a no-skillset container still resolves the
|
||||
# AGENTS.md 'read the pi-extensions skill' pointer).
|
||||
run "image-baked pi-extensions fallback skill" \
|
||||
@@ -811,7 +818,7 @@ exec_test "mempalace skill snapshot is current" 'f=$HOME/.agents/skills/mempa
|
||||
# Link TARGETS, not just link existence: with no skillset mounted (as here) the
|
||||
# baked tree must be what resolves, for all four vendored skills.
|
||||
exec_test "vendored skills resolve to the baked tree (no skillset mounted)" \
|
||||
'for s in mempalace pi-extensions pi-devbox-environment credential-incident-response; do
|
||||
'for s in mempalace pi-extensions pi-devbox-environment credential-incident-response pi-devbox-firstboot; do
|
||||
case "$(readlink -f $HOME/.agents/skills/$s)" in
|
||||
/usr/local/share/pi-devbox/skills/$s) ;;
|
||||
*) echo "$s resolves to $(readlink -f $HOME/.agents/skills/$s)" >&2; exit 1 ;;
|
||||
@@ -825,7 +832,7 @@ exec_test "vendored skills resolve to the baked tree (no skillset mounted)" \
|
||||
exec_test "pi-devbox-version reports skill sources (all baked, no skillset here)" \
|
||||
'out=$(pi-devbox-version)
|
||||
echo "$out" | grep -q "skills:" || { echo "no skills section" >&2; exit 1; }
|
||||
for s in mempalace pi-extensions pi-devbox-environment credential-incident-response; do
|
||||
for s in mempalace pi-extensions pi-devbox-environment credential-incident-response pi-devbox-firstboot; do
|
||||
echo "$out" | grep -qE "^ $s +baked( \([^)]*\))?$" \
|
||||
|| { echo "$s not reported as baked" >&2; exit 1; }
|
||||
done; echo ok'
|
||||
|
||||
Reference in New Issue
Block a user