import { a as UiFinding, U as UiLens } from './substrate-DO2GHNg2.js';
export { C as CoderTask, b as UI_FINDING_SEVERITIES, c as UI_LENSES, d as UiFindingScreenshot, e as UiFindingSeverity, f as coderTaskToPrompt } from './substrate-DO2GHNg2.js';
import { S as SandboxClient, b as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-ESeMOj94.js';
import { SandboxEvent } from '@tangle-network/sandbox';
import { AgentProfile } from '@tangle-network/agent-interface';
import '@tangle-network/agent-eval';

/**
 *
 * UI-audit issue writer — pure I/O. Takes a workspace dir + `UiFinding[]`
 * and emits:
 *   - `<workspace>/issues/NNN--<lens>--<slug>.md` — one self-contained
 *     GitHub-issue-ready Markdown per finding, with embedded screenshot
 *     references.
 *   - `<workspace>/registry.json` — finding index for dedup and audit
 *     resume across iterations.
 *   - `<workspace>/index.md` — human-readable rollup (severity / lens /
 *     route counts plus a sorted finding list).
 *
 * The writer is deterministic, idempotent for `appendFindings()`, and
 * never invokes an LLM. It assigns the next monotonic id to a finding the
 * caller did not pre-id.
 *
 * @experimental
 */

/** @experimental */
interface AuditRegistry {
    schemaVersion: 1;
    findings: UiFinding[];
    /** Route → URL + captures sidecar; preserved across runs. */
    routes: Record<string, {
        url?: string;
        captures: AuditRegistryCapture[];
    }>;
}
/** @experimental */
interface AuditRegistryCapture {
    file: string;
    viewport?: string;
    fullPage?: boolean;
    elementSelector?: string;
    capturedAt: string;
}
/** Create the `issues/`, `screenshots/`, and `registry.json` scaffold in a new audit workspace. @experimental */
declare function initAuditWorkspace(workspaceDir: string): Promise<void>;
/** Read and validate the `registry.json` from an audit workspace. @experimental */
declare function readAuditRegistry(workspaceDir: string): Promise<AuditRegistry>;
/** @experimental */
interface AppendFindingsResult {
    /** Findings with id + createdAt assigned, in input order. */
    written: UiFinding[];
    /** Workspace-relative path to each issue Markdown file, in input order. */
    files: string[];
}
/**
 * Append findings to a workspace, writing one Markdown file per finding
 * and updating registry.json. Assigns monotonically increasing ids to
 * findings that arrived without one.
 *
 * Findings already carrying an id that collides with the registry are
 * rejected — callers must either freshly mint findings (id undefined) or
 * use a separate update path. This protects against accidental overwrite.
 *
 * @experimental
 */
declare function appendFindings(workspaceDir: string, findings: readonly UiFinding[]): Promise<AppendFindingsResult>;
/** @experimental */
interface RegisterCapturesOptions {
    route: string;
    url?: string;
    captures: readonly AuditRegistryCapture[];
}
/**
 * Record screenshots taken for a route in the registry, without filing a
 * finding. Useful when the auditor wants to remember which captures
 * exist for resume / dedup purposes.
 *
 * @experimental
 */
declare function registerCaptures(workspaceDir: string, options: RegisterCapturesOptions): Promise<void>;
/** @experimental */
interface AuditIndex {
    /** Total findings in the workspace. */
    total: number;
    bySeverity: Record<UiFinding['severity'], number>;
    byLens: Partial<Record<UiLens, number>>;
    byRoute: Record<string, number>;
}
/** Compute finding counts by severity, lens, and route from an `AuditRegistry`. @experimental */
declare function summarizeRegistry(reg: AuditRegistry): AuditIndex;
/**
 * Regenerate `<workspace>/index.md` from registry.json.
 *
 * @experimental
 */
declare function writeAuditIndex(workspaceDir: string): Promise<string>;

/**
 *
 * UI auditor task + output shapes — what one iteration of the audit loop
 * does and what it returns.
 *
 * An iteration is one (lens × route × viewport) audit pass. The driver
 * decides which iterations to plan (lens-cycling, route-cycling,
 * refine-on-low-yield, etc.); the iteration itself captures screenshots
 * and asks a vision judge to identify findings under that lens.
 *
 * @experimental
 */

/** @experimental */
interface UiAuditViewport {
    width: number;
    height: number;
}
/** @experimental */
interface UiAuditCaptureRequest {
    /**
     * Logical route name (e.g. `home`, `checkout-step-2`). Used in screenshot
     * filenames and finding metadata.
     */
    route: string;
    /** Fully qualified URL the iteration audits. */
    url: string;
    /** Default `{ width: 1280, height: 800 }`. */
    viewport?: UiAuditViewport;
    /** Default `false`. */
    fullPage?: boolean;
    /** CSS selector to wait for before capturing. */
    waitFor?: string;
    /** Extra milliseconds to wait after navigation settles. Default `500`. */
    waitMs?: number;
    /** Optional CSS selector — capture only the matched element. */
    elementSelector?: string;
    /** Optional human-readable label appended to the screenshot filename. */
    label?: string;
}
/**
 * One iteration's task: audit a single (lens × route) pair, capturing the
 * surfaces the lens needs.
 *
 * `captures` lists the screenshots to take BEFORE the judge is invoked.
 * The judge sees all captures from this iteration plus the lens-specific
 * brief.
 *
 * @experimental
 */
interface UiAuditTask {
    /** The audit lens that scopes which findings are valid this iteration. */
    lens: UiLens;
    /** Required captures. Order is preserved; index 0 is the primary frame. */
    captures: readonly UiAuditCaptureRequest[];
    /**
     * Free-form context the consumer wants the judge to know about (product
     * name, target audience, copy tone). Surfaced as a prompt prelude.
     */
    productContext?: string;
    /**
     * IDs of findings already on file across earlier iterations. The judge
     * uses these to mark cross-references via `similarTo` instead of filing
     * pile-on duplicates.
     */
    knownFindingIds?: readonly number[];
}
/** @experimental */
interface UiAuditCapture {
    /** Workspace-relative path to the screenshot file. */
    path: string;
    viewport: string;
    fullPage: boolean;
    elementSelector?: string;
    label?: string;
    route: string;
    url: string;
    /** Wall-clock when the capture completed. */
    capturedAt: string;
}
/**
 * Output of one iteration. `findings` is the headline payload; `captures`
 * is the screenshot manifest the writer needs to link evidence. `notes`
 * carries judge commentary that didn't rise to a finding.
 *
 * @experimental
 */
interface UiAuditOutput {
    lens: UiLens;
    findings: UiFinding[];
    captures: UiAuditCapture[];
    /** Optional judge commentary (debug / triage aid). */
    notes?: string;
}

/**
 *
 * UI judge seam — consumer-supplied vision LLM hook the in-process
 * auditor client invokes to identify findings from captured screenshots.
 *
 * The seam stays model-agnostic so consumers can plug in OpenAI vision,
 * Anthropic vision, gemini, a local model, or a deterministic stub for
 * tests. The auditor handles browser capture + Markdown emission; the
 * judge owns the perception + judgment.
 *
 * Implementor contract:
 *   - Treat `lens` as authoritative — only emit findings that belong to
 *     that lens. Findings with `lens !== input.lens` will fail the
 *     iteration validator.
 *   - Reference screenshots via the `path` strings provided in
 *     `input.captures`. Inventing a path will cause the validator to
 *     reject the iteration.
 *   - Be conservative — a finding the judge cannot actually see in the
 *     screenshots is a hallucination and pollutes the audit.
 *   - Treat any exception thrown by the judge as the iteration's failure —
 *     do not swallow LLM errors. Per agent-runtime's fail-loud doctrine,
 *     surfacing the error to the kernel beats producing a silent zero.
 *
 * @experimental
 */

/** @experimental */
interface UiJudgeTokenUsage {
    input: number;
    output: number;
}
/** @experimental */
interface UiJudgeInput {
    lens: UiLens;
    captures: readonly UiAuditCapture[];
    /** Free-form product context the consumer wants the judge to know. */
    productContext?: string;
    /** Findings already on file across earlier iterations — for similarTo linkage. */
    knownFindingIds?: readonly number[];
    /** The full prompt the loop kernel synthesized for this iteration. */
    promptText: string;
    /** Cooperative cancellation. */
    signal: AbortSignal;
}
/** @experimental */
interface UiJudgeOutput {
    findings: UiFinding[];
    /** Optional triage commentary. */
    notes?: string;
    /** Optional usage; folded into the kernel cost ledger when present. */
    tokenUsage?: UiJudgeTokenUsage;
    /** Optional total cost in USD. */
    costUsd?: number;
}
/** @experimental */
type UiJudge = (input: UiJudgeInput) => Promise<UiJudgeOutput>;

/**
 *
 * `createInProcessUiAuditClient` — a `SandboxClient` that drives a
 * Playwright browser in-process and delegates finding identification to a
 * consumer-supplied {@link UiJudge}.
 *
 * Why this exists: `runLoop` is built around a sandbox-SDK seam — each
 * iteration is `client.create() → box.streamPrompt() → box.delete()`.
 * For UI audit, spinning up a real container running a coding harness
 * per iteration is overkill: the work is one browser capture + one
 * vision LLM call. This client satisfies the kernel contract while
 * doing the audit in-process; no container, no sandbox-SDK backend.
 *
 * The client owns ONE browser for its lifetime and creates a fresh
 * context per iteration (isolated cookies/storage). Playwright is
 * dynamically imported so consumers who use a different `SandboxClient`
 * — e.g. a fleet executor that drives Playwright remotely — do not pay
 * the peer dep cost.
 *
 * Concurrency: each iteration's prompt carries a self-describing task
 * envelope (see `prompt.ts`), so concurrent fanout iterations do not race
 * over per-client side state.
 *
 * @experimental
 */

/** @experimental */
interface InProcessUiAuditClientOptions {
    /**
     * Absolute path under which screenshots are written. Each capture lands
     * at `<workspaceDir>/screenshots/<filename>`; finding screenshot paths
     * are workspace-relative (`screenshots/<filename>`).
     */
    workspaceDir: string;
    /** The vision judge that turns captures into findings. */
    judge: UiJudge;
    /**
     * Navigation policy.
     *
     * `'strict'` (default) waits for `networkidle` and fails the iteration
     * if the page does not settle. `'spa'` waits for `domcontentloaded` —
     * use for single-page apps that hold open long-poll/websocket
     * connections and never settle.
     */
    navPolicy?: 'strict' | 'spa';
    /**
     * Browser launch override. Default: chromium headless via Playwright.
     * Consumers pass a custom factory to target a remote browser, a
     * different channel, or a fleet adapter.
     */
    launchBrowser?: () => Promise<BrowserHandle>;
}
/** @experimental */
interface BrowserHandle {
    newContext(options?: {
        viewport?: {
            width: number;
            height: number;
        };
    }): Promise<BrowserContextHandle>;
    close(): Promise<void>;
}
/** @experimental */
interface BrowserContextHandle {
    newPage(): Promise<PageHandle>;
    close(): Promise<void>;
}
/** @experimental */
interface PageHandle {
    setViewportSize(size: {
        width: number;
        height: number;
    }): Promise<void>;
    goto(url: string, options?: {
        waitUntil?: string;
        timeout?: number;
    }): Promise<unknown>;
    waitForSelector(selector: string, options?: {
        timeout?: number;
    }): Promise<unknown>;
    waitForTimeout(ms: number): Promise<void>;
    screenshot(options: {
        path: string;
        fullPage?: boolean;
    }): Promise<void>;
    locator(selector: string): {
        first(): {
            screenshot(options: {
                path: string;
            }): Promise<void>;
        };
    };
}
/** Create a `SandboxClient` that drives a local Playwright browser for in-process UI audits. @experimental */
declare function createInProcessUiAuditClient(options: InProcessUiAuditClientOptions): SandboxClient & {
    /**
     * Close the underlying browser. Idempotent.
     *
     * Contract: callers MUST ensure no iterations are in flight when this is
     * called. The kernel respects this — `runLoop` awaits every iteration
     * before returning, so `await runLoop(...); await client.close()` is the
     * intended pattern (see `examples/ui-audit`). If `close()` is invoked
     * concurrently with a running iteration, the browser teardown will race
     * against in-flight page operations; the iteration will surface an
     * AggregateError carrying both the iteration error and the close error,
     * but no work is lost silently.
     */
    close(): Promise<void>;
};

/**
 *
 * Per-lens guidance the auditor inlines into its system prompt for an
 * iteration. Each entry is a self-contained brief — the same content the
 * standalone ui-issue-finder skill ships, embedded as a string constant so
 * agent-runtime carries no runtime dep on that external workspace.
 *
 * Briefs are deliberately concrete: they enumerate the SIGNALS to look for
 * and the cross-lens distinctions to respect, so the judge files fewer
 * pile-on findings under generic labels.
 *
 * @experimental
 */

/** Cross-lens rules injected into every UI audit iteration: finding quality standards and scope limits. @experimental */
declare const SHARED_AUDITOR_RULES: string;
/** Per-lens auditor briefs: concrete signals to look for and cross-lens distinctions to respect. @experimental */
declare const LENS_BRIEFS: Record<UiLens, string>;
/**
 * Build a system prompt for a single auditor iteration.
 *
 * @experimental
 */
declare function buildAuditorSystemPrompt(lens: UiLens): string;

/**
 *
 * Sandbox-event stream → UiAuditOutput decoder. The custom auditor
 * `SandboxClient` emits events of the form:
 *
 *   { type: 'audit.capture', data: UiAuditCapture }
 *   { type: 'audit.finding', data: UiFinding }
 *   { type: 'audit.notes',   data: { notes: string } }
 *   { type: 'audit.lens',    data: { lens: UiLens } }
 *   { type: 'done',          data: { tokenUsage: { ... }, totalCostUsd?: number } }
 *
 * Other event types are tolerated and ignored. The adapter is pure: it
 * folds an already-collected event array into a UiAuditOutput.
 *
 * @experimental
 */

/** Parse raw `SandboxEvent` emissions from an audit iteration into structured `UiAuditOutput`. @experimental */
declare function parseAuditorEvents(events: SandboxEvent[]): UiAuditOutput;

/**
 *
 * `uiAuditorProfile` — preset for vision-driven UI audit iterations.
 *
 * A `runLoop` bundle: it returns the `AgentRunSpec`, output adapter, validator, and prompt
 * formatter the loop kernel needs. The agent's "harness" is not a sandbox-SDK code-runner — it's a
 * vision-capable judge driving a browser. The loop kernel still iterates
 * `client.create() → box.streamPrompt() → box.delete()`; the client/box pair are provided by
 * `createInProcessUiAuditClient` (in `./in-process-client.ts`) or a consumer-supplied `SandboxClient`.
 *
 * @experimental
 */

/** @experimental */
interface UiAuditorProfileOptions {
    /**
     * Stable name surfaced in trace events. Defaults to `ui-auditor`.
     */
    name?: string;
    /**
     * Optional model identifier passed in `AgentProfile.model.default`.
     * The consumer's `SandboxClient` chooses how to interpret it.
     */
    model?: string;
    /**
     * Task bound to the validator. Without it the validator uses the lens
     * embedded in the iteration output as its expectation — fine for one-off
     * use; less strict than passing the task explicitly.
     */
    task?: UiAuditTask;
}
/**
 * Preset `runLoop` bundle for vision-driven UI audits: returns the `AgentRunSpec`, output adapter, validator, and prompt formatter the loop kernel needs.
 *
 * @experimental
 */
declare function uiAuditorProfile(options?: UiAuditorProfileOptions): {
    profile: AgentProfile;
    taskToPrompt: (task: UiAuditTask) => string;
    output: OutputAdapter<UiAuditOutput>;
    validator: Validator<UiAuditOutput>;
    agentRunSpec: AgentRunSpec<UiAuditTask>;
};

/**
 *
 * Prompt formatter for the auditor profile. `formatAuditorPrompt` produces
 * the user message handed to the iteration — describes the captures to be
 * taken and the lens to apply. The system prompt comes from
 * `buildAuditorSystemPrompt(lens)` (lens-prompts.ts).
 *
 * The formatter prepends a machine-readable envelope (`<<UI_AUDIT_TASK>>`
 * … `<<UI_AUDIT_TASK_END>>`) carrying a JSON-serialised task. The
 * in-process auditor client recovers the task from this envelope so the
 * iteration is self-describing — robust to concurrent fanout, where any
 * per-client side state (e.g. a "current task" register) would race.
 *
 * The formatter is pure and deterministic — re-run on the same task
 * produces the same prompt. Tests and trace replays rely on this.
 *
 * @experimental
 */

/** Wrap a `UiAuditTask` in a machine-readable envelope so iterations are self-describing. @experimental */
declare function encodeAuditTaskEnvelope(task: UiAuditTask): string;
/**
 * Parse a task envelope back out of a prompt string. Returns undefined if
 * the prompt does not contain a complete envelope OR if the payload is
 * not valid JSON.
 *
 * @experimental
 */
declare function decodeAuditTaskEnvelope(prompt: string): UiAuditTask | undefined;
/** Produce the user message for one audit iteration: lens, captures to take, and the task envelope. @experimental */
declare function formatAuditorPrompt(task: UiAuditTask): string;

/**
 *
 * Auditor validator — scores a single iteration's findings for actionability
 * and gates the iteration result. The kernel uses `valid` + `score` for
 * winner selection across fanned-out iterations and to detect a degenerate
 * iteration (lens-violating findings, no screenshot evidence, no findings
 * at all on a route where we expected some).
 *
 * Hard fails (`valid = false`):
 *   - A finding is filed under a lens that does not match the iteration's
 *     lens. The whole iteration is bad — the judge isn't following the
 *     lens discipline and the resulting Markdown would mislead reviewers.
 *   - A finding has no screenshot reference.
 *   - A finding's screenshot references a path that wasn't captured in
 *     this iteration.
 *
 * Score (0..1, max two decimals stable):
 *   - 0.4 * specificityRatio    — proportion of findings with a selector
 *   - 0.4 * evidenceRatio       — proportion of findings whose screenshots resolve to captures
 *   - 0.2 * (1 - genericTitleRatio) — proportion of findings whose titles
 *     are concrete (not "improve UX", "fix layout", etc.)
 *
 * An iteration with zero findings scores 0.5 by convention — neither a
 * confident pass nor a hard failure (the judge might just have nothing to
 * say on this lens). The driver decides what to do with it.
 *
 * @experimental
 */

/** Build a `Validator` that rejects off-lens findings and findings missing screenshot evidence. @experimental */
declare function createUiAuditorValidator(task: UiAuditTask): Validator<UiAuditOutput>;

export { type AppendFindingsResult, type AuditIndex, type AuditRegistry, type AuditRegistryCapture, type BrowserContextHandle, type BrowserHandle, type InProcessUiAuditClientOptions, LENS_BRIEFS, type PageHandle, type RegisterCapturesOptions, SHARED_AUDITOR_RULES, type UiAuditCapture, type UiAuditCaptureRequest, type UiAuditOutput, type UiAuditTask, type UiAuditViewport, type UiAuditorProfileOptions, UiFinding, type UiJudge, type UiJudgeInput, type UiJudgeOutput, type UiJudgeTokenUsage, UiLens, appendFindings, buildAuditorSystemPrompt, createInProcessUiAuditClient, createUiAuditorValidator, decodeAuditTaskEnvelope, encodeAuditTaskEnvelope, formatAuditorPrompt, initAuditWorkspace, parseAuditorEvents, readAuditRegistry, registerCaptures, summarizeRegistry, uiAuditorProfile, writeAuditIndex };
