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.
Closes maalbilde §5 gap #1 (the one missing "feedback-into-prompt" dataflow)
for the OKF-bundle path. Before, ExpeL was computed AFTER generation into a
discarded SessionContext, so a prior verdict could not influence any hypothesis
(context_providers=0).
- New okf.py: framework-neutral OKF bundle navigation (index + frontmatter +
cross-links), pure stdlib, no agent_framework/mcp (D7-portable), enforced by
test_okf_is_maf_free.
- verdicts.py: seed_store_from_bundle + bundle_candidate_features build the
ExpeL substrate + the pre-hypothesis query key from a bundle.
- run_project(bundle_dir=...): folds the candidate's prior verdicts into the
generation context BEFORE generate_via_llm; the road path is unchanged.
Load-bearing (maalbilde §7): test_step1_expel_loadbearing proves a prior verdict
reaches the hypothesis prompt and goes RED when the fold is detached (shown via
TDD red->green). The marker is the minted verdict id (content hash) because
docs_dir==bundle_dir lets keyword chunk-stuffing leak the realization rate;
clean layer separation is Fase 2b.
Suite 121->133 passed; mypy + ruff check clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE