fix(ui): thinking window no longer scrolls — live 320px view pinned to the stream tail
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user