fix(ui): thinking window no longer scrolls — live 320px view pinned to the stream tail

This commit is contained in:
2026-08-24 20:28:12 -04:00
parent 986e704eb1
commit 22a6121411
3 changed files with 224 additions and 0 deletions
@@ -0,0 +1,55 @@
# Phase 21 — Thinking Window: No Scroll Back, Just Live
**Status:** Complete
**Date:** 2026-08-25
## Objective
Disable user scrolling in the Thinking window so it always shows the live tail
of the reasoning stream in a fixed 320px clip.
## What was implemented
### Task 01 — CSS change + unit pins (completed by prior agent)
- `frontend/assets/styles.css`: `details.thinking .thinking-text` changed from
`overflow-y: auto` to `overflow-y: hidden` (with owner-choice comment).
- `tests/unit/test_thinking_no_scroll.py`: source-level pins for CSS value,
comment, and JS bottom-pin integrity.
### Task 02 — E2E story suite, story file, validation, commit (completed this run)
- `tests/e2e/test_thinking_no_scroll.py` (5 tests):
1. `test_thinking_window_not_user_scrollable` — wheel/drag/keyboard on the
frozen live tail do not move the window.
2. `test_thinking_window_tracks_live_tail` — per-chunk pin keeps the window
glued to the tail; last chunk's text is inside the visible rectangle.
3. `test_thinking_window_css_contract` — computed `overflow-y` is `hidden`,
`max-height` is `320px`, clip is real.
4. `test_answer_bubble_still_scrollable` (regression, phase 11) — answer
bubble overflow is untouched, page scrolls normally.
5. `test_restored_collapsed_thinking_unaffected` (regression, phase 17) —
stored thinking restores collapsed with full text.
- `.agent/user_stories/thinking-no-scroll.md` — story file with bug report,
narrative, acceptance criteria, owner-confirmed decisions, and Playwright
mapping.
## Test / lint / coverage results
| Check | Command | Result |
|-------|---------|--------|
| E2E story suite | `uv run pytest tests/e2e/test_thinking_no_scroll.py -v --no-cov` | **5/5 passed** |
| Regression: thinking display | `uv run pytest tests/e2e/test_thinking_display.py -v --no-cov` | **5/5 passed** |
| Regression: long answers | `uv run pytest tests/e2e/test_long_answers.py -v --no-cov` | **2/2 passed** |
| Full suite | `uv run pytest --no-cov` | **319 passed** |
| Coverage | `uv run pytest --cov=app --cov-report=term-missing` | **99%** (gate: >90%) |
| Lint | `uv run ruff check .` | **All checks passed** |
| Types | `uv run pyright` | **0 errors** |
## Notable decisions
- No JS changes: the phase-17 bottom-pin (`textEl.scrollTop = textEl.scrollHeight`)
already works under `overflow-y: hidden`, so the CSS-only change is sufficient.
- The E2E tests use the mock's `think out loud then hesitate` trigger (phase 20)
to create a 4s frozen window where user scroll would be observable if regressed.
- The long thinking body (~2,700 chars, lengthened in phase 21) overflows the
320px window by ~2x, making the live-tail clip contract E2E-observable.
## Deviations
None. All changes follow LOCKED DECISIONS A11 (no CDN, pure CSS), A16 (one E2E
suite per story), and the owner-confirmed roadmap A2 decisions.