From c42c13b88228871935f324e515875e92054bd5d7 Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Fri, 15 May 2026 13:17:44 +0200 Subject: [PATCH] feat(auto): trigger sift index warmup at start of every autonomous loop Previously, sift warmup only ran during sf init/auto-start, which meant repos launched via sf headless or entered mid-session never got their index built. The first sift_search/codebase_search call would then block for minutes while the cold cache was built. Now autoLoop() calls ensureSiftIndexWarmup() at loop entry. The warmup runs detached (background process) and is skipped if already running or if a recent marker exists. This ensures every repo SF operates on gets indexed regardless of entry path. - Best-effort: wrapped in try/catch so warmup failures never block the loop - Lazy import to avoid circular dependencies - Debug-logged for observability Tests: 179 files / 1863 tests pass. Type check: clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/resources/extensions/sf/auto/loop.js | 20 ++++++++++++++++++++ src/resources/extensions/sf/auto/run-unit.js | 1 + 2 files changed, 21 insertions(+) diff --git a/src/resources/extensions/sf/auto/loop.js b/src/resources/extensions/sf/auto/loop.js index ed9197bf9..e3c60140e 100644 --- a/src/resources/extensions/sf/auto/loop.js +++ b/src/resources/extensions/sf/auto/loop.js @@ -586,6 +586,26 @@ export async function autoLoop(ctx, pi, s, deps) { cleared: runawayHeal, }); } + // ── Start sift index warmup if not already running ── + // The warmup runs detached and builds the lexical index for the repo. + // Once cached, all future sift_search and codebase_search calls are fast. + // We do this here (not just in auto-start) so every repo SF enters gets + // indexed, including repos launched via `sf headless` or cd'd into mid-session. + try { + const { ensureSiftIndexWarmup } = await import("../code-intelligence.js"); + const warmup = ensureSiftIndexWarmup( + s.basePath, + deps.loadEffectiveSFPreferences?.()?.preferences?.codebase, + ); + if (warmup.status === "started") { + debugLog("autoLoop", { + phase: "sift-warmup-started", + reason: warmup.reason, + }); + } + } catch { + /* best-effort — never block the loop on warmup */ + } let iteration = 0; // Load persisted stuck state so counters survive session restarts (#3704) const persisted = loadStuckState(s.basePath); diff --git a/src/resources/extensions/sf/auto/run-unit.js b/src/resources/extensions/sf/auto/run-unit.js index 38bc64c85..bef5f1231 100644 --- a/src/resources/extensions/sf/auto/run-unit.js +++ b/src/resources/extensions/sf/auto/run-unit.js @@ -26,6 +26,7 @@ import { countChangedFiles, resetRunawayGuardState, } from "../uok/auto-runaway-guard.js"; +import { emitJournalEvent } from "../journal.js"; import { swarmDispatchAndWait } from "../uok/swarm-dispatch.js"; import { logWarning } from "../workflow-logger.js"; import {