3.4 KiB
3.4 KiB
Story: Whole-Document Context — a matched document is never truncated
Phase: 24_whole_document_context · E2E: tests/e2e/test_whole_document_context.py
Bug report (TODO.md L3–L4, verbatim)
"Documents are truncated for some reason? This should never happen"
"When the LLM matches a chunk it should get the entire document placed in its context so it can see the whole thing before answering the question"
Narrative
As a user asking about an indexed note, I want the entire document in the LLM's context whenever retrieval matches one of its chunks — so the answer is grounded in the whole note, not a silently cut-down version of it.
- Given a question whose chunk matches a document
- When the turn assembles context
- Then the LLM receives the entire parent document — never a
[…truncated…]-cut version — so the answer is grounded in the whole note.
Owner-confirmed (2026-08-24, roadmap D1–D5)
- D1 — no cap at all (revises LOCKED A7):
select_documentsreturns the full top-N document texts, always. Themax_context_charssetting andBOR_MAX_CONTEXT_CHARSenv var are removed. If a future KB ever makes the prompt too large for the model, the existingLLMError→ SSEerrorpath surfaces it loudly — no silent partial context. The emergency-valve variant (raised cap + warning log) was explicitly rejected. - D2 —
top_n_docs = 2unchanged (the TODO is about truncation, not about how many documents). - D3 — no viewer/import changes — both already serve full content (verified diagnosis above).
- D4 — E2E evidence via a deterministic mock tail-echo (repo pattern,
cf. the phase-15 tuning-note echo); the big documents are seeded
directly in the DB inside the E2E test —
tests/fixtures/docs/must not grow, because other suites pinsummary.added == 8. - D5 — no
query_logschema change (no new columns, no migration).
Acceptance criteria
- No budget parameter in
select_documents— it never truncates (TRUNCATION_MARKERremains for the steering section only). BOR_MAX_CONTEXT_CHARSgone from settings/env/README (app/config.py,.env.example,README.md).- The story E2E's three tests green in isolation
(
uv run pytest tests/e2e/test_whole_document_context.py -v --no-cov). - Steering-note truncation (phase 15,
BOR_STEERING_MAX_CHARS+ shared marker) unchanged. - Unit + integration green,
app/coverage >90%, one--no-gpg-signcommit.
Playwright Mapping Rule
Test Scenario → tests/e2e/test_whole_document_context.py (mock LLM
tail-echo, oversized documents seeded directly in the DB):
test_whole_document_over_old_cap_reaches_llm— a 30 000-char document (past the old 24 000 cap): its tail sentinel (last line) is echoed in the rendered answer,[…truncated…]is absent, the source chip renders,query_logrowdeflected == False.test_second_document_of_over_cap_pair_reaches_llm— two ~16 000-char documents (32 000 combined — the exact case the old budget cut): the second, lower-ranked document's tail sentinel is echoed (doc 1's is not — it pins the rank order), both source chips render.test_small_document_path_unchanged— regression: standard fixtures via the real importer → grounded answer with thekubernetes.mdchip, no[…truncated…](the under-cap path is byte-identical to before).