/**
 * Deterministic selection of a single integration-* skill when multiple
 * .claude/skills/integration-* directories with SKILL.md could exist on disk
 * (e.g. leftovers from prior runs, or staging failed while directories remain).
 *
 * The agent prompt must not rely on the model to pick among several matches.
 */
import type { Integration } from './constants.js';
/**
 * Lists integration skill directory names under `.claude/skills/` that contain
 * a SKILL.md file. Sorted lexicographically for stable iteration.
 */
export declare function listIntegrationSkillIdsOnDisk(installDir: string): string[];
/**
 * Narrow disk candidates to ids that plausibly belong to the active wizard
 * integration. When nothing matches (odd disk state), the resolver falls back
 * to the full disk list so we can still pick a deterministic winner.
 *
 * @see {@link resolveIntegrationSkillId} — TODO(PM): tighten react-router /
 * TanStack overlap (file-based vs code-based) when we have explicit user or
 * package signals beyond `routerMode`.
 */
export declare function filterIntegrationSkillIdsForIntegration(integration: string, diskIds: readonly string[]): string[];
export type ResolveIntegrationSkillContext = {
    /** Active framework integration (metadata.integration). */
    integration: Integration | string;
    /**
     * Bundled id from `getIntegrationSkillId` / `integration-${integration}`
     * fallback — preferred when it exists on disk (covers staging failure with
     * a prior successful copy).
     */
    primaryBundledId: string | null;
    /** Same object passed to `buildIntegrationPrompt` / analytics. */
    frameworkContext: Record<string, unknown>;
    /** Output of {@link listIntegrationSkillIdsOnDisk} for this installDir. */
    candidateSkillIds: readonly string[];
};
export type ResolveIntegrationSkillIdSource = 'primary_on_disk' | 'framework_hint' | 'single_candidate' | 'lexicographic_tiebreak';
export type ResolveIntegrationSkillIdResult = {
    skillId: string;
    source: ResolveIntegrationSkillIdSource;
} | null;
/**
 * Pick exactly one `integration-*` skill id from on-disk candidates.
 *
 * Rules (in order):
 * 1. **Primary** — If `primaryBundledId` is in the scoped candidate pool, use it.
 * 2. **Framework hints** — Next.js `context.router` and React Router
 *    `context.routerMode` map to their bundled skill ids when present in the pool.
 * 3. **Single candidate** — If the scoped pool has one id, return it.
 * 4. **Lexicographic tie-break** — Sort the scoped pool (UTF-16, `localeCompare`)
 *    and take the first entry. Caller should log when `source` is
 *    `lexicographic_tiebreak` (possible mis-stale skills on disk).
 *
 * Scoping: {@link filterIntegrationSkillIdsForIntegration}; if that yields no
 * matches, the pool is the full sorted `candidateSkillIds` (conservative fallback).
 *
 * @returns `null` if there are zero candidates on disk.
 */
export declare function resolveIntegrationSkillId(ctx: ResolveIntegrationSkillContext): ResolveIntegrationSkillIdResult;
