phase: 153_document_viewer_context
Build and Push Containers / build-and-push-app (push) Successful in 2m45s
Build and Push Containers / build-and-push-db (push) Successful in 19s

That last `--co` (collect-only) run was my probe mistake — it shows 34% because no tests execute under collect-only. The valid coverage run was the real gate command executed earlier: `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (exit 0, all 3544 tests executed). All gates are verified.

## Phase 153 — final verification pass report

**Verified (all tasks 01–04 complete in `complete/`):**
- Modal `fullPageUrl(source, path, back = null)` + `openDocumentModal(…, back = null)` with module-level `currentBack`; 5 chat call sites pass `"/"`, sources.js call site unchanged (byte-identical Sources path); `documentUrl` comment now true
- Copy-path control (shared `renderDocument` core, icon+text, text = accessible name) on both surfaces; per-page clipboard helpers with the fallback-field + status-line contract; `#doc-copy-announcer` live region; styles + 44px touch floor
- Unit pins: `&back=%2F` / no-`back` byte-identity, `currentBack` single-writer guard, copy strings byte-pinned, phase-13 regression pins untouched

**Test / lint / coverage results:**
- `uv run pytest` → **3544 passed**, 0 failed (full unit + integration)
- `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (>90% gate)
- `uv run pytest tests/e2e/test_document_viewer_context.py -v --no-cov` → **8 passed** in 47.33s, in isolation (DB up, mock LLM)
- `uv run ruff check . && uv run pyright` → clean (0 errors/warnings)

**Completion criteria:** all met — (1) chat→modal→Full page: `href="/"` + "Chat"; Sources→modal→Full page: `href="/sources.html"` + "Sources" with `back=` asserted absent; (2) no-`back` URLs byte-identical to pre-phase; (3) Copy path: "Path copied." on success (clipboard readback), prefilled select-on-focus fallback field + "Path ready — copy it from the field." on rejected clipboard, both surfaces parameterized; (4) copied string exactly `docs/homelab/kubernetes.md`; (5) full suite green, E2E isolated green, lint clean, coverage 99%; (6) commit by harness.

**Documentation:** README.md reviewed in full — phase-153 feature already named in the Chat section; routes, env reference, workflows, deployment all consistent — no changes needed. AGENTS.md reviewed in full — rules, gates, and quick-reference commands verified against the repo (incl. `test_smoke.py`, `.env.example`, gitignore entries) — consistent, no changes needed.

**Notable:** pytest 9.1.1 quirk — a doubled `-q` (pyproject `addopts` + explicit `-q`) swallows the final "N passed" summary line while still exiting 0; the plain `uv run pytest` gate command prints it. No defects found in prior work.

**Next pending phase:** `154_sync_status_freshness`.
This commit is contained in:
2026-10-04 09:23:54 -04:00
parent 12fa69b7ea
commit 966c4b0540
59 changed files with 4304 additions and 34 deletions
+90
View File
@@ -4461,6 +4461,95 @@ a.answer-image:hover { text-decoration: underline; } /* flat — the caption und
text-decoration: none;
}
.doc-origin:hover, .doc-origin:focus-visible { text-decoration: underline; }
/* Phase 153 (task 02): the meta row's "Copy path" control — the
row-action language (icon + label, the .git-source-remove idiom)
in a NEUTRAL secondary fill (the .git-source-ignore hover pair —
brand-soft, 12.4:1 on --surface; the meta row's text sits on the
titlebar's --surface). Compact on desktop (the meta row's 0.78rem
scale — a 44px floor would grow the bar); the ≤640px block gives
it the ≥44px touch-target floor (PLAN §7.1). The VISIBLE "Copy
path" text is the accessible name (no aria-label); the icon is
aria-hidden. */
.doc-copy-path {
display: inline-flex;
align-items: center;
gap: 0.3rem;
padding: 0.12rem 0.5rem;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
background: transparent;
color: var(--ink-soft); /* 5.1:1 on --surface (the meta row's pair) */
font: inherit;
font-weight: 600;
font-size: 0.78rem;
white-space: nowrap;
cursor: pointer;
}
.doc-copy-path svg { width: 13px; height: 13px; display: block; flex: 0 0 auto; }
.doc-copy-path:hover { background: var(--brand-soft); color: var(--brand-ink); }
.doc-copy-path:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }
/* Phase 153 (task 02): the Copy-path status line — the VISIBLE
confirmation (aria-hidden — the surface's role=status live region
is the a11y announcer, the share pattern): the meta row's text
scale, var(--ink-soft) on --surface (5.1:1 — the pair recorded at
:root). Serves BOTH surfaces: the page's floating block and the
modal's wrapping meta block. */
.doc-copy-status {
margin: 0;
font-size: 0.78rem;
color: var(--ink-soft); /* 5.1:1 on --surface */
}
/* Phase 153 (task 02): the /document.html page's Copy-path state
block — a floating panel anchored under the control (absolutely
positioned in the header — the meta row must never wrap or grow
the bar, the phase-12/34 contract, so the state floats OUT of
the row). Surface fill, --line border, the standard shadow;
wraps (the field + the status may share a row or take separate
rows at narrow widths). z-index 30 sits inside the header's own
z-20 root context, so the block floats above the page content. */
.doc-copy-pop {
position: absolute;
z-index: 30;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.4rem;
max-width: min(36rem, calc(100vw - 2rem));
padding: 0.45rem 0.6rem;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-sm);
box-shadow: var(--shadow);
}
/* Phase 153 (task 02): the Copy-path inline fallback field — the
.share-link-fallback pattern (input variant): a non-secure (http)
origin rejects the clipboard, so the full path is offered as an
input-like <input> that selects itself on focus — click or Tab,
then Ctrl/Cmd+C. readOnly (a copy surface, not an editor), mono
(the path is data — the .share-link-fallback font), surface
fill, --line border; truncates with an ellipsis at narrow widths
(the selection is the copy). Ink on surface ≈13.8:1 (the
.share-link-fallback pair). */
.doc-path-fallback {
max-width: 26rem;
padding: 0.3rem 0.55rem;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
background: var(--surface);
color: var(--ink);
font-family: var(--mono);
font-size: 0.78rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.doc-path-fallback:hover { border-color: var(--brand); }
.doc-path-fallback:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }
.doc-chunks { font-family: var(--mono); }
/* Phase 106 (task 08, D8): the Created badge — the SAME family as the
Indexed one (no own look: the meta row's text, var(--ink-soft) on
@@ -5552,6 +5641,7 @@ a.answer-image:hover { text-decoration: underline; } /* flat — the caption und
#doc-title { font-size: 1.1rem; }
.doc-path { max-width: 16rem; }
.doc-origin { max-width: 16rem; } /* phase 145 (task 03): the Original anchor squeezes like the path */
.doc-copy-path { min-height: 44px; min-width: 44px; } /* phase 153 (task 02): the Copy path control's ≥44px touch-target floor (PLAN §7.1) */
.doc-md { padding: 1.1rem 1rem; }
.doc-summary { padding: 0.75rem 0.9rem; }
.doc-raw { padding: 1rem; font-size: 0.8rem; }