/**
 * What the run loop derives from a tool call's occurrence (`tool-occurrence.ts`), in every leg that opens or
 * closes one: the `tool_start` and `tool_end` frames (the ONE start projection and the ONE end projection the
 * live loop, the resumed batch and both reconciles go through, with the frame body), the `toolResult`
 * transcript message the resume engine closes pending calls with, the thin
 * `response` digest the post-tool-batch observer is handed, and the canonical write-tool → reminder-window
 * family the attachment reducer keys on when a write tool ends.
 *
 * Projections over values the caller already holds, with ONE clock read: `toolResultMsg` stamps the message
 * it mints with `Date.now()` (as it did inside the driver — the transcript's timestamp is minted where the
 * message is). The one callback here is the leg's card projector, handed in by every caller (it keeps the
 * once-per-leg announce state; this module keeps none). Nothing here awaits.
 * Layer-1 machinery, not a driven lane; the prefix rule it follows is written once, on initial-run-state.ts.
 */
import { type AgentMessage } from "../../internal/harness.js";
import type { GateOutcome } from "../gate-outcome.js";
import type { TaskEvent, TaskEventIdentity } from "../types.js";
import type { OccurrenceStart, ToolOccurrenceTable } from "./tool-occurrence.js";
import { type McpDelivered } from "../mcp-failure.js";
import { type RecoveredOrphan } from "../session-reconcile.js";
import { type StructuredProjector } from "./tool-output-projection.js";
import type { WriteFamily } from "./turn-attachments.js";
/** Derive the thin `response` digest from a harness tool result: model-facing text
 *  content only (never `details` — the H4 thin-projection discipline), capped with a truncation note. */
export declare function batchResponseDigest(result: unknown): string | undefined;
/** The `tool_end` body fields projected from a harness tool result — output/truncated/totalChars via
 *  {@link toolOutputFrom} and the CC card via the LEG's projector (`Prepared.structuredProjector`: the engine card set
 *  ∪ the caller rows' declared `renderHints.resultCards`, an undeclared type dropped and announced once per leg —
 *  handed in because the once-per-leg state lives on the leg. Single construction point for BOTH
 *  the live loop's frames and the resumed batch's frames (`resolvePendingCall` + the deferred-sibling
 *  close): the resumed frames used to carry only `isError`, so a client rendering tool output from frames
 *  showed an empty body for every durable-approved call. Same projection = same source as the transcript.
 *  Also the one place the gate outcome reaches a frame — see the parameter. */
export declare function toolEndBodyFrom(result: unknown, isError: boolean, 
/** The leg's card projector (never a module default: the engine set alone drops every declared caller card unannounced) and media budget. */
leg: Pick<OccurrenceFrames, "structured" | "mediaByteCapBytes">, 
/** The gate's record of the pass that admitted or refused this call, supplied by the CALLER of this
 *  projection — the end projection ({@link emitSettled}) reads it off the call's occurrence (its latest gate
 *  record). Deliberately a parameter and never derived from `result`: a tool's own `details`
 *  (which post-tool hooks may also replace) is writable by layers that adjudicate nothing, so reading
 *  provenance out of it would let a failing tool claim a person approved it. Omitted ⇒ the call never
 *  went through the gate (see the `tool_end.gate` doc, the one home). */
gate?: GateOutcome, 
/** WHICH call this run's committed durable park is holding ({@link import("./park-commit.js").gatedCallIdOf}), for the frames the
 *  abort short-circuits. Same never-derived-from-`result` posture as the outcome above, and for the
 *  sharpest version of that reason: this one is an assertion about a DIFFERENT call, so a tool able to
 *  author it could point an approval UI at a call nobody is waiting on. Omitted ⇒ no park is holding a
 *  call (nothing parked, or the park that did holds none), and the frame then carries no id at all. */
gatedCallIdOfRun?: string): {
    output?: unknown;
    truncated?: boolean;
    totalChars?: number;
    structured?: unknown;
    errorCode?: string;
    delivered?: McpDelivered;
    gatedCallId?: string;
    gate?: GateOutcome;
};
/** A frame of one tool call before the leg stamps its identity. */
export type OccurrenceFrame = Omit<Extract<TaskEvent, {
    type: "tool_start";
}>, keyof TaskEventIdentity> | Omit<Extract<TaskEvent, {
    type: "tool_end";
}>, keyof TaskEventIdentity>;
/** Where an occurrence's frames go: the leg's push (it stamps the identity and picks the queue), its card projector and its media budget. */
export interface OccurrenceFrames {
    push(frame: OccurrenceFrame): void;
    structured: StructuredProjector;
    /** `RunnerDeps.mediaByteCapBytes` as given — the request strip's budget, read through the same `mediaBudgetBytes`; required, so no site reads a second one. */
    mediaByteCapBytes: number | undefined;
}
/** The START projection: the call's occurrence opens and its start frame goes out. Every leg that announces a call
 *  comes through here (the live loop's `tool_execution_start`, the resumed leg's approved call). */
