Remove the blanket .agent/ gitignore so the phase roadmap, user stories, reports, and PLAN.md are versioned with the code. Only runtime artifacts (.agent/phase-sessions/, .agent/pipeline.log) remain ignored. Update AGENTS.md git protocol rule to match.
3.3 KiB
3.3 KiB
Story: Clickable Document Viewer
Phase: 10_story_document_viewer.md · E2E: tests/e2e/test_document_viewer.py
Narrative
As a user, I want to click any document Brain cites (the source chips under an answer) or any row in the Sources table and have the actual document open in the browser — in whatever format it is — so I can read the full context and verify the answer against my real notes.
- Given an answer with source chips (
Homelab/active/container_gitlab/ gitlab.md) or the Sources page table - When I click a chip or a path
- Then a new tab opens the viewer: title, source/format/path meta, and the full content — markdown rendered with the existing local escape-first renderer, other formats as escaped monospace text.
Acceptance criteria
GET /api/documents/content?source=…&path=…→ 200{source, path, title, format, content, indexed_at, chunks}; 404{detail}when the pair is not indexed. Served from the database only — no filesystem access, hence no path-traversal surface.GET /document.html?source=…&path=…renders the document: back link, title, meta row (source, format badge, mono path, indexed date, chunk count), content — md via the shared local renderer; other formats as escaped<pre>(mono, horizontal scroll).- Chat source chips link to the viewer in a new tab
(
target="_blank" rel="noopener"), accessible name intact. - Sources table: the path cell is a link to the viewer (new tab).
- XSS-safe: document content is never injected as raw HTML (renderer escapes first; raw formats use text nodes).
- The viewer inherits the dark tech theme; the no-CDN invariant is
extended to
/document.html; landmarks/labels/aria-liveon the new page. - Missing doc → designed not-found state with a link to the Sources page.
- Unit + integration green,
app/coverage >90%, story E2E green in isolation, one--no-gpg-signcommit.
UI Visualization & Structure
- Viewer page: sticky header (back link + title + meta badges) +
<main>: markdown column centered at ≤46rem; raw content in a full-widthprewithoverflow-x: auto. Dark tokens from Phase 08. - Chips/links: source chips keep the mono pill; path links get
hover/focus underline;
:focus-visiblering; ≥44px touch targets on mobile. - Not-found state: centered card (no emoji — SVG or plain text), message + "Open Sources" link.
Playwright Mapping Rule
Test Scenario → tests/e2e/test_document_viewer.py (mock LLM, seeded KB):
test_source_chip_opens_document— on-topic question → click the.source-chip→ a new tab at/document.html?…shows the fixture doc's title + a known content string + the format badge.test_sources_row_links_to_viewer—/sources.html→ click a path link for a.yamlfixture → viewer shows its raw content in apre.test_markdown_renders_and_stays_xss_safe— an md fixture containing<script>alert(1)</script>renders as visible escaped text (no execution).test_missing_doc_shows_not_found— unknown path → not-found state + Sources link; no console crash.test_viewer_theme_and_no_cdn— dark background + everyscript[src]/link[href]local ordata:.