From 2905dd3e3e4469f33ada3ba3362136bfed82a46c Mon Sep 17 00:00:00 2001 From: jetsetterfl Date: Mon, 18 May 2026 08:49:47 -0400 Subject: [PATCH] fix(gbrain-sync): --full must walk the filesystem before reindex-code on a fresh source runCodeImport selected the code-stage command by mode: --full ran only `gbrain reindex-code`, incremental ran `gbrain sync --strategy code`. reindex-code re-embeds pages that already exist and never walks the filesystem, so the first --full on a freshly-registered source found no pages ("No code pages to reindex"), finished in ~1s, and left the code index permanently empty while the stage still reported OK. Semantic code search then silently returned nothing for that repo. Always run the page-creating `sync --strategy code` walk first, then run reindex-code when mode is --full. This honors the documented "full walk + reindex" contract for both freshly-registered and already-populated sources. Verified end-to-end: a fresh source that previously stayed at 0 pages now fully populates under --full. Co-Authored-By: Claude Opus 4.7 (1M context) --- bin/gstack-gbrain-sync.ts | 41 +++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/bin/gstack-gbrain-sync.ts b/bin/gstack-gbrain-sync.ts index 61d9e677f7..8207137ca6 100644 --- a/bin/gstack-gbrain-sync.ts +++ b/bin/gstack-gbrain-sync.ts @@ -589,28 +589,53 @@ async function runCodeImport(args: CliArgs): Promise { }; } - // Step 2: Run sync or reindex. - const syncArgs = args.mode === "full" - ? ["reindex-code", "--source", sourceId, "--yes"] - : ["sync", "--strategy", "code", "--source", sourceId]; - - const syncResult = spawnGbrain(syncArgs, { + // Step 2: Always run the page-creating file walk first, then (for --full) + // a full re-embed. + // + // `gbrain reindex-code` only RE-EMBEDS pages that already exist; it never + // walks the filesystem. On a freshly-registered source (0 pages) a --full + // run that called reindex-code alone found nothing ("No code pages to + // reindex"), finished in ~1s, and left the code index permanently empty + // while still reporting OK. The page-creating walk is `sync --strategy + // code`, so --full must run it FIRST, then reindex-code, to honor the + // documented "full walk + reindex" contract for both fresh and populated + // sources. + const walkResult = spawnGbrain(["sync", "--strategy", "code", "--source", sourceId], { stdio: args.quiet ? ["ignore", "ignore", "ignore"] : ["ignore", "inherit", "inherit"], timeout: 35 * 60 * 1000, baseEnv: gbrainEnv, }); - if (syncResult.status !== 0) { + if (walkResult.status !== 0) { return { name: "code", ran: true, ok: false, duration_ms: Date.now() - t0, - summary: `gbrain ${syncArgs.join(" ")} exited ${syncResult.status}`, + summary: `gbrain sync --strategy code --source ${sourceId} exited ${walkResult.status}`, detail: { source_id: sourceId, source_path: root, status: "failed" }, }; } + if (args.mode === "full") { + const reindexResult = spawnGbrain(["reindex-code", "--source", sourceId, "--yes"], { + stdio: args.quiet ? ["ignore", "ignore", "ignore"] : ["ignore", "inherit", "inherit"], + timeout: 35 * 60 * 1000, + baseEnv: gbrainEnv, + }); + + if (reindexResult.status !== 0) { + return { + name: "code", + ran: true, + ok: false, + duration_ms: Date.now() - t0, + summary: `gbrain reindex-code --source ${sourceId} exited ${reindexResult.status}`, + detail: { source_id: sourceId, source_path: root, status: "failed" }, + }; + } + } + // Step 3: Pin this worktree's CWD to the source via .gbrain-source. Subsequent // gbrain code-def / code-refs / code-callers calls from anywhere under // route to this source by default — no --source flag needed.