feat(verdicts): promoted verdicts carry a verified field with the actor verbatim
Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
9e35cfefbf
commit
3d76a46d76
3 changed files with 170 additions and 1 deletions
|
|
@ -19,12 +19,13 @@ from __future__ import annotations
|
|||
|
||||
import ast
|
||||
import itertools
|
||||
import shutil
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from portfolio_optimiser import okf
|
||||
from portfolio_optimiser import okf, verdicts
|
||||
from portfolio_optimiser.okf import _read_body, parse_frontmatter
|
||||
|
||||
_OKF_SOURCE = Path(okf.__file__)
|
||||
|
|
@ -509,3 +510,122 @@ def test_a_human_LAST_entry_still_resolves_to_human_reviewed() -> None:
|
|||
)
|
||||
== "machine-confirmed"
|
||||
)
|
||||
|
||||
|
||||
# --- Step 6: the writers emit `verified`, with the actor verbatim ------------------------------
|
||||
|
||||
_ENERGI_BUNDLE = Path(__file__).resolve().parents[1] / "shared" / "examples" / "bygg-energi-mikro"
|
||||
|
||||
|
||||
def _bundle_copy(tmp_path: Path) -> str:
|
||||
"""Promotion WRITES into the bundle, so every arm works on a throwaway copy — the shared,
|
||||
pull-only framework-neutral fixture is never mutated (the Step-8 discipline)."""
|
||||
dst = tmp_path / "bundle"
|
||||
shutil.copytree(_ENERGI_BUNDLE, dst)
|
||||
return str(dst)
|
||||
|
||||
|
||||
def _approved(bundle_dir: str) -> verdicts.Verdict:
|
||||
return verdicts.Verdict(
|
||||
id="PROVENANCE-ROUNDTRIP",
|
||||
proposal_features=verdicts.bundle_candidate_features(bundle_dir),
|
||||
decision="approved",
|
||||
rationale="godkjent",
|
||||
)
|
||||
|
||||
|
||||
def test_verified_field_emits_the_spec_shorthand_exactly() -> None:
|
||||
"""(a) The §5.2 single-verifier flow shorthand, byte for byte."""
|
||||
assert (
|
||||
okf.verified_field("persona", "2026-06-30T09:00:00Z")
|
||||
== "{ by: persona, at: 2026-06-30T09:00:00Z }"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("actor", ["a,b", "a{b", "a}b", "a[b", "a]b", "a\nb", "a: b"])
|
||||
def test_verified_field_refuses_an_actor_that_would_restructure_the_value(actor: str) -> None:
|
||||
"""(d) The unsafe set, and ``": "`` is in it for a reason that is NOT decoration.
|
||||
|
||||
``decode_flow_value`` splits pairs on colon-SPACE. An actor containing it would be written out
|
||||
cleanly and then MIS-DECODED on the way back — the writer and the reader must agree on the
|
||||
unsafe set, or the round trip lies while every byte looks fine.
|
||||
"""
|
||||
with pytest.raises(ValueError):
|
||||
okf.verified_field(actor, "2026-06-30T09:00:00Z")
|
||||
|
||||
|
||||
def test_a_promoted_verdict_round_trips_to_machine_confirmed(tmp_path: Path) -> None:
|
||||
"""(b) Write with ``promote_verdict``, read with ``read_provenance``, tier with ``trust_tier``.
|
||||
|
||||
A plain approver lands in ``machine-confirmed``, and that is TRUE of it: the demo passes
|
||||
``"ekspert-persona (sim)"``, a scripted stand-in, and prefixing it with ``human:`` on the
|
||||
caller's behalf would mint a human sign-off nobody gave — the fabricated-provenance defect one
|
||||
layer up.
|
||||
"""
|
||||
bundle_dir = _bundle_copy(tmp_path)
|
||||
path = verdicts.promote_verdict(
|
||||
bundle_dir,
|
||||
_approved(bundle_dir),
|
||||
approver="ekspert-persona (sim)",
|
||||
experiment="exp-B",
|
||||
timestamp="2026-06-30T09:00:00Z",
|
||||
)
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
assert "verified: { by: ekspert-persona (sim), at: 2026-06-30T09:00:00Z }" in raw
|
||||
|
||||
entries = okf.read_provenance(path, "verified")
|
||||
assert entries == ({"by": "ekspert-persona (sim)", "at": "2026-06-30T09:00:00Z"},)
|
||||
assert okf.trust_tier(entries) == "machine-confirmed"
|
||||
|
||||
|
||||
def test_a_human_prefixed_approver_reaches_the_human_tier(tmp_path: Path) -> None:
|
||||
"""(b, second half) The ``human-reviewed`` tier is reached by a CALLER saying so."""
|
||||
bundle_dir = _bundle_copy(tmp_path)
|
||||
path = verdicts.promote_verdict(
|
||||
bundle_dir,
|
||||
_approved(bundle_dir),
|
||||
approver="human:ktg",
|
||||
experiment="exp-B",
|
||||
timestamp="2026-06-30T09:00:00Z",
|
||||
)
|
||||
assert okf.trust_tier(okf.read_provenance(path, "verified")) == "human-reviewed"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("bad", "marker"),
|
||||
[
|
||||
("{ by: a, at: b }\n{ by: c, at: d }", "one line"),
|
||||
("- { by: a, at: b }", "neither a flow sequence nor a flow mapping"),
|
||||
("[ a.pdf ]", "bare scalar"),
|
||||
],
|
||||
)
|
||||
def test_write_concept_file_refuses_a_verified_value_outside_the_subset(
|
||||
tmp_path: Path, bad: str, marker: str
|
||||
) -> None:
|
||||
"""(c) Validation, never repair — and NOTHING is written.
|
||||
|
||||
``render_frontmatter`` collapses newlines for every key, which for ``verified`` would turn a
|
||||
block value into a single line that decodes to something nobody wrote. The refusal is scoped
|
||||
to ``verified`` BY NAME; every other key keeps the old collapsing behaviour, and that is stated
|
||||
rather than hidden by the control arm below.
|
||||
"""
|
||||
with pytest.raises(okf.FlowDecodeError) as excinfo:
|
||||
okf.write_concept_file(str(tmp_path), "c.md", {"type": "concept", "verified": bad}, "b\n")
|
||||
# The marker pins that the writer's refusal IS the reader's refusal, not a second rule beside
|
||||
# it — a hand-rolled copy here would refuse with words of its own and be free to drift.
|
||||
assert marker in str(excinfo.value)
|
||||
assert not (tmp_path / "c.md").exists(), "the refusal wrote a file anyway"
|
||||
|
||||
|
||||
def test_the_refusal_is_scoped_to_verified_and_other_keys_are_untouched(tmp_path: Path) -> None:
|
||||
"""CONTROL — a refusal that fired on every key would break `render_frontmatter`'s contract for
|
||||
the whole repo, and a refusal that fired on nothing would be worthless. Both are excluded."""
|
||||
path = okf.write_concept_file(
|
||||
str(tmp_path),
|
||||
"c.md",
|
||||
{"type": "concept", "provenance": "line one\nline two", "verified": "{ by: p, at: t }"},
|
||||
"body\n",
|
||||
)
|
||||
written = path.read_text(encoding="utf-8")
|
||||
assert "provenance: line one line two" in written, "an unrelated key stopped being collapsed"
|
||||
assert "verified: { by: p, at: t }" in written
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue