/**
 * Deep-clean / residue detection for ShieldCortex ↔ OpenClaw integration.
 *
 * The standard `uninstall` and `uninstallPlugin` code paths only fire when
 * the on-disk artefacts they expected are still present. Partial uninstalls,
 * manual cleanups, and version-to-version shape changes left orphaned config
 * entries in `~/.openclaw/openclaw.json` and `~/.openclaw/workspace/.clawhub/lock.json`
 * that kept producing "plugin references without files" and "missing skill file"
 * warnings until purged by hand (see incident notes 2026-04-23/24).
 *
 * This module scans every known residue location once, independently of disk
 * state, and offers a single surgical clean-up pass.
 *
 * Scope: read/write of JSON config files + directory removal under the user's
 * home directory. No network, no sudo, no shell invocation.
 */
/**
 * Resolve the real user's home directory (mirrors openclaw.ts behaviour so the
 * two modules agree on which home to touch under sudo).
 */
declare function resolveHome(): string;
type Removal = {
    kind: 'delete-config-key';
    file: string;
    keyPath: string[];
} | {
    kind: 'filter-config-array';
    file: string;
    keyPath: string[];
    contains: string;
} | {
    kind: 'delete-directory';
    path: string;
};
/**
 * Classification of residue paths. Drives orphan detection: a `plugin-config`
 * entry is legitimate (not an orphan) while the plugin extension dir is on disk;
 * a `legacy-hook-dir` is always an orphan because the current install uses a
 * different path.
 */
export type ResidueCategory = 'plugin-config' | 'hook-config' | 'clawhub-skill-lock' | 'plugin-dir' | 'hook-dir' | 'legacy-hook-dir';
export interface ResiduePath {
    description: string;
    removal: Removal;
    present: boolean;
    category: ResidueCategory;
}
export interface ResidueReport {
    paths: ResiduePath[];
    dirtyCount: number;
    cleanCount: number;
}
export interface OrphanReport {
    paths: ResiduePath[];
    orphanCount: number;
    installState: {
        pluginInstalled: boolean;
        hookInstalled: boolean;
    };
}
export interface CleanOptions {
    dryRun?: boolean;
}
export interface CleanResult {
    removed: string[];
    errors: Array<{
        description: string;
        error: string;
    }>;
}
/**
 * Build the full list of known residue locations and whether each one is
 * currently populated. Pure read — no mutation.
 */
export declare function scanForResidue(): ResidueReport;
/**
 * Detect whether the SC plugin / hook are currently installed on disk.
 * Used by `scanForOrphans()` to tell legitimate install state from true orphans.
 *
 * Plugin install location depends on which install mode OpenClaw chose:
 *
 *   1. **native-package** (Mac homebrew, npm-global in OpenClaw's search path) —
 *      plugin lives at `${npmRoot}/shieldcortex/plugins/openclaw/dist/`. The
 *      user-space `~/.openclaw/extensions/` is NOT populated.
 *   2. **trusted-local-copy** (Linux fleet, npm-global outside the search path) —
 *      plugin is copied to `~/.openclaw/extensions/shieldcortex-realtime/`.
 *
 * The most reliable signal is the `installPath` recorded under
 * `openclaw.json: .plugins.installs[shieldcortex-realtime]` — that's the path
 * the installer actually used. We honour that first, then fall back to the
 * known install locations so we can still detect installs that pre-date the
 * `installPath` field.
 */
/**
 * The plugin counts as installed when OpenClaw has registered it in BOTH
 * `plugins.entries[<id>]` AND `plugins.allow[]`.
 *
 * Background: when the plugin was installed via `openclaw plugins install <pkg>`
 * (native-package mode — Mac homebrew, Linux global), OpenClaw stores the plugin
 * in its own internal tree, NOT under `~/.openclaw/extensions/`. From the doctor's
 * perspective there are no plugin bytes on disk in any of the paths it checks.
 * Without this check the doctor false-flags `plugins.entries[<id>]` and
 * `plugins.allow[<id>]` as "OpenClaw residue" on every Mac homebrew install
 * (the user-reported symptom on 4 May 2026 that triggered this fix).
 *
 * Exported for direct unit testing without having to mock fs / os.homedir().
 */
export declare function isPluginRegisteredInOpenClawConfig(cfg: unknown): boolean;
/**
 * Return only residue entries that are TRUE ORPHANS — meaning the config /
 * lock-file entry references a ShieldCortex artefact that is NOT currently
 * installed on disk, OR it's a legacy path that shouldn't exist anymore.
 *
 * This is what `shieldcortex doctor` wants: it should flag partial-uninstall
 * wreckage without flagging every legitimate install as "residue" (which was
 * the v4.12.0 bug — the doctor couldn't tell a healthy install from a leftover).
 *
 * The `--deep` purge path continues to use `scanForResidue()` because its job
 * is to remove ALL traces unconditionally, not just orphans.
 */
export declare function scanForOrphans(): OrphanReport;
/**
 * Apply all pending removals from a residue report. Config mutations for the
 * same file are batched so we write each JSON file at most once.
 */
export declare function cleanResidue(report: ResidueReport, options?: CleanOptions): CleanResult;
/**
 * Best-effort restart of the OpenClaw gateway so the purged config takes
 * effect. Returns a structured report; never throws.
 *
 * Order of attempts:
 *   - Linux:  `systemctl --user restart openclaw-gateway`
 *   - macOS:  `launchctl kickstart -k gui/<uid>/ai.openclaw.gateway`
 *   - Fallback: skip with info message.
 */
export declare function restartOpenClawGateway(): Promise<{
    attempted: boolean;
    restarted: boolean;
    method: string;
    detail?: string;
}>;
/**
 * High-level entry point used by `shieldcortex uninstall --deep`.
 * Scans → cleans → (optionally) restarts gateway.
 */
export declare function runDeepClean(options?: {
    dryRun?: boolean;
    restartGateway?: boolean;
}): Promise<{
    report: ResidueReport;
    result: CleanResult;
    gateway?: Awaited<ReturnType<typeof restartOpenClawGateway>>;
}>;
export declare const _internals: {
    PLUGIN_ID: string;
    HOOK_NAME: string;
    resolveHome: typeof resolveHome;
};
export {};
