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:
+22
-7
@@ -388,9 +388,10 @@ class DocContent(BaseModel):
|
||||
path: str
|
||||
title: str
|
||||
format: str
|
||||
#: Lite-model summary (phase 30) — non-markdown A9 docs only; None for
|
||||
#: markdown documents, pre-phase-30 rows, and the fail-soft path where
|
||||
#: summary generation failed but the document was still indexed.
|
||||
#: Lite-model summary (phase 30) — every A9 doc, markdown included
|
||||
#: since phase 118 A2; None for pre-phase-30 rows, the fail-soft path
|
||||
#: where summary generation failed, and until the phase-118 backfill
|
||||
#: stores one on the next sync.
|
||||
summary: str | None = None
|
||||
#: The document's creation date (phase 106, D8) — ISO-8601, verbatim
|
||||
#: from the row; the viewer's top meta row renders the ``Created``
|
||||
@@ -742,14 +743,26 @@ class ChatMessage(BaseModel):
|
||||
"""One conversation record in the ``bor.chat.v1`` localStorage shape
|
||||
(phase 14) — the stored ``messages`` payload of a saved chat (phase 50).
|
||||
|
||||
``{who, text, sources?, deflected?, suggestions?, thinking?, tools?,
|
||||
stopped?}`` — raw text, never HTML, so a saved chat restores
|
||||
pixel-identical through the existing ``renderStoredMessage`` path.
|
||||
``{who, text, sources?, related?, deflected?, suggestions?,
|
||||
thinking?, tools?, stopped?}`` — raw text, never HTML, so a saved
|
||||
chat restores pixel-identical through the existing
|
||||
``renderStoredMessage`` path.
|
||||
``extra="forbid"`` rejects unknown keys (a corrupted or HTML-shaped
|
||||
payload, e.g. a stray ``<b>``-ish extra key) at the boundary with a
|
||||
422, so nothing outside this shape can poison a restored
|
||||
conversation.
|
||||
|
||||
``related`` (phase 113, the related-doc tier the UI persists with
|
||||
every grounded brain record — the restore path re-renders the
|
||||
de-emphasized row from it): the same :class:`SourceRef` list shape
|
||||
as ``sources``, the same cap. Its absence from this model was a
|
||||
phase-113 omission — the ``extra="forbid"`` boundary 422'd every
|
||||
done-time auto-save carrying the key (the A2 quiet-failure path
|
||||
swallowed it), leaving grounded turns' brain messages unsaved;
|
||||
pinned by ``tests/integration/test_chats_api.py`` (the full brain
|
||||
record carries ``related``) and the E2E ``test_share_chat``
|
||||
auto-save count.
|
||||
|
||||
Phase 83 (SEC-05) bounds the anonymous write surface (``POST/PUT
|
||||
/api/chats`` is public — the row id is the credential, phase 55 A1):
|
||||
``text`` / ``thinking`` carry :class:`HistoryTurn`'s 32 000 caps
|
||||
@@ -757,7 +770,8 @@ class ChatMessage(BaseModel):
|
||||
path, so a saved chat can never legitimately carry more), and the
|
||||
nested lists get length caps (``max_length``) sized to the realistic
|
||||
``bor.chat.v1`` record the UI produces (``sources`` ≤ 20 — top-N docs
|
||||
+ agent reads; ``suggestions`` ≤ 50 chips of ≤ 200 chars; ``tools``
|
||||
+ agent reads; ``related`` ≤ 20 — the related-doc tier, same ref
|
||||
shape; ``suggestions`` ≤ 50 chips of ≤ 200 chars; ``tools``
|
||||
≤ 50 — one entry per tool call, the round cap is 10). Only value
|
||||
bounds were added — the accepted/rejected KEYS are unchanged.
|
||||
"""
|
||||
@@ -767,6 +781,7 @@ class ChatMessage(BaseModel):
|
||||
who: Literal["user", "brain"]
|
||||
text: str = Field(min_length=1, max_length=32_000)
|
||||
sources: list[SourceRef] | None = Field(default=None, max_length=20)
|
||||
related: list[SourceRef] | None = Field(default=None, max_length=20)
|
||||
deflected: bool | None = None
|
||||
suggestions: list[_Chip] | None = Field(default=None, max_length=50)
|
||||
thinking: str | None = Field(default=None, max_length=32_000)
|
||||
|
||||
Reference in New Issue
Block a user