Files
brain-of-reese/.agent/phases/complete/36_summary_in_viewer/00_phase.md
T
ducoterra 02c76ad328 chore(agent): phase roadmap from TODO.md — 8 phases (40–47), 24 tasks
Converts the 9 TODO items into an executable phase roadmap (Protocol B,
appended after phase 39):

- 40 tuning toggle anonymous flash (TODO L3)
- 41 sync fail-fast + modal when a model is down (TODO L4)
- 42 no reply autoscroll (TODO L5)
- 43 thinking scroll back — user scroll + gated autoscroll (TODO L7)
- 44 markdown tables (TODO L6)
- 45 agent unlimited tool calls behind BOR_AGENT_MAX_ROUNDS (TODO L8)
- 46 mobile hamburger nav (TODO L9)
- 47 quadlet + jinja import formats, A9 revision (TODO L10–L11)

Each phase carries a user story, a dedicated Playwright E2E suite plan,
and owner-locked decisions (R1 A9 format extension, R2 phase-37 budget
revision, A1–A5 scope decisions) confirmed 2026-08-27.

Also records the completed phases 30–39 todo/ -> complete/ moves that
were pending in the working tree. TODO.md is cleared (items now live in
.agent/phases/todo/).
2026-08-27 18:25:53 -04:00

4.0 KiB

Phase 36 — Document Summary Shown Together With the Original

Source: TODO.md L5 — "When I click on a document with a summary I should be able to see the summary and the original document together." Story: .agent/user_stories/summary-in-viewer.md Context: Phase 30 stores a lite-model summary on documents.summary for every non-markdown document (plus an indexed is_summary chunk) — but the viewer never shows it: GET /api/documents/content omits the field and the shared renderer renderDocument (frontend/assets/document.js, used by BOTH the full-page viewer document.html and the chat/sources modal, phase 26) only renders the raw content. Markdown documents carry no summary (phase 30) and must render exactly as before.

Objective

When a document has a summary, show it and the original content together — a labeled Summary panel above the content, on both viewer surfaces at once (shared renderer); documents without a summary are unchanged.

Dependencies

  • 30_document_summaries (complete) — the documents.summary column (migration 0004), the summarizer, the summary_kb E2E fixture + the deterministic mock SUMMARY_MODE digest.
  • 10_story_document_viewer + 26_document_modal_viewer (complete) — the viewer page, the modal, and the shared renderDocument(doc, {titleEl, metaEl, contentEl}) core both surfaces render through.
  • 16_admin_auth (complete) — the soft rule this phase must not touch: the content endpoint stays public + stateless (catalog gated, viewer public).

Tasks

  1. 01_content_api_summary_field.md — DocContent.summary + the endpoint returns it; integration tests.
  2. 02_viewer_summary_panel.md — the shared renderer draws the .doc-summary panel (both surfaces) + theme-matched styles.
  3. 03_e2e_and_regression.md — the story E2E suite test_summary_in_viewer.py; regressions; full gate; commit.

Testing & Quality

  • Unit/integration: the content endpoint returns the summary for a summarized non-markdown doc and null for a markdown doc; anonymous access unchanged.
  • Coverage: >90% on app/ (the touched endpoint stays covered).
  • E2E (mandatory, A16): tests/e2e/test_summary_in_viewer.py — the story gate, run in isolation.

Completion Criteria

  • GET /api/documents/content returns summary (string or null); no auth/shape change beyond the added nullable field; the endpoint is still public.
  • A summarized document shows the labeled Summary panel above the original content in the full-page viewer AND the modal; the original content (including content the summary digest doesn't contain) is fully visible.
  • A markdown document (no summary) renders exactly as before on both surfaces — no empty panel.
  • uv run pytest green; uv run pytest --cov=app --cov-report=term-missing >90%; uv run pytest tests/e2e/test_summary_in_viewer.py -v --no-cov green in isolation; regressions (task 03 list) green.
  • uv run ruff check . && uv run pyright clean.
  • UI Structure Check (AGENTS.md rule 5): the panel is a labeled section, contrast ≥4.5:1, no CDN (rule 6).
  • One --no-gpg-sign commit; phase directory moved to .agent/phases/complete/.

Locked decisions

  • A7 / A15 untouched — retrieval, context assembly, and the SSE contract are unchanged; this is a display + API-field phase.
  • Phase 16 soft rule untouched — GET /api/documents/content stays public + stateless (anyone who can open a document sees its summary; the catalog stays admin-gated).
  • Phase 30 untouched — summaries are still generated at import, still markdown-excluded, still fail-soft (NULL possible); this phase only surfaces the existing field.
  • Shared-renderer principle (phase 26) — the panel is drawn in renderDocument, so the page and the modal can never drift.
  • A11 untouched — vanilla HTML/CSS/JS, no CDN, no new packages; summary text rendered with textContent (XSS contract unchanged).
  • A16 / A17 honoured — one new story E2E suite + one atomic --no-gpg-sign commit.