fix: platform reads #61's actual manifest schema, not invented keys

The reader asked for `version` and `bootstrapped`. #61 specifies `schema`,
`bootstrapped_by`/`bootstrapped_at` and `converged_by`/`converged_at` — so
no writer would ever have produced the keys being read, and the day #61
landed this command would have rendered 'unknown' with the timestamp
omitted, forever, with nothing to say why.

Keyed to #61's spelling, with fixtures carrying that schema verbatim so
the contract is pinned rather than assumed. Birth and latest are reported
separately and neither is inferred from the other: under #61 rule 2
converged_* is written only when the version differs, so its absence is a
legitimate state on a freshly bootstrapped box, printed 'not recorded'
rather than backfilled from birth. A manifest whose schema this rig does
not know is named as such instead of being half-read in silence.

Found in review of #74.

Refs #64
This commit is contained in:
dan-claude-bot 2026-07-20 00:22:01 +00:00
parent 3cfbb8921c
commit 91a8905a71
4 changed files with 70 additions and 16 deletions

View file

@ -29,8 +29,11 @@ on the way to cutting its first release, and this file starts there.
the harness can RUN for real instead of grepping: the tests assert the
actual answer describes the actual test machine. Provenance is read, never
written, and degrades per-file — `/etc/rig/manifest` is #61 and does not
exist yet, so that line reads `not bootstrapped` on every machine today and
nothing else depends on it. Named `platform` and not `status` on purpose:
exist yet, so those lines read `not bootstrapped` on every machine today and
nothing else depends on it. The reader is keyed to #61's documented schema
(`schema`, `bootstrapped_by`/`_at`, `converged_by`/`_at`) and fixtures pin
that exact spelling, so the integration cannot land silently broken; birth
and latest stay separate rather than one being inferred from the other. Named `platform` and not `status` on purpose:
`users status` and `runner status` cross-check recorded against live state
and print `DRIFT`, and a command that records nothing cannot drift — which
also leaves `rig status` free for the machine-wide roll-up. Known

View file

@ -738,7 +738,8 @@ DISK 456Gi total, 201Gi free on /
VIRT kvm
PROVENANCE
RIG 0.4.0, bootstrapped 2026-07-19T14:24:51Z
CONVERGED 0.6.0, 2026-08-02T09:11:03Z
BOOTSTRAP 0.4.0, 2026-07-19T14:24:51Z
ROLE dev (class=human host=yes join=authkey)
```
@ -763,11 +764,20 @@ needs no root, makes no network call, and writes nothing, ever.
The `PROVENANCE` block is the complementary half — which rig, and when, which
is *decided* rather than observed, so it is stored. It is **read, never
written**: `RIG` comes from `/etc/rig/manifest` and `ROLE` from
`/etc/rig/role`. Neither file is required — a machine missing one reads `not
bootstrapped` for that line, which is itself the useful answer. The manifest
is #61 and is not implemented yet, so today that line reads `not bootstrapped`
on every machine; nothing else in the command depends on it.
written**: `CONVERGED`/`BOOTSTRAP` come from `/etc/rig/manifest` and `ROLE`
from `/etc/rig/role`. Neither file is required — a machine missing one reads
`not bootstrapped` for that line, which is itself the useful answer. The
manifest is #61 and is not implemented yet, so today those lines read `not
bootstrapped` on every machine; nothing else in the command depends on it.
**The two dates are deliberately separate**, matching #61's schema: `BOOTSTRAP`
is birth (`bootstrapped_by`/`bootstrapped_at`, first-write-wins, pinned
forever) and `CONVERGED` is latest (`converged_by`/`converged_at`, updated only
when the converging version actually differs). That distinction is what answers
"is this machine still converged by a rig that predates the fix?" — so
`CONVERGED` reads `not recorded` rather than being backfilled from birth on a
box that has only ever been bootstrapped once. A manifest whose `schema=` this
rig does not know is named as such instead of being half-read in silence.
**Known limitation — `CPU` and `MEMORY` inside a container-style guest are
unverified.** `CPU` and `MEMORY` are read straight from `/proc/cpuinfo` and

View file

@ -155,10 +155,29 @@ manifest_field() { # $1 = key — empty when absent, unreadable or unset
}
printf '%s\n' "PROVENANCE"
# Keys are #61's documented schema verbatim — schema/bootstrapped_by/
# bootstrapped_at/converged_by/converged_at — NOT invented ones. #61 keeps
# birth and latest deliberately separate ("is this machine converged by a rig
# that predates the fix?"), so both are reported and neither is inferred from
# the other: CONVERGED answers currency, BOOTSTRAPPED answers provenance.
# Every field degrades independently, so a partial manifest from a future
# schema still renders what it does carry.
if [ -r "$MANIFEST" ]; then
RIG_VER="$(manifest_field version)"
RIG_WHEN="$(manifest_field bootstrapped)"
field RIG "${RIG_VER:-unknown}${RIG_WHEN:+, bootstrapped $RIG_WHEN}"
M_SCHEMA="$(manifest_field schema)"
B_BY="$(manifest_field bootstrapped_by)"; B_AT="$(manifest_field bootstrapped_at)"
C_BY="$(manifest_field converged_by)"; C_AT="$(manifest_field converged_at)"
# A manifest with no schema= line is pre-#61; say so rather than render blanks.
if [ -z "$M_SCHEMA$B_BY$B_AT$C_BY$C_AT" ]; then
field RIG "manifest present but carries no recognised fields ($MANIFEST)"
else
# 'not recorded' rather than 'unknown': under #61's rule 2 converged_* is
# written only when the version actually differs, so its absence is a
# legitimate state on a freshly bootstrapped box, not a lost value.
field CONVERGED "${C_BY:-not recorded}${C_AT:+, $C_AT}"
field BOOTSTRAP "${B_BY:-not recorded}${B_AT:+, $B_AT}"
[ -n "$M_SCHEMA" ] && [ "$M_SCHEMA" != "1" ] && \
field NOTE "manifest schema=$M_SCHEMA is newer than this rig reads (expects 1)"
fi
else
field RIG "not bootstrapped (no $MANIFEST)"
fi

View file

@ -1006,23 +1006,45 @@ check "platform: MEMORY carries real numbers" 0 "total," "$ROOT/bin/rig" platfor
# not exist yet, so 'not bootstrapped' is the state of the world today and the
# command must ship complete without it. Both paths driven against fixtures.
PLATWORK="$(mktemp -d)"
printf 'version=9.9.9\nbootstrapped=2026-07-19T14:24:51Z\n' > "$PLATWORK/manifest"
# THE INTEGRATION CONTRACT (#61, found in #74 review): these fixtures carry
# #61's documented schema VERBATIM — schema/bootstrapped_by/bootstrapped_at/
# converged_by/converged_at. An earlier draft of this reader invented `version`
# and `bootstrapped`, which no writer would ever have produced: the command
# would have rendered 'unknown' forever the day #61 landed, and nothing here
# would have said so. Keep these keys in step with #61; that is the point.
printf 'schema=1\nbootstrapped_by=0.4.0\nbootstrapped_at=2026-07-19T14:24:51Z\nconverged_by=0.6.0\nconverged_at=2026-08-02T09:11:03Z\n' > "$PLATWORK/manifest"
check "platform: no manifest reads 'not bootstrapped'" 0 "RIG not bootstrapped" \
env RIG_MANIFEST="$PLATWORK/absent" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
check "platform: no role marker reads 'not bootstrapped'" 0 "ROLE not bootstrapped" \
env RIG_MANIFEST="$PLATWORK/absent" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
# A manifest that DOES exist is read, never written — the forward-compatible
# half, so #61 landing needs no change here.
check "platform: reads the manifest version" 0 "9.9.9" \
check "platform: reads #61's converged_by/at" 0 "CONVERGED 0.6.0, 2026-08-02T09:11:03Z" \
env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
check "platform: reads the manifest timestamp" 0 "bootstrapped 2026-07-19T14:24:51Z" \
check "platform: reads #61's bootstrapped_by/at" 0 "BOOTSTRAP 0.4.0, 2026-07-19T14:24:51Z" \
env RIG_MANIFEST="$PLATWORK/manifest" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
# Birth and latest stay SEPARATE: #61 rule 2 writes converged_* only when the
# version actually differs, so its absence on a freshly bootstrapped box is a
# legitimate state — it must not be silently backfilled from bootstrapped_*.
printf 'schema=1\nbootstrapped_by=0.4.0\nbootstrapped_at=2026-07-19T14:24:51Z\n' > "$PLATWORK/manifest-birth"
check "platform: unconverged box says so, never infers from birth" 0 "CONVERGED not recorded" \
env RIG_MANIFEST="$PLATWORK/manifest-birth" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
# A newer schema renders what it recognises and says the rest is unreadable,
# rather than pretending a partial read is the whole truth.
printf 'schema=2\nbootstrapped_by=9.9.9\nbootstrapped_at=2027-01-01T00:00:00Z\n' > "$PLATWORK/manifest-v2"
check "platform: a newer schema is named, not silently half-read" 0 "schema=2 is newer" \
env RIG_MANIFEST="$PLATWORK/manifest-v2" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
# A manifest carrying none of #61's keys is reported as such — the pre-#61 or
# corrupt case, distinct from both 'absent' and 'read fine'.
printf 'somethingelse=1\n' > "$PLATWORK/manifest-alien"
check "platform: an unrecognised manifest is not read as empty" 0 "no recognised fields" \
env RIG_MANIFEST="$PLATWORK/manifest-alien" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
# ...including one whose last line has no trailing newline: `read` returns 1 at
# EOF even having filled the variables, so an unguarded loop drops that line
# silently — the timestamp would vanish while the version still rendered. #61's
# writer must not have to know this reader's tolerances (found in #74 review).
printf 'version=9.9.9\nbootstrapped=2026-07-19T14:24:51Z' > "$PLATWORK/manifest-nonl"
check "platform: reads a manifest with no trailing newline" 0 "bootstrapped 2026-07-19T14:24:51Z" \
printf 'schema=1\nbootstrapped_by=0.4.0\nbootstrapped_at=2026-07-19T14:24:51Z' > "$PLATWORK/manifest-nonl"
check "platform: reads a manifest with no trailing newline" 0 "BOOTSTRAP 0.4.0, 2026-07-19T14:24:51Z" \
env RIG_MANIFEST="$PLATWORK/manifest-nonl" RIG_ROLE_MARKER="$PLATWORK/absent" "$ROOT/bin/rig" platform
printf 'role=dev class=human host=yes join=authkey\n' > "$PLATWORK/role"
check "platform: renders the role marker's traits" 0 "dev (class=human host=yes join=authkey)" \