phase: 166_hide_empty_answer_bubble
**Phase 166 — final verification pass: green.** All 3 task files already in `complete/`, so this was verification + defect/doc fixing.
- **Verified:** `.msg .bubble:empty { display: none; }` exists once in the Messages block with provenance; `frontend/` diff is styles.css only (**no app.js change**); `tests/unit/test_no_empty_answer_bubble.py` 26 pins pass; phase-158/161 anchor pins (thinking_timeline + tool_states + edit_message) **75 passed**.
- **Phase E2E in isolation:** `uv run pytest tests/e2e/test_no_empty_box.py --no-cov` → **5 passed**. Mutation check (rule removed) → 2 failures, so the suite genuinely pins the defect.
- **Regression set, isolated:** thinking_timeline 6 · turn_progress_loader 3 · chat_history 5 · share_chat 4 · save_share_ux 5 · failed_turn_retry 4 · chat_answer_clusters 4 · chat_error_honesty 4 → all pass.
- **Full gates:** `uv run pytest --cov=app --cov-report=term-missing` → **3880 passed, app/ 99%** (gate >90%); `uv run ruff check .` → clean; `uv run pyright` → **0 errors**.
- **Whole E2E tree swept file-by-file (150 files, own pytest process each).** 4 suites were broken by *earlier* phases; fixed and re-run green:
- `test_kb_tree`, `test_sync_summary_visibility`, `test_folder_summary_voice` — `td:nth-child(4) span` became a strict-mode violation when phase 156 wrapped the Edit label in `.cell-clip` → scoped to `span.kb-desc-text`.
- `test_search_tool_scope` — pinned the pre-`690fd98` per-run `<summary>`/`open` shape → re-pinned to the ONE `details.reasoning` container + `.tool-calls-summary`.
- `test_header_consistency` — `.doc-meta` pixel bound (`<34px`) was broken by phase 153's 44px touch-target floor at ≤640px → replaced with a shape-first single-line check that still fails a real wrap.
- **Completion criteria:** mid-turn box hidden ✅ · bubble appears at first delta, phase-130 rows below unchanged ✅ · restored/shared empty answer paints no box ✅ · no app.js change + anchors + full gates ✅ · commit/`complete/` move = harness's job (I ran no git index/history commands).
- **Docs:** README — added the phase-166 "no empty answer box mid-turn" note; fixed a **stale** Thinking lead ("collapsible Thinking blocks", pre-dated the 2026-10-06 one-disclosure refinement); QA section now states E2E isolation is mandatory (shared Postgres + fixed ports 8123/8901) with the per-file sweep loop. AGENTS.md — rule 5 UI checklist now names the phase-166 suppression rule.
- **Notable:** running all of `tests/e2e/` in one pytest session is not supported (fixture/port interleaving causes ~126 spurious failures) — documented in README. Restored the tracked `.agents/screenshots/doc_modal_scrollbar_1280.png` that `test_document_viewer.py` rewrites on every run.
- **Next pending phase:** `167_api_payload_diet`.
This commit is contained in:
@@ -862,7 +862,7 @@ def test_missing_folder_summaries_read_as_pending_and_self_heal(
|
||||
src_row = page.locator("#folders-tbody tr")
|
||||
expect(src_row.locator("a.folder-link")).to_have_text(SOURCE)
|
||||
expect(src_row.locator("td:nth-child(2)")).to_have_text(str(N_FILES))
|
||||
expect(src_row.locator("td:nth-child(4) span")).to_have_text(SUM_ROOT)
|
||||
expect(src_row.locator("td:nth-child(4) span.kb-desc-text")).to_have_text(SUM_ROOT)
|
||||
expect(page.locator(".kb-summary-pending")).to_have_count(0)
|
||||
|
||||
# The gap: delete the bravo row AND the source-root row directly
|
||||
@@ -877,7 +877,7 @@ def test_missing_folder_summaries_read_as_pending_and_self_heal(
|
||||
page.click("#nav-sources")
|
||||
_wait_top_level(page)
|
||||
src_row = page.locator("#folders-tbody tr")
|
||||
s_span = src_row.locator("td:nth-child(4) span")
|
||||
s_span = src_row.locator("td:nth-child(4) span.kb-desc-text")
|
||||
expect(s_span).to_have_text(PENDING_COPY)
|
||||
# Phase 99 (task 01): the marker toggles onto the cell's base
|
||||
# .kb-desc-text span (the one-line clamp) — the class pair, exact.
|
||||
@@ -900,13 +900,13 @@ def test_missing_folder_summaries_read_as_pending_and_self_heal(
|
||||
bravo_row = rows.nth(1)
|
||||
expect(alpha_row.locator("a.folder-link")).to_have_text(FOLDER_A)
|
||||
# The intact folder: the stored line, never the marker.
|
||||
expect(alpha_row.locator("td:nth-child(4) span")).to_have_text(SUM_ALPHA)
|
||||
expect(alpha_row.locator("td:nth-child(4) span")).not_to_have_class(
|
||||
expect(alpha_row.locator("td:nth-child(4) span.kb-desc-text")).to_have_text(SUM_ALPHA)
|
||||
expect(alpha_row.locator("td:nth-child(4) span.kb-desc-text")).not_to_have_class(
|
||||
"kb-summary-pending"
|
||||
)
|
||||
# The affected folder: the marker (copy + class + title) — the
|
||||
# class pair with the phase-99 .kb-desc-text base span, exact.
|
||||
b_span = bravo_row.locator("td:nth-child(4) span")
|
||||
b_span = bravo_row.locator("td:nth-child(4) span.kb-desc-text")
|
||||
expect(b_span).to_have_text(PENDING_COPY)
|
||||
expect(b_span).to_have_class("kb-desc-text kb-summary-pending")
|
||||
expect(b_span).to_have_attribute("title", PENDING_TITLE)
|
||||
@@ -929,7 +929,7 @@ def test_missing_folder_summaries_read_as_pending_and_self_heal(
|
||||
expect(bravo_row.locator(".kb-summary-status")).to_have_text(
|
||||
"Description updated."
|
||||
)
|
||||
b_span = bravo_row.locator("td:nth-child(4) span")
|
||||
b_span = bravo_row.locator("td:nth-child(4) span.kb-desc-text")
|
||||
expect(b_span).to_have_text(MANUAL_BRavo)
|
||||
expect(b_span).not_to_have_class("kb-summary-pending")
|
||||
|
||||
@@ -962,14 +962,14 @@ def test_missing_folder_summaries_read_as_pending_and_self_heal(
|
||||
expect(page.locator("#kb-level-title")).to_have_text(SOURCE)
|
||||
expect(page.locator("#kb-level-summary")).to_have_text(SUM_ROOT)
|
||||
rows = page.locator("#folders-tbody tr")
|
||||
expect(rows.nth(0).locator("td:nth-child(4) span")).to_have_text(SUM_ALPHA)
|
||||
expect(rows.nth(1).locator("td:nth-child(4) span")).to_have_text(MANUAL_BRavo)
|
||||
expect(rows.nth(0).locator("td:nth-child(4) span.kb-desc-text")).to_have_text(SUM_ALPHA)
|
||||
expect(rows.nth(1).locator("td:nth-child(4) span.kb-desc-text")).to_have_text(MANUAL_BRavo)
|
||||
expect(page.locator(".kb-summary-pending")).to_have_count(0)
|
||||
# And at the top level: the source row's cell carries the
|
||||
# regenerated root line, no marker.
|
||||
page.locator("#kb-crumb a.kb-crumb-link").nth(0).click()
|
||||
src_row = page.locator("#folders-tbody tr")
|
||||
s_span = src_row.locator("td:nth-child(4) span")
|
||||
s_span = src_row.locator("td:nth-child(4) span.kb-desc-text")
|
||||
expect(s_span).to_have_text(SUM_ROOT)
|
||||
expect(s_span).not_to_have_class("kb-summary-pending")
|
||||
expect(page.locator(".kb-summary-pending")).to_have_count(0)
|
||||
|
||||
Reference in New Issue
Block a user