import { type SkillDefinition } from '../extensibility/skillLoader';
import { type SkillUsageRecord, type SkillUsageStore } from '../extensibility/skillUsage';
import { type SafetyViolation } from '../learning/promotionGate';
export interface CuratorConfig {
    /** Days without use before a skill is considered stale. */
    staleDays: number;
    /** A skill must have at least this many views before it can be archived (protects fresh skills with low use). */
    minViewsBeforeArchive: number;
    /** Maximum number of skills the curator may archive in a single run. */
    maxArchivePerRun: number;
    /** When false, Phase 2 (LLM merge proposals) is skipped. */
    enableLlmPhase: boolean;
}
export declare const DEFAULT_CURATOR_CONFIG: CuratorConfig;
export type CuratorActionKind = 'archive' | 'restore' | 'merge-proposed' | 'skip-pinned' | 'skip-active' | 'skip-cap' | 'skip-safety';
export interface CuratorAction {
    kind: CuratorActionKind;
    skill: string;
    reason: string;
    ageDays?: number;
    daysSinceUse?: number;
    viewCount?: number;
    useCount?: number;
    /** Populated when kind === 'skip-safety'. */
    safetyViolations?: SafetyViolation[];
}
export interface CuratorRunSummary {
    startedAt: string;
    finishedAt: string;
    dryRun: boolean;
    staleCandidates: CuratorAction[];
    archived: CuratorAction[];
    proposals?: string;
    proposalsPath?: string;
    llmSkipped?: string;
}
export interface CuratorDeps {
    /** Async function that returns true when the global kill switch is engaged. */
    isKillSwitchActive(): boolean;
    /** Optional LLM call used by Phase 2. Receives a prompt, returns the response text. */
    callModel?(prompt: string): Promise<string>;
}
/**
 * Phase 1: identify skills the curator considers stale. Pure function over
 * loaded definitions and usage records. Always safe to call.
 */
export declare function findStaleSkills(skills: SkillDefinition[], usage: SkillUsageStore, config: CuratorConfig, now?: Date): CuratorAction[];
/**
 * Move a skill folder into the archive subdirectory and update the usage record.
 * Reversible via restoreSkill.
 */
export declare function archiveSkill(projectDir: string, name: string): Promise<{
    from: string;
    to: string;
}>;
export declare function restoreSkill(projectDir: string, name: string): Promise<{
    from: string;
    to: string;
}>;
export declare function runDeterministicPhase(projectDir: string, config: CuratorConfig, deps: CuratorDeps, options?: {
    dryRun?: boolean;
}): Promise<CuratorRunSummary>;
/**
 * Phase 2: ask the LLM to cluster related skills and propose merges into
 * umbrella skills. Writes proposals to .harness/curator/proposals.md for
 * human review. Does not auto-apply changes in this version.
 */
export declare function runLlmPhase(projectDir: string, config: CuratorConfig, deps: CuratorDeps): Promise<{
    proposals?: string;
    proposalsPath?: string;
    skipped?: string;
}>;
export declare function runCurator(projectDir: string, config: CuratorConfig, deps: CuratorDeps, options?: {
    dryRun?: boolean;
}): Promise<CuratorRunSummary>;
export declare function readCuratorLog(projectDir: string, limit?: number): Promise<unknown[]>;
export declare function readCuratorProposals(projectDir: string): Promise<string | null>;
export interface MergeProposal {
    /** Suggested umbrella name (slugified). */
    umbrellaName: string;
    /** Original heading text from the proposal. */
    heading: string;
    /** Skills the proposal wants to merge. */
    mergeSkills: string[];
    /** Optional rationale line. */
    rationale?: string;
    /** Optional proposed description for the new umbrella skill. */
    proposedDescription?: string;
}
/**
 * Parse the proposals markdown into a structured list. The format the LLM is
 * asked to follow is:
 *   ### Cluster: <umbrella name>
 *   - merge: a, b, c
 *   - rationale: ...
 *   - proposed description: ...
 * This parser is intentionally lenient: missing fields are tolerated.
 */
export declare function parseMergeProposals(content: string): MergeProposal[];
export interface ApplyMergeOptions {
    /** Override the umbrella name from the proposal. */
    umbrellaName?: string;
    /** Override the description. */
    description?: string;
    /** When true, writes the umbrella but does not archive originals. */
    dryRun?: boolean;
}
export interface ApplyMergeResult {
    umbrellaName: string;
    umbrellaPath: string;
    archived: string[];
    skipped: string[];
    dryRun: boolean;
}
/**
 * Apply a single LLM merge proposal: writes a new umbrella SKILL.md that
 * concatenates the source skill bodies, then archives the originals.
 * Pinned skills are not archived (the umbrella still references them in its
 * body for transparency).
 */
export declare function applyMergeProposal(projectDir: string, proposal: MergeProposal, options?: ApplyMergeOptions): Promise<ApplyMergeResult>;
export declare function clearCuratorProposals(projectDir: string): Promise<void>;
export { loadSkillUsage, saveSkillUsage } from '../extensibility/skillUsage';
export type { SkillUsageRecord };
//# sourceMappingURL=curator.d.ts.map