diff --git a/Deployment/master.conf.template b/Deployment/master.conf.template index cc1a4f4..95517d6 100644 --- a/Deployment/master.conf.template +++ b/Deployment/master.conf.template @@ -1622,7 +1622,11 @@ # walk — an embedded secret cannot be rotated out of a vector. AI_INDEX_DB="$DATA_DIR/ai_index.db" AI_INDEX_BATCH=32 # chunks per embed request - AI_INDEX_ON_PULL=false # re-index after a successful git pull once AI is in use +# A pull is the only thing that changes tracked files on a server, so it is the only moment the +# index can go stale — and staleness is invisible in the answers, which keep citing the old +# text with full confidence. Incremental: unchanged files are skipped, a no-op run is ~66ms. +# Also gated on AI_ENABLED, and ai_index.sh refuses on its own unless that is true. + AI_INDEX_ON_PULL=true # re-index after a git pull that changed tracked files AI_SEARCH_K=8 # chunks retrieved per query AI_SEARCH_PER_FILE=3 # cap per file so one document cannot fill the context diff --git a/git_pull_execute.sh b/git_pull_execute.sh index fe0d4ff..114a66f 100755 --- a/git_pull_execute.sh +++ b/git_pull_execute.sh @@ -357,6 +357,43 @@ elif [[ "$SYNC_SUCCESS" == true ]]; then fi fi +# ============================================================================================== +# ━━━ AI Index Refresh ━━━ +# ============================================================================================== +# +# A pull is the only thing that changes tracked files on a server — prod never edits them — so +# it is the only moment the AI index can go stale. A timer would be the wrong shape: it would +# do nothing 23 times a day and still drift from the pull that matters. +# +# Staleness is invisible in the answers themselves. The index keeps returning the old text with +# full confidence and correct-looking citations, so a day of drift means the assistant quoting +# code that no longer exists. That is why this runs here rather than being left to a human. +# +# Three gates, any of which skips it: the pull must have succeeded, AI_INDEX_ON_PULL must be +# true, and AI_ENABLED must be true. ai_index.sh also refuses on its own unless AI_ENABLED is +# exactly "true", so a node with AI off never pays for this even if the flags disagree. +# +# Never fatal. Indexing is an enhancement; a git pull must not be reported as failed because an +# embedding call timed out. +if [[ "$DRY_RUN" == true ]]; then + [[ "${AI_INDEX_ON_PULL:-false}" == "true" ]] && warn "DRY RUN — would refresh the AI index" +elif [[ "$SYNC_SUCCESS" == true \ + && "${AI_INDEX_ON_PULL:-false}" == "true" \ + && "${AI_ENABLED:-false}" == "true" ]]; then + + _AI_INDEX="$TARGET_DIR/AI/ai_index.sh" + if [[ -f "$_AI_INDEX" ]]; then + log "Refreshing AI index (incremental — unchanged files are skipped)..." + if bash "$_AI_INDEX" >/dev/null 2>&1; then + echo " AI index refreshed" + else + warn "AI index refresh failed — answers may cite outdated code until it is rerun" + fi + else + warn "AI_INDEX_ON_PULL is true but $_AI_INDEX not found — skipping" + fi +fi + # ============================================================================================== # ━━━ Summary ━━━ # ==============================================================================================