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:
parent
812db2363e
commit
8814a698c2
7 changed files with 117 additions and 29 deletions
|
|
@ -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."""
|
||||
|
|
|
|||
|
|
@ -31,13 +31,16 @@ _ENERGY_REPLY = (
|
|||
)
|
||||
_VERDICT_INPUT = {"decision": "approved", "rationale": "expert reviewed (sim)"}
|
||||
|
||||
# The load-bearing marker is the seed verdict's MINTED id (a 16-char content hash that
|
||||
# ``ExpeLContextProvider.format_fewshot`` emits as ``- [<id>] ...``). It cannot appear in the
|
||||
# bundle's raw text, so its presence in the prompt isolates the STRUCTURAL ExpeL path. (The
|
||||
# realization rate "0.82" is NOT a usable marker here: ``docs_dir == bundle_dir``, so keyword
|
||||
# chunk-stuffing reads the verdict file and would leak "0.82" regardless of the fold. Layer
|
||||
# separation — verdicts out of the keyword docs folder — is Fase 2b.)
|
||||
# Two load-bearing markers, by design:
|
||||
# - the seed verdict's MINTED id (16-char content hash ``format_fewshot`` emits as ``- [<id>] ...``);
|
||||
# it cannot appear in the bundle's raw text, so it isolates the STRUCTURAL ExpeL path.
|
||||
# - the realization rate "0.82". Fase 2b replaced keyword chunk-stuffing with OKF-navigation that
|
||||
# EXCLUDES ``type: verdict`` from the bundle context, so the signal now reaches a prompt ONLY via
|
||||
# the gated ExpeL fold. Pre-2b (``docs_dir == bundle_dir``) chunk-stuffing leaked "0.82" from the
|
||||
# verdict + golden files into the debate prompt regardless of the fold — which the empty-store
|
||||
# control below asserts is no longer true (it goes RED against the pre-2b chunk-stuffing path).
|
||||
_SEED_ID = seed_store_from_bundle(str(BUNDLE_DIR)).verdicts[0].id
|
||||
_REALIZATION_SIGNAL = "realiseringsgrad=0.82" # the exact ``_verdict_rationale`` fewshot string
|
||||
|
||||
|
||||
def _generation_prompts(sink: list[str]) -> list[str]:
|
||||
|
|
@ -69,6 +72,11 @@ async def test_prior_verdict_reaches_hypothesis_prompt(make_recording_client_fac
|
|||
assert any(_SEED_ID in p for p in gen_prompts), (
|
||||
"the seed verdict did not reach the hypothesis prompt — the ExpeL->prompt fold is detached"
|
||||
)
|
||||
# Fase 2b: the realization SIGNAL itself (not just the id) is now a clean marker — it can only
|
||||
# reach the prompt via the gated fold, since OKF-navigation excludes the verdict from context.
|
||||
assert any(_REALIZATION_SIGNAL in p for p in gen_prompts), (
|
||||
"the realization signal did not reach the hypothesis prompt via the ExpeL fold"
|
||||
)
|
||||
|
||||
|
||||
async def test_empty_store_leaves_no_signal_in_prompt(make_recording_client_factory) -> None:
|
||||
|
|
@ -91,3 +99,10 @@ async def test_empty_store_leaves_no_signal_in_prompt(make_recording_client_fact
|
|||
"no seed verdict in the store, yet its id appeared in a prompt — "
|
||||
"the assertion is not actually load-bearing"
|
||||
)
|
||||
# Fase 2b LOAD-BEARING: with no fold, the realization rate must appear in NO prompt. This goes
|
||||
# RED against the pre-2b chunk-stuffing path (which leaked "0.82" from the verdict + golden files
|
||||
# into the debate prompt) and only passes once OKF-navigation excludes the verdict from context.
|
||||
assert all("0.82" not in p for p in recorded), (
|
||||
"the realization rate leaked into a prompt without a seed verdict — bundle context is still "
|
||||
"chunk-stuffing the verdict/golden files (Fase 2b OKF-navigation not in effect)"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue