feat: scaffold Brain of Reese — FastAPI RAG chat over Postgres 17 + pgvector

Foundation (phase 01, verified):
- FastAPI app: /api/health, /api/suggestions, /api/chat (placeholder),
  static frontend served locally (no CDN)
- Postgres 17 + pgvector via db/Containerfile + compose.yaml
  (podman compose up -d db), Alembic initial migration (documents,
  chunks with vector(768), query_log)
- LLM client targeting https://aipi.reeseapps.com/v1 (turbo/embed);
  scripts/llm_probe.py verified models + 768-dim embeddings live
- Conditional debugpy: imported only when DEBUGPY=1 (attach on demand,
  :5678); logging config for clean single-line logs
- Frontend shell: mobile-first chat + Sources pages, tokens, a11y baselines
- Tests: 24 unit+integration (99% coverage on app/), ruff + pyright clean,
  Playwright smoke E2E (3 tests) against a deterministic mock LLM
- Planning: .agent/PLAN.md (architecture + LOCKED decisions), AGENTS.md,
  6 user stories, 7 phase files (one story / one phase / one Playwright
  suite each)
This commit is contained in:
2026-08-21 13:42:21 -04:00
commit 022da8e2bc
63 changed files with 5225 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
# Story: Responsive, Polished, Accessible UI
**Phase:** `07_story_responsive_polish.md` · **E2E:** `tests/e2e/test_responsive_polish.py`
## Narrative
As **a user on any device** — phone at the coffee shop, laptop at the
desk — I want the chat to be comfortable to read and drive: no pinched
layout, no tiny tap targets, no contrast failures, no wasted whitespace —
so asking Brain feels effortless everywhere.
- **Given** any viewport from 360px to 1600px+
- **When** I use the chat and the Sources page
- **Then** the layout follows the PLAN §7 standards (containers, chat
column, full-width table), all interactive elements are reachable by
keyboard, and every color pair meets WCAG 2.1 AA.
## Acceptance criteria
1. **Layout:** container 72rem centered with side padding; chat column
capped at 46rem centered; Sources table uses full container width with
horizontal scroll below 640px (never a squeezed single hairline column).
2. **Mobile (375px):** header condenses, composer reachable above the home
indicator (`safe-area-inset-bottom`), chips scroll horizontally, bubbles
≤92% width, no horizontal page overflow (document `scrollWidth ==
clientWidth`).
3. **A11y sweep:** landmarks present on both pages (`header/nav/main/
footer`); skip link works (focus `#main`); all inputs have labels
(visible or programmatically associated); all icon-only buttons have
`aria-label`; `:focus-visible` outline on every control (Tab through).
4. **Contrast:** automated check of the key pairs (ink/surface,
ink-soft/surface, white/brand, chip-ink/chip-bg, deflection pairs) ≥4.5:1
(test computes from computed styles; PLAN §7.2 table is the baseline).
5. **No-CDN re-verification** on both pages (no `http(s)://` src/href
except same-origin `/…`).
6. **Reduced motion:** with `prefers-reduced-motion`, typing dots and
spinner do not animate (computed `animation: none` or duration ≥2s).
7. Long words/paths (e.g. a 60-char file path) wrap or ellipsize without
breaking the bubble (overflow-wrap anywhere).
## UI Visualization & Structure
- This phase is the **visual audit + fix pass**: it does not add features,
it enforces PLAN §7 end-to-end on chat + sources.
- Desktop 1440px screenshot pass: header 64px, chat centered with balanced
margins, sources table edge-to-edge within the container.
- Tablet 768px: chat column uses most of the width (≤46rem cap), no
mid-column dead zones; stat cards 3-across.
- Phone 375px: one-column flow, 44px+ targets, thumb-zone composer.
- Any deviation found → fix in `frontend/assets/styles.css` (tokens first),
re-verify with the E2E below.
## Playwright Mapping Rule
**Test Scenario → `tests/e2e/test_responsive_polish.py`**:
1. `test_no_horizontal_overflow_at_viewports` — for 360/375/768/1280/1600:
`document.documentElement.scrollWidth <= clientWidth` on both pages.
2. `test_chat_column_capped_and_centered` — at 1600px, `.chat-shell`
width ≤ 46rem (736px) + 2% and horizontally centered (±2%).
3. `test_sources_table_full_width` — at 1280px, `.table-wrap` width ≥ 80%
of `.container` width.
4. `test_a11y_landmarks_and_labels` — both pages: landmarks present,
skip link target `#main` focusable, `#message-input` has an associated
label, no `<img>`/icon buttons without accessible name.
5. `test_contrast_pairs_pass_aa` — computed-color contrast assertions for
the PLAN §7.2 pairs (helper computes WCAG relative luminance).
6. `test_reduced_motion_respected` — emulate `reducedMotion: 'reduce'`;
typing dots have no running animation (or ≥2s duration).