export interface ProbeExtension { path: string; tools: string[]; commands: string[]; flags: string[]; activeTools: string[]; } export interface ProbeReport { errors: string[]; extensions: ProbeExtension[]; skills: string[]; /** Registrations claimed by more than one package in the probed set. */ conflicts: string[]; } /** Identity, tool, command, flag, and skill names claimed more than once. */ export function registrationConflicts( extensions: readonly Pick< ProbeExtension, "path" | "tools" | "commands" | "flags" >[], packageNames: readonly string[], skills: readonly string[], ): string[] { const conflicts: string[] = []; const owners = ( kind: string, items: readonly (readonly [string, string])[], ) => { const byName = new Map(); for (const [name, owner] of items) byName.set(name, [...(byName.get(name) ?? []), owner]); for (const [name, list] of byName) if (list.length > 1) conflicts.push(`${kind} ${name} registered by ${list.join(", ")}`); }; owners( "package", packageNames.map((name) => [name, name] as const), ); for (const kind of ["tools", "commands", "flags"] as const) owners( kind.slice(0, -1), extensions.flatMap((extension) => extension[kind].map((name) => [name, extension.path] as const), ), ); owners( "skill", skills.map( (path) => [path.split("/").slice(-2, -1)[0] ?? path, path] as const, ), ); return conflicts.sort(); }