Files
brain-of-reese/.agents/user_stories/document-back-navigation.md
T
ducoterra dbf2af26c6 refactor(agents): migrate .agent/ planning tree to .agents/
Standardize on the .agents/ directory (shared with project skills):
phases/, user_stories/, reports/, screenshots/, validate.sh, and
phase-sessions/ + pipeline.log all move to .agents/ (git mv preserves
history; runtime artifacts move alongside).

Updates every reference in AGENTS.md, README.md, .gitignore, app
docstrings, and test story headers. Historical KB content in data/
and the runtime pipeline.log transcript are left untouched.
2026-09-05 10:57:07 -04:00

42 lines
2.1 KiB
Markdown

# Story: Document Back Button Returns to Where You Came From
**Phase:** `13_document_back_navigation.md` · **E2E:** `tests/e2e/test_document_back_navigation.py`
## Narrative
As **a user**, when I open a document **from the chat tab** (a source
chip), the viewer's back button must take me **back to the chat** — not
to Sources. When I open it from Sources, it takes me to Sources.
Today every chip/link opens the viewer in a **new tab**, where there is
no browser history, so the fallback always lands on `/sources.html` —
which is wrong for chat-originated visits.
- **Given** I open a document from chat (chip) or from Sources (table)
- **When** I click the viewer's back button
- **Then** I land on the page I opened it from — Chat or Sources.
## Acceptance criteria
1. Chat source chips carry `&back=%2F` (chat) in the viewer URL; Sources
table links keep the default (no `back` param → `/sources.html`).
2. The viewer resolves the back target: `back` param wins when it is a
same-origin relative URL (starts with `/`, not `//`); anything else
(missing, absolute, protocol-relative, garbage) falls back to
`/sources.html`. The back link's **label** matches (Chat / Sources).
3. Clicking back navigates to the resolved target (deterministic — no
`history.length` heuristics).
4. Phase-10 viewer behavior and a11y frame unchanged.
5. Unit + integration green, `app/` coverage >90%, story E2E green in
isolation, one `--no-gpg-sign` commit.
## Playwright Mapping Rule
**Test Scenario → `tests/e2e/test_document_back_navigation.py`** (seeded KB):
1. `test_back_from_chat_returns_to_chat` — question → click source chip →
new tab at `/document.html?…&back=%2F` → back link href is `/` and
labeled "Chat" → click → URL is the chat page.
2. `test_back_from_sources_returns_to_sources` — Sources → click path
link → new tab (no `back` param) → back link href is `/sources.html`,
labeled "Sources" → click → URL is Sources.
3. `test_malicious_back_param_is_rejected` — `back=https%3A%2F%2Fevil.com`
and `back=%2F%2Fevil.com` → back link falls back to `/sources.html`.