export declare function announceToolCall(table: ToolOccurrenceTable, start: OccurrenceStart, frames: Pick<OccurrenceFrames, "push">): void;
/** How a call ended, as the station closing it knows it. */
export interface OccurrenceEnd {
    /** The harness result (or the exact text the closing station records). */
    result: unknown;
    isError: boolean;
    /** The CLOSING STATION's own POSITIVE evidence the call never executed — the loop's mark (a halted sibling may well have been let go by the gate) or the reconcile's never-started class; the engine's refusal is read off the occurrence. Absent = no such evidence, never "it ran". */
    notExecuted?: true;
    /** The call is closed by an interruption rather than a result of its own. */
    interrupted?: true;
    /** See {@link toolEndBodyFrom}'s parameter of the same name. */
    gatedCallIdOfRun?: string;
}
/** What the end projection decided, for the readers that ride beside the frame (the trace row, the row's record, the rows' `notExecuted`). */
export interface SettledOccurrence extends Pick<OccurrenceEnd, "notExecuted"> {
    /** The latest gate record — the call's disposition (absent when no gate exit saw it). */
    gate?: GateOutcome;
    /** The tool's own error bit, or a refusal recorded after the gate: the engine's record wins over the tool's word. */
    isError: boolean;
}
/**
 * The END projection — the ONE mint of `tool_end`, for every station that closes a call: the live loop's
 * `tool_execution_end`, the resumed leg's resolution, an interrupted run's reconcile and the reconcile replayed at
 * the next process start. It reads the occurrence and nothing else: `gate` is its latest gate record, `isError` is
 * the tool's bit or the refusal that record names, and `notExecuted` rides on positive evidence only: the station's own or `refusedBeforeRelease` (returned for the rows).
 *
 * A call whose start never went out on this stream (a call the loop never reached, a call announced by a dead
 * process) gets its start minted here first, marked `recovered` and carrying the input the closing station holds —
 * every end is preceded by a start with the same id. `start` opens the occurrence only when this leg holds none.
 */
export declare function emitSettled(table: ToolOccurrenceTable, start: OccurrenceStart, end: OccurrenceEnd, frames: OccurrenceFrames): SettledOccurrence;
/** The end of a call an interrupted run's reconcile closed: the persisted `[INTERRUPTED]` text is the body and its
 *  `errorKind` the frame's `errorCode` (no card — the reconcile mints none), and the never-started class is the
 *  positive evidence `notExecuted` needs. One reading for both reconciling legs (the live abort, the next start). */
export declare function reconciledEnd(orphan: Pick<RecoveredOrphan, "text" | "errorKind">): OccurrenceEnd;
/** task #51 F2/F3 — the CANONICAL write-tool → reminder-window mapping (CC qFm :480253-480254
 *  `a.name === bD || a.name === hF` = TaskCreate/TaskUpdate; BFm :480217-480219 = TodoWrite). Live
 *  deployment-alias resolution happens at the call sites (run-local `writeFamilyOf` over the mounted
 *  roster); retired-name normalization is gone. */
export declare function writeFamilyOfCanonical(name: string): WriteFamily | undefined;
/** A `toolResult` transcript message (text content). Used by the resume engine to close pending calls. */
export declare function toolResultMsg(toolCallId: string, toolName: string, text: string, isError: boolean): AgentMessage;
