phase: 156_table_ux_polish
Everything is verified. All gates green on the current working tree. Final report: **Phase 156 — final verification pass (all 4 task files present in `complete/` — no outstanding work)** - **Verified (not re-implemented):** bounded-panel `.table-wrap` (`max-height: min(70vh, 64rem)`, `overflow: auto`, opaque sticky `th` via `var(--brand-soft)`), `.cell-clip` ellipsis rule + the five label families in the three renderers, the added aria-labels, unit pins (incl. `.md-table-wrap` byte-unchanged scope guard, `#git-sources-table-wrap` harmony — no divergent rule), dedicated E2E suite (sticky ×3 tables, horizontal contract, computed-style ellipsis + reachable full text, mobile hamburger + scroll + pin) - **Tests/lint/coverage:** `uv run pytest --cov=app --cov-report=term-missing` → **3570 passed, 99% on `app/`** (gate >90%); `uv run pytest tests/e2e/test_table_ux_polish.py -v --no-cov` (DB up) → **6/6 passed in isolation**; `uv run ruff check . && uv run pyright` → **clean** (0 errors) - **Completion criteria:** sticky header all 3 tables (exact-0 offset while `scrollTop > 0`) ✅ · horizontal scroll unchanged ✅ · ellipsis computed style + actual clip + title/aria reachable ✅ · mobile ≤640px contract ✅ · full suite/E2E/lint/coverage ✅ · atomic commit: **harness commits this phase after the pass** (per pipeline protocol — no git history commands run by me) - **Documentation:** AGENTS.md phase-156 wording (bounded panels, sticky headers, `.cell-clip` + aria-label idiom) matches the implementation exactly — verified consistent; README.md reviewed in full (pages/URLs vs registered routes, all `.env.example` vars documented, Quick Start, eval/llm scripts, compose prod profile, E2E examples) — verified consistent, no changes needed (README describes no table layout/scroll, so no phase-156 mention required) - **Deviations:** none — all work was already in the working tree; this pass re-verified every gate and the docs - **Next pending phase:** `157_chat_chip_cap`
This commit is contained in:
@@ -34,6 +34,15 @@ This module pins the source-level contract (the house pattern of
|
||||
``tests/unit/test_hamburger_nav.py``: read ``styles.css`` as text, no
|
||||
browser) so the regression that omitted the containing block cannot
|
||||
return.
|
||||
|
||||
Phase 156 (task 01) superseded two of these pins: the card's
|
||||
``overflow-x: auto`` became ``overflow: auto`` (both axes — the
|
||||
tables' min-width still triggers the in-card horizontal scroll) plus
|
||||
the bounded-panel ``max-height: min(70vh, 64rem)`` (owner-locked A1:
|
||||
the card is the vertical scroll region the sticky ``th`` pins to),
|
||||
and the ``#git-sources-table-wrap`` id override was harmonized into
|
||||
the base ``.table-wrap`` (the wrapper carries ``class="table-wrap"`,
|
||||
so its duplicate declarations were removed — one-rule contract).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -90,26 +99,40 @@ def test_table_wrap_is_a_positioned_containing_block() -> None:
|
||||
|
||||
|
||||
def test_table_wrap_keeps_the_horizontal_scroll_contract() -> None:
|
||||
"""The fix preserves the phase-07 scroll contract: the card keeps
|
||||
overflow-x:auto — at any viewport narrower than the tables' 640px
|
||||
min-width the table scrolls INSIDE the card (AGENTS.md rule 5:
|
||||
full-width tables stay) while the document itself no longer pans."""
|
||||
"""Phase 156 (task 01) supersedes the phase-86 overflow-x pin:
|
||||
the card carries overflow:auto (BOTH axes — at any viewport
|
||||
narrower than the tables' min-width the table still scrolls
|
||||
INSIDE the card, AGENTS.md rule 5: full-width tables stay) plus
|
||||
the bounded-panel max-height: min(70vh, 64rem) (owner-locked A1:
|
||||
the card is the vertical scroll region — a 15-row table scrolls,
|
||||
a 3-row one fits without a scrollbar) so the sticky th pins to
|
||||
the card instead of scrolling away with the page."""
|
||||
block = _rule_block(_css(), ".table-wrap")
|
||||
assert "overflow-x: auto" in block, (
|
||||
"the .table-wrap card must keep overflow-x:auto (the in-card "
|
||||
"scroll the fix protects)"
|
||||
assert "overflow: auto" in block, (
|
||||
"the .table-wrap card must carry overflow: auto (both axes — "
|
||||
"the in-card horizontal scroll + the bounded vertical scroll)"
|
||||
)
|
||||
assert "max-height: min(70vh, 64rem)" in block, (
|
||||
"the .table-wrap card must be bounded: max-height: "
|
||||
"min(70vh, 64rem) (the A1 bounded-panel design)"
|
||||
)
|
||||
|
||||
|
||||
def test_the_fix_touched_only_the_shared_card() -> None:
|
||||
"""The one-rule scope (A3): the fix lives on .table-wrap ONLY —
|
||||
.md-table-wrap (chat answer tables — different class, different
|
||||
context) and the #git-sources-table-wrap id card keep their
|
||||
pre-phase-86 rules (no position declaration acquired)."""
|
||||
"""The one-rule scope (A3, harmonized by phase 156 task 01): the
|
||||
positioning fix lives on .table-wrap ONLY — .md-table-wrap (chat
|
||||
answer tables — different class, different context) keeps its
|
||||
pre-phase-86 rules (no position declaration), and the
|
||||
#git-sources-table-wrap id override is GONE: the wrapper carries
|
||||
class="table-wrap" and inherits the base card, so a divergent
|
||||
unbounded id rule cannot return."""
|
||||
css = _css()
|
||||
for sel in (".md-table-wrap", "#git-sources-table-wrap"):
|
||||
block = _rule_block(css, sel)
|
||||
assert not re.search(r"position\s*:", block), (
|
||||
f"{sel} must not acquire a position declaration (the fix is "
|
||||
"the ONE .table-wrap rule)"
|
||||
)
|
||||
block = _rule_block(css, ".md-table-wrap")
|
||||
assert not re.search(r"position\s*:", block), (
|
||||
".md-table-wrap must not acquire a position declaration (the "
|
||||
"fix is the ONE .table-wrap rule)"
|
||||
)
|
||||
assert not re.search(r"(?<![\w-])#git-sources-table-wrap\s*\{", css), (
|
||||
"the #git-sources-table-wrap id override must be harmonized "
|
||||
"into the base .table-wrap (phase 156 — no divergent rule)"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user