/**
 * olam doctor — pass/fail host-health command.
 *
 * Phase A3 of olam-operator-onboarding-parity (original 5 probes) +
 * Phase C / C2 of olam-host-cp-k3s-prereqs (engine + colima probes) +
 * Phase 2 Phase A A5 (probeNodeMemory — kubernetes-only, D29).
 *
 * Probe layout — Decision 16 positional contract for `--json` consumers:
 *
 *   On engine=docker (default):
 *     1. docker daemon                — probeDockerDaemon (fast-fail gate)
 *     2. images                       — probeImagePresence (per-image)
 *     3. host-cp /health              — probeHostCpHealth
 *     4. auth vault                   — probeAuthVault
 *     5. KG storage                   — probeKgStorage
 *     6. engine                       — probeEngine (NEW Phase C / C2)
 *     7. colima version               — probeColimaVersion (NEW Phase C / C2)
 *     8. bundle freshness             — probeBundleFreshness (NEW olam-world-bundle-freshness Phase A1)
 *        Position 8 in docker mode is docker-only (per-MODE positional contract;
 *        kubernetes mode keeps slot 8 = node memory). Non-gating: WARN when any
 *        world's `/opt/olam/agent-stream/dist/` differs from the host's freshly
 *        built `packages/intelligence/dist/agent-stream/`; PASS otherwise.
 *        Silent in kubernetes substrate mode (worlds-as-pods don't support
 *        `docker exec` reach-through; Phase C of the plan addresses cloud paths).
 *
 *   On engine=kubernetes:
 *     1. api server                   — probeK8sApiReachable     (slot replaced)
 *     2. images                       — probeK8sImagePresence    (slot replaced)
 *     3. host-cp /health              — probeHostCpHealth        (unchanged)
 *     4. auth vault                   — probeAuthVault           (unchanged)
 *     5. KG storage                   — probeKgStorage           (unchanged)
 *     6. engine                       — probeEngine              (unchanged)
 *     7. colima version               — probeColimaVersion       (unchanged)
 *     8. node memory                  — probeNodeMemory          (NEW Phase 2 A5, D29)
 *        Position 8 is kubernetes-only (D11 per-MODE positional contract).
 *        Non-gating: WARN when free RAM <4 GiB; PASS otherwise.
 *        Silent in docker/compose substrate mode.
 *
 * The `--json` payload's `probes[]` indexes are stable across engine swap:
 * consumers parsing `probes[0]` for "daemon-reachability" still see a
 * daemon-reachability probe; consumers parsing `probes[5]` for engine
 * identity see it regardless of which runtime is active.
 *
 * Exit code:
 *   - 0 on all PASS
 *   - 0 on PASS+WARN  (WARN doesn't block — Colima 0.10.x is a hint)
 *   - 1 on any FAIL
 *
 * Output format:
 *   - `[PASS]` / `[WARN]` / `[FAIL]` prefix per row.
 *   - Indented detail under WARN/FAIL.
 *   - `--json` emits the same probe array (canonical positional shape).
 */
import type { Command } from 'commander';
import { defaultDetectK8sClusterType, buildDockerSocketRemedy, type ProbeResult, type DockerExec, type FetchLike, type DetectK8sClusterTypeFn } from '../lib/health-probes.js';
import { kubectlWrap } from '../lib/kubectl-wrap.js';
import * as fs from 'node:fs';
interface DoctorOptions {
    readonly json?: boolean;
}
interface ProbeRow {
    readonly name: string;
    readonly result: ProbeResult;
    /** D11 positional contract. 1-indexed stable position for --json consumers. */
    readonly position: number;
}
interface DoctorReport {
    readonly rows: ReadonlyArray<ProbeRow>;
    readonly summary: 'OK' | 'FAILED';
    readonly failureCount: number;
    readonly warnCount: number;
}
export interface RunDoctorDeps {
    readonly dockerExec?: DockerExec;
    readonly fetchImpl?: FetchLike;
    readonly olamHomeOverride?: string;
    /** Override registry prefix used to derive registry-prefixed image refs. Defaults to ghcr.io/pleri. */
    readonly registry?: string;
    /**
     * Phase C / C2: explicit engine override. When omitted the engine is
     * derived from `OLAM_HOST_CP_ENGINE` (falls back to 'docker'). Tests
     * use this hook to exercise both index-stability paths without
     * spinning up a real K8s cluster.
     */
    readonly engine?: 'docker' | 'kubernetes';
    /**
     * Phase 2 A5: kubectl context name passed to probeNodeMemory.
     * When omitted, kubectl uses the current context from kubeconfig.
     */
    readonly kubectlContext?: string;
    /**
     * olam-world-bundle-freshness Phase A1: repo-root override for the
     * bundle freshness probe. When omitted the probe walks up from
     * `process.argv[1]` to find a parent with both `packages/` and
     * `package.json` (source-mode CLI). Tests inject a fixture root.
     */
    readonly repoRootOverride?: string;
    /**
     * D2: injectable kubectlWrap for peripheral probes. Defaults to real kubectlWrap.
     * Tests inject a mock to avoid real kubectl invocations.
     */
    readonly kubectlWrapImpl?: typeof kubectlWrap;
    /**
     * D2: injectable readFileSync for probeStorageClassMatch (reads PVC manifest).
     * Defaults to fs.readFileSync.
     */
    readonly readFileSyncImpl?: typeof fs.readFileSync;
    /**
     * D2: override for the k8s manifests dir (default: ~/.olam/k8s/manifests).
     */
    readonly manifestsDir?: string;
    /**
     * olam-k3d-on-mac-substrate-decision Phase C C1: injectable host-side
     * proxy status check for probeHostSideProxyReachability. Receives the
     * resolved compose-yaml path and returns 'running' / 'stopped' /
     * 'unknown'. Tests inject a mock to avoid real `docker compose` calls.
     * Replaces D7's `dockerSocketCheckImpl` semantic — same field name kept
     * for back-compat with existing test fixtures; type signature changed
     * (composePath instead of kubectl context).
     */
    readonly dockerSocketCheckImpl?: DockerSocketCheckFn;
    /**
     * Phase C C1: override the resolved compose-yaml path for the host-side
     * proxy probe. Tests pass a fixture path; production resolves via
     * resolveK8sAssetsRoot().
     */
    readonly hostSideProxyComposePathOverride?: string | null;
    /**
     * Issue #713 (RETIRED in olam-k3d-on-mac-substrate-decision Phase C C1):
     * the colima cluster detector was used by the previous
     * probeDockerSocketBindMount's remedy-text differentiation. The new
     * probeHostSideProxyReachability emits one remedy with both macOS and
     * Linux variants inline, so the detector is no longer consulted. Field
     * kept for back-compat with existing tests; the value is never read.
     */
    readonly detectK8sClusterTypeImpl?: DetectK8sClusterTypeFn;
    /**
     * Override the Hermes home directory for the hermes-integration probe.
     * Tests inject a non-existent path to suppress the probe (no ~/.hermes/
     * on the test machine expectation). Production: defaults to `~/.hermes`.
     * Set to a specific temp dir to exercise the probe in tests.
     */
    readonly hermesHomeOverride?: string;
    /**
     * Phase D D1: override the olam config path for engine resolution.
     * When omitted defaults to `~/.olam/config.json`. Tests inject a temp
     * path with a fixture config to exercise the config-file fallback in
     * `resolveEngine()` without touching the real ~/.olam/config.json.
     */
    readonly configPath?: string;
}
interface RunResult {
    readonly exitCode: number;
    readonly report: DoctorReport;
}
/**
 * Run probes against the host. Probe-1 (daemon / API) runs FIRST + ALONE.
 * If it fails, the remaining slot-1+2 probes are SKIPPED — image presence
 * probes against a paused daemon / unreachable cluster return confusing
 * errors that misdirect the operator's fix (Risk T5 mitigation per plan).
 *
 * On daemon-success, probes 2-7 run in parallel via Promise.all
 * (P1 budget: doctor < 2s on healthy host).
 *
 * Phase C / C2: engine-aware. When `engine=kubernetes` we substitute
 * positions 1 + 2 in-place to preserve the positional `--json` contract.
 */
export declare function runDoctor(opts: DoctorOptions, deps?: RunDoctorDeps): Promise<RunResult>;
/** Injectable type for the host-side docker-socket-proxy status check. */
export type DockerSocketCheckFn = (composePath: string) => Promise<'running' | 'stopped' | 'unknown'>;
export { defaultDetectK8sClusterType, buildDockerSocketRemedy };
export type { DetectK8sClusterTypeFn };
/**
 * runK8sPreflight — Issue #713 narrowed pre-deploy check for `olam substrate set kubernetes`.
 *
 * The full `runDoctor` kubernetes probe suite (probes 3-7: host-cp /health,
 * auth vault, KG storage, engine, colima) requires host-cp to be already deployed.
 * When the operator runs `substrate set kubernetes` on a fresh cluster BEFORE
 * `olam upgrade`, those probes fail with ok:false because host-cp doesn't exist yet.
 *
 * This narrowed preflight only checks gates the operator CAN satisfy BEFORE
 * `olam upgrade`:
 *   1. kubectl binary present + cluster reachable (probeK8sApiReachable)
 *
 * Exits 0 when the single gate passes; 1 when kubectl/cluster is unreachable.
 * The full `olam doctor --substrate=kubernetes` covers the complete post-deploy
 * suite — operators should run that AFTER `olam upgrade` to confirm health.
 *
 * Exported for injection into substrate.ts's handleSet via SubstrateDeps.runDoctor.
 */
export declare function runK8sPreflight(opts: DoctorOptions, deps?: Pick<RunDoctorDeps, 'dockerExec'>): Promise<RunResult>;
/**
 * runComposePreflight — narrowed pre-deploy check for `olam substrate set compose`.
 *
 * Mirrors {@link runK8sPreflight} for the compose direction. The full
 * `runDoctor` compose suite (probes 3-5: host-cp /health, auth vault, KG storage)
 * requires host-cp to be already running under docker compose. When the operator
 * switches FROM kubernetes TO compose on a host that has never run compose
 * host-cp, those probes fail with ok:false because the container doesn't exist yet.
 *
 * This narrowed preflight only checks the gates the operator CAN satisfy BEFORE
 * `olam bootstrap` / `olam upgrade`:
 *   1. docker daemon reachable    (probeDockerDaemon)
 *   2. docker compose v2 plugin    (probeComposePlugin — B2: npm-only-via-Homebrew operators)
 *
 * Daemon comes first (fast-fail per Risk T5). If the daemon is down, the compose
 * plugin probe would emit a redundant / confusing remedy.
 *
 * Exits 0 when both probes pass; 1 when either fails. The full
 * `olam doctor` covers the complete post-deploy suite — operators run that
 * AFTER `olam bootstrap` to confirm host-cp health.
 *
 * Exported for injection into substrate.ts's handleSet via SubstrateDeps.runComposePreflightFn.
 */
export declare function runComposePreflight(opts: DoctorOptions, deps?: Pick<RunDoctorDeps, 'dockerExec'>): Promise<RunResult>;
/**
 * Non-gating WARN probe: surfaces when a hermes directory exists but olam is
 * not bootstrapped (missing mcp_servers.olam or kg-first hook).
 *
 * hermesDir: the Hermes home directory to inspect (typically ~/.hermes).
 * Callers that inject a non-existent path get PASS immediately (probe silent).
 */
export declare function probeHermesIntegration(hermesDir: string): ProbeResult;
export declare function registerDoctor(program: Command): void;
//# sourceMappingURL=doctor.d.ts.map