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
|
|
@ -17,6 +17,7 @@ from typing import Any
|
|||
|
||||
from agent_framework import FunctionTool, tool
|
||||
|
||||
from portfolio_optimiser.okf import Bundle
|
||||
from portfolio_optimiser.provenance import Citation
|
||||
from portfolio_optimiser.retrieval import RetrievedChunk, TextSpan, retrieve
|
||||
|
||||
|
|
@ -36,6 +37,21 @@ def retrieve_chunks(query: str, docs_dir: str, top_k: int = 3) -> list[dict[str,
|
|||
return [_chunk_to_dict(c) for c in retrieve(query, docs_dir, top_k)]
|
||||
|
||||
|
||||
def bundle_citations(bundle: Bundle) -> list[Citation]:
|
||||
"""First-class citations for the OKF-navigated bundle context: one ``Citation`` per non-verdict
|
||||
concept file (exactly the files ``okf.bundle_context`` renders). Whole-file locators, exact by
|
||||
construction (``snippet == body[start:end]``). The verdict layer is deliberately uncited — it is
|
||||
not cost documentation; it enters only via the gated ExpeL fold."""
|
||||
return [
|
||||
Citation(
|
||||
file=f.name,
|
||||
locator=TextSpan(start_index=0, end_index=len(f.body)),
|
||||
snippet=f.body,
|
||||
)
|
||||
for f in bundle.context_files
|
||||
]
|
||||
|
||||
|
||||
def chunk_dict_to_citation(d: dict[str, Any]) -> Citation:
|
||||
"""Map a structuredContent chunk dict into a first-class ``provenance.Citation``."""
|
||||
loc = d["locator"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue