/**
 * Post-rollout verification for `agents fleet update` / `agents devices update`.
 *
 * The rollout runs `agents upgrade --yes` per box and calls a box `ok` on
 * `exit 0` alone ({@link ../devices/fleet.js runFleet}, `fleet.ts:262`), rendered
 * as `ok  exit 0` (`commands/ssh.ts:416`). That exit code says the npm global was
 * upgraded — it says nothing about **which copy `agents` resolves to on that
 * box**. Any install earlier on PATH than the npm global — a stale copy in
 * another node prefix, a Homebrew shim, a hand-made symlink — keeps winning the
 * name after the upgrade. The upgrade then succeeds, the rollout prints `ok`,
 * and every `agents` command on that box still runs the old code (RUSH-2446).
 *
 * `scripts/install.sh` used to be the usual culprit, linking its side-by-side
 * dev build over `~/.local/bin/agents`; it now publishes `agents-dev` instead and
 * cleans up the links it left. This probe stays as the general backstop — it is
 * name-based (`command -v agents`), so it catches every other cause too.
 *
 * So the rollout asks each box one more question after upgrading: what does
 * `agents` resolve to here, and what version does it report? A box whose
 * resolved `agents` is not on the target is reported as **not upgraded**, and a
 * dev stamp is named as such — never counted as a success.
 *
 * Everything below the probe argv is pure: the shell output is parsed and
 * classified without touching a filesystem or a network, so the verdicts are
 * unit-tested against real probe output rather than a mocked fleet.
 */
import { runLocalCommand, runOnDevice, type FleetRunResult, type FleetTarget } from './fleet.js';
/**
 * Argv for the verification probe, run on each box right after its upgrade.
 *
 * Space-joined and evaluated by a shell on both fleet paths — `runOnDevice`
 * hands the tokens to ssh (the remote shell parses them) and `runLocalCommand`
 * joins them under `shell: true` (`fleet.ts:runLocalCommand` docblock) — so the
 * quoting here is the same on the self target and every peer.
 *
 * POSIX only, deliberately: the two `sh` builtins it needs (`command -v`,
 * parameter substitution) do not exist in cmd.exe, so a Windows box yields no
 * parseable output and {@link classifyRolloutVerification} reports it
 * `unverified` rather than silently passing it.
 *
 * `command -v agents` is the resolution the user's own shell performs;
 * `readlink -f` follows the npm/dev bin symlink to the copy that actually runs,
 * falling back to the unresolved path where `readlink -f` is unavailable.
 */
export declare function rolloutVerifyCommand(): string[];
export interface RolloutProbe {
    /** Path the box's own `agents` resolves to, symlinks followed. */
    resolvedPath?: string;
    /** Version that resolved copy reports. */
    reportedVersion?: string;
}
/** Parse the probe's stdout. Unlabelled lines (shell banners, motd) are ignored. */
export declare function parseRolloutVerifyOutput(stdout: string): RolloutProbe;
export type RolloutVerdict = 
/** The resolved `agents` reports the target version. */
'on-target'
/** The resolved `agents` is a `scripts/install.sh` dev build shadowing the upgraded global. */
 | 'dev-shadowed'
/** The resolved `agents` reports some other version — the upgrade did not reach it. */
 | 'not-upgraded'
/** The probe produced no usable answer, so upgraded-ness is unknown. */
 | 'unverified';
export interface RolloutVerification extends RolloutProbe {
    verdict: RolloutVerdict;
    /** One-line human reason, always set for a non-`on-target` verdict. */
    detail: string;
}
/** A verdict other than `on-target` MUST NOT be reported as a successful rollout. */
export declare function isRolloutSuccess(verdict: RolloutVerdict): boolean;
/**
 * Resolve the version the rollout was aiming at.
 *
 * An explicit `agents fleet update <version>` names it. A bare
 * `agents fleet update` resolves the `latest` dist-tag independently on every
 * box, so the aggregator never sees a number — it is derived here as the highest
 * **released** version any probed box reports. Dev stamps are excluded from that
 * derivation: a fleet of dev builds must not elect one of them as the target and
 * report itself upgraded. Returns undefined when nothing released was observed,
 * which makes every box `unverified` rather than falsely `on-target`.
 */
export declare function resolveRolloutTarget(explicitVersion: string | undefined, probes: RolloutProbe[]): string | undefined;
/** Classify one box's probe against the rollout target. */
export declare function classifyRolloutVerification(probe: RolloutProbe, targetVersion: string | undefined): RolloutVerification;
export interface VerifyFleetRolloutOptions {
    /** Name of THIS machine; its target is probed locally, mirroring `runFleet`. */
    self?: string;
    /** Injectable ssh runner (tests). */
    runner?: typeof runOnDevice;
    /** Injectable local runner (tests). */
    localRunner?: typeof runLocalCommand;
}
/**
 * Probe every box the upgrade reported `ok` and classify what its `agents`
 * actually resolves to. Keyed by device name.
 *
 * Only `ok` boxes are probed: a `skipped` or `failed` row already reports itself
 * loudly, and re-probing it would add a second confusing line for one fault.
 * A probe that throws or exits non-zero yields `unverified`, never `on-target` —
 * "we could not check" and "it is upgraded" are different answers.
 */
export declare function verifyFleetRollout(targets: FleetTarget[], results: FleetRunResult[], explicitVersion: string | undefined, opts?: VerifyFleetRolloutOptions): Map<string, RolloutVerification>;
