**Phase 13 complete** — committed as `2485b50`, tree clean. **Implemented** - Chat source chips carry `&back=%2F`: `documentUrl(source, path, back = "/")` in `frontend/assets/app.js` (percent-encoded). - Viewer (`frontend/assets/document.js`): back target resolved from the `back` param — honored only for same-origin relative URLs (starts with `/`, not `//`); `https://`, `//`, `javascript:` etc. fall back to `/sources.html`. Label set to Chat / Sources / Back. Dropped the `history.length` heuristic entirely — with `href` set, the anchor's default click IS the deterministic navigation; static `href="/sources.html"` no-JS fallback untouched. - Sources links unchanged (no `back` param → default `/sources.html`). - New E2E `tests/e2e/test_document_back_navigation.py` (3 tests per story mapping, incl. malicious-param rejection); updated stale contract pins: phase-10 E2E chip href, phase-03 `test_chat_rag.py` href, and phase-10 unit pins in `tests/unit/test_document_viewer.py` (re-pinned to the new builder/resolution contract, plus a node behavioral check for `back` encoding). **Verification (all green)** - `uv run pytest tests/e2e/test_document_back_navigation.py -v --no-cov` → 3 passed - `uv run pytest tests/e2e/test_document_viewer.py -v --no-cov` → 5 passed - `uv run pytest --cov=app --cov-report=term` → 203 passed, `app/` coverage **99%** (>90%) - `uv run ruff check .` → clean; `uv run pyright` → 0 errors - Full E2E regression sweep (`uv run pytest tests/e2e --no-cov`) → 51 passed **Decisions**: removed the click listener rather than forcing `location.assign` (cleaner, same determinism); a pyright complaint in the new E2E was fixed by using the phase-10 named dialog-handler pattern. **Next pending phase**: `.agent/phases/todo/14_chat_persistence.md`