**Phase 100 — final verification pass: all green.** - Verified the shipped CSS contract directly: `--chat-column: 72rem` in `:root`; 0 literal `max-width: 46rem`; no `@media (min-width: 1500px)` block; exactly 4 token-capped reading columns; tuning/theme/doc-edit shells cap-free, structurally `.sources-shell`; `mock_llm.py` diff is comment-only. - Defect found & fixed (phase-93 suite): `test_theme_semantic_completion.py::test_reset_removes_tag_byte_identical` raced theme.js's post-PUT refetch — it asserted the `#bor-theme` tag was gone right after the result line, but tag removal lands in the reconcile after the re-fetch (failed ~1 in 5 runs after `test_chat_rag`, reproduced). Fixed with an auto-waiting `expect(...).to_have_count(0)` (settled-state wait, the file's existing house pattern). 6/6 clean on the repro loop after. - Tests/lint/coverage: `uv run pytest --cov=app --cov-report=term-missing` → 2052 passed, **99%** on `app/`; `uv run ruff check .` + `uv run pyright` → 0 errors. - E2E in isolation (all passed): `test_wide_desktop_column.py` 3 (the phase suite — chat==tuning==theme==RAG ±4px at 1280 & 1920, ≈1152px; shared ≈1152px; standalone doc ≈1112px; modal unchanged ≈1100px; 360px overflow-free), `test_ui_customization` 4, `test_admin_theme_tab` 5, `test_document_viewer` 7, `test_save_share_ux` 5, `test_sticky_navbar` 3, `test_markdown_tables` 6, `test_responsive_polish` 7, `test_chat_rag` 3, `test_theme_semantic_completion` 8. - Completion criteria: ① measured 72rem everywhere (≥~1200px, ±4px) + full-width below + 360px clean — **PASS** (E2E); ② zero 46rem rules / no 1500px block / four token selectors — **PASS** (grep + unit pins); ③ B4 byte-identical no-op + mobile squeeze — **PASS** (theme + responsive suites green); ④ full suite / coverage / lint — **PASS**; ⑤ atomic commit — left to the harness per executor protocol (all changes in the working tree, uncommitted). - Deviations: none from phase decisions; only change in this pass is the race fix above (test-only, behavior unchanged). - Next pending phase: `98_sync_summary_visibility` (numeric order in `todo/`; also pending: 99, 101–105).
7.5 KiB
Phase 100 — Every page matches the RAG page's width (the 72rem container, at every viewport)
Source: Owner request (chat, 2026-09-12) — "The theme, tuning, and chat pages are still pretty narrow, I want you to match the width of the RAG page for all other pages to keep things consistent."
Story: n/a (owner request — supersedes the PLAN §7.1 "centered 46rem chat column (2× = 92rem at ≥1500px)" rule and the phase-58/27/91 form-column caps; the width lineage: 58_wide_desktop_column, 86_history_page_width).
Context: frontend/assets/styles.css: .container is the shared 72rem centered column (width: 100%; max-width: 72rem; padding-inline: 1.25rem;). The RAG view's .sources-shell (and .git-sources-shell / .history-shell / .tokens-shell) carry NO max-width — their content is the full 72rem container: that is the width the owner wants everywhere. The narrow pages: :root { --chat-column: 46rem; } caps .chat-shell (the chat view — the div IS .container.chat-shell, the later rule overriding the 72rem cap), .shared-shell (shared.html), .doc-md (the document viewer's reading column) and .doc-summary:has(+ .doc-md) (exactly four selectors use the token); @media (min-width: 1500px) { :root { --chat-column: 92rem; } .doc-shell { max-width: calc(var(--chat-column) + 2 * 1.25rem); } } (phase 58 — the wide-desktop doubling + the standalone document page's cap lift); and three hard-coded max-width: 46rem form columns: .tuning-shell, .theme-shell (phase 91), .doc-edit-shell (phase 59). Width pins live in: tests/unit/test_wide_column_css.py (the phase-58 contract file — 46rem base, the 92rem media block, the four-token count, the three-hard-coded-46rem negative pin, the provenance comments), tests/unit/test_markdown_tables.py, test_shared_page.py, test_pinned_composer.py, test_doc_edit_screen.py, test_remove_confirm_modal.py, test_source_ignore_paths.py (grep 46rem|92rem|chat-column under tests/ for the authoritative list — some hits are fixture text, judge per pin), and E2E measured-width suites: tests/e2e/test_wide_desktop_column.py (the measured 1472px/736px contract), test_document_viewer.py, test_save_share_ux.py, test_sticky_navbar.py, test_markdown_tables.py, test_responsive_polish.py (mobile no-overflow).
Objective
Every view and page renders its content at the RAG page's width — the full 72rem container at every viewport (centered, with the container's 1.25rem gutters): the chat column, the Tuning and Theme form columns, the doc-edit screen, the shared page, and the document viewer all widen to 72rem; the phase-58 ≥1500px 92rem doubling and the 46rem form caps are retired; the mobile (≤640px) and tablet layouts are unchanged (everything was already full-width below the caps).
Dependencies
86_history_page_width/58_wide_desktop_column(complete) — the width lineage being revised (their suites are updated IN THIS PHASE, the phase-97 task-07/08 precedent — asserted behavior preserved, only the width contract changes).- No code dependencies beyond
frontend/assets/styles.css(CSS-only —app/,frontend/*.html, and every JS module are untouched).
Decisions recorded here (owner instruction 2026-09-12 — PLAN.md is being redone by the owner)
- D1 — one width for everything: the reading/form columns ALL ride the 72rem container.
:root { --chat-column: 72rem; }(the token stays — the four reading-column selectors keepmax-width: var(--chat-column), so.doc-md/.shared-shell/.chat-shell/the doc-summary panel follow automatically); the@media (min-width: 1500px)block is DELETED entirely (the 92rem doubling AND the.doc-shellcap lift — with the token at 72rem the standalone document page's.container.doc-shellsimply keeps the 72rem cap); the three hard-codedmax-width: 46remcaps (.tuning-shell,.theme-shell,.doc-edit-shell) are REMOVED (plus theirmargin-inline: autocentering — the.containerancestor centers; the shells keep their flex-column + gap rules, matching.sources-shellexactly). Net effect: ZERO literalmax-width: 46remrules remain in the file (the negative pin flips). This SUPERSEDES PLAN §7.1's 46rem/92rem rule and the phase-58 owner instruction of 2026-08-31 (recorded here per the phase-94/96/97 convention — the owner's new instruction wins; the PLAN.md anchor table gets the owner's sign-off separately). - D2 — the document viewer's modal is untouched: the same-page doc modal's 1100px panel stays its effective ceiling (
.doc-mdat 72rem is wider than the panel's inner width, so the panel binds — no panel resize, no modal change). The standalonedocument.htmlpage rides the 72rem container like every other page. - D3 — CSS-only, contracts intact: no HTML change (the B4 byte-identical theme contract is unaffected — the served HTML is unchanged; only
styles.cssbytes change), no JS change, no endpoint change; A19's?v=<deploy-token>versioning busts the old CSS automatically. The≤640pxmobile block is UNCHANGED (at 360px the container is already 100% — the caps never bound there; the mobile squeeze rules for chat/shared/tokens/theme keep working). - D4 — the comment sweep: every stale "46rem base, 92rem at >=1500px" / "46rem column contract" / phase-58-provenance comment in
styles.cssis updated to the new contract (the owner instruction 2026-09-12 as provenance at the token + the note that the wide-desktop doubling was retired) — the house rule that comments carry the contract (andtest_wide_column_css.pypins the comment states).
Tasks
01_width_css.md— the CSS change: the token to 72rem, the media block deleted, the three form caps removed, the comment sweep02_width_unit_pins.md— the unit pin updates:test_wide_column_css.pyrewritten to the new contract + the grep-sweep of the other unit files03_e2e_width_sweep.md—test_wide_desktop_column.pyrewritten to the measured 72rem contract + the other E2E width pins + the regression sweep + the atomic commit
Testing & Quality
- Unit:
tests/unit/test_wide_column_css.pyREWRITTEN to the new contract (the pins below); every other unit file whose pins reference the old widths updated (the grep sweep —46rem|92rem|chat-columnundertests/unit/, judged per pin: a width assertion updates, fixture text does not). - E2E (mandatory, A16):
uv run pytest tests/e2e/test_wide_desktop_column.py -v --no-covin isolation — the phase's dedicated width suite, REWRITTEN to the measured 72rem contract (the phase-97 task-07/08 precedent for updating a completed phase's suite when its contract changes); the other measured-width suites updated in place. - Coverage: >90% on
app/(untouched — the full-suite gate still runs). - Lint/types:
uv run ruff check . && uv run pyright.
Completion Criteria
- at any viewport ≥ ~1200px, the chat, shared, document-viewer, Tuning, Theme, and doc-edit content columns measure the 72rem container width (E2E-measured, ±4 px) — identical to the RAG page's; below that, everything is full-width as today; 360px has no horizontal overflow
styles.csshas ZERO literalmax-width: 46remrules and NO@media (min-width: 1500px)block; the four reading-column selectors still cap withvar(--chat-column)(now 72rem)- the B4 byte-identical theme contract holds (no HTML change — the theme no-op test suite green); the mobile squeeze layouts green
uv run pytestgreen; coverage >90%; ruff + pyright clean- one atomic Conventional Commit,
--no-gpg-sign(e.g.feat(ui): match every page to the RAG page's 72rem width)