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.
Findings 4-7 from the 2026-07-02 status analysis, per the session plan (S1):
- CHANGELOG rewritten truthfully (was: 'Plan phase - no framework code yet')
- README stack line names the split GA packages, not the agent-framework meta-package
- CLAUDE.md: MCP downgraded to extension point (in-process FunctionTool is the default seam)
- Verdict conflict semantics documented as chosen (store first-write-wins per id,
disk/wiki last-write-wins per file; full B10 taxonomy deliberately deferred)
- docs/extending.md: explicit 90%-principle cut-list (B10, B11, U12, U14, concurrent fan-out)
- .gitignore covers .trekexecute-progress-* (docs/.DS_Store was already untracked/ignored -
the plan's git rm --cached assumption was stale; no-op)
No code behavior changed (docstring only in verdicts.py). Suite 152/4 green, mypy clean,
ruff format --check clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AaQCFnfsh3tfq1VfzdJpoi
Close the last agentic-loop seam (målbilde §3/§6/§7/§11 step 6): an
APPROVED verdict is promoted from the raw output layer into the context
layer (the OKF bundle) as a navigable `type: verdict` concept file, so
human/persona-approved knowledge reaches the next run's hypothesis.
- okf.py (pure stdlib, MAF-free): render_frontmatter / write_concept_file
/ link_in_index — the D7-portable OKF write counterpart of navigate.
- verdicts.py: promote_verdict + PromotionRefused gate (fail-closed; only
approved decisions enter the wiki, never raw agent output), provenance
stamp (who/experiment/when; timestamp a required kwarg), neutral index
label (signal reaches a prompt only via the gated ExpeL fold, never
bundle_context), _safe_filename_token (id sanitised for path/link).
- R4 = optional+gated: a public opt-in primitive, NOT wired into
run_project (mirrors write_verdict — the system reads, the gate promotes).
- Load-bearing trio (test_step8_promotion_loadbearing.py): gate refuses a
non-approved verdict, approved verdict is navigable, promoted signal
stays out of the read-context — all proven RED-on-detach. Suite 144->148.
Design hardened by an adversarial plan-critic (12 findings; the BLOCKER —
index-link leak into bundle_context via index_summary — closed by the
neutral label + a no-leak test). Honesty limits documented: promoted file
is minimal (signal as prose only), and the learning-key id means
same-candidate approvals share a filename (last-write-wins).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE
The short loop captured the expert verdict inline into an in-memory store, so a
verdict arriving days/weeks later in a separate run could not influence any future
hypothesis (målbilde §5 row 7). Steg 7 adds the long timescale: run_project gains an
opt-in verdict_dir async inbox that load_verdicts_from_dir -> store.add MERGES into the
store BEFORE the Step-1 ExpeL fold, so a verdict dropped after an earlier run reaches a
separate, later run's hypothesis — fully resumable across runs separated in time.
- verdicts.py: verdict_to_dict / verdict_from_dict (id read verbatim, never re-minted),
write_verdict (public authoring primitive, NOT wired into run_project — system reads
the folder, expert/persona writes it, §3 role split), tolerant load_verdicts_from_dir
(missing/foreign/half-written files skipped, not raised — RAW layer per §10 R2),
VerdictStore.from_dir.
- run.py: verdict_dir kwarg; ingest-merge block after load_contracts (merge not replace
keeps run_portfolio's cross-project threading; store.add idempotent on content-hash id;
no change to the fold). CLI --bundle-dir/--verdict-dir thread the long loop to the
console entry. No auto-persist of the run's own captured verdict (outbox/Steg 8).
- Load-bearing PAIR (test_step7_async_loop_loadbearing.py): a verdict dropped after run A
must reach run B's prompt (run B uses a FRESH store -> the transfer is the file loop,
not in-memory carryover); empty-inbox control proves causality. Marker = a realization
value absent from the bundle (not the seed's 0.82). Proven RED on ingest detach.
Suite 138 -> 140 passed, 4 skipped; mypy + ruff check clean. Målbilde treated as frozen
(no §3/§5/§7 edit). Step 8 (gated wiki promotion) remains.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE
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