/**
 * # sdk/op-schema — the ONE self-description of the agent JSONL protocol (kestrel-yuw4)
 *
 * The `kestrel agent` JSONL face lists its ops (`kestrel agent --help`, and the `unknown-op` refusal, #115)
 * but historically documented NONE of the per-op ARGUMENT OBJECT shapes — the `{ kind: … }` unions a
 * `subject` / `advance.response` must carry, and the exact accepted field NAMES (`document`, not
 * `text`/`bytes`/`source`/`content`). A cold integrator had to brute-force ~14 trial-and-error guesses to
 * discover them. This module is the SINGLE, machine-readable catalogue of those shapes:
 *
 *  - {@link AGENT_OP_SCHEMAS} — one {@link AgentOpSchema} per op (its args + response shape), the source the
 *    `describe` op emits VERBATIM on the wire, the source `kestrel agent --help` renders, and the source the
 *    MCP face's argument descriptions read. ONE definition; the cross-face drift guards
 *    (tests/cli.agent-describe.test.ts, tests/mcp.projection.test.ts) pin that nothing forks from it.
 *  - The shape VOCABULARY constants ({@link SUBJECT_SHAPE} et al.) — referenced by BOTH the catalogue entries
 *    AND the argument VALIDATORS below, so a refusal that names the expected shape can never drift from the
 *    shape the catalogue advertises (they read the same string).
 *  - The argument VALIDATORS ({@link asSessionRef} / {@link asAuthoredResponse} / {@link asBoundResponse} /
 *    {@link asEventCursor}) — a malformed argument object is a fail-closed {@link ArgShapeError} whose message
 *    NAMES the expected `{ kind: … }` vocabulary. STRUCTURE only: a well-formed-but-unresolvable VALUE (an
 *    unknown catalog id, an unsupported subject kind) is deliberately passed through to the SDK, whose typed
 *    DOMAIN refusal answers it — the transport/argument-error class must never absorb a Kestrel refusal.
 *
 * ZERO-WEIGHT: pure data + pure functions over type-only imports (erased at build). No runtime-semantics
 * import, so the light agent/SDK projection stays light (pinned by tests/package.boundary.test.ts).
 */
import type { AuthoredResponse, BoundResponse, SessionRef } from "./types.ts";
import type { EventCursor } from "../protocol/index.ts";
/** The `openSession.subject` shape — a discriminated {@link SessionRef} union (a STRING is rejected). */
export declare const SUBJECT_SHAPE = "{ \"kind\": \"catalog\", \"id\": string } | { \"kind\": \"dataset\", \"source\": string, \"dataset\": string }";
/**
 * The `advance.response` / `revise.response` shape — an {@link AuthoredResponse} union. `document` is the
 * ONLY accepted authored-body field name (NOT `text` / `bytes` / `source` / `content`), the exact fact a cold
 * integrator could not discover from any published surface (kestrel-yuw4).
 */
export declare const AUTHORED_RESPONSE_SHAPE = "{ \"kind\": \"authored\", \"document\": string } | { \"kind\": \"pass\" } | { \"kind\": \"stand-down\", \"reason\": string }";
/**
 * The CLOSED `AuthoredResponse.kind` union (kestrel-lzz7). UNLIKE `subject.kind` — an open discovery union
 * whose unknown values the SDK answers with an `unsupported-subject` DOMAIN refusal — the authored-response
 * kind is a fixed protocol enum with NO domain answer for an unknown value: a `frobnicate` kind reaches the
 * controller's exhaustive `responseToBody` switch, matches no case, and dereferences `body.kind` on the
 * resulting `undefined` (a raw `TypeError` surfaced as `code:"error"`). An unknown value is therefore a
 * malformed ARGUMENT, caught at the boundary as `bad-arg`, not passed through.
 */
export declare const AUTHORED_RESPONSE_KINDS: readonly ["authored", "pass", "stand-down"];
/** The `submit.response` shape — a fully-bound {@link BoundResponse} (the full pentad header + a TurnBody). */
export declare const BOUND_RESPONSE_SHAPE = "{ \"sessionId\": string, \"ordinal\": number, \"parentHash\": string, \"frameRoot\": string, \"body\": TurnBody }";
/**
 * The CLOSED {@link import("../protocol/session.ts").TurnBody}`.kind` union (kestrel-lzz7). A `submit`
 * response whose `body` is absent or carries an unknown `kind` reaches the controller's exhaustive
 * `reconcileTurn` switch, matches no case, and dereferences `body.kind` on `undefined` — the same raw
 * `code:"error"` leak as an unknown authored kind. A missing/unknown body kind is a malformed argument.
 */
export declare const TURN_BODY_KINDS: readonly ["authored", "stand-down", "failure"];
/** The optional `resume.after` / `resumeOperation.after` resume-cursor shape — an {@link EventCursor}. */
export declare const EVENT_CURSOR_SHAPE = "{ \"sequence\": number, \"token\": string }";
/** The `validate.document` shape — the Kestrel plan document source text (REQUIRED). */
export declare const VALIDATE_DOCUMENT_SHAPE = "the Kestrel plan document (source text)";
/** The `grade.blotters` shape — a REQUIRED non-empty array of Blotter artifact ids. */
export declare const BLOTTERS_SHAPE = "string[] \u2014 Blotter artifact ids (a Blotter's sessionId is its id)";
/** The `artifact.ref` shape — a REQUIRED content-addressed artifact reference. */
export declare const ARTIFACT_REF_SHAPE = "a content-addressed artifact ref";
/** The `resumeOperation.operationId` shape — the REQUIRED durable Operation id. */
export declare const OPERATION_ID_SHAPE = "the durable Operation id";
/**
 * The `catalog` op's response ROW shape — a {@link import("../protocol/catalog.ts").CatalogListing} (kestrel-dnxq).
 * The catalog op UNDER-specified its response before dnxq (`"CatalogEntry[] — each carries the id"`, no field
 * schema), so two divergent shapes both satisfied it; this pins the exact canonical fields BOTH transports emit
 * byte-identically. The reproducibility pins (content roots / engine versions / View identities) are NOT part of
 * discovery — they resolve at `openSession`/grade.
 */
export declare const CATALOG_LISTING_SHAPE = "{ \"id\": string, \"title\": string, \"description\": string, \"instrument\": string, \"period\": { \"start\": string, \"end\": string }, \"frameCount\": number, \"free\": boolean }";
/** One argument of an agent op: its wire field name, whether it is required, its JSON type, and — the point
 *  of this whole module — the exact `{ kind: … }` object SHAPE it must carry. */
export interface AgentOpArg {
    readonly name: string;
    readonly required: boolean;
    readonly type: "string" | "object" | "array";
    /** The exact accepted shape, in the `{ kind: … }` vocabulary — what a cold integrator needs to stop guessing. */
    readonly shape: string;
}
/** The self-description of one agent op: its args and its response shape, plus whether it needs a live Session. */
export interface AgentOpSchema {
    /** The `op` field a request line carries (`{ "op": <name>, …args }`). */
    readonly op: string;
    /** `true` ⇒ the op requires a prior `openSession` in the same stream (else it refuses `no-session`). */
    readonly session: boolean;
    /** A one-line human summary of what the op does. */
    readonly summary: string;
    /** The op's argument fields (empty for the session-free discovery ops). */
    readonly args: readonly AgentOpArg[];
    /** A one-line description of the protocol payload the op emits on the `value` channel. */
    readonly response: string;
}
/**
 * THE single ordered catalogue of the agent protocol's ops — the source `describe` emits, `--help` renders,
 * and the MCP argument descriptions read. `describe` leads (the self-description entry point); the order is
 * the handler/dispatch order and is the order {@link agentOpNames} (and thus `AGENT_OPS`) preserves.
 */
export declare const AGENT_OP_SCHEMAS: readonly AgentOpSchema[];
/** The ordered op names — derived from {@link AGENT_OP_SCHEMAS} so the advertised set can never fork from the
 *  described set. `AGENT_OPS` (src/cli/commands/agent.ts) is this list; the switch dispatches exactly it. */
export declare const agentOpNames: readonly string[];
/** The `describe` op's on-the-wire payload — the whole catalogue, tagged with the protocol version. */
export interface AgentDescribe {
    readonly protocol: string;
    readonly ops: readonly AgentOpSchema[];
}
/** Build the `describe` payload for a given protocol version tag (the agent face passes its own version). */
export declare function agentDescribe(protocolVersion: string): AgentDescribe;
/**
 * A fail-closed ARGUMENT-SHAPE refusal: a malformed argument OBJECT whose message NAMES the expected shape.
 * Carries a stable `code` (`bad-arg`) an agent matches on, and the offending `field`. DISTINCT from a Kestrel
 * DOMAIN refusal (an unresolvable but well-formed value) — validators throw this only for STRUCTURE errors.
 */
export declare class ArgShapeError extends Error {
    readonly name = "ArgShapeError";
    readonly code = "bad-arg";
    readonly field: string;
    constructor(field: string, expected: string, got: unknown);
}
/**
 * VALIDATE an `openSession.subject` — an OBJECT with a string `kind` and the fields its known kind requires
 * (`catalog` → `id`; `dataset` → `source` + `dataset`). An UNKNOWN kind value is passed through UNCHANGED to
 * the SDK (its `unsupported-subject` domain refusal answers it) — only STRUCTURE is enforced here.
 */
export declare function asSessionRef(v: unknown, field?: string): SessionRef;
/**
 * VALIDATE an `advance.response` / `revise.response` — an {@link AuthoredResponse} union. Enforces the exact
 * accepted authored-body field name (`document`, a string) — the fact a cold integrator could not discover.
 * `pass` needs no field; `stand-down` needs a string `reason`. An UNKNOWN kind is passed through to the SDK.
 */
export declare function asAuthoredResponse(v: unknown, field?: string): AuthoredResponse;
/**
 * VALIDATE a `submit.response` — a fully-bound {@link BoundResponse} OBJECT carrying a well-formed
 * {@link import("../protocol/session.ts").TurnBody} `body`. Field-level RECONCILIATION (a sessionId / ordinal
 * / parentHash mismatch against the recorded slot) stays the Session's DOMAIN job; only the STRUCTURE is
 * enforced here — including that `body` is present with a known `kind` (kestrel-lzz7), because a missing or
 * unknown body kind reaches the exhaustive `reconcileTurn` switch and dereferences `body.kind` on `undefined`.
 */
export declare function asBoundResponse(v: unknown, field?: string): BoundResponse;
/**
 * VALIDATE a REQUIRED string arg — `artifact.ref`, `resumeOperation.operationId`, `validate.document`
 * (kestrel-8h9f). An ABSENT value (`undefined`, or an empty `""` string) is a malformed ARGUMENT: the
 * `describe` catalogue marks the field `required: true`, and forwarding the absent value as `""` made the
 * server answer a MISDIRECTING `not-found` (404) / `422` instead of naming the omitted field. Refuse it
 * client-side as `bad-arg` naming the described shape, matching `openSession.subject` / `resume.after`.
 */
export declare function asRequiredString(v: unknown, field: string, shape: string): string;
/**
 * VALIDATE `grade.blotters` — a REQUIRED non-empty array of Blotter id strings (kestrel-8h9f). An absent /
 * empty / non-string-element array is a malformed argument refused `bad-arg` naming the shape, rather than the
 * server-side `empty-grade` domain refusal (inconsistent validation locus with the client-side arg checks).
 */
export declare function asBlotters(v: unknown, field?: string): readonly string[];
/**
 * VALIDATE an optional resume `after` cursor. ABSENT (`undefined`) is fine (resume from the start); a PRESENT
 * one must be a well-formed {@link EventCursor} `{ sequence:number, token:string }`. A malformed present
 * cursor is a bad ARGUMENT SHAPE (never silently ignored). STRICT: `null` is a present, wrong-typed value and
 * fails closed (deliberately NOT coalesced to undefined).
 */
export declare function asEventCursor(v: unknown, field?: string): EventCursor | undefined;
//# sourceMappingURL=op-schema.d.ts.map