import type { AgentMessage, ExecutionEnv, GitAnnouncementKind, SessionTreeEntry } from "../../internal/harness-types.js";
/** Bound into the hash domain: bump when the frame's wording/structure changes so the upgraded
 *  renderer re-announces on its first leg instead of being suppressed by a pre-upgrade hash. */
export declare const GIT_STATUS_FRAME_FORMAT_VERSION = 1;
/**
 * The frame's own first paragraph (replaces the CC "will not update during the conversation" head,
 * which would be FALSE under the frame protocol). Wording obligations: self-declares the update
 * semantics (latest frame supersedes earlier ones), promises re-send on VISIBLE-view change only
 * (truncation-bound honesty), and "observed while preparing" does not claim an atomic instant (the
 * probe is two shell round-trips and a write can land between them).
 */
export declare const GIT_STATUS_FRAME_PREAMBLE = "This is the git status observed while preparing this request. When the visible snapshot changes it will be re-sent in a later message \u2014 the most recent git status frame supersedes earlier ones.";
/** Tombstone body — the probes could not reach git at all while earlier frames announced a
 *  positive view (sent once, on the availability flip edge only). */
export declare const GIT_STATUS_UNAVAILABLE_BODY = "Git status is currently unavailable; the most recent git status frame above may be stale.";
/** Tombstone body — the directory stopped being a git repository while earlier frames announced a
 *  positive view (sent once, on the flip edge; the env block's static is-repo line flips the same leg). */
export declare const GIT_STATUS_NON_REPO_BODY = "The working directory is no longer a git repository; earlier git status frames no longer apply.";
/** The `steering_injected` echo previews for the frame — CONSTANT wordings on purpose: branch and
 *  status text are repo-controlled and must not enter the event telemetry plane through the echo. */
export declare const GIT_STATUS_ECHO_PREVIEW: Record<GitAnnouncementKind, string>;
/** The raw material of one probe cycle, as prepare-task resolved it (§4.3 unified ladder):
 *  - `full`     — §E14 and the H4 snapshot both succeeded: `snapshot` = the pre-rendered
 *                 {@link import("../../prompts/default.js").buildGitSnapshot} block (CC template,
 *                 sanitized + bounded by its renderer);
 *  - `degraded` — §E14 yielded git facts but the H4 snapshot failed (exit 41/42, timeout, sentinel
 *                 mis-split): branch + dirtiness are all that is honestly known;
 *  - `unavailable` — the §E14 probe itself failed (git facts unknowable this leg);
 *  - `non-repo` — the probe ran and the cwd is not a git repository. */
export type GitStatusProbeOutcome = {
    kind: "full";
    snapshot: string;
} | {
    kind: "degraded";
    branch?: string;
    dirty?: boolean;
} | {
    kind: "unavailable";
} | {
    kind: "non-repo";
};
/** Render the frame BODY (the text inside the `<system-reminder>` shell) for one probe outcome. */
export declare function renderGitStatusFrameBody(outcome: GitStatusProbeOutcome): string;
/**
 * Content hash of a rendered frame body — the hash half of the `(kind, hash)` comparison tuple.
 * Digest domain = format version + canonical repo root + kind + body, NUL-separated (none of the
 * inputs may contain NUL: the body is sanitized text, the root a canonical path). `canonicalRoot`
 * is the ExecutionEnv-canonicalized worktree root (or cwd outside a repo) so identical bytes from
 * two different checkouts never share an announcement.
 */
