/** A workflow (prompt-template) command: built-in PROMPT_COMMANDS or a custom
 *  `.gg/commands/*.md` entry. `prompt` is the full template body the command
 *  expands to when run. */
export interface WorkflowCommandSpec {
    name: string;
    aliases?: readonly string[];
    prompt: string;
}
/** The exact separator AgentSession.prompt() inserts between a command's
 *  template and the user's extra args (see agent-session.ts prompt expansion).
 *  Must stay byte-identical or expanded-command detection silently breaks. */
export declare const USER_INSTRUCTIONS_HEADER = "\n\n## User Instructions\n\n";
/**
 * True when `text` invokes a known workflow command (first token, name or
 * alias, case-insensitive). Registry/UI commands and unknown `/foo` return
 * false — those add no assistant work and are caught by the
 * `no-assistant-output` gate instead.
 */
export declare function isWorkflowCommandText(text: string, commands: readonly WorkflowCommandSpec[]): boolean;
/**
 * Match a transcript user-message body back to the workflow command it was
 * expanded from. AgentSession stores the EXPANDED template as a plain user
 * message, so without this Ken's digest renders 400-line templates as
 * `**User:** …` and treats them as user-authored asks.
 *
 * Returns the matched command plus any trailing user args, or null.
 */
export declare function matchExpandedCommand(text: string, commands: readonly WorkflowCommandSpec[]): {
    command: WorkflowCommandSpec;
    args: string | null;
} | null;
/** Count assistant messages — the "did this run produce reviewable work"
 *  signal. Compared before/after a run by the sidecar. */
export declare function countAssistantMessages(messages: ReadonlyArray<{
    role: string;
}>): number;
/** Extract every tool call made by assistant messages from `startIndex`
 *  onward — i.e. the tool calls added during one turn, given the message
 *  array length captured before that turn ran. Used to feed
 *  isMechanicalOnlyTurn without the gate module depending on gg-ai's full
 *  Message type (kept structurally typed so it's easy to unit test). */
export declare function extractTurnToolCalls(messages: ReadonlyArray<{
    role: string;
    content: string | ReadonlyArray<{
        type: string;
        name?: string;
        args?: Record<string, unknown>;
    }>;
}>, startIndex: number): TurnToolCall[];
export type AutopilotSkipReason = "disabled" | "cancelled" | "plan-mode" | "workflow-command" | "mechanical-only" | "no-assistant-output";
export interface AutopilotGateInput {
    /** The window's autopilot toggle. */
    enabled: boolean;
    /** True when /cancel fired during the turn. */
    cancelled: boolean;
    /** True when the session ended the turn in plan mode (plan modal pending). */
    planMode: boolean;
    /** True when the turn SUBMITTED a plan (exit_plan fired — the sidecar's
     *  pendingPlanPath is set). Ken reviews the plan itself instead of the
     *  work. Optional so existing callers/tests default to false. */
    planPending?: boolean;
    /** True when the turn was a workflow slash command (see isWorkflowCommandText). */
    workflowCommand: boolean;
    /** Assistant messages ADDED by this turn (after minus before). */
    assistantMessagesAdded: number;
    /** True when every tool call this turn was mechanical bash usage (see
     *  isMechanicalOnlyTurn) — nothing for Ken to review. Optional so existing
     *  callers/tests that don't set it default to false (reviewable). */
    mechanicalOnly?: boolean;
}
export type AutopilotGateDecision = {
    start: true;
    kind: "work" | "plan";
} | {
    start: false;
    reason: AutopilotSkipReason;
};
/**
 * Decide whether the autopilot cycle may start for a just-finished turn.
 * Checks are ordered cheapest/most-fundamental first; the reason is logged by
 * the sidecar so skips are debuggable from gg-app-sidecar.log.
 *
 * `planPending` beats the workflow/mechanical/no-output checks: a plan
 * submission via exit_plan flips plan mode OFF and often has only mechanical
 * tool calls, but it IS reviewable work — Ken reviews the plan itself
 * (kind: "plan") instead of skipping. `planMode` still wins over it: a turn
 * that ended INSIDE plan mode (enter without exit) has no submitted plan and
 * Ken must never prompt into a read-only session.
 */
export declare function shouldStartAutopilotCycle(input: AutopilotGateInput): AutopilotGateDecision;
/** A tool call made during a turn, as recorded on an assistant message's
 *  content parts. Mirrors gg-ai's `ToolCall` shape minus the fields the gate
 *  doesn't need (id). */
export interface TurnToolCall {
    name: string;
    args?: Record<string, unknown>;
}
/**
 * True when the turn has nothing for Ken to review: either it made NO tool
 * calls at all (a plain-text answer — "a plain question that got answered
 * with no code touched" is IGNORE per the autopilot contract), or EVERY tool
 * call was mechanical (a dedicated read-only tool, or bash usage that starts
 * a background process / is read-only / is a plain git commit-push chain).
 * ANY non-mechanical call (edit, write, subagent, generate_image, or bash
 * outside these safe shapes) makes the whole turn reviewable — conservative
 * default: keep reviewing whenever it's unclear.
 */
export declare function isMechanicalOnlyTurn(toolCalls: readonly TurnToolCall[]): boolean;
//# sourceMappingURL=autopilot-gate.d.ts.map