/**
 * Product-flow playback — drive the REAL product through a user story and
 * score the produced state per requirement (the launch "Jira tick-off").
 *
 * This is the substrate adapter + contract only. It plugs a `PlaybackDriver`
 * into the existing `runProfileMatrix` dispatch seam: a driver drives the real
 * product (a Playwright UI session or a sandbox workspace) and returns the
 * runtime event stream; `extractProducedState` + `verifyCompletion` then score
 * each requirement PASS/FAIL. The concrete drivers live in consumers — they
 * depend on browser / runtime infra the substrate must not import — so
 * agent-eval owns the seam, the `UserStory` contract, and the scoreboard.
 */
import type { AgentProfile } from '@tangle-network/agent-interface';
import { type CompletionRequirement, type CompletionVerdict, type CorrectnessChecker, type ProducedState } from '../../completion-verifier';
import { type RuntimeEventLike } from '../../produced-state';
import type { DispatchContext, Scenario } from '../types';
import type { ProfileDispatchFn } from './run-profile-matrix';
/** One step of a user story — what the user does. The driver interprets
 *  `payload` (a Playwright selector + action, or a sandbox chat turn). */
export interface PlaybackStep {
    /** Human-readable action, captured verbatim in the UX narrative. */
    action: string;
    /** Driver-specific payload (e.g. `{ selector, fill }` or `{ turn }`). */
    payload?: Record<string, unknown>;
}
/**
 * A user story = a runnable product journey plus the requirements that define
 * "this story works". Each requirement is one Jira ticket line. Extends
 * `Scenario` so a catalog drops straight into `runProfileMatrix({ scenarios })`.
 */
export interface UserStory extends Scenario {
    /** Human-readable story title (the ticket headline). */
    title: string;
    /** Ordered steps the driver executes. */
    steps: PlaybackStep[];
    /** What must hold in the produced state for the story to pass. */
    requirements: CompletionRequirement[];
}
/** Dispatch context plus the profile under test (which cheap model, etc.). */
export interface PlaybackContext extends DispatchContext {
    profile: AgentProfile;
}
/**
 * Drives the real product through a story and returns the runtime event stream
 * `extractProducedState` consumes. Implemented by CONSUMERS —
 * `SandboxPlaybackDriver` (real API / sandbox workspace) and
 * `PlaywrightPlaybackDriver` (real UI) — because they depend on runtime /
 * browser infra the substrate must not import. The driver MUST report LLM
 * usage via `ctx.cost.observeTokens` so the backend-integrity guard sees real
 * tokens (a run that never reports tokens reads as a stub).
 */
export interface PlaybackDriver<TStory extends UserStory = UserStory> {
    run(story: TStory, ctx: PlaybackContext): Promise<readonly RuntimeEventLike[]>;
}
/**
 * Adapt a `PlaybackDriver` into a `runProfileMatrix` dispatch. The artifact the
 * matrix scores is the `ProducedState` extracted from the driver's event
 * stream — grade it with `scoreUserStory` (or a judge wrapping it).
 */
export declare function makePlaybackDispatch<TStory extends UserStory>(driver: PlaybackDriver<TStory>): ProfileDispatchFn<TStory, ProducedState>;
/** A scored user story — the completion verdict plus its human title. */
export interface UserStoryVerdict extends CompletionVerdict {
    title: string;
}
/**
 * Score one story's produced state against its requirements. Thin wrapper over
 * `verifyCompletion` that builds the gold from the story and returns a
 * per-requirement PASS/FAIL verdict. `checkCorrectness` is injected — a
 * deterministic stub in tests, `createLlmCorrectnessChecker` in production.
 */
export declare function scoreUserStory(story: UserStory, state: ProducedState, checkCorrectness: CorrectnessChecker): Promise<UserStoryVerdict>;
/** One row of the launch scoreboard — story × requirement → PASS/FAIL. */
export interface ScoreboardRow {
    storyId: string;
    storyTitle: string;
    reqId: string;
    reqTitle: string;
    status: 'PASS' | 'FAIL';
    evidence: string[];
}
/**
 * Flatten story verdicts into the per-requirement scoreboard — the literal
 * Jira tick-off: one row per (story, requirement) with PASS/FAIL and the
 * evidence behind the verdict.
 */
export declare function userStoryScoreboard(verdicts: readonly UserStoryVerdict[]): ScoreboardRow[];
/** Launch-readiness headline counts rolled up from the per-requirement rows. */
export interface ScoreboardSummary {
    /** Distinct user stories on the board. */
    stories: number;
    /** Stories whose every requirement passed. */
    storiesFullyComplete: number;
    /** Total (story, requirement) rows. */
    requirements: number;
    /** Rows with status PASS. */
    passed: number;
    /** Rows with status FAIL. */
    failed: number;
    /** passed / requirements; 0 when there are no rows. */
    passRate: number;
}
/** Roll the per-requirement rows up into the launch headline counts. */
export declare function scoreboardSummary(rows: readonly ScoreboardRow[]): ScoreboardSummary;
export interface ScoreboardRenderOptions {
    /** Document H1. Defaults to a generic playback title. */
    title?: string;
    /** Key/value run metadata rendered under the headline (runId, backend, model, date). */
    meta?: Record<string, string>;
    /** Max chars of joined evidence shown per row. Default 160. */
    maxEvidenceChars?: number;
}
/**
 * Render the scoreboard as a launch-readiness Markdown document — the literal
 * "tick off every user story" artifact: a headline roll-up, the open tickets
 * (FAIL rows) up top as the launch blockers, then a per-story table of
 * requirement → PASS/FAIL with the evidence behind each verdict. Pure: same
 * rows in, same bytes out (no clock/random), so it is safe to snapshot.
 */
export declare function renderScoreboardMarkdown(rows: readonly ScoreboardRow[], opts?: ScoreboardRenderOptions): string;
//# sourceMappingURL=playback.d.ts.map