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
+23
View File
@@ -89,6 +89,29 @@
<span id="kb-banner-text"></span>
</div>
<!-- Phase 53 (task 05): the stale-saved-chat banner. The /?chat=<id>
boot load reveals it ONLY when the fetched row reports
stale: true (the server computes it — the row's sources stamp
is behind the current generation, task 03; the client never
does staleness math). Regenerate (the exact brand-pill family
of the Save/Share pair; the redo glyph is the phase-49 Retry
asset) re-asks the last question against the new index via
retryLastTurn and re-saves the linked row (the server
re-stamps sources_version → stale: false), clearing the
banner. A stale chat with no brain answer is revealed
text-only — app.js removes the button, so retryLastTurn is
never called. Stacks directly below #kb-banner when both are
visible (kb-banner keeps the top slot; the .chat-shell flex
gap spaces them). -->
<section class="kb-banner stale-banner" id="stale-banner" role="status" hidden>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>
<span>The sources have been updated since this chat was saved.</span>
<button type="button" class="stale-regenerate" id="stale-regenerate">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>
<span>Regenerate</span>
</button>
</section>
<!-- Phase 15 (now every page — phase 34, owner confirmation
2026-08-26): the tuning-notes panel (stored notes, newest
first) — rendered + driven by assets/header.js (shared), not