fix(storage): count a shared checkout's commit graph as its code index (#3352)

A clean shared checkout reads a commit graph and owns no graph file, so
the code-index presence check made status report it unindexed and
registry validation skip it. The check now follows the slot's
validated graphPath.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Gergo Magyar 2026-09-24 08:06:25 +00:00
parent 6aaeee994f
commit 8cdb05c22e
2 changed files with 21 additions and 2 deletions

View file

@ -9,7 +9,7 @@ import {
LEGACY_METADATA_FILE,
LBUG_DIRECTORY,
} from './storage-constants.js';
import { resolveSharedStore } from './shared-store.js';
import { resolveGraphPath, resolveSharedStore } from './shared-store.js';
import { slotNameForCanonicalPath, STORAGE_PATH_ENV, STORAGE_ROOT_ENV } from './storage-slot.js';
export { STORAGE_PATH_ENV, STORAGE_ROOT_ENV };
@ -387,8 +387,13 @@ const inspectCodeIndexDB = async (
if (lbugRel.startsWith('..') || path.isAbsolute(lbugRel)) {
return { present: false };
}
// A shared-store checkout slot (#3352) may read a commit graph instead of
// owning one; `resolveGraphPath` only returns a path inside the same store's
// commit graphs, else the slot's own graph.
const graphPath = resolveGraphPath(resolved);
const target = graphPath === lbugPath ? lbugPath : graphPath;
try {
await fsp.access(lbugPath);
await fsp.access(target);
return { present: true };
} catch (error) {
const code = (error as NodeJS.ErrnoException)?.code;

View file

@ -107,6 +107,20 @@ describe('shared sibling store analyze (#3352)', () => {
}
}, 180_000);
it('reports a checkout that reads a commit graph as indexed', async () => {
const { runFullAnalysis } = await import('../../src/core/run-analyze.js');
await runFullAnalysis(wtA, {}, { onProgress: () => {} });
await runFullAnalysis(wtB, {}, { onProgress: () => {} });
const slot = layoutOf(wtB).checkoutSlot;
expect(existsSync(path.join(slot, 'lbug'))).toBe(false);
const { inspectRegisteredStorage } = await import('../../src/storage/storage-resolver.js');
const inspection = await inspectRegisteredStorage({ path: wtB, storagePath: slot });
expect(inspection).toMatchObject({ state: 'owned', hasCodeIndexDB: true });
const validated = await listRegisteredRepos({ validate: true });
expect(validated.map((e) => e.path)).toEqual(expect.arrayContaining([wtA, wtB]));
}, 180_000);
it('serves a sibling the same relative file paths from the shared graph', async () => {
const { runFullAnalysis } = await import('../../src/core/run-analyze.js');
await runFullAnalysis(wtA, {}, { onProgress: () => {} });