Files
brain-of-reese/.agent/phases/complete/44_markdown_tables/00_phase.md
T
ducoterra 4971e2859d
Build and Push Containers / build-and-push-app (push) Successful in 12s
Build and Push Containers / build-and-push-db (push) Successful in 10s
chore(agent): track .agent/ planning tree in git
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.
2026-09-01 10:18:22 -04:00

3.5 KiB
Raw Blame History

Phase 44 — Markdown tables (chat, viewer, thinking)

Source: TODO.md L6 — "Certain markdown formatting isn't working - tables for example don't get rendered as tables in the chat response." Story: .agent/user_stories/markdown-tables.md Context: frontend/assets/markdown.js is the shared escape-first renderer (no libs, A11): fence protection → escape → inline transforms (code, **bold**, *em*, h1–h3, lists) → paragraph pass → fence restore. It has no table support — GFM pipe tables render as one raw |-littered paragraph. The renderer serves the chat answer, the document viewer/modal, and the thinking block, so one change covers all three.

Objective

GFM pipe tables render as semantic, styled, XSS-safe <table> elements everywhere the shared renderer runs, with a horizontal-overflow guard for wide tables.

Dependencies

  • 43_thinking_scroll_back (todo) — sequential only (the thinking block also renders markdown; no shared-file conflict beyond the renderer itself).
  • 08_story_dark_tech_theme (complete) — the palette tokens .md-table must use.
  • 26_document_modal_viewer / 10_story_document_viewer (complete) — the second renderer consumer (viewer/modal).

Tasks

  1. 01_table_renderer_and_styles.md — table pass in markdown.js + .md-table CSS.
  2. 02_mock_table_trigger.md — deterministic table answer (incl. a wide table) in mock_llm.py.
  3. 03_tables_e2e_and_commit.md — unit pins + story E2E suite + regressions + commit.

Testing & Quality

  • Unit: new tests/unit/test_markdown_tables.py — source pins in the house style (regex over markdown.js / styles.css): the table-protection pass exists and runs after the fence pass and before the escape pass; cells are escaped + inline-transformed; output carries class="md-table", <thead>, th scope="col", and the .md-table-wrap wrapper; styles.css has the wrapper overflow rule + table borders + reduced-motion-relevant rules. (Behavior is browser-proven by the E2E; unit pins catch silent regressions without a browser — the established frontend pattern.)
  • Coverage: frontend-only — app/ TOTAL unchanged, >90%.
  • E2E (mandatory, A16): tests/e2e/test_markdown_tables.py, run in isolation.

Completion Criteria

  • A pipe table in a chat answer renders <div class="md-table-wrap"><table class="md-table"> with <thead>/<tbody>, <th scope="col"> headers, correct cell texts; no raw |---| in the bubble.
  • A wide table scrolls inside its wrapper; the 46rem column does not overflow the page.
  • XSS-safe (escaped cells), fences win over tables, lone pipes stay text.
  • The document viewer/modal renders the same table for a fixture document containing one.
  • uv run pytest green; coverage TOTAL unchanged.
  • uv run pytest tests/e2e/test_markdown_tables.py -v --no-cov green in isolation (DB up).
  • Regression E2E suites green in isolation: test_chat_rag.py, test_document_viewer.py, test_document_summaries.py, test_smoke.py.
  • uv run ruff check . && uv run pyright clean.
  • One --no-gpg-sign commit; phase dir moved to .agent/phases/complete/.

Locked decisions

  • A11 untouched — still the local ~90-line renderer, no library, no CDN.
  • Owner-locked (2026-08-27, roadmap A3): scope = GFM pipe tables (header + separator + body); links/blockquotes/hr out of scope; alignment colons parsed but rendered left; wide tables get the overflow-x: auto wrapper.
  • A16/A17 honoured — one story E2E suite, one atomic commit.