phase: 118_summary_seed_context
Build and Push Containers / build-and-push-app (push) Successful in 2m2s
Build and Push Containers / build-and-push-db (push) Successful in 14s

**Phase 118 final verification pass — complete.** All criteria verified; 4 pre-existing defects found and fixed.

- **Verified:** summary-seed wiring (`select_suggested` top-5 no-floor → summary blocks, no full text in HIGH prompt), all-doc markdown summaries + NULL backfill (`summary_backfilled`, no `sources_meta` bump), `read` adds full text with `read_docs`-only dedupe, `done.sources` = suggested+read / durable record = suggested+related+read + `suggested=N` log line (seen live in E2E), byte-locked PERSONA/LOW/TOOLS_SECTION, battery gate PASS recorded in `TOOL_CALLING_TESTING.md` §10 (turbo 2026-09-16: 1/2/4 GREEN, cond-3 reported 9/10 per A7, contract 21/21, caps 0).
- **Defects fixed (all pre-existing, none phase-118):** ① `ChatMessage` schema missing the phase-113 `related` key → `extra="forbid"` 422'd every done-time auto-save of grounded turns with a related tier, leaving `message_count=1` (root cause of `test_share_chat` 3F; browser-level instrumentation proved the PUT 422) — added the field + unit/integration pins; ② `test_theme_semantic_completion` pins stale vs phase-117 debox (border/chip removed) — re-targeted to assert border/chip *absence*; ③ `test_header_consistency` `<26`px pin red on 26.125px native date-input line — bound relaxed to `<34` (wrap-detection intent kept); ④ `test_navbar_refresh` bor.chat.v1 key set updated for `related`.
- **Test/lint/coverage:** `uv run pytest --cov=app --cov-report=term-missing` → **2506 passed, app/ 99%** (>90%); `uv run ruff check . && uv run pyright` → clean, 0 errors.
- **E2E:** new story suite in isolation → **2 passed**; full 103-suite matrix sweep (each isolated) → **all 103 green** after the fixes; `test_share_chat` 4 passed, `test_theme_semantic_completion` 8 passed, `test_header_consistency` 3 passed, `test_navbar_refresh` 7 passed.
- **Deviations:** none from LOCKED decisions. Note: orphaned diagnostic uvicorn processes briefly made E2E sessions exercise stale code — killed and re-verified; a sweep-regenerated tracked screenshot was restored. No commits made (harness commits).
- **Completion criteria:** all 7 ✅ (commit/phase-move is the harness's step).
- **Next pending phase:** none — `todo/` holds only this phase's overview pending the harness move.
This commit is contained in:
2026-09-16 06:57:49 -04:00
parent 21aad84a6d
commit 9820c361b0
80 changed files with 4690 additions and 1302 deletions
+229
View File
@@ -11,12 +11,16 @@ from types import SimpleNamespace
import pytest
from app.config import Settings
from app.models import Document
from app.rag import retriever
from app.rag.retriever import (
TRUNCATION_MARKER,
RetrievedChunk,
select_documents,
select_documents_tiered,
select_related,
select_suggested,
)
@@ -258,6 +262,231 @@ def test_select_documents_wrapper_is_legacy_tiering() -> None:
)[0]
# ---------------------------------------------------------------------------
# Phase 118 — select_suggested: the top-N "start here" tier, NO floor (A3)
# ---------------------------------------------------------------------------
def test_suggested_rank_order_by_first_seen_chunk() -> None:
"""The SAME stable walk as ``select_documents_tiered``: a document's
rank is fixed by its FIRST seen chunk in score-descending order — a
doc whose best chunk appears later in the input list still ranks
where that chunk falls."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
c = _doc("c.md", "C" * 50)
chunks = [
_chunk(a, 0.4, position=0), # a's weak chunk comes first
_chunk(b, 0.8),
_chunk(a, 0.9, position=2), # a's best chunk comes last
_chunk(c, 0.5),
]
out = select_suggested(chunks, n=5)
assert [d.path for d in out] == ["a.md", "b.md", "c.md"]
# The rows carry the full content byte-identical (A6: the content is
# what ``read`` serves later — never truncated).
assert out[0].content == "A" * 50
assert TRUNCATION_MARKER not in out[0].content
def test_suggested_dedupes_multiple_chunks_to_one_row() -> None:
"""Multiple hit chunks of one document collapse to a single row."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
chunks = [
_chunk(a, 0.2),
_chunk(b, 0.7),
_chunk(a, 0.9, position=2),
_chunk(a, 0.5),
]
out = select_suggested(chunks, n=5)
assert [d.path for d in out] == ["a.md", "b.md"] # one row per document
assert out[0] is a
def test_suggested_caps_at_n_in_rank_order() -> None:
docs_in = [_doc(f"d{i}.md", "X" * 20) for i in range(7)]
chunks = [_chunk(d, 0.9 - 0.1 * i) for i, d in enumerate(docs_in)]
out = select_suggested(chunks, n=3)
assert [d.path for d in out] == ["d0.md", "d1.md", "d2.md"]
def test_suggested_default_cap_is_the_settings_value(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""``n`` omitted → ``BOR_SUGGESTED_DOCS`` caps the walk — default 5
(LOCKED A3, the top-5 "start here" directive, TODO L3) — and the cap
is the setting's LIVE value, not a frozen constant."""
docs_in = [_doc(f"d{i}.md", "X" * 20) for i in range(7)]
chunks = [_chunk(d, 0.9 - 0.1 * i) for i, d in enumerate(docs_in)]
settings = Settings(_env_file=None) # pyright: ignore[reportCallIssue]
assert settings.suggested_docs == 5 # the production default
monkeypatch.setattr(retriever, "get_settings", lambda: settings)
assert [d.path for d in select_suggested(chunks)] == [
f"d{i}.md" for i in range(5)
]
small = Settings(_env_file=None, suggested_docs=2) # pyright: ignore[reportCallIssue]
monkeypatch.setattr(retriever, "get_settings", lambda: small)
assert [d.path for d in select_suggested(chunks)] == ["d0.md", "d1.md"]
def test_suggested_never_filters_on_cosine_floor() -> None:
"""NO floor (LOCKED A3): a lexical-only hit (cosine 0.0 by
construction) is a suggestion when it ranks — the contrast pin
against ``select_documents_tiered``'s floored cited tier on the SAME
input, which demotes it to the related tier."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
lexical_only = RetrievedChunk(
chunk_id=uuid.uuid4(),
position=0,
content="X" * 10,
score=0.9, # top fused rank (the FTS hit)
document=a,
cosine=0.0, # no vector rank — lexical-only
fts_hit=True,
)
chunks = [lexical_only, _cos_chunk(b, 0.8, 0.5)]
# Suggested: the floor never filters — a leads, b follows in rank order.
assert [d.path for d in select_suggested(chunks, n=5)] == ["a.md", "b.md"]
# Contrast: the same input through the phase-113 cited tier — the
# 0.35 usefulness bar demotes the lexical-only doc to related.
cited, related = select_documents_tiered(chunks, n=2, floor=0.35, related_cap=2)
assert [d.path for d in cited] == ["b.md"]
assert [d.path for d in related] == ["a.md"]
def test_suggested_tie_break_inherited_from_fused_order() -> None:
"""Equal fused scores keep the input (fused) order — the stable
score-only walk inherits ``fuse()``'s (-score, -cosine, path,
position) tie-break; the selector never re-sorts it away."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
chunks = [_cos_chunk(a, 0.7, 0.5), _cos_chunk(b, 0.7, 0.4)] # a wins on cosine
assert [d.path for d in select_suggested(chunks, n=5)] == ["a.md", "b.md"]
# A FULL tie (score AND cosine): the input position — ``fuse()``'s
# path/position tie-break already applied — decides. ``m.md`` sorts
# AFTER ``b2.md`` alphabetically, so any re-sort by path would flip
# the order; the fused input order must win.
m = _doc("m.md", "M" * 50)
b2 = _doc("b2.md", "B" * 50)
chunks = [_cos_chunk(m, 0.7, 0.4), _cos_chunk(b2, 0.7, 0.4)]
assert [d.path for d in select_suggested(chunks, n=5)] == ["m.md", "b2.md"]
def test_suggested_empty_chunks_yield_no_documents() -> None:
assert select_suggested([], n=5) == []
# ---------------------------------------------------------------------------
# Phase 118, task 05 — select_related: the rank-6+ tier after the suggested set
# ---------------------------------------------------------------------------
def test_related_walk_order_after_excluded_set() -> None:
"""The SAME stable score-descending walk as ``select_suggested``:
a document's rank is fixed by its FIRST seen chunk; documents in
*excluded_ids* (the suggested set) are skipped and the rest come
back in rank order."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
c = _doc("c.md", "C" * 50)
d = _doc("d.md", "D" * 50)
chunks = [
_chunk(a, 0.4, position=0), # a's weak chunk comes first
_chunk(b, 0.8),
_chunk(a, 0.9, position=2), # a's best chunk last — a ranks first
_chunk(c, 0.5),
_chunk(d, 0.3),
]
out = select_related(chunks, {a.id, b.id}, cap=2)
assert [x.path for x in out] == ["c.md", "d.md"]
def test_related_skips_excluded_documents() -> None:
"""Every document in *excluded_ids* is skipped, even when it would
rank inside the cap — the suggested set never rides the related row."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
c = _doc("c.md", "C" * 50)
chunks = [_chunk(a, 0.9), _chunk(b, 0.8), _chunk(c, 0.5)]
out = select_related(chunks, {a.id, b.id}, cap=5)
assert out == [c]
# Every doc excluded → empty, even with room left in the cap.
assert select_related(chunks, {a.id, b.id, c.id}, cap=5) == []
def test_related_caps_at_cap_in_rank_order() -> None:
"""The phase-118 turn wiring on 9 docs: suggested = the top 5,
related = rank 6–7 (capped at 2), disjoint from the suggested set."""
docs_in = [_doc(f"d{i}.md", "X" * 20) for i in range(9)]
chunks = [_chunk(d, 0.9 - 0.1 * i) for i, d in enumerate(docs_in)]
suggested = select_suggested(chunks, n=5)
out = select_related(chunks, {d.id for d in suggested}, cap=2)
assert [x.path for x in out] == ["d5.md", "d6.md"] # rank 6–7, capped
suggested_paths = {d.path for d in suggested}
assert suggested_paths.isdisjoint({x.path for x in out})
def test_related_cap_zero_yields_empty() -> None:
"""cap=0 is the kill switch (related_max_docs=0): no related docs,
the pre-phase-113 visibility."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
c = _doc("c.md", "C" * 50)
chunks = [_chunk(a, 0.9), _chunk(b, 0.8), _chunk(c, 0.5)]
assert select_related(chunks, {a.id}, cap=0) == []
def test_related_never_filters_on_cosine_floor() -> None:
"""NO floor: a lexical-only (cosine 0.0) doc is related when it
ranks after the excluded set — the related tier is visibility, not
citation (phase 118 applies no cosine floor to it)."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
lexical_only = RetrievedChunk(
chunk_id=uuid.uuid4(),
position=0,
content="X" * 10,
score=0.9, # top fused rank (the FTS hit)
document=a,
cosine=0.0, # no vector rank — lexical-only
fts_hit=True,
)
chunks = [lexical_only, _cos_chunk(b, 0.8, 0.5)]
out = select_related(chunks, set(), cap=5)
assert [x.path for x in out] == ["a.md", "b.md"]
def test_related_dedupes_multiple_chunks_to_one_row() -> None:
"""Multiple hit chunks of one document collapse to a single row
(first-seen-chunk rank, dedupe by document.id — the shared walk)."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
chunks = [_chunk(a, 0.2), _chunk(b, 0.7), _chunk(a, 0.9, position=2)]
out = select_related(chunks, set(), cap=5)
assert [x.path for x in out] == ["a.md", "b.md"] # one row per document
assert out[0] is a
def test_related_tie_break_inherited_from_fused_order() -> None:
"""Equal fused scores keep the input (fused) order — the stable
score-only walk inherits ``fuse()``'s (-score, -cosine, path,
position) tie-break; the selector never re-sorts it away."""
a = _doc("a.md", "A" * 50)
b = _doc("b.md", "B" * 50)
chunks = [_cos_chunk(a, 0.7, 0.5), _cos_chunk(b, 0.7, 0.4)] # a wins on cosine
assert [x.path for x in select_related(chunks, set(), cap=5)] == ["a.md", "b.md"]
m = _doc("m.md", "M" * 50)
b2 = _doc("b2.md", "B" * 50)
chunks = [_cos_chunk(m, 0.7, 0.4), _cos_chunk(b2, 0.7, 0.4)] # full tie
assert [x.path for x in select_related(chunks, set(), cap=5)] == ["m.md", "b2.md"]
def test_related_empty_chunks_yield_no_documents() -> None:
assert select_related([], set(), cap=5) == []
# ---------------------------------------------------------------------------
# Hybrid retrieval (A7): RRF fusion + lexical tsquery
# ---------------------------------------------------------------------------