feat(chat): invalidate saved chats on sources sync — versioned stamps, stale marker, Regenerate against the new index

This commit is contained in:
2026-08-30 23:39:15 -04:00
parent ea8e041189
commit 32b7bfd4b3
26 changed files with 2145 additions and 63 deletions
+61
View File
@@ -1267,6 +1267,42 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
}
.kb-banner.is-error { background: var(--err-bg); color: var(--err-ink); border-color: var(--err-line); }
.kb-banner svg { width: 18px; height: 18px; flex: 0 0 auto; display: block; }
/* Phase 53 (task 05): the stale-saved-chat banner — the .kb-banner
FAMILY (the section carries both classes: same flex row, accent
tokens — accent-ink on accent-bg 9.5:1 — 18px glyph), but the
leading mark is the REDO glyph, distinct from the warning triangle.
It sits directly after #kb-banner in .chat-shell, so when both are
visible the empty-KB banner keeps the top slot and the stale banner
stacks directly below (the flex column's gap spaces them). The text
takes the row; the Regenerate pill right-aligns (margin-left: auto)
and the row wraps only when it must. The pill is the EXACT
brand-pill family of Save/Share: solid --brand, --bg text (5.2:1,
AA), borderless, 999px radius, ≥44px target, hover lightens the
brand fill; the 16px redo glyph is the phase-49 Retry asset. The
≤640px block below makes the pill a full-width row. */
.stale-banner { flex-wrap: wrap; }
.stale-banner > span { flex: 1 1 auto; }
.stale-regenerate {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.4rem;
min-height: 44px;
margin-left: auto;
padding: 0.5rem 0.9rem;
border-radius: 999px;
border: 0;
background: var(--brand);
color: var(--bg);
font: inherit;
font-weight: 700;
font-size: 0.95rem;
white-space: nowrap;
cursor: pointer;
}
.stale-regenerate:hover { background: #f55a72; color: var(--bg); }
.stale-regenerate:disabled { opacity: 0.6; cursor: wait; }
.stale-regenerate svg { width: 16px; height: 16px; display: block; }
/* ---------- Login page (phase 16) ---------- */
/* Centered card in the standard frame: one admin, one password. */
@@ -1930,6 +1966,27 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
/* Updated: locale date+time (ink-soft), the full ISO in the title
attribute (history.js). */
.history-updated-cell { color: var(--ink-soft); white-space: nowrap; }
/* Stale marker (phase 53, task 04): the READ-ONLY staleness badge on
rows saved before the last KB-changing sync (the Regenerate action
lives on the chat-page banner — the marker is a pill, never a
control). The rose family, i.e. the Stop-treatment tokens, so
"stale" reads in the same visual language as the in-flight control:
err-ink on err-bg ≈9.3:1 (≥4.5:1 on --surface too), err-line
border — theme tokens, AA in the palette as a whole. Fresh rows'
em-dash rides the cell's ink-soft (5.1:1 on --surface). */
.history-stale-cell { color: var(--ink-soft); white-space: nowrap; }
.stale-pill {
display: inline-block;
padding: 0.15rem 0.55rem;
border: 1px solid var(--err-line);
border-radius: 999px;
background: var(--err-bg);
color: var(--err-ink);
font-size: 0.75rem;
font-weight: 700;
line-height: 1.45;
white-space: nowrap;
}
/* Actions: the Delete ghost button (the tuning row-action language)
+ the inline two-step confirm pair (phase 50 task 04). */
.history-actions { display: inline-flex; align-items: center; gap: 0.4rem; }
@@ -2650,6 +2707,10 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
.chat-shell .save-chat-btn svg { display: none; }
.chat-shell .share-chat-label { display: inline; }
.chat-shell .share-chat-btn svg { display: none; }
/* Phase 53: the stale banner's row wraps at phone width (message
above, action below) — the pill takes a full-width comfortable
row instead of squeezing into the text. */
.stale-regenerate { margin-left: 0; width: 100%; }
/* Phase 16: the auth pill goes icon-only like New chat — brand text
ellipsizes as the designated squeeze target, no bar overflow. */
.auth-link { padding: 0.4rem 0.3rem; }