Replace the combined concept total, the distinct-token total and the per-level document count of earlier example bases with general wording in prose, comments and docstrings. No constant, assertion or test data changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
348 lines
17 KiB
Python
348 lines
17 KiB
Python
"""The falsification-verdict seam — load-bearing gates for reading OKF provenance.
|
|
|
|
This module opens with the ONE thing that has to be captured before any decoder exists: the
|
|
bytes today's ``bundle_context`` renders from a **block-form** provenance bundle. Later steps
|
|
add a decoder that reads ``verified``/``sources`` in that form; this gate is what proves the
|
|
decoder did not move the read-context on its way in.
|
|
|
|
The comparison is **byte-for-byte**, with no trailing-whitespace normalisation. The commons
|
|
nav-goldens normalise because commons owns their line endings and this repo consumes them
|
|
through a pull-only subtree; ``tests/golden/block-form-provenance/`` is repo-owned, so the
|
|
stricter comparison is available and is what the criterion asks for.
|
|
|
|
The resolver below is LOCAL on purpose. ``tests/test_okf.py::_nav_golden`` hard-codes
|
|
``shared/examples/`` (``test_okf.py:51``) and lives in a module this work must not touch, so
|
|
reusing it would mean editing a frozen module to reach a repo-owned fixture.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from portfolio_optimiser import okf, tools, verdicts
|
|
|
|
_GOLDEN_DIR = Path(__file__).resolve().parents[1] / "tests" / "golden" / "block-form-provenance"
|
|
|
|
|
|
def _block_form_golden() -> tuple[str, str]:
|
|
"""The repo-owned block-form case: ``(bundle_dir, expected_read_context)``."""
|
|
return (
|
|
str(_GOLDEN_DIR / "bundle"),
|
|
(_GOLDEN_DIR / "expected-read-context.md").read_text(encoding="utf-8"),
|
|
)
|
|
|
|
|
|
def test_block_form_bundle_renders_the_captured_bytes() -> None:
|
|
"""Navigation is TOLERANT of block-form provenance, and these are the bytes it produces.
|
|
|
|
THREE claims on ONE fixture in ONE test, and the coexistence is the property (S7). First,
|
|
``navigate_bundle`` reaches every file and skips nothing — a block ``verified:`` sequence is
|
|
ordinary frontmatter to a line-oriented parser, so it must not break navigation, and ``skipped``
|
|
being empty is the positive statement that no link was silently passed over. Second, the
|
|
decoder REFUSES the same document's ``sources``. Third, the rendered read-context is
|
|
byte-identical to the committed fasit. The fasit was generated by the code that predates any
|
|
decoder work: if it were regenerated afterwards, the comparison would prove an implementation
|
|
identical to itself and nothing else.
|
|
|
|
Splitting the refusal and the byte identity into two tests would lose exactly what is being
|
|
asserted — that a decoder strict enough to refuse this document did not make navigation any
|
|
less tolerant of it.
|
|
"""
|
|
bundle_dir, expected = _block_form_golden()
|
|
bundle = okf.navigate_bundle(bundle_dir)
|
|
|
|
assert bundle.skipped == (), (
|
|
f"navigation skipped a link it should have followed: {bundle.skipped}"
|
|
)
|
|
assert [f.name for f in bundle.files] == ["index.md", "attested.md", "multi-verified.md"]
|
|
|
|
# (2) The decoder READS the same document's block `sources`, on the very same fixture — the
|
|
# direction REVERSED by P13b, and the fixture's own body is what asked for it ("a reader that
|
|
# only understands the flow shorthand loses the provenance of this concept entirely"). The
|
|
# coexistence claim is unchanged and is now the stronger one: a decoder that reads this
|
|
# document did not make navigation any less tolerant of it, and did not move a byte of (3).
|
|
sources = okf.read_provenance(Path(bundle_dir) / "attested.md", "sources")
|
|
assert sources == (
|
|
{
|
|
"resource": "https://example.invalid/fixture-cost-baseline",
|
|
"id": "fixture-cost-baseline",
|
|
},
|
|
)
|
|
|
|
# (3) And the bytes have not moved. This clause is the one a no-op cannot fake: tolerant
|
|
# navigation was ALREADY today's behaviour, so clauses (1) and (2) alone are green on a tree
|
|
# with none of this work in it. The commons nav-goldens carry no block-form provenance
|
|
# anywhere, so every existing byte fasit could stay green while the decoder broke navigation
|
|
# for real corpus documents — this repo-owned fixture is the one that could not.
|
|
assert okf.bundle_context(bundle) == expected
|
|
|
|
|
|
# --- Step 7: the falsification verdict, with the third state carrying its reason ---------------
|
|
|
|
_ENERGI_BUNDLE = Path(__file__).resolve().parents[1] / "shared" / "examples" / "bygg-energi-mikro"
|
|
|
|
|
|
def _unreadable_document(tmp_path: Path, entries: int = 1) -> Path:
|
|
"""A document whose ``verified`` is a block sequence the decoder REFUSES, with a chosen count.
|
|
|
|
P13b widened the reader to the block sequence of mappings (measured: every concept in
|
|
the four delivered bases write it, and po reported every one of them unreadable). The arms below
|
|
need a specimen that is still unreadable for a reason of its own, or they would be asserting
|
|
against a state the reader no longer produces. This one refuses on SPEC §5.2 — an entry naming
|
|
no ``by`` actor — which keeps the reason token ``block-sequence`` and lets the count be chosen,
|
|
so the triple those arms assert on is unchanged rather than relabelled.
|
|
"""
|
|
path = tmp_path / f"unreadable-{entries}.md"
|
|
items = "".join(f" - at: 2026-01-0{n + 1}T00:00:00Z\n" for n in range(entries))
|
|
path.write_text(f"---\ntype: concept\nverified:\n{items}---\n\nInnhold.\n", encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def _present_document(tmp_path: Path) -> Path:
|
|
"""A REAL flow-form document, produced by our own writer — never a mock.
|
|
|
|
All three arms below read committed or freshly-written files, because the property under test
|
|
is what the reader does with bytes on disk, and a stubbed reader would test the stub.
|
|
"""
|
|
dst = tmp_path / "bundle"
|
|
shutil.copytree(_ENERGI_BUNDLE, dst)
|
|
return verdicts.promote_verdict(
|
|
str(dst),
|
|
verdicts.Verdict(
|
|
id="EVIDENCE-PRESENT",
|
|
proposal_features=verdicts.bundle_candidate_features(str(dst)),
|
|
decision="approved",
|
|
rationale="godkjent",
|
|
),
|
|
approver="process:fixture-check",
|
|
experiment="exp-B",
|
|
timestamp="2026-06-30T09:00:00Z",
|
|
)
|
|
|
|
|
|
def test_a_flow_form_document_is_present_and_tiered(tmp_path: Path) -> None:
|
|
"""CONTROL — without it, every arm below is satisfied by a reader that always says "absent"."""
|
|
evidence = okf.evidence_for(_present_document(tmp_path))
|
|
assert evidence.state == "present"
|
|
assert evidence.tier == "machine-confirmed"
|
|
assert evidence.reason is None, (
|
|
"a present state has no reason to carry, and must not invent one"
|
|
)
|
|
assert evidence.items_seen == 1
|
|
|
|
|
|
def test_a_document_without_the_key_is_absent_and_carries_no_tier() -> None:
|
|
"""``absent`` is what a document that never claimed verification says — and it is NOT the same
|
|
fact as ``unreadable``."""
|
|
evidence = okf.evidence_for(_GOLDEN_DIR / "bundle" / "index.md")
|
|
assert evidence.state == "absent"
|
|
assert evidence.tier is None
|
|
assert evidence.reason is None
|
|
assert evidence.items_seen == 0
|
|
|
|
|
|
def test_an_undecodable_document_is_unreadable_and_says_WHY(tmp_path: Path) -> None:
|
|
"""The third state, and the arm asserts the REASON, not merely the state.
|
|
|
|
A collapsed ``unreadable`` → ``absent`` is a verdict on missing evidence presented as evidence
|
|
of absence. Asserting only ``state != "present"`` would stay green against exactly that
|
|
collapse, so the reason token is what this arm pins.
|
|
|
|
The specimen moved off the committed fixture when P13b made the block sequence READABLE. What
|
|
the arm claims is unchanged — the third state still exists and still carries its reason — and
|
|
the specimen now refuses on a rule of its own (SPEC §5.2, an entry naming no actor) rather than
|
|
on the carrier having no reader.
|
|
"""
|
|
evidence = okf.evidence_for(_unreadable_document(tmp_path))
|
|
assert evidence.state == "unreadable"
|
|
assert evidence.reason == "block-sequence"
|
|
assert evidence.items_seen == 1
|
|
|
|
|
|
def test_the_committed_block_form_fixture_is_now_READ(tmp_path: Path) -> None:
|
|
"""The direction P13b reversed, pinned where the old arm stood so the change cannot be silent.
|
|
|
|
``attested.md`` was the repo's specimen for "the reader cannot read this". It is the SPEC §5.1
|
|
block form, which all four delivered knowledge bases write on every concept, and it now
|
|
yields its single verification entry with the actor intact."""
|
|
evidence = okf.evidence_for(_GOLDEN_DIR / "bundle" / "attested.md")
|
|
assert evidence.state == "present"
|
|
assert evidence.reason is None
|
|
assert evidence.items_seen == 1
|
|
assert evidence.entries[0]["by"] == "process:fixture-check"
|
|
assert evidence.tier == "machine-confirmed"
|
|
|
|
|
|
def test_a_two_entry_block_document_keeps_the_human_sign_off() -> None:
|
|
"""The defect this fixture was AUTHORED for, finally checkable rather than merely avoided.
|
|
|
|
``multi-verified.md`` carries a human sign-off FIRST and a process entry SECOND. Until P13b the
|
|
block form came back unreadable, so "no tier at all" was the honest answer — and the
|
|
second-entry-wins defect the fixture's body describes could not be tested for, only sidestepped.
|
|
Now that the form is read, the claim is the real one: both entries survive IN ORDER and the tier
|
|
is the human one. A reader keeping the last entry it saw would report ``machine-confirmed`` for
|
|
a concept a human signed, with nothing failing.
|
|
"""
|
|
evidence = okf.evidence_for(_GOLDEN_DIR / "bundle" / "multi-verified.md")
|
|
assert evidence.state == "present"
|
|
assert evidence.items_seen == 2
|
|
assert [entry["by"] for entry in evidence.entries] == [
|
|
"human:fixture-reviewer",
|
|
"process:fixture-nightly",
|
|
]
|
|
assert evidence.tier == "human-reviewed"
|
|
|
|
|
|
def test_an_unreadable_document_yields_NO_tier(tmp_path: Path) -> None:
|
|
"""The half of the arm above that P13b did NOT change: the honest answer to a value that could
|
|
not be read is no tier at all, never a tier derived from what the reader limped past."""
|
|
evidence = okf.evidence_for(_unreadable_document(tmp_path, entries=2))
|
|
assert evidence.state == "unreadable"
|
|
assert evidence.tier is None
|
|
assert evidence.items_seen == 2
|
|
|
|
|
|
def test_evidence_notice_is_None_when_there_is_nothing_to_say(tmp_path: Path) -> None:
|
|
"""Omission, never an empty row — the ``cost_baseline_notice`` precedent."""
|
|
assert okf.evidence_notice(okf.evidence_for(_present_document(tmp_path))) is None
|
|
|
|
|
|
def test_evidence_notice_prints_the_reason_TOKEN_itself(tmp_path: Path) -> None:
|
|
"""No second display vocabulary. A prose translation here would be free to drift from
|
|
``ProvenanceReason``, and the drifted copy is the one the operator would read.
|
|
|
|
The specimen moved from the committed fixture to ``_unreadable_document`` because P13b made the
|
|
fixture READABLE; the token and the count asserted are unchanged."""
|
|
notice = okf.evidence_notice(okf.evidence_for(_unreadable_document(tmp_path)))
|
|
assert notice is not None
|
|
assert "block-sequence" in notice
|
|
assert "items_seen=1" in notice
|
|
|
|
|
|
# --- Amendment A: the K5 threshold ------------------------------------------------------------
|
|
|
|
|
|
def test_admits_falsification_refuses_a_state_that_is_not_present(tmp_path: Path) -> None:
|
|
"""AMENDMENT A, first conjunct — a verdict may not rest on evidence that was never read.
|
|
|
|
Both non-present states are exercised: unreadable (the specimen, since P13b made the committed
|
|
fixture readable) and absent (``index.md``, which declares no ``verified`` at all)."""
|
|
assert not okf.admits_falsification(okf.evidence_for(_unreadable_document(tmp_path)))
|
|
assert not okf.admits_falsification(okf.evidence_for(_GOLDEN_DIR / "bundle" / "index.md"))
|
|
|
|
|
|
def test_admits_falsification_refuses_an_unverified_tier() -> None:
|
|
"""AMENDMENT A, second conjunct — its OWN arm, because one arm cannot separate two conjuncts.
|
|
|
|
**This state is not reachable through ``evidence_for`` today, and that is measured, not
|
|
assumed:** ``decode_flow_value`` refuses an empty flow sequence, so a ``present`` value always
|
|
carries at least one entry naming an actor, and ``trust_tier`` therefore never answers
|
|
``unverified`` for it. The conjunct is DEFENSIVE, which is precisely why it needs an arm of its
|
|
own — a single arm over a reachable document would leave it untested, and an untested conjunct
|
|
is one a later simplification deletes without anything going red.
|
|
"""
|
|
unverified = okf.FalsificationEvidence(
|
|
file="crafted.md", state="present", tier="unverified", reason=None, entries=(), items_seen=0
|
|
)
|
|
assert not okf.admits_falsification(unverified)
|
|
|
|
|
|
def test_admits_falsification_ADMITS_the_positive_case(tmp_path: Path) -> None:
|
|
"""CONTROL — an always-refusing threshold passes both negative arms and is worthless."""
|
|
assert okf.admits_falsification(okf.evidence_for(_present_document(tmp_path)))
|
|
|
|
|
|
def test_a_discounted_concept_reports_the_TRIPLE_not_merely_the_refusal(tmp_path: Path) -> None:
|
|
"""AMENDMENT A — "why it was discounted" is the operative fact.
|
|
|
|
A dropped concept and a discounted one are different facts, and only the second is honest about
|
|
what was read. Asserting that admission was denied says nothing about which of them happened;
|
|
the triple ``(state, reason, items_seen)`` is what makes the difference legible.
|
|
"""
|
|
evidence = okf.evidence_for(_unreadable_document(tmp_path, entries=2))
|
|
assert not okf.admits_falsification(evidence)
|
|
assert (evidence.state, evidence.reason, evidence.items_seen) == (
|
|
"unreadable",
|
|
"block-sequence",
|
|
2,
|
|
)
|
|
|
|
|
|
# --- Step 8: the adjudication state, named and never collapsed to absent ------------------------
|
|
|
|
|
|
def _concept(text: str) -> Path:
|
|
path = Path(tempfile.mkdtemp(prefix="okf-adjudication-")) / "c.md"
|
|
path.write_text(text, encoding="utf-8")
|
|
return path
|
|
|
|
|
|
@pytest.mark.parametrize("value", ["proposed", "adjudicated"])
|
|
def test_the_two_named_states_are_read_back(value: str) -> None:
|
|
"""Hand-written fixtures, to the contract as delivered.
|
|
|
|
**Honesty limit, stated:** these are written to the contract, NOT produced by
|
|
``llm-ingestion-okf``. Integration against the producer's own golden is later work and is not
|
|
claimed here.
|
|
"""
|
|
assert okf.adjudication_for(
|
|
_concept(f"---\ntype: concept\nadjudication: {value}\n---\nb\n")
|
|
) == (value)
|
|
|
|
|
|
def test_a_missing_key_is_unknown_and_NEVER_absent() -> None:
|
|
"""The third token is the whole step.
|
|
|
|
A concept that does not carry the key means *we did not learn whether this was adjudicated* —
|
|
an older bundle. Collapsing that into "it was not adjudicated" is the same defect as collapsing
|
|
``unreadable`` into ``absent`` one layer up, and the same defect removed from
|
|
``RunResult.verdict``.
|
|
"""
|
|
assert okf.adjudication_for(_concept("---\ntype: concept\ntitle: x\n---\nb\n")) == "unknown"
|
|
|
|
|
|
@pytest.mark.parametrize("value", ["ratified", "PROPOSED", ""])
|
|
def test_a_value_outside_the_vocabulary_is_refused_by_name(value: str) -> None:
|
|
"""Validation, never repair. Mapping an unknown value to ``unknown`` would invent the very
|
|
state this contract exists to keep honest — and an EMPTY value is present-but-empty, which is a
|
|
different fact from absent and must not be folded into it either."""
|
|
with pytest.raises(okf.AdjudicationValueError) as excinfo:
|
|
okf.adjudication_for(_concept(f"---\ntype: concept\nadjudication: {value}\n---\nb\n"))
|
|
assert "adjudication" in str(excinfo.value)
|
|
|
|
|
|
def test_the_carrier_hands_the_STATE_to_a_hypothesiser(tmp_path: Path) -> None:
|
|
"""THE LOAD-BEARING ARM — the gate is the CARRIER, not the enum.
|
|
|
|
An accessor that returns three tokens which nothing propagates is a vocabulary, not a seam. So
|
|
the assertion is on what the tool actually hands back: a payload carrying the state. A carrier
|
|
that returned the concept without its state would leave ``adjudication_for`` correct and the
|
|
hypothesiser none the wiser, which is the exact shape this step exists to close.
|
|
"""
|
|
bundle = tmp_path / "bundle"
|
|
bundle.mkdir()
|
|
(bundle / "a.md").write_text(
|
|
"---\ntype: concept\nadjudication: proposed\n---\nbody\n", encoding="utf-8"
|
|
)
|
|
|
|
carrier = tools.make_adjudication_tool(str(bundle))
|
|
payload = tools.adjudication_payload(str(bundle), "a.md")
|
|
|
|
assert payload["adjudication"] == "proposed"
|
|
assert payload["concept"] == "a.md"
|
|
assert carrier.name == "concept_adjudication_state"
|
|
|
|
|
|
def test_the_carrier_is_a_library_primitive_not_wired_into_the_run(tmp_path: Path) -> None:
|
|
"""``run.py`` must not import the carrier: wiring it into the run surface would move the
|
|
byte-pinned demo transcript, and would make the state reachable only by reading a run's output
|
|
rather than by calling a function."""
|
|
run_source = (
|
|
Path(__file__).resolve().parents[1] / "src" / "portfolio_optimiser" / "run.py"
|
|
).read_text(encoding="utf-8")
|
|
assert "make_adjudication_tool" not in run_source
|
|
assert "adjudication_payload" not in run_source
|