phase: 118_summary_seed_context
**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:
@@ -111,6 +111,9 @@ class Settings(BaseSettings):
|
||||
|
||||
# --- RAG tuning ---
|
||||
embedding_dim: int = 768 # verified against aipi /v1 (embed model)
|
||||
#: Phase 118 retired the full-text seeding role (A6); the suggested
|
||||
#: tier (``select_suggested``) seeds the prompt now — kept for env
|
||||
#: back-compat (no ``app/`` consumer left).
|
||||
top_n_docs: int = 2
|
||||
# Honesty gate (A8, re-tuned 2026-08-21): the ``embed`` model's cosine
|
||||
# scores compress into 0.41–0.84 on the real corpus, so the old 0.30
|
||||
@@ -126,6 +129,9 @@ class Settings(BaseSettings):
|
||||
# ``relevance_threshold`` (a floor above the threshold is a typo that
|
||||
# would make every FTS hit require a HIGH cosine anyway).
|
||||
lexical_support_floor: float = 0.35
|
||||
#: Phase 118 retired the full-text seeding role (A6); the suggested
|
||||
#: tier (``select_suggested``) seeds the prompt now (no floor, A3) —
|
||||
#: kept for env back-compat (no ``app/`` consumer left).
|
||||
#: Usefulness bar for the citation slot (phase 113, LOCKED A2): a
|
||||
#: retrieved document earns ``done.sources`` (the UI's citation chip)
|
||||
#: only when the **cosine** of its best hit chunk clears this floor —
|
||||
@@ -149,6 +155,26 @@ class Settings(BaseSettings):
|
||||
#: docs at all (the kill switch); a negative value fails startup
|
||||
#: loudly (the ``agent_max_rounds`` pattern).
|
||||
related_max_docs: int = 2
|
||||
#: Cap on the "start here" suggestion tier (phase 118, LOCKED A3 —
|
||||
#: the owner directive, TODO L3): a grounded turn seeds the top-N
|
||||
#: related documents into the prompt as SUMMARY blocks (opt-in
|
||||
#: starting points, never citations) and the LLM extends its context
|
||||
#: by reading only what it needs. NO cosine floor applies — unlike
|
||||
#: the cited tier's ``source_usefulness_floor``, a lexical-only hit
|
||||
#: (cosine 0.0) is a valid starting point when it ranks. Default 5;
|
||||
#: tunable via ``BOR_SUGGESTED_DOCS``. A value below 1 is a typo —
|
||||
#: the validator fails startup loudly (the ``agent_max_rounds``
|
||||
#: pattern).
|
||||
suggested_docs: int = 5
|
||||
#: Preview cap for a suggestion block whose document summary is missing
|
||||
#: (phase 118, task 03, LOCKED A5): a NULL/blank ``doc.summary`` (a
|
||||
#: fail-soft import miss) falls back to the first ``suggestion_preview_chars``
|
||||
#: characters of the document content plus the shared
|
||||
#: ``[…truncated…]`` marker — deterministic, no LLM call at chat time.
|
||||
#: Tolerates content at or under the cap whole (no marker — nothing was
|
||||
#: cut). ``0``/negative is a typo (empty preview) — the validator fails
|
||||
#: startup loudly (the ``agent_max_rounds`` pattern).
|
||||
suggestion_preview_chars: int = 400
|
||||
#: Maximum output tokens a chat answer may use (owner instruction
|
||||
#: 2026-08-22: answers must run to their natural end — the old hard
|
||||
#: 700-token cap cut long answers off mid-sentence).
|
||||
@@ -387,6 +413,25 @@ class Settings(BaseSettings):
|
||||
raise ValueError("related_max_docs must be >= 0 (0 = no related docs)")
|
||||
return v
|
||||
|
||||
@field_validator("suggested_docs")
|
||||
@classmethod
|
||||
def _suggested_docs_at_least_one(cls, v: int) -> int:
|
||||
"""The suggestion tier always seeds at least one summary block —
|
||||
``0`` (no starting points) and negatives are typos (the
|
||||
``agent_max_rounds`` pattern, phase 118)."""
|
||||
if v < 1:
|
||||
raise ValueError("suggested_docs must be >= 1")
|
||||
return v
|
||||
|
||||
@field_validator("suggestion_preview_chars")
|
||||
@classmethod
|
||||
def _suggestion_preview_chars_positive(cls, v: int) -> int:
|
||||
"""``0``/negative would preview an empty/absent prefix — fail loud at
|
||||
startup (the ``agent_max_rounds`` pattern, phase 118)."""
|
||||
if v <= 0:
|
||||
raise ValueError("suggestion_preview_chars must be > 0 (chars)")
|
||||
return v
|
||||
|
||||
@field_validator("import_extensions")
|
||||
@classmethod
|
||||
def _import_extensions_known(cls, v: str) -> str:
|
||||
|
||||
Reference in New Issue
Block a user