/**
 * Follow a dispatched host run by streaming its remote log.
 *
 * The run writes combined output to a log file on the host and its exit code to
 * a sibling `.exit` file. The primary path opens one long-lived
 * `ssh ... tail -f` stream (durable, offset-tracked — a dropped connection
 * reconnects from the saved offset) and finishes when the remote-side watcher
 * emits the exit sentinel. Rich transcript-parser rendering is a fast-follow.
 *
 * Efficiency: a healthy follow holds exactly one ssh process/socket for the
 * whole run instead of spawning once per poll cycle. If the connection drops,
 * the next stream resumes at the byte offset already flushed locally.
 */
/**
 * Cap for the LOCAL mirror of a distributed teammate's remote log. `followHostTask`
 * appends remote bytes into the local mirror forever; a team can spin 10+ chatty
 * remote teammates, so the orchestrator must keep a bounded window (the full log
 * always lives on the host). The teams remote path (agents.ts readNewEvents) writes
 * its own append into each teammate's `stdout.log`, then truncates that file to its
 * trailing `REMOTE_MIRROR_MAX_BYTES` — the parser has already consumed the bytes
 * (status/digest updated via lastReadPos), so trailing-tail history is dead weight.
 */
export declare const REMOTE_MIRROR_MAX_BYTES: number;
/**
 * Pull the new bytes of a remote log since `offset` in ONE ssh round-trip.
 *
 * The teams remote-teammate monitor calls this each poll to advance its offset-tail
 * cursor into the host's log, mirroring only the delta into the local `stdout.log`
 * the stream-json parser consumes. Byte-exact (raw Buffer, no UTF-8 decode) so a
 * multibyte character split at the `tail -c` boundary neither drifts the offset nor
 * renders as U+FFFD — the same discipline `fetchProgress` uses. `bytes.length` is
 * the exact wire count; `newOffset` is `offset + bytes.length`.
 *
 * Returns null on a transient ssh failure (the caller retries next poll without
 * advancing). `remoteLog` is a $HOME-prefixed path with a safe basename; it's
 * shell-quoted defensively even so.
 */
export declare function pullRemoteLogDelta(target: string, opts: {
    remoteLog: string;
    offset: number;
    extraSshArgs?: string[];
}): {
    bytes: Buffer;
    newOffset: number;
} | null;
export interface FollowOptions {
    remoteLog: string;
    remoteExit: string;
    /** Mirror remote output into this task's local log too. */
    taskId: string;
    /** Print streamed output to stdout. */
    echo?: boolean;
    /** Overall wall-clock cap; returns -1 on timeout. */
    timeoutMs?: number;
    /** Fast poll interval while output is flowing (default 1500ms). */
    pollMs?: number;
    /** Idle-backoff ceiling (default 4× the fast interval, min 4000ms). */
    maxPollMs?: number;
    extraSshArgs?: string[];
    remoteShell?: 'posix' | 'powershell';
}
/**
 * Build the per-task sentinel that separates the log tail from the exit-file
 * contents in one combined fetch. The task id (8 hex chars) makes collision with
 * the agent's own output effectively impossible; callers still split on the LAST
 * occurrence so a token echoed into the log can never be mistaken for the real
 * trailing marker.
 */
export declare function exitMarker(taskId: string): string;
/**
 * Split a combined fetch (`<log bytes><marker><exit>`) back into its parts at the
 * BYTE level. Splits on the LAST marker occurrence, so even if the agent's own
 * output happened to echo the token, the real trailing sentinel still wins.
 * Returns null when the marker is absent (a transient fetch miss — the remote
 * shell never ran our printf), telling the caller to retry without advancing.
 *
 * Byte-level (not string) is load-bearing: `logChunk.length` is the EXACT number
 * of log bytes consumed on the wire, which the follow loop adds to its offset. A
 * string split would first UTF-8-decode, turning any multibyte char split at the
 * `tail -c` boundary into a U+FFFD whose re-encoded length ≠ the wire bytes,
 * drifting the offset (see followHostTask). `consumed` is returned explicitly for
 * clarity; it always equals `logChunk.length`.
 */
export declare function splitProgressBytes(buf: Buffer, taskId: string): {
    logChunk: Buffer;
    exit: Buffer;
    consumed: number;
} | null;
/**
 * One round-trip: new log bytes since `offset`, the sentinel, then the exit
 * file. Returns null on a transient fetch miss (ssh error / marker absent) so
 * the caller simply retries next cycle without advancing the offset.
 *
 * `remoteLog`/`remoteExit` are $HOME-prefixed paths with safe (hex) basenames —
 * intentionally unquoted so the remote shell expands $HOME.
 */
export declare function fetchProgress(target: string, opts: {
    remoteLog: string;
    remoteExit: string;
    taskId: string;
    offset: number;
    extraSshArgs?: string[];
    remoteShell?: 'posix' | 'powershell';
}): {
    logChunk: Buffer;
    exit: string;
} | null;
export declare function buildWindowsProgressCommand(opts: {
    remoteLog: string;
    remoteExit: string;
    taskId: string;
    offset: number;
}): string;
/**
 * Remote shell for the persistent follow stream.
 *
 * Protocol: stream `tail -c +<offset+1> -f <log>` as raw stdout until `.exit`
 * becomes non-empty, give tail one more polling interval to flush final bytes,
 * stop it, then print the same per-task sentinel and `cat` the exit file on
 * stderr. Keeping the terminal frame off stdout lets log bytes pass through
 * live without buffering and without confusing agent output for our marker.
 * `remoteLog`/`remoteExit` are dispatch-generated `$HOME` paths with safe hex
 * basenames (or absolute paths in localhost integration tests), so they stay
 * unquoted to preserve `$HOME` expansion just like `fetchProgress`.
 */
export declare function buildStreamingFollowCommand(opts: {
    remoteLog: string;
    remoteExit: string;
    taskId: string;
    offset: number;
}): string;
/** Extract the remote watcher frame from stderr, if the stream ended normally. */
export declare function parseStreamingExitFrame(stderr: Buffer, taskId: string): Buffer | null;
/**
 * File identity (`dev:ino`) of a path on the remote host, or null if it can't be
 * stat'd. GNU (`-c`) then BSD (`-f`) format, so it works on Linux and macOS hosts.
 */
export declare function readRemoteFileId(target: string, remotePath: string, extraSshArgs?: string[]): string | null;
/**
 * True when the local mirror file IS the very file we're tailing — the
 * localhost-as-host case, where `remoteLog` ($HOME-expanded) and `localLogPath`
 * resolve to the same inode. Appending our read bytes back into it would feed the
 * tail and multiply the log, so the caller must skip the mirror write.
 */
export declare function mirrorAliasesSource(localId: string | null, remoteId: string | null): boolean;
/** Tail the remote log to stdout until the run finishes; return its exit code. */
export declare function followHostTask(target: string, opts: FollowOptions): Promise<number>;
