feat(fase2b): OKF-navigated bundle context replaces chunk-stuffing

Closes the honest Fase 2a limitation: docs_dir==bundle_dir let keyword
chunk-stuffing leak the verdict's realization rate ("0.82") into the debate /
generation prompt regardless of the ExpeL fold (it surfaced from both
verdict-led-fro.md AND golden.json). The realization signal now reaches the
hypothesis prompt ONLY via the gated ExpeL fold.

- okf.py: bundle_context() + Bundle.context_files render the navigated bundle
  (index + frontmatter + cross-links) as the agent read-context, EXCLUDING
  type: verdict (maalbilde §2/§4). Pure stdlib, still MAF-free.
- datasource.py: bundle_citations() derives first-class citations from the
  navigated non-verdict files.
- run_project: on the bundle path context + citations + debate tools come from
  navigation (tools=[]; navigation replaces query-time RAG); the road path keeps
  chunk-stuffing unchanged.

Load-bearing (maalbilde §7): the marker is upgraded from the minted verdict id
to the realization signal itself. The empty-store control now asserts "0.82"
reaches NO prompt — RED against the pre-2b chunk-stuffing path, green after
navigation (TDD red->green). New okf-level test_bundle_context_excludes_verdict_layer
guards the seam directly.

Suite 133->134 passed, 4 skipped; mypy + ruff check clean. Reverted unrelated
ruff-format drift (backends/budget/verdicts/test_contracts) to keep the diff
surgical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE
This commit is contained in:
Kjell Tore Guttormsen 2026-06-30 06:42:19 +02:00
commit 8814a698c2
7 changed files with 117 additions and 29 deletions

View file

@ -48,6 +48,26 @@ def test_navigate_index_summary_is_progressive_disclosure() -> None:
assert "progressiv disclosure" in bundle.index_summary.lower()
def test_bundle_context_excludes_verdict_layer() -> None:
"""Fase 2b LOAD-BEARING (okf level): ``bundle_context`` renders the concept files for the agent
prompt but EXCLUDES the ``type: verdict`` file, so the realization signal reaches a prompt only
via the gated ExpeL fold never by stuffing it into the read-context (målbilde §2/§4)."""
bundle = okf.navigate_bundle(str(BUNDLE_DIR))
assert {f.type for f in bundle.context_files} == {
"project",
"hypothesis",
"methodology",
"reference",
}
context = okf.bundle_context(bundle)
assert "0.82" not in context # the verdict's realization signal is NOT stuffed in
assert (
bundle.verdicts[0].frontmatter["realization_rate"] == "0.82"
) # though it IS in the bundle
assert "## hypothesis:" in context # concept files ARE rendered (progressive disclosure)
assert "progressiv disclosure" in context.lower() # the index summary is the entry point
def test_navigate_tolerates_broken_links(tmp_path) -> None:
"""OKF SPEC §4: a consumer MUST tolerate broken links. An index linking a missing file
navigates without raising, simply omitting the absent target."""