feat(okf): evidence_for distinguishes present, absent and unreadable with a reason
Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
3d76a46d76
commit
d62e89935c
2 changed files with 232 additions and 1 deletions
|
|
@ -455,6 +455,101 @@ def trust_tier(entries: tuple[dict[str, str], ...] | None) -> TrustTier:
|
|||
return "machine-confirmed"
|
||||
|
||||
|
||||
#: What a document says about ONE provenance key. Three states, and the third is the whole point:
|
||||
#: collapsing ``unreadable`` into ``absent`` turns a verdict on missing evidence into evidence of
|
||||
#: absence.
|
||||
EvidenceState = Literal["present", "absent", "unreadable"]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FalsificationEvidence:
|
||||
"""What one document offers a falsification verdict, and how much of it could be read.
|
||||
|
||||
Each field asserts only what its state can honestly carry: ``tier`` is ``None`` unless the state
|
||||
is ``present`` (an unread value tiers nothing), and ``reason`` is ``None`` when it IS present
|
||||
(there is nothing to explain). ``items_seen`` is its own field rather than folded into a token,
|
||||
the ``BudgetExceeded`` kø-(y) rule: "which shape" and "how many" are two operative questions."""
|
||||
|
||||
#: Path of the document the evidence was read from.
|
||||
file: str
|
||||
state: EvidenceState
|
||||
#: The derived trust tier — ``None`` unless ``state`` is ``present``.
|
||||
tier: TrustTier | None
|
||||
#: WHY the value could not be read — ``None`` unless ``state`` is ``unreadable``.
|
||||
reason: ProvenanceReason | None
|
||||
#: The decoded entries, empty unless ``state`` is ``present``.
|
||||
entries: tuple[dict[str, str], ...]
|
||||
#: How many entries were seen, INCLUDING ones that could not be decoded. Part of the
|
||||
#: ``(state, reason, items_seen)`` triple a discounted concept is reported with.
|
||||
items_seen: int
|
||||
|
||||
|
||||
def evidence_for(path: str | Path, key: str = "verified") -> FalsificationEvidence:
|
||||
"""Read one document's provenance into the three-state answer a falsification verdict needs.
|
||||
|
||||
**A library primitive, deliberately NOT wired into ``run_project`` or ``explore``**, mirroring
|
||||
``promote_verdict`` and ``write_verdict``: the system reads, the caller decides. Wiring it into
|
||||
the run surface would move the byte-pinned demo transcript, which nothing asks for.
|
||||
|
||||
Gated by ``tests/test_falsification_verdict_loadbearing.py``."""
|
||||
result = read_provenance(path, key)
|
||||
if result is None:
|
||||
return FalsificationEvidence(
|
||||
file=str(path), state="absent", tier=None, reason=None, entries=(), items_seen=0
|
||||
)
|
||||
if isinstance(result, UnreadableProvenance):
|
||||
return FalsificationEvidence(
|
||||
file=str(path),
|
||||
state="unreadable",
|
||||
tier=None,
|
||||
reason=result.reason,
|
||||
entries=(),
|
||||
items_seen=result.items_seen,
|
||||
)
|
||||
return FalsificationEvidence(
|
||||
file=str(path),
|
||||
state="present",
|
||||
tier=trust_tier(result),
|
||||
reason=None,
|
||||
entries=result,
|
||||
items_seen=len(result),
|
||||
)
|
||||
|
||||
|
||||
def evidence_notice(evidence: FalsificationEvidence) -> str | None:
|
||||
"""One line about evidence that could not be used, or ``None`` when there is nothing to say.
|
||||
|
||||
Omission, never an empty row (the ``cost_baseline_notice`` precedent). The reason TOKEN is
|
||||
printed raw rather than translated into prose, so no second display vocabulary exists to drift
|
||||
from ``ProvenanceReason``."""
|
||||
if evidence.state == "present":
|
||||
return None
|
||||
detail = "" if evidence.reason is None else f"; reason {evidence.reason}"
|
||||
return (
|
||||
f"provenance {evidence.state} in {evidence.file}{detail}; items_seen={evidence.items_seen}"
|
||||
)
|
||||
|
||||
|
||||
def admits_falsification(evidence: FalsificationEvidence) -> bool:
|
||||
"""The K5 threshold, expressed in ONE place: ``present`` AND a tier above ``unverified``.
|
||||
|
||||
An operator decision, not a default. A second copy of a threshold drifts (kø-(p)), and a
|
||||
threshold spelled inline at each caller is a threshold nobody can find.
|
||||
|
||||
Everything it refuses is meant to be REPORTED with ``(state, reason, items_seen)`` and
|
||||
explicitly discounted — never silently excluded, because a dropped concept and a discounted one
|
||||
are different facts and only one of them is honest about what was read.
|
||||
|
||||
**``author`` / ``usage_count`` / ``last_modified`` are deliberately NOT required, and the
|
||||
denominator is written down rather than implied:** SPEC §5.1 names SIX entry keys and the
|
||||
producer writes TWO of them. Requiring keys the producer does not emit would make the threshold
|
||||
unreachable in practice while looking strict on paper. The threshold names only what is
|
||||
actually written. See ``docs/okf-konsum-kontrakter.md`` § 1, which is the source for this rule.
|
||||
|
||||
Gated by ``tests/test_falsification_verdict_loadbearing.py``."""
|
||||
return evidence.state == "present" and evidence.tier != "unverified"
|
||||
|
||||
|
||||
#: WHY a provenance value could not be read. The tokens name the SHAPE the value is written in
|
||||
#: and NOTHING else — the same discipline ``SkipReason`` carries. A block sequence and a block
|
||||
#: mapping are both CONFORMANT OKF (SPEC §5.2 writes ``verified`` in exactly those forms); they are
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue