fix(okf): evidence_for derives a tier only for the key SPEC 5.3 tiers
[skip-docs] PM addendum 5 to order 20260902T151931Z-250257273, reported at the close of B4 and deliberately left unfixed there as outside that order. evidence_for(path, key="sources") raised ValueError. The tier was derived unconditionally through trust_tier, which refuses an entry that names no `by` actor -- correctly, because a trust level derived from an entry identifying nobody mints the provenance it claims to read. But `by` is required of a VERIFICATION entry (SPEC 5.2), not of every provenance key: the agreed segmented form carries segment_id/source_offset and a sources list carries id/resource. The guard belonging to one key was being applied to all of them. trust_tier is UNCHANGED. evidence_for stops applying it to keys it was never about: _TIERED_KEY names the one key SPEC 5.3 tiers, and every other key comes back with state / reason / items_seen / entries and tier=None. admits_falsification moved WITH it, and that is the same fact rather than scope: it read `tier != "unverified"`, and None != "unverified" is TRUE, so a present `sources` list would have cleared a threshold about verification. It now names the tiers that clear it. For every value reachable before this change both spellings are identical, which is why the existing K5 arms stay green. Measured, and it corrected the test: an actorless `verified` value never reaches trust_tier through evidence_for at all -- the decoder refuses that shape first as unreadable / unsupported-flow. Both guards are now asserted where each actually lives instead of one asserted where it is not. Load-bearing measured, four mutations, all red against the WHOLE suite: derive the tier unconditionally (3 red) - revert the K5 threshold (1, the consequence arm alone) - "fix" it by never tiering at all (3, including two pre-existing falsification arms) - loosen trust_tier instead (2, including its own pre-existing gate). Green control 1208 passed / 5 skipped; golden demo-transcript.stdout unchanged (ea8c534773acdbe41ae68f2c55724d69aaf8be4f).
This commit is contained in:
parent
7552c0ef73
commit
d296cffcd5
2 changed files with 167 additions and 5 deletions
|
|
@ -35,7 +35,7 @@ import posixpath
|
|||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
from typing import Any, Final, Literal
|
||||
|
||||
from portfolio_optimiser.ir import CostBaseline
|
||||
from portfolio_optimiser.retrieval import PathSecurityError, safe_resolve
|
||||
|
|
@ -538,14 +538,28 @@ class FalsificationEvidence:
|
|||
items_seen: int
|
||||
|
||||
|
||||
def evidence_for(path: str | Path, key: str = "verified") -> FalsificationEvidence:
|
||||
#: The ONE provenance key SPEC §5.3 derives a trust tier from. Named rather than spelled inline at
|
||||
#: the two places that care, so "which key is tiered" cannot answer differently in each of them.
|
||||
_TIERED_KEY: Final = "verified"
|
||||
|
||||
|
||||
def evidence_for(path: str | Path, key: str = _TIERED_KEY) -> 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``."""
|
||||
**A tier is derived ONLY for the key SPEC §5.3 tiers.** ``tier`` used to be derived
|
||||
unconditionally, so ``key="sources"`` — or the agreed segmented form's
|
||||
``segment_id``/``source_offset`` — crashed in ``trust_tier``, which refuses an entry naming no
|
||||
``by`` actor. That refusal is right, and it belongs to ``verified`` alone: ``by`` is required of
|
||||
a verification entry (SPEC §5.2), not of every provenance key. So the guard stays exactly where
|
||||
it is and this function stops applying it to keys it was never about. Measured at the close of
|
||||
B4: all 11 call sites in the repo use the default, so the parameter had never been exercised.
|
||||
|
||||
Gated by ``tests/test_falsification_verdict_loadbearing.py`` and
|
||||
``tests/test_evidence_key_parameter_loadbearing.py``."""
|
||||
result = read_provenance(path, key)
|
||||
if result is None:
|
||||
return FalsificationEvidence(
|
||||
|
|
@ -563,7 +577,7 @@ def evidence_for(path: str | Path, key: str = "verified") -> FalsificationEviden
|
|||
return FalsificationEvidence(
|
||||
file=str(path),
|
||||
state="present",
|
||||
tier=trust_tier(result),
|
||||
tier=trust_tier(result) if key == _TIERED_KEY else None,
|
||||
reason=None,
|
||||
entries=result,
|
||||
items_seen=len(result),
|
||||
|
|
@ -601,7 +615,12 @@ def admits_falsification(evidence: FalsificationEvidence) -> bool:
|
|||
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"
|
||||
# NAMES the tiers that clear it, rather than excluding the one that does not. ``tier`` is now
|
||||
# ``None`` for any key other than ``verified`` (SPEC §5.3 tiers that key alone), and
|
||||
# ``None != "unverified"`` is TRUE — so the exclusion spelling would let a present ``sources``
|
||||
# list clear a threshold about verification. For every value reachable before that change the
|
||||
# two spellings are identical, which is why this is a tightening and not a new rule.
|
||||
return evidence.state == "present" and evidence.tier in ("human-reviewed", "machine-confirmed")
|
||||
|
||||
|
||||
#: WHY a provenance value could not be read. The tokens name the SHAPE the value is written in
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue