/**
 * Shared drift-detection internals for `agents doctor` (overview mode) and
 * `agents doctor --check` (the scriptable, CI-friendly gate).
 *
 * This is the single source of truth for "is the install out of sync?": the
 * per-version sync status (fresh / stale / never-synced) and the orphan census.
 * `agents doctor` renders it as a human report; `agents doctor --check` reduces it
 * to an exit code. Neither reimplements the diagnostic — both call `computeDrift`.
 */
import type { AgentId } from './types.js';
import { type VersionResourceReport, type SourceLayerBehind } from './doctor-diff.js';
export interface SyncStatusRow {
    agent: AgentId;
    version: string;
    status: 'fresh' | 'stale' | 'never-synced';
    isDefault: boolean;
    /** For stale rows: prioritized lines naming exactly what diverged (plugins first).
     *  Also carries hook-wiring divergence for a version whose hooks are present but
     *  not wired into settings.json — independent of manifest staleness. */
    divergence?: string[];
    /** Count of hooks present on disk but NOT wired into the version's settings.json
     *  (claude/droid). A non-zero value makes the version out-of-sync even when the
     *  manifest reads fresh — the yosemite-s1 blind spot the CI gate must catch. */
    unwiredHooks?: number;
    /** Generated hooks whose shared runtime wrapper is missing or unusable. */
    brokenHookRuntime?: number;
}
export interface OrphanRow {
    agent: AgentId;
    version: string;
    commands: number;
    skills: number;
    hooks: number;
}
export declare function divergenceLines(report: VersionResourceReport): string[];
export declare function checkSyncStatus(cwd: string): SyncStatusRow[];
export declare function countOrphans(): OrphanRow[];
/**
 * Probe each source layer (user, system, enabled extras) for how far it trails
 * its upstream, from the LAST-FETCHED remote-tracking ref (no network). A layer
 * behind origin means every version home is reconciled against stale truth — a
 * drift signal `agents doctor --check` must fail on, not a buried preamble. Returns
 * only the behind layers. Canonical home for both `agents doctor` and `agents doctor --check`.
 */
export declare function computeSourceBehind(): SourceLayerBehind[];
export interface DriftSummary {
    syncRows: SyncStatusRow[];
    orphanRows: OrphanRow[];
    /** Versions whose sources changed since last sync. */
    staleCount: number;
    /** Versions installed but never synced. */
    neverSyncedCount: number;
    /** Versions carrying orphan resources (informational — not a drift signal). */
    orphanVersionCount: number;
    /** Versions with hooks present on disk but not wired into settings.json. */
    unwiredHookVersions: number;
    /** Versions with at least one broken generated hook-runtime wrapper. */
    brokenHookRuntimeVersions: number;
    /** Source layers behind their upstream (reconciled against stale truth). */
    sourceBehind: SourceLayerBehind[];
    /**
     * True when the install is out of sync: any installed version is stale,
     * never-synced, carries unwired hooks, or has a broken generated hook runtime,
     * OR a source layer is behind origin.
     * `agents doctor` surfaces it as "run `agents sync status`"; `agents doctor --check`
     * maps it to a non-zero exit. Orphans are a `prune` concern, not sync drift, so they do
     * NOT set this flag (mirrors the sync-status engine: an orphan alone never
     * flags needsSync).
     */
    hasDrift: boolean;
}
/**
 * Compute the same drift/divergence diagnostic `agents doctor` prints, reduced
 * to a summary with a single `hasDrift` boolean. The gate `agents doctor --check`
 * maps to an exit code; the readout `agents doctor` renders in full.
 */
export declare function computeDrift(cwd: string): DriftSummary;
