/**
 * Unified sync-status engine — the SINGLE source of truth for "is this resource
 * synced to this agent version?" consumed by `agents doctor`, `agents view`, the
 * menu-bar app, and any Agency surface.
 *
 * Why this exists: before this module there were four different notions of
 * "synced" living in four files:
 *   - doctor:  isStale() vs .sync-manifest.json  — catches SOURCE drift only.
 *   - view:    git working-tree state of ~/.agents/ — a resource can show green
 *              while its installed copy is stale/deleted/corrupted (false positive).
 *   - lists:   file-exists-in-home — never reports content drift at all.
 *   - menubar: read doctor --json (so it inherited doctor's source-only blind spot).
 *
 * The reliable signal is diffVersionResources() (src/lib/doctor-diff.ts): it reads
 * the ACTUAL version home and compares it to the resolved sources, so it catches
 * every drift class — source-side changes AND home-side rot (deleted / corrupted /
 * hand-edited installed copies) AND orphans. This module wraps it once, maps its
 * per-resource DiffStatus onto one stable enum, folds in `.system` repo freshness,
 * and lets every surface render the same warnings instead of re-deriving them.
 */
import { AgentId } from './types.js';
import { type DoctorKind } from './doctor-diff.js';
import { type ConfigDrift } from './config-drift.js';
/**
 * One stable status per resource, unified across every surface.
 *  - `synced`  — installed copy matches the resolved source (DiffStatus 'ok').
 *  - `drifted` — installed copy exists but differs from source (DiffStatus 'diff').
 *  - `missing` — source exists, nothing installed in the version home ('missing').
 *  - `orphan`  — installed in the home with no source ('extra'); prune's job, not sync's.
 */
export type ResourceSyncStatus = 'synced' | 'drifted' | 'missing' | 'orphan';
export interface ResourceStatusRow {
    agent: AgentId;
    version: string;
    kind: DoctorKind;
    name: string;
    status: ResourceSyncStatus;
    /** Human-readable specifics for a drifted row (e.g. plugin version delta). */
    detail?: string;
}
export interface AgentVersionStatus {
    agent: AgentId;
    version: string;
    isDefault: boolean;
    /** False = no .sync-manifest.json: this version was never synced (cold). */
    everSynced: boolean;
    counts: {
        synced: number;
        drifted: number;
        missing: number;
        orphan: number;
    };
    /** drifted + missing > 0 — a real reconcile is owed. Orphans do NOT set this
     * (heal never deletes; orphan removal is `agents prune cleanup`). */
    needsSync: boolean;
    resources: ResourceStatusRow[];
}
export interface SystemRepoStatus {
    dir: string;
    /** Commits the local `.system` checkout is behind its tracking branch, as of
     * the last background fetch (no network is performed here). 0 = up to date. */
    behind: number;
    ahead: number;
    branch: string | null;
    /** True when the dir isn't a git repo or has no upstream — behind is unknown. */
    unknown: boolean;
}
export interface UserRepoStatus {
    dir: string;
    /**
     * True when `~/.agents` exists but is not a git repo (or is a repo with no
     * `origin`) — a partial install `agents repo sync user` will adopt in place
     * (PHNX-3301). A DISTINCT drift state, not a per-agent "N missing" count.
     */
    notGitRepo: boolean;
}
export interface UnifiedSyncStatus {
    system: SystemRepoStatus;
    user: UserRepoStatus;
    /** Config drift: has this box drained its device-scoped state, or is it still
     *  carrying per-box state in the shared top-level agents.yaml? (PHNX-3315) */
    config: ConfigDrift;
    agents: AgentVersionStatus[];
    totals: {
        drifted: number;
        missing: number;
        orphan: number;
        /** Versions with a manifest that are behind on content. */
        versionsNeedingSync: number;
        /** Versions that were never synced at all. */
        versionsNeverSynced: number;
        /** Distinct agent ids that own at least one version needing sync. */
        agentsNeedingSync: number;
    };
}
/**
 * Residual drift for a single (agent, version) after a reconcile — the drifted
 * and missing rows that a sync claimed to fix but did not. `orphan` rows are
 * deliberately excluded: sync never removes them (that is `agents prune`'s job),
 * so they are not "unfinished sync". Empty `drifted`+`missing` ⇒ converged.
 */
export interface ResidualDrift {
    agent: AgentId;
    version: string;
    rows: ResourceStatusRow[];
}
/**
 * Re-check that a version's home now matches its resolved sources after a
 * reconcile. This is the post-write verification the `agents sync` success line
 * depends on (PHNX-3186): the exit line must not read "reconciled" while drift
 * it was asked to fix stays put. Resolves against non-project layers only
 * (`excludeProject: true`), mirroring what the sync writer targets. Returns null
 * when the version converged (no drifted/missing), else the residual rows.
 */
export declare function verifyVersionConverged(agent: AgentId, version: string, cwd?: string): ResidualDrift | null;
/** One-line-per-resource description of residual drift, for the sync exit line. */
export declare function formatResidualDrift(residual: ResidualDrift[]): string[];
export interface SyncStatusOptions {
    cwd?: string;
    /** Restrict to specific agent ids; undefined = every supported agent. */
    agents?: AgentId[];
    /** Restrict to specific resource kinds; undefined = all. */
    kinds?: DoctorKind[];
}
/**
 * Read `.system` repo freshness WITHOUT touching the network. `git status`
 * reports ahead/behind against the remote-tracking ref, which the detached
 * auto-pull worker keeps warm via periodic `git fetch`. This is the same number
 * the menu-bar surfaces; we read it once, here, so every surface agrees.
 */
export declare function getSystemRepoStatus(): Promise<SystemRepoStatus>;
/**
 * Detect whether `~/.agents` (the user config layer) is git-backed. A partial
 * install — runtime state present but no `.git` (or no `origin`) — is a distinct
 * drift state that `agents repo sync user` heals by adopting in place (PHNX-3301),
 * surfaced separately from per-version resource gaps. Purely local; no network.
 */
export declare function getUserRepoStatus(): Promise<UserRepoStatus>;
/**
 * Compute unified sync status across the fleet. Resolves against non-project
 * layers only (`excludeProject: true`) — the GLOBAL version home is never
 * reconciled against per-cwd `<cwd>/.agents/` resources, so counting them as
 * "missing" there would be a false gap (matches doctor's overview semantics).
 */
export declare function computeSyncStatus(options?: SyncStatusOptions): Promise<UnifiedSyncStatus>;
