feat(ui): clickable document viewer — open any cited document in the browser from chat chips and the sources table

This commit is contained in:
2026-08-22 02:08:49 -04:00
parent 7e8d14702e
commit 6ec6181c7b
15 changed files with 1218 additions and 58 deletions
+23 -6
View File
@@ -52,12 +52,16 @@ def test_suggestions_honors_bor_suggestions_env_override(monkeypatch) -> None:
@pytest.mark.parametrize(
("path", "marker"),
[("/", "Brain of Reese"), ("/sources.html", "Knowledge base")],
[
("/", "Brain of Reese"),
("/sources.html", "Knowledge base"),
("/document.html", "Brain of Reese"), # phase 10: viewer page
],
)
def test_html_pages_served_locally_no_cdn(client, path: str, marker: str) -> None:
"""No-CDN check (PLAN §7.3, re-verified on BOTH pages in phase 07):
each page is served by FastAPI and references only same-origin assets
(no https:// script/link tags)."""
"""No-CDN check (PLAN §7.3, re-verified on BOTH pages in phase 07 and
on the viewer page in phase 10): each page is served by FastAPI and
references only same-origin assets (no https:// script/link tags)."""
r = client.get(path)
assert r.status_code == 200
assert marker in r.text
@@ -68,6 +72,9 @@ def test_html_pages_served_locally_no_cdn(client, path: str, marker: str) -> Non
def test_styles_and_js_served(client) -> None:
assert client.get("/assets/styles.css").status_code == 200
assert client.get("/assets/app.js").status_code == 200
assert client.get("/assets/sources.js").status_code == 200
assert client.get("/assets/markdown.js").status_code == 200 # phase 10: shared renderer
assert client.get("/assets/document.js").status_code == 200 # phase 10: viewer page
# Emoji code points banned from UI chrome (phase 08): the pictograph
@@ -92,10 +99,20 @@ def _find_emoji(text: str) -> list[str]:
@pytest.mark.parametrize(
"path", ["/", "/sources.html", "/assets/app.js", "/assets/styles.css"]
"path",
[
"/",
"/sources.html",
"/document.html",
"/assets/app.js",
"/assets/sources.js",
"/assets/markdown.js",
"/assets/document.js",
"/assets/styles.css",
],
)
def test_ui_chrome_has_no_emoji(client, path: str) -> None:
"""Permanent regression guard (phase 08): the UI chrome — both pages,
"""Permanent regression guard (phase 08): the UI chrome — all pages,
the JS that renders it, and the stylesheet — is emoji-free."""
r = client.get(path)
assert r.status_code == 200