export declare function hashGitStatusFrame(kind: GitAnnouncementKind, body: string, canonicalRoot: string): string;
/** One resolved frame — outcome rendered and hashed, ready for the (kind, hash) compare. */
export interface ResolvedGitStatusFrame {
    kind: GitAnnouncementKind;
    body: string;
    hash: string;
    /** Pre-rendered DEGRADED body + hash for the same probe cycle (present only when kind is
     *  `full`): the one-shot deterministic shrink target of the irreducible-core over-budget arc —
     *  computed at prepare time because the request-build path must not re-run probes. */
    shrunk?: {
        body: string;
        hash: string;
    };
}
/** Render + hash one probe outcome (and its deterministic degraded shrink target when full). */
export declare function resolveGitStatusFrame(outcome: GitStatusProbeOutcome, canonicalRoot: string, degradedMaterial?: {
    branch?: string;
    dirty?: boolean;
}): ResolvedGitStatusFrame;
/**
 * The run-local git-status lane state (one per run, on `Prepared`) — the coordination surface
 * between prepare (probe resolution), the run loop (delivery + receipt + compaction re-assertion)
 * and the request-build context handler (trim protection). Deliberately a plain mutable ref, the
 * `announcedListingsRef` discipline.
 */
export interface GitStatusLaneRef {
    /** This leg's resolved frame (undefined ⇒ hands-less leg: the lane is out of scope, announced
     *  state untouched — the env block equally carried no git facts for such a leg). */
    frame?: ResolvedGitStatusFrame;
    /** Canonical repo root the frame was hashed against. */
    canonicalRoot?: string;
    /** The announced state as THIS run knows it (seeded from the read ladder at leg start, advanced
     *  at each receipt) — mirrored onto the suspend checkpoint. `pending: true` ⇒ a re-announcement
     *  is owed (frame append failed / compaction restated pending); the next boundary retries. */
    announced?: {
        kind: GitAnnouncementKind;
        hash: string;
        entryId?: string;
        pending?: true;
    };
    /** Exact WRAPPED text of the newest announced frame — the frame SEGMENT, on both carry forms
     *  (this moved off "the whole first-message text"; the contract here had
     *  kept the pre-r1 words). The context guard finds the carrier by CONTAINING this engine-held
     *  string (engine-region gated), protects that carrier as a replace-by-key slot — only the newest
     *  carrier is protected, older frames trim like ordinary history — and charges the irreducible
     *  core by THIS segment, never by the whole carrier (the objective riding the same message keeps
     *  its own overflow exit). */
    protectedText?: string;
    /** One-shot latch of the irreducible-core arc's DISCLOSURE: the request view substituted the
     *  degraded rendering at least once (the substitution itself is per-request deterministic; the
     *  disclosure + pending re-announcement fire only on the first). */
    overBudgetShrunk?: boolean;
    /** The exact WRAPPED frame segment of the protected carrier and its degraded substitution target
     *  (both `<system-reminder>`-shelled, exactly as delivered) — the irreducible-core shrink is a
     *  literal string replace of `find` with `replace` inside the carrier's text. Set at delivery
     *  alongside {@link GitStatusLaneRef.protectedText}; present only for a full-kind frame. */
    wrappedShrink?: {
        find: string;
        replace: string;
    };
    /** Wired by the run loop once its queue exists: re-assert the current frame (compaction landing
     *  + boundary retry both call this). */
    reassert?: () => Promise<void>;
    /** F5 — the typed terminal's surface bridge: the loop converts a
     *  context-hook throw into a failure MESSAGE (text only), so the thrown `code` never reaches
     *  result assembly on its own. Set alongside the throw; the run loop lifts it into
     *  `TaskResult.errorCode`. */
    terminalCode?: "irreducible_core_over_budget";
    /** F4 — the receipt's mirror write, PARKED instead of fired: a
     *  fire-and-forget CAS append from inside the message_end walk can race the loop's own next
     *  transcript append and fail the CRITICAL write with a conflict. The run loop flushes this at
     *  serialization points only (turn boundary, prompt settle); an unflushed slot at suspend is
     *  covered by the checkpoint rung (the frame IS on the branch — visibility check passes). */
    mirrorOwed?: {
        kind: GitAnnouncementKind;
        hash: string;
        entryId: string;
    };
}
/**
 * prepare-side probe half of the lane (H4, extracted from prepareTask): run the CC-shape snapshot
 * round-trip through the SAME ExecutionEnv seam when the
 * §E14 probe confirmed a repo, resolve the outcome through the §4.3 unified kind ladder, and hash
 * the rendered frame with the canonical repo root bound in. `envFacts` carries the §E14 results
 * (read-only here). Every degrade names its reason through `onDegrade` — including the sentinel
 * MIS-SPLIT arm (parts !== 4), which previously dropped the snapshot with ZERO telemetry (the
 * loud-bad-value fix). Returns the run's lane ref (empty on a hands-less leg).
 *
 * H4 anchor notes carried from the prepareTask body: four sections split by a sentinel line —
 * main-branch inference (CC qP symref → [inferred, main, master] each show-ref → renderer falls
 * back "main"), `git config user.name`, `git --no-optional-locks status --short`, and
 * `git --no-optional-locks log --oneline -n 5` (CC-exact commands). The two
 * REQUIRED sections fail the WHOLE script with distinct exit codes (41 = status, 42 = log) so a
 * failing status never half-renders as "(clean)"; both now DEGRADE the frame to the branch+dirty
 * residual instead of silently skipping. The main-branch/user sections stay best-effort.
 */
export declare function probeGitStatusLane(args: {
    executionEnv: Pick<ExecutionEnv, "exec" | "canonicalPath">;
    envFacts: {
        isGitRepo?: boolean;
        gitBranch?: string;
        gitDirty?: boolean;
        gitWorktreeRoot?: string;
        cwd?: string;
    };
    handsEnabled: boolean;
    taskRoot: string;
    onDegrade: (reason: string) => void;
}): Promise<GitStatusLaneRef>;
/**
 * Request-build half of the trim protection (extracted from prepareTask's context handler under the
 * same D-7 ratchet): wraps {@link protectGitFrame} with the lane ref's state — the substitution
 * pair, the one-shot disclosure latch and the pending re-announcement on the first shrink — and
 * converts the over-budget verdict into the LOUD typed terminal (`irreducible_core_over_budget`),
 * never a pretended trim success. Returns the (possibly re-inserted / shrunk) request view.
 */
export declare function applyGitFrameGuard(args: {
    before: AgentMessage[];
    trimmed: AgentMessage[];
    budgetTokens: number;
    ref: GitStatusLaneRef;
    charsPerToken?: number;
    onDegrade: (message: string) => void;
}): AgentMessage[];
/**
 * The transcript-side classifier of engine
 * git frames. The mirror plane is a CACHE of "which frame is newest"; the TRANSCRIPT is the truth,
 * and the two diverge exactly when a mirror write was lost. This scan finds the NEWEST engine git
 * frame on the branch, with TOP-LEVEL WRAPPED-UNIT matching:
 *   - positive frame: the wrapped unit's head (open tag + newline + the frame preamble);
 *   - tombstone: the exact wrapped unit (open tag + newline + tombstone body + newline + close tag);
 *   - the occurrence must sit inside the message's ENGINE region (engineMinted / enginePrefixChars
 *     / engineSegments — metadata gates, never user-text shape-guessing), AND at TOP LEVEL (r4-2:
 *     start-of-text or right after a close tag — a hook relay that QUOTES the exact frame unit
 *     nests it inside its own shell with prose before the open tag, and is rejected);
 *   - within one message the LAST top-level unit wins (textual order = issue order).
 */
export declare function newestEngineGitFrame(branch: SessionTreeEntry[], mark?: string): {
    entryId: string;
    positive: boolean;
} | undefined;
export declare function stripGitStatusUnits(text: string, mark?: string): string;
/**
 * The readable-absence tombstone question (R2-1), answered by the classifier above: does the
 * branch carry a still-context-visible POSITIVE engine frame as its newest git frame? A newest
 * TOMBSTONE means the disowning already happened (no re-spam); no frame at all means a genuinely
 * fresh lane (no tombstone out of nowhere).
 */
export declare function branchCarriesVisiblePositiveGitFrame(branch: SessionTreeEntry[], mark?: string): boolean;
