diff --git a/packages/core/src/epiphany-identities.ts b/packages/core/src/epiphany-identities.ts index 6a51d7d..f4e3d26 100644 --- a/packages/core/src/epiphany-identities.ts +++ b/packages/core/src/epiphany-identities.ts @@ -39,6 +39,7 @@ const faceIdentitySchema = z.object({ identityKind: z.enum(["repo_face", "native_persona"]).default("repo_face"), displayName: z.string().trim().min(1).max(80), repoName: z.string().trim().min(1).optional(), + sourceRepoName: z.string().trim().min(1).optional(), repoPath: z.string().trim().min(1).optional(), roleId: z.string().trim().min(1).optional(), allowedChannelIds: z.array(z.string().trim().min(1)).default([]), @@ -122,6 +123,7 @@ export function faceToRepoDiscordIdentity(face: ResolvedFaceIdentity): RepoDisco id: face.id, identityKind: face.identityKind, repoName, + sourceRepoName: face.sourceRepoName, displayName: face.displayName, repoPath: face.repoPath, roleId: face.roleId, @@ -186,6 +188,7 @@ function repoIdentityToEpiphany(identity: RepoDiscordIdentity): EpiphanyIdentity id: identity.id, displayName: identity.displayName, repoName: identity.repoName, + sourceRepoName: identity.sourceRepoName, repoPath: identity.repoPath, roleId: identity.roleId, identityKind: identity.identityKind, @@ -240,6 +243,7 @@ function normalizeEpiphanies(epiphanies: EpiphanyIdentity[]): EpiphanyIdentity[] id: face.id.trim(), displayName: face.displayName.trim().slice(0, 80), repoName: face.repoName?.trim(), + sourceRepoName: face.sourceRepoName?.trim(), repoPath: face.repoPath?.trim(), roleId: face.roleId?.trim(), identityKind: face.identityKind, diff --git a/packages/core/src/repo-discord-identities.ts b/packages/core/src/repo-discord-identities.ts index bbce11c..4e8ed14 100644 --- a/packages/core/src/repo-discord-identities.ts +++ b/packages/core/src/repo-discord-identities.ts @@ -7,6 +7,7 @@ const repoDiscordIdentitySchema = z.object({ id: z.string().trim().min(1), identityKind: z.enum(["repo_face", "native_persona"]).default("repo_face"), repoName: z.string().trim().min(1), + sourceRepoName: z.string().trim().min(1).optional(), displayName: z.string().trim().min(1).max(80), repoPath: z.string().trim().min(1).optional(), roleId: z.string().trim().min(1).optional(), @@ -154,6 +155,16 @@ export function resolveRepoFaceStatePath( return resolve(storageRoot, "private", "repo-faces", `${sanitizePathSegment(identity.id)}.cc`); } +/** + * The searchable source corpus is explicit. A native Persona's public label + * must never accidentally become a repository-index filter. + */ +export function getRepoFaceSourceRepoName(identity: RepoDiscordIdentity): string | undefined { + return identity.identityKind === "repo_face" + ? identity.sourceRepoName ?? identity.repoName + : undefined; +} + export function findCrossRepoJurisdictionMentions( identity: RepoDiscordIdentity, registry: RepoDiscordIdentityRegistry, @@ -208,6 +219,7 @@ function normalizeRepoDiscordIdentities( id: identity.id.trim(), identityKind: identity.identityKind, repoName: identity.repoName.trim(), + sourceRepoName: identity.sourceRepoName?.trim(), displayName: identity.displayName.trim().slice(0, 80), repoPath: identity.repoPath?.trim(), roleId: identity.roleId?.trim(), diff --git a/scripts/git-post-push-index.mjs b/scripts/git-post-push-index.mjs index 93b9c57..d5fb8a1 100644 --- a/scripts/git-post-push-index.mjs +++ b/scripts/git-post-push-index.mjs @@ -134,24 +134,23 @@ async function runWorker() { } try { - const child = - process.platform === "win32" - ? spawn( - "cmd.exe", - ["/d", "/s", "/c", "npm.cmd", "run", "rag:index-sources", "--", "--repo", args.repoName], - { - cwd: voidbotRoot, - windowsHide: true, - env: process.env, - stdio: ["ignore", "pipe", "pipe"], - }, - ) - : spawn("npm", ["run", "rag:index-sources", "--", "--repo", args.repoName], { - cwd: voidbotRoot, - windowsHide: true, - env: process.env, - stdio: ["ignore", "pipe", "pipe"], - }); + const tsxCliPath = join(voidbotRoot, "node_modules", "tsx", "dist", "cli.mjs"); + if (!(await pathExists(tsxCliPath))) { + throw new Error( + `VoidBot's repo-local tsx runtime is missing at ${tsxCliPath}; run npm ci in ${voidbotRoot} before retrying source indexing.`, + ); + } + + const child = spawn( + process.execPath, + [tsxCliPath, join(voidbotRoot, "scripts", "index-source-repos.ts"), "--repo", args.repoName], + { + cwd: voidbotRoot, + windowsHide: true, + env: process.env, + stdio: ["ignore", "pipe", "pipe"], + }, + ); child.stdout.on("data", (chunk) => { process.stdout.write(chunk); diff --git a/scripts/run-repo-face-heartbeats.ts b/scripts/run-repo-face-heartbeats.ts index 772a6d5..c0ec98d 100644 --- a/scripts/run-repo-face-heartbeats.ts +++ b/scripts/run-repo-face-heartbeats.ts @@ -12,6 +12,7 @@ import { ContextBuilder, createStateStorage, ensureRepoFaceInitialized, + getRepoFaceSourceRepoName, getRepoDiscordIdentityAllowedChannelIds, faceRegistryAsRepoDiscordRegistry, projectRepoFaceSleepCycleForNow, @@ -3187,12 +3188,15 @@ async function renderRepoFaceCuriosityGraphFacts( try { const retrieval = createRepoFaceCuriosityRetrievalService(config); const nodesById = new Map(); + const sourceRepoName = getRepoFaceSourceRepoName(identity); for (const seed of seedQueries) { const [historyResults, sourceResults, homeSourceResults] = await Promise.all([ retrieval.searchHistory(seed.query, 8), retrieval.searchRepositorySources(seed.query, 8), - retrieval.searchRepositorySources(seed.query, 6, { repoName: identity.repoName }), + sourceRepoName + ? retrieval.searchRepositorySources(seed.query, 6, { repoName: sourceRepoName }) + : Promise.resolve([]), ]); for (const result of [...historyResults, ...sourceResults, ...homeSourceResults]) { const id = `${result.sourceKind}:${result.chunkId}`;