import type { Conversation, TaskExecutionState } from './protocol/types.js';
export interface WriteGuardViolation {
    attemptedPath: string;
    allowedPaths: string[];
    message: string;
}
export declare function ensureTaskExecutionState(conversation: Conversation, cwd?: string): TaskExecutionState;
export declare function deriveTaskExecutionState(conversation: Conversation, cwd?: string, previous?: TaskExecutionState): TaskExecutionState;
export declare function describeTaskExecutionState(taskState: TaskExecutionState): string | null;
export declare function markTaskIteration(taskState: TaskExecutionState, details: {
    iterations: number;
    currentFocus?: string | null;
    dominantGap?: string | null;
}): void;
export declare function markTaskProgress(taskState: TaskExecutionState, focus?: string | null): void;
export declare function markTaskBlocked(taskState: TaskExecutionState, reason: string, focus?: string | null): void;
export declare function markTaskGuardBlocked(taskState: TaskExecutionState, reason: string): void;
export declare function markTaskWaitingUser(taskState: TaskExecutionState, reason: string): void;
export declare function markTaskWriteScopeBlocked(taskState: TaskExecutionState, reason: string, attemptedPath: string): void;
export declare function approveTaskWriteScope(taskState: TaskExecutionState, attemptedPath: string): boolean;
export declare function markTaskCompleted(taskState: TaskExecutionState, summary?: string | null): void;
export declare function shouldTreatTaskRunStatusAsFailure(status: TaskExecutionState['run']['status'] | null | undefined): boolean;
export declare function evaluateWriteGuard(toolName: string, input: Record<string, unknown>, taskState?: TaskExecutionState): WriteGuardViolation | null;
export declare function recordWriteSuccess(taskState: TaskExecutionState | undefined, toolName: string, input: Record<string, unknown>, metadata?: Record<string, unknown>): void;
export declare function recordBashArtifactProgress(taskState: TaskExecutionState | undefined, toolName: string, input: Record<string, unknown>, executionStartMs?: number): Promise<void>;
export declare function recordToolExecutionProgress(taskState: TaskExecutionState | undefined, toolName: string, input: Record<string, unknown>, metadata?: Record<string, unknown>): void;
export interface EnsureRunWorkspaceResult {
    created: boolean;
    reason?: string;
    outputRoot?: string;
    runDir?: string;
}
export declare function ensureRunWorkspaceForStructuredTask(taskState: TaskExecutionState | undefined, toolName: string, input: Record<string, unknown>, metadata?: Record<string, unknown>): Promise<EnsureRunWorkspaceResult>;
/**
 * Returns all scopes from `allowedWritePaths` that were declared by the user
 * as external deliverable targets (origin === 'user-external'), preserving the
 * `kind` field so fs-policy can apply the correct matching semantics:
 *   - kind === 'file': exact-match only (no descendants)
 *   - kind === 'directory': exact or descendant paths allowed
 *
 * Consumed by fs-policy callers via `externalScopes` in FsPolicyOptions.
 */
export declare function extractUserDeclaredExternalRoots(taskState: TaskExecutionState | undefined): Array<{
    path: string;
    kind: 'file' | 'directory';
}>;
export declare function hasRecentArtifactProgress(taskState: TaskExecutionState, repairWindowIterations: number): boolean;
export declare function buildTaskRealignPrompt(taskState: TaskExecutionState): string;
export declare function describeAllowedWriteScope(taskState: TaskExecutionState): string;
export declare function buildTaskContinuePrompt(taskState: TaskExecutionState, latestAssistantText: string): string;
/**
 * Build the runtime-injected nudge that fires when the model's
 * previous response hit `stop_reason: 'max_tokens'` (0.13.64). The
 * model wanted to write more but its per-response output cap cut
 * the reply mid-content; without a follow-up nudge the conversation
 * loop just continues and the model often re-renders the whole
 * thing again from scratch (and may hit the same cap). New behavior:
 * inject a specific "continue from where you left off" message that
 * names the truncation and tells the model exactly what to do.
 *
 * Includes a tail snippet of the truncated text so the model can
 * resume rather than restart. Cap at ~400 chars to keep the inject
 * itself small.
 */
export declare function buildMaxTokensContinuationPrompt(truncatedText: string, consecutiveTruncations: number): string;
/**
 * Build the runtime-injected nudge that fires when the assistant has
 * produced large inline output for several iterations in a row
 * without making progress (0.13.63 D). The pattern: model gets
 * stuck, dumps a 30K-char "fallback summary table" each turn rather
 * than tool-calling forward — the cumulative text bloats both
 * context and host heap (the latter caused the 0.13.62 OOM).
 *
 * Once-per-session by design: the goal is to interrupt a runaway
 * inline-dump pattern, not to nag for every long answer.
 */
export declare function buildOutputBloatPrompt(consecutiveLargeOutputCount: number, approxCharsPerOutput: number): string;
/**
 * Build the runtime-injected nudge that fires when the conversation's
 * post-compact context usage crosses a pressure threshold (0.13.58).
 * Two thresholds in practice (0.6 = soft, 0.85 = strict). Each fires
 * once per session per threshold; the conversation loop tracks fired
 * thresholds on `conversation.options.contextPressureNudgesFired`.
 *
 * The mionyee-hermes long-context dogfood (deepseek-v4-pro at 800K+
 * tokens) showed two specific degradation modes that this nudge
 * targets:
 *   1. Model re-asks facts already in scrollback (long-context
 *      recall failure). The nudge tells it to grep before asking.
 *   2. Model writes paragraphs of plan-restating prose. The nudge
 *      tells it to lead with the key fact in one line, then take
 *      action.
 *
 * Tone: the nudge is a *system observation* fed back as context, not
 * a punitive rule. The model reads it and adapts; if it doesn't, the
 * other guards (continue-while-open, summary gate, soft loop
 * intercept) still apply.
 */
export declare function buildContextPressurePrompt(threshold: number, usageRatio: number, totalTokens: number, contextWindow: number): string;
/**
 * 0.13.70 execution_economics_v1 — production_gate_v1.
 *
 * Inject when the task contract requires a write deliverable, the
 * model has done genuine investigation (>=3 distinct files read,
 * >=5 lifetime iterations elapsed), but no deliverable has landed
 * (touchedPaths still empty). This is the soft, one-shot push
 * Codex/Sonnet 4 give themselves implicitly: "you have enough
 * source evidence; switch to producing now."
 *
 * Distinct from:
 *   - 0.13.66 narration-loop detector: catches PURE-text loops, hard-stop.
 *   - 0.13.68 task-no-progress ceiling: catches lifetime > 8, hard-stop.
 *
 * production_gate_v1 fires earlier (lifetime >= 5), is one-shot,
 * does NOT terminate. It's an advisory inject in the
 * "tool-surface side-channel signaling" tradition (SWE-agent ACI).
 */
export declare function buildProductionGatePrompt(details: {
    distinctFilesRead: number;
    lifetimeIterations: number;
    taskWriteScope: string | null;
}): string;
export declare function detectCompletionClaim(text: string): boolean;
/**
 * True when `text` already cites concrete file evidence for at least
 * one of the paths in `touchedPaths`. The delivery-check hook treats
 * this as "claim is self-evidencing" and skips the nudge — there's
 * no point nagging the model to audit a claim it already backed up
 * with file paths.
 *
 * Match is on basename only (so `docs/final-report.md` in touchedPaths
 * matches "wrote final-report.md to docs/" in the text). Cheap regex,
 * no path resolution.
 */
export declare function completionCitesTouchedPaths(text: string, touchedPaths: string[]): boolean;
/**
 * Build the runtime-injected nudge that fires when a completion claim
 * is detected but DeliveryAudit hasn't run yet (or hasn't run since
 * the most recent file mutation). Phrased as a single user-role
 * message so it slots cleanly into the existing inject pattern used
 * by buildTaskContinuePrompt / buildTaskRealignPrompt.
 */
export declare function buildDeliveryCheckPrompt(taskState: TaskExecutionState, latestAssistantText: string): string;
/**
 * User intent classification, derived from the latest substantive user
 * message. Used by the autonomy-boundary guards added in 0.13.48 to
 * stop the agent from auto-jumping from "what do you think?" to
 * "I edited 5 files for you."
 *
 *   - 'analysis'      — user asked for judgment / opinion / explanation only
 *   - 'implementation'— user gave an explicit verb to do something
 *   - 'mixed'         — both signals present (treat as implementation; user named the action)
 *   - 'neutral'       — neither (or message is empty); status quo behaviour
 */
export type UserIntent = 'analysis' | 'implementation' | 'mixed' | 'neutral';
/**
 * Classify the intent of a single user-message string. The latest
 * substantive user message is what counts — `infer*` callers should
 * pre-filter `继续` / `continue` shorthand themselves.
 */
export declare function inferUserIntent(text: string): UserIntent;
export interface IntentGuardViolation {
    toolName: string;
    intent: UserIntent;
    reason: string;
    /** Why it gated: 'analysis' = inferred analysis-only intent (softened to a
     *  hint under OWLCODA_MODES); 'probeplan' = ProbePlan allowlist (stays hard). */
    reasonKind: 'analysis' | 'probeplan';
}
export declare function evaluateIntentGuard(toolName: string, intent: UserIntent, toolInput?: Record<string, unknown>, probeMatcher?: (toolName: string, input: Record<string, unknown>) => {
    groupId: string;
    probeId: string;
} | null, hasActiveProbePlan?: boolean): IntentGuardViolation | null;
/**
 * Latest substantive user message (skips bare "继续" / "continue"
 * shorthand). Exported so the conversation loop and the intent guard
 * can share a single source of truth on what counts as the user's
 * most recent ask.
 */
export declare function latestSubstantiveUserText(conversation: Conversation): string | null;
