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
`while IFS='=' read -r k v` drops an unterminated final line: read returns
1 at EOF even having filled k and v. A manifest ending `bootstrapped=...Z`
with no trailing \n rendered `RIG 1.2.3` with the timestamp silently gone
— the version read fine, so nothing looked wrong.
Guarded with `|| [ -n "$k" ]`, the same shape parse_users_file already
uses (lib/users-config.sh:47). #61's writer should not have to know
whether this reader tolerates a missing newline.
Also make human_b fall back like human_kb. With numfmt absent, memory
degraded to a raw number while disk printed 'unknown' beside it, from data
already in hand.
Both found in review of #74.
Refs #64
rig read no hardware at all. The single exception was `uname -m` in
runner-install.sh, used to pick a runner tarball and then discarded — so
"is this the 32GB one, or the M900?" was a question you answered by
logging in and running free -h, nproc, df -h and uname -r by hand, four
commands deep, on a machine you were already unsure about.
`rig platform` prints hostname, OS, kernel, CPU, memory, disk and
virtualization, then a provenance block: which rig, when, and the role
marker's traits.
It COMPUTES rather than stores, and that is the design rather than an
implementation detail. Specs change without rig doing anything — RAM
added, root disk resized, the unattended-upgrades bootstrap itself
enables patching the kernel — so a stored spec is stale the moment the
machine changes, and refreshing one on every run would collide with
bootstrap's "safe to re-run; a second run changes nothing" contract.
Nothing is written, so nothing can go stale.
The corollary is deliberate: reading only /proc, uname, /etc/os-release,
df and systemd-detect-virt means no root, no network, and it runs on a
pristine Debian box rig has never bootstrapped — useful for deciding
what to converge a machine into, not only for auditing it afterwards.
That also makes it the rare rig command the harness can RUN for real
rather than grep: the tests assert the answer describes the actual test
machine (kernel and hostname compared against independently computed
values), and assert it writes nothing.
Both known traps are handled explicitly. /etc/os-release is sourced in a
SUBSHELL — it defines VERSION, NAME and ID and would otherwise clobber
same-named script variables, the form every other site in this tree uses
and test/cli.sh already greps for. systemd-detect-virt exits non-zero on
bare metal while printing 'none', a normal answer that set -e would
otherwise turn into a failed run, so it is wrapped in `|| true`.
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; the command ships complete
without it and neither blocks the other.
Named `platform` and not `status`: `users status` and `runner status`
cross-check recorded against live state and print DRIFT, and a command
that records nothing cannot drift, so calling it status would borrow a
promise it structurally cannot make. It also leaves `rig status` free
for the machine-wide roll-up it will eventually want to be.
Refs #64