feat(okf): adjudication_for names the unknown state and a tool carries it
Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
d62e89935c
commit
ccd65d3b01
3 changed files with 191 additions and 1 deletions
|
|
@ -18,9 +18,12 @@ 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
|
||||
|
||||
from portfolio_optimiser import okf, verdicts
|
||||
import pytest
|
||||
|
||||
from portfolio_optimiser import okf, tools, verdicts
|
||||
|
||||
_GOLDEN_DIR = Path(__file__).resolve().parents[1] / "tests" / "golden" / "block-form-provenance"
|
||||
|
||||
|
|
@ -188,3 +191,79 @@ def test_a_discounted_concept_reports_the_TRIPLE_not_merely_the_refusal() -> Non
|
|||
"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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue