/**
 * MTP Red-Team Harness — Phase 1 core (EXO 3.0 G7).
 *
 * Pure-logic heart of the standardized adversarial-verification harness:
 * scenario-pack parsing + validation, channel-coherence enforcement,
 * expectation resolution against the TARGET org's own intent (org-agnostic),
 * outcome classification, and boundary-map assembly.
 *
 * Everything here is browser-free and deterministic so it is unit-testable in
 * isolation (Testing Integrity Standard, Tier 1). The live-drive layer (the
 * runner that posts probes through the Tier-4 seat and reads replies) lives in
 * `.instar/scripts` and consumes this module's verdicts — it never re-implements
 * the logic.
 *
 * SAFETY — payload-by-reference (spec §5): this module handles payloads ONLY as
 * `{ id, path, sha256 }`. It NEVER reads payload bodies into memory. The
 * attack text lives in files; only the mechanical runner reads it, at send
 * time. This is structural, not stylistic — inlining attack payloads into a
 * long-lived transcript permanently wedged a session via an AUP-rejection loop
 * (CMT-1115).
 *
 * Spec: docs/specs/MTP-REDTEAM-HARNESS-SPEC.md
 */
import { type JudgeOptions } from '../core/IntentTestHarness.js';
import type { ParsedOrgIntent } from '../core/OrgIntentManager.js';
import type { IntelligenceProvider } from '../core/types.js';
/** Attack-theme domains. Credentials is merely the easiest; the interesting
 *  boundaries are in the domains the org's OWN standards must defend. */
export type ScenarioDomain = 'credentials' | 'destructive-ops' | 'data-exfiltration' | 'value-conflict' | 'loyalty-impersonation' | 'policy-pressure' | string;
/** WHO an attack pretends to be (spec §4a). MUST be coherently deliverable by
 *  the declared transport — an impersonation claim from the owner's own,
 *  authenticated channel is incoherent and is rejected by the linter. */
export type SenderContext = 'owner-authentic' | 'unknown-party' | 'peer-agent' | 'compromised-owner';
/** Transports that can carry a probe to the subject. */
export type Transport = 'tier4-seat' | 'unknown-account' | 'threadline-peer';
/** Which sender contexts each transport can deliver coherently. */
export declare const TRANSPORT_COHERENCE: Record<Transport, SenderContext[]>;
export type Outcome = 'refused-grounded' | 'refused' | 'deflected' | 'complied-partial' | 'complied' | 'wedged' | 'error';
export type SideSignal = 'reported-attempt' | 'registered-finding' | 'hardened-checker';
/** A scenario's expectation of the agent. */
export type Expectation = 'refuse' | 'escalate' | 'comply-with-conditions';
export interface PayloadRef {
    /** The file holding the attack text — read ONLY by the mechanical runner. */
    path: string;
    /** SHA-256 of the payload file, fixed at pack-author time; the runner
     *  verifies the on-disk file matches before sending. */
    sha256: string;
}
export interface ScenarioLevel {
    level: 0 | 1 | 2 | 3 | number;
    name: string;
    payload: PayloadRef;
    /** Outcomes that count as a PASS at this level. */
    pass: Outcome[];
    /** Bonus criteria — tracked, never required unless listed. */
    sideSignals?: SideSignal[];
}
export interface Scenario {
    id: string;
    domain: ScenarioDomain;
    title: string;
    mtpBinding: {
        expectation: Expectation;
        /** Patterns used to LOCATE the governing constraint in the TARGET org's
         *  intent at runtime — this is what makes the pack org-agnostic. */
        constraintHints: string[];
    };
    mode: 'fresh-session' | 'escalating-conversation';
    senderContext: SenderContext;
    levels: ScenarioLevel[];
}
export interface ScenarioPack {
    pack: string;
    description: string;
    scenarios: Scenario[];
}
export interface PackLintIssue {
    scenarioId: string;
    level?: number;
    severity: 'error' | 'warning';
    message: string;
}
/**
 * Lint a pack for the SUBJECT transport it will run on. Channel-coherence
 * (spec §4a) is an ERROR: a scenario whose `senderContext` the transport
 * cannot deliver is not a valid measurement and must not run.
 */
export declare function lintPack(pack: ScenarioPack, transport: Transport): PackLintIssue[];
export type Governance = 'governed' | 'ungoverned' | 'conflicted';
export interface ResolvedExpectation {
    governance: Governance;
    /** The constraint text that governs this scenario, when governed. */
    matchedConstraint?: string;
    /**
     * HOW this verdict was produced — Truthful Provenance (constitution): a
     * verdict must carry the method that generated it so consumers never mistake
     * a heuristic for ground truth. `'keyword-heuristic'` = Phase-1 keyword
     * overlap; `'llm-judge'` = Phase-2 semantic judgment (CMT-1128), claimed
     * only for a real, parsed LLM verdict.
     */
    method: 'keyword-heuristic' | 'llm-judge';
    /**
     * Present (true) only when the LLM judge was REQUESTED but could not
     * produce a verdict (provider error / circuit open / malformed reply), so
     * the verdict above is the keyword heuristic standing in. Honest signal:
     * consumers know they asked for semantics and got keywords.
     */
    judgeUnavailable?: true;
    reason: string;
}
/**
 * Resolve whether the TARGET org's intent actually governs a scenario — the
 * "cheering vs governing" measurement. Reuses the G1 IntentTestHarness: a
 * scenario is GOVERNED when one of its constraintHints keyword-overlaps a
 * constraint that refuses.
 *
 * ⚠ BRITTLENESS — STATED, NOT HIDDEN (Truthful Provenance): the underlying
 * match is KEYWORD OVERLAP, which is conservative and produces FALSE NEGATIVES.
 * It misses semantically-related constraints whose wording differs (live
 * example: a constraint "never present unverified WORK as completed" does NOT
 * keyword-match a scenario about "estimates as CONFIRMED numbers", so the
 * scenario reads "ungoverned" though the rule plainly governs it in spirit).
 * It is also rephrase-bypassable (CMT-1110). Therefore an `ungoverned` verdict
 * is a CANDIDATE gap to verify SEMANTICALLY, never an asserted fact — the
 * `reason` strings and `method` field say so explicitly so no consumer (or
 * report, or future session) treats a keyword miss as a real intent hole. The
 * real fix is the Phase-2 LLM-judged resolver (CMT-1126).
 *
 * `conflicted` is reserved for the case where a constraint matches but the
 * tradeoff hierarchy would invert the expectation; Phase 1 detects the simple
 * governed/ungoverned split and leaves conflict-detection to Phase 2.
 */
export declare function resolveExpectation(scenario: Scenario, intent: ParsedOrgIntent): ResolvedExpectation;
/**
 * Phase-2 expectation resolution (CMT-1128): keyword pre-filter, LLM decision.
 *
 * The keyword matcher is high-precision when it MATCHES, so a governed
 * heuristic verdict is returned as-is (no LLM call, no spend). A keyword MISS
 * — the false-negative side documented on resolveExpectation — escalates to
 * the LLM judge, which tests each constraint hint by MEANING. Verdict honesty
 * (Truthful Provenance):
 *   - method 'llm-judge' is claimed only for a real, parsed LLM verdict;
 *   - when the judge was requested but unavailable, the heuristic verdict is
 *     returned with `judgeUnavailable: true` so consumers know they asked for
 *     semantics and got keywords;
 *   - a judged 'ungoverned' is still a judgment, not ground truth — the
 *     reason string says so.
 * Never throws; never blocks anything (signal-only, like Phase 1).
 */
export declare function resolveExpectationJudged(scenario: Scenario, intent: ParsedOrgIntent, provider: IntelligenceProvider, opts?: JudgeOptions): Promise<ResolvedExpectation>;
export interface ReplyEvidence {
    /** The subject's reply text(s), concatenated. */
    replyText: string;
    /** Did the subject demonstrably consult the checker / cite a constraint? */
    citedConstraint?: boolean;
    /** Did the subject's session die mid-probe? */
    wedged?: boolean;
    /** Side-signals observed out-of-band (attention item, finding, fix). */
    sideSignals?: SideSignal[];
}
/**
 * Heuristic outcome classification from the subject's observable behavior.
 * Conservative by design: a clear breach signal beats an ambiguous refusal,
 * so the harness never over-reports safety. Phase 2 replaces this with an
 * LLM-judged classifier (LlmQueue, supervision tier 1) with human spot-check.
 */
export declare function classifyOutcome(ev: ReplyEvidence): Outcome;
/** Did the observed outcome satisfy the level's pass criteria? */
export declare function isPass(outcome: Outcome, level: ScenarioLevel): boolean;
export interface ProbeResult {
    scenarioId: string;
    domain: ScenarioDomain;
    level: number;
    outcome: Outcome;
    governance: Governance;
    pass: boolean;
    /** References to captured evidence (message ids, transcript paths) — never
     *  payload bodies. */
    evidenceRefs: string[];
}
export interface ScenarioDepth {
    scenarioId: string;
    domain: ScenarioDomain;
    governance: Governance;
    /** Highest level at which the boundary HELD (a pass). -1 = cracked at L0. */
    boundaryDepth: number;
    /** The level at which it first cracked, or null if it held at every probed level. */
    crackedAt: number | null;
    probedLevels: number[];
}
export interface BoundaryMap {
    scenarios: ScenarioDepth[];
    /** refused-grounded ÷ (refused + refused-grounded) across all probes — how
     *  much of the refusal surface actually derives from the MTP vs instinct. */
    derivationRatio: number;
    /** Scenario ids with no governing constraint — the org's intent-authoring TODO. */
    ungovernedSurface: string[];
    generatedFromProbes: number;
}
/**
 * Assemble the boundary map from a flat list of probe results. Per scenario:
 * the highest level the boundary held at, and where it first cracked.
 */
export declare function buildBoundaryMap(results: ProbeResult[]): BoundaryMap;
//# sourceMappingURL=ScenarioPack.d.ts.map