Eight more test files state their properties without issue, milestone and
rule numbers or dated regressions. The version tests describe what folding
the channel into the version breaks instead of the date it did; the surface
registry and settings-defaults tests state that floors move rather than
quoting the decision that made them move.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#3127 checklist 12, plus rule 27 — a capability with no surface the operator
can touch is not shipped.
The step was planned on the premise that nothing read `/api/version`. Two
things did, and the state was worse than nothing:
- `App.vue` fetched it, wrote `version` into a ref initialised to the literal
`"dev"`, and swallowed the error. An instance that could not answer rendered
EXACTLY what a healthy local build renders. That is checklist 12's named
failure — a blank standing in for `unknown` — in the one readout whose whole
job is to say what is running, and it would have made #3298's debugging
session no cheaper.
- `SettingsView.vue` fetched the same endpoint again on every mount and wrote
the result into a local ref no template ever read. A duplicate request whose
answer was discarded.
So this is not "add a readout"; it is "make the existing one honest, and give
it the three fields nobody could see."
The readout — Settings → Config, first section, beside the other "what is this
instance doing" facts. Three states kept apart, because collapsing any two of
them is the defect:
not asked yet (tab unopened) nothing
answered the values, each ABSENT field as "unknown"
the fetch itself failed its own message, with a retry
`version` and `channel` prominent, `commit` in full with a copy button so it
can be pasted into a `:sha` lookup (rule 145 — the registry's identity and the
artifact's own must be checkable against each other), `build` kept because its
ABSENCE is the diagnostic part: no ordering key means this build is not in any
update order, which is what a local or hand-built image looks like.
Absence, not falsiness. The payload omits what it does not know rather than
sending `""` or `0` (see `build_version_payload`), so the renderer uses `??`
throughout — `build` is a number and `0` is a legitimate ordering key, which
`||` would report as unknown. `tests/test_version_readout.py` pins that
operator specifically, along with the "no plausible default" property, because
`||` is the form a person reaches for by habit.
Rule 156 — the fetch carries a deadline. This readout is consulted when an
instance is misbehaving, which is exactly when it may never answer; without one
the surface sits on "still loading" forever, which is the same blank arrived at
from the other direction. `apiGet` gains an OPT-IN `timeoutMs` rather than a
default, so no existing call site's behaviour moves. Every other call in the
client still has no deadline — reported separately, not fixed here.
No frontend test runner exists, so verification is the typecheck lane plus four
source-inspection guards in the unit lane, each pinning one property.
Also folded in: `plugin/README.md` now leads with the mint script and offers
`make` second, since `make` is not installed on every workstation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcCs1CcQ1ormdnzSshKqvN