feat(chat): invalidate saved chats on sources sync — versioned stamps, stale marker, Regenerate against the new index
This commit is contained in:
+32
-1
@@ -39,7 +39,16 @@ decisions):
|
||||
CLI's no-prune default is unchanged);
|
||||
5. when the import changed the KB (added + updated > 0),
|
||||
``regenerate_overview`` refreshes the single ``kb_overview`` row
|
||||
(phase 31 trigger, best-effort inside).
|
||||
(phase 31 trigger, best-effort inside);
|
||||
6. when the import changed the KB (added + updated + pruned > 0 — the
|
||||
saved-chat invalidation gate, phase 53 task 02: a pruned document
|
||||
can invalidate a saved answer that cited it, deliberately broader
|
||||
than step 5's overview gate), the single-row ``sources_meta``
|
||||
version counter is bumped exactly once in a short-lived session and
|
||||
the resulting generation lands in the status detail as
|
||||
``sources_version`` (an unchanged re-sync reports the current
|
||||
generation without advancing it). A FAILED sync never bumps — the
|
||||
run aborts in the ``failed`` state before this step.
|
||||
|
||||
Status is in memory: a restart mid-sync loses the running state
|
||||
(accepted — the next click re-syncs idempotently).
|
||||
@@ -63,6 +72,7 @@ from app.rag.git_sources import effective_sources
|
||||
from app.rag.importer import ImportSummary, import_sources
|
||||
from app.rag.llm import LLMClient, check_models
|
||||
from app.rag.overview import regenerate_overview
|
||||
from app.rag.sources_meta import bump_sources_version, current_sources_version
|
||||
from scripts.git_sync import GitSyncError, clone_or_pull
|
||||
from scripts.import_docs import repo_name
|
||||
|
||||
@@ -202,6 +212,26 @@ async def _run_sync() -> None:
|
||||
overview = False
|
||||
if summary.added + summary.updated > 0:
|
||||
overview = await regenerate_overview(llm)
|
||||
# Phase 53 (task 02): a sync that changed the KB advances the
|
||||
# sources version exactly once — the saved-chat invalidation
|
||||
# marker (task 03 stamps rows against it). The gate is
|
||||
# deliberately broader than the overview's above: a pruned
|
||||
# document can invalidate a saved answer that cited it, so
|
||||
# ``pruned > 0`` bumps too. The bump commits in its own short
|
||||
# session (the ``effective_sources`` pattern above), so it
|
||||
# lands even if the best-effort overview then fails — the index
|
||||
# really did change. An unchanged re-sync never bumps; it
|
||||
# reports the current generation instead, so the detail always
|
||||
# carries the generation the KB is now at.
|
||||
db = SessionLocal()
|
||||
try:
|
||||
if summary.added + summary.updated + summary.pruned > 0:
|
||||
sources_version = bump_sources_version(db)
|
||||
db.commit()
|
||||
else:
|
||||
sources_version = current_sources_version(db)
|
||||
finally:
|
||||
db.close()
|
||||
_status.state = "success"
|
||||
_status.finished_at = datetime.now(UTC)
|
||||
_status.detail = {
|
||||
@@ -215,6 +245,7 @@ async def _run_sync() -> None:
|
||||
"summaries": summary.summaries,
|
||||
"summary_errors": summary.summary_errors,
|
||||
"overview": overview,
|
||||
"sources_version": sources_version,
|
||||
}
|
||||
logger.info("sync: done detail=%s", _status.detail)
|
||||
except Exception as e: # noqa: BLE001 — a background task dies in state, see above
|
||||
|
||||
Reference in New Issue
Block a user