fix(s51): close 2 review MINORs — non-UTF-8 skip + affected_codes parity
Both live in the tolerant inbox-read path and both contradicted the module's own "skipped, never raised" / loader-parity docstrings (S5.1 review: ALLOW, 2 MINOR, non-gating): - UnicodeDecodeError (a *.json hand-saved in Latin-1 with Norwegian æ/ø/å is invalid UTF-8) now SKIPPED in hitl._load_json_dict AND verdicts.load_verdicts_from_dir — was: crashed pending/route with a raw traceback (a ValueError subclass, caught by neither OSError nor JSONDecodeError). Fix symmetric across both readers. - hitl._inbox_verdict_ids now skips a non-iterable affected_codes exactly as load_verdicts_from_dir does (frozenset() raises TypeError) — was: marked the proposal judged on key-presence alone → a silent false-negative in the operator pending queue. hitl-only: verdicts is the correct reference. TDD: 3 RED-then-green (both UnicodeDecodeError twins + the parity gap) + 1 ground-truth pin locking the loader side so the parity cannot rot. Gate: pytest → 389 passed, 4 skipped (was 385); ruff check + format clean; mypy clean.
This commit is contained in:
parent
5807ac428c
commit
7e86896bc8
5 changed files with 131 additions and 4 deletions
|
|
@ -193,6 +193,36 @@ def test_inbox_idset_skips_malformed_features(tmp_path: Path) -> None:
|
|||
assert [p.run_id for p in hitl.pending(str(outbox), str(inbox))] == ["run-1"]
|
||||
|
||||
|
||||
def test_inbox_idset_skips_non_iterable_affected_codes(tmp_path: Path) -> None:
|
||||
"""PARITY (wrong-type): an inbox verdict with every required key present but ``affected_codes`` a
|
||||
NON-ITERABLE (``null``) is skipped — the real loader's ``frozenset(pf['affected_codes'])``
|
||||
(verdicts.py) raises ``TypeError`` and ``load_verdicts_from_dir`` drops it. So ``pending`` must NOT
|
||||
count it as judged; otherwise ``hitl`` marks the proposal judged while the learning pipeline still
|
||||
treats it pending — a silent false-negative in the operator queue, the exact failure the parity
|
||||
docstring says it prevents. Detach the ``affected_codes`` iterability check (accept on key-presence
|
||||
alone) → the file clears pending → RED. Ground-truth twin:
|
||||
``test_verdicts.test_load_skips_non_iterable_affected_codes``."""
|
||||
outbox = tmp_path / "outbox"
|
||||
inbox = tmp_path / "inbox"
|
||||
_write_proposal(outbox, "run-1", verdict_id="SHARED-VID")
|
||||
_write_raw_verdict(
|
||||
inbox,
|
||||
"SHARED-VID",
|
||||
{
|
||||
"id": "SHARED-VID",
|
||||
"decision": "approved",
|
||||
"rationale": "ok",
|
||||
"proposal_features": {
|
||||
"affected_codes": None, # non-iterable → real loader's frozenset() raises → skips
|
||||
"measure_type": "scope_reduction",
|
||||
"claimed_saving_nok": 200.0,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert [p.run_id for p in hitl.pending(str(outbox), str(inbox))] == ["run-1"]
|
||||
|
||||
|
||||
# --- transitive import-graph MAF-freedom probe (Step 5) -------------------------------------------
|
||||
|
||||
_SRC_DIR = Path(__file__).resolve().parents[1] / "src" / "portfolio_optimiser"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue