import { z } from 'zod';
import { type EntityDriftEvidence } from './drift.js';
import { type LiveEntity, type LiveEntityIndex } from './resolve.js';
import { type EntitySuccessorOutcome } from './successor.js';
import type { CodebaseIndex } from '../types.js';
import type { TestRecognizer } from '../tests.js';
import type { EntityIndex } from './store.js';
import type { EntityDiagnostic, LineageEvent } from './types.js';
import type { EntityEvidenceGapSummary } from './evidence.js';
import type { OccEntityErrorCode, OccEntityFreshness, OccEntityRef } from './api-types.js';
export declare const ENTITY_ANCHOR_DEFAULT_MAX_ANCHORS = 1000;
export declare const ENTITY_ANCHOR_HARD_MAX_ANCHORS = 10000;
/**
 * Distinct base commits per batch. Each distinct commit costs one memoized
 * O(events) replay (~16ms on this repository's own 265-commit window), so the
 * bound rests on the memo's memory footprint — every cached projection holds a
 * full LiveEntityIndex — not on replay time. Capture stamps one baseCommit per
 * capture session, so distinct commits grow with ordinary memory age; a low
 * default would refuse the headline consolidation use case.
 */
export declare const ENTITY_ANCHOR_MAX_DISTINCT_BASE_COMMITS = 64;
/** CLI wire bounds, enforced by the NDJSON reader before parsing. */
export declare const ENTITY_ANCHOR_DEFAULT_MAX_TOTAL_BYTES: number;
export declare const ENTITY_ANCHOR_HARD_MAX_TOTAL_BYTES: number;
export declare const EntityAnchorExpectedSchema: z.ZodObject<{
    bodyHash: z.ZodString;
    normalizedHash: z.ZodOptional<z.ZodString>;
    structuralHash: z.ZodOptional<z.ZodString>;
    exactSpanHash: z.ZodOptional<z.ZodString>;
    hashVersion: z.ZodOptional<z.ZodNumber>;
    algo: z.ZodOptional<z.ZodEnum<{
        none: "none";
        lexer: "lexer";
        declaration: "declaration";
    }>>;
}, z.core.$strip>;
export type EntityAnchorExpected = z.infer<typeof EntityAnchorExpectedSchema>;
export declare const EntityAnchorSymbolKeySchema: z.ZodObject<{
    relativePath: z.ZodString;
    name: z.ZodString;
    kind: z.ZodOptional<z.ZodEnum<{
        function: "function";
        file: "file";
        enum: "enum";
        module: "module";
        class: "class";
        interface: "interface";
        "type-alias": "type-alias";
        variable: "variable";
        parameter: "parameter";
    }>>;
    containerName: z.ZodOptional<z.ZodString>;
}, z.core.$strip>;
export type EntityAnchorSymbolKey = z.infer<typeof EntityAnchorSymbolKeySchema>;
export declare const EntityAnchorInputSchema: z.ZodObject<{
    id: z.ZodString;
    lineageId: z.ZodOptional<z.ZodString>;
    symbolKey: z.ZodOptional<z.ZodObject<{
        relativePath: z.ZodString;
        name: z.ZodString;
        kind: z.ZodOptional<z.ZodEnum<{
            function: "function";
            file: "file";
            enum: "enum";
            module: "module";
            class: "class";
            interface: "interface";
            "type-alias": "type-alias";
            variable: "variable";
            parameter: "parameter";
        }>>;
        containerName: z.ZodOptional<z.ZodString>;
    }, z.core.$strip>>;
    baseCommit: z.ZodOptional<z.ZodString>;
    expected: z.ZodOptional<z.ZodObject<{
        bodyHash: z.ZodString;
        normalizedHash: z.ZodOptional<z.ZodString>;
        structuralHash: z.ZodOptional<z.ZodString>;
        exactSpanHash: z.ZodOptional<z.ZodString>;
        hashVersion: z.ZodOptional<z.ZodNumber>;
        algo: z.ZodOptional<z.ZodEnum<{
            none: "none";
            lexer: "lexer";
            declaration: "declaration";
        }>>;
    }, z.core.$strip>>;
}, z.core.$strip>;
export type EntityAnchorInput = z.infer<typeof EntityAnchorInputSchema>;
export declare const VerifyEntityAnchorsOptionsSchema: z.ZodObject<{
    anchors: z.ZodArray<z.ZodObject<{
        id: z.ZodString;
        lineageId: z.ZodOptional<z.ZodString>;
        symbolKey: z.ZodOptional<z.ZodObject<{
            relativePath: z.ZodString;
            name: z.ZodString;
            kind: z.ZodOptional<z.ZodEnum<{
                function: "function";
                file: "file";
                enum: "enum";
                module: "module";
                class: "class";
                interface: "interface";
                "type-alias": "type-alias";
                variable: "variable";
                parameter: "parameter";
            }>>;
            containerName: z.ZodOptional<z.ZodString>;
        }, z.core.$strip>>;
        baseCommit: z.ZodOptional<z.ZodString>;
        expected: z.ZodOptional<z.ZodObject<{
            bodyHash: z.ZodString;
            normalizedHash: z.ZodOptional<z.ZodString>;
            structuralHash: z.ZodOptional<z.ZodString>;
            exactSpanHash: z.ZodOptional<z.ZodString>;
            hashVersion: z.ZodOptional<z.ZodNumber>;
            algo: z.ZodOptional<z.ZodEnum<{
                none: "none";
                lexer: "lexer";
                declaration: "declaration";
            }>>;
        }, z.core.$strip>>;
    }, z.core.$strip>>;
    maxAnchors: z.ZodOptional<z.ZodNumber>;
}, z.core.$strip>;
export type VerifyEntityAnchorsOptions = z.infer<typeof VerifyEntityAnchorsOptionsSchema>;
export interface VerifyEntityAnchorsRuntimeOptions extends VerifyEntityAnchorsOptions {
    signal?: AbortSignal;
}
/** The working-tree lane, priced only when at least one anchor needs it. */
export interface EntityAnchorLiveContext {
    live: LiveEntityIndex;
    index: CodebaseIndex;
    /**
     * Whether this index provably mirrors the working tree (reconciled against
     * a manifest stat-diff, or built in-process this invocation). Absent means
     * trusted. When false, hash-lane verdicts degrade to `unknown` with reason
     * `index-stale` — never a `fresh` graded from possibly-stale bytes.
     */
    trusted?: boolean;
}
export interface EntityAnchorVerifyContext {
    repoRoot: string;
    entityIndex: EntityIndex;
    freshness: OccEntityFreshness;
    recognizer: TestRecognizer;
    /**
     * Thunked so the event-scan lane never pays for a code-index build. Consumed
     * only by the expected-tuple lane and successor resolution; head state for
     * lineage-lane facts comes from the committed projection, never from here.
     */
    getLive?: () => Promise<EntityAnchorLiveContext>;
}
export declare const EntityAnchorVerdictSchema: z.ZodEnum<{
    unknown: "unknown";
    deleted: "deleted";
    renamed: "renamed";
    fresh: "fresh";
    "normalized-equal": "normalized-equal";
    "semantic-drift": "semantic-drift";
    moved: "moved";
}>;
export type EntityAnchorVerdict = z.infer<typeof EntityAnchorVerdictSchema>;
export declare const EntityAnchorUnknownReasonSchema: z.ZodEnum<{
    "unknown-tier": "unknown-tier";
    "evidence-unavailable": "evidence-unavailable";
    "outside-window": "outside-window";
    "lineage-version-mismatch": "lineage-version-mismatch";
    "index-stale": "index-stale";
}>;
export type EntityAnchorUnknownReason = z.infer<typeof EntityAnchorUnknownReasonSchema>;
export type EntityAnchorRefusalCode = 'base-commit-not-found' | 'base-commit-not-indexed' | 'base-commit-resolution-failed' | 'base-commit-budget-exceeded' | 'unverifiable-anchor' | 'symbol-key-ambiguous' | 'symbol-key-not-found-at-base';
export interface EntityAnchorDiagnostic {
    code: EntityAnchorRefusalCode | 'lineage-collision' | 'base-entity-unresolved' | 'handle-mismatch';
    message: string;
    anchorId: string;
    baseCommit?: string;
    underlyingCode?: OccEntityErrorCode;
    candidates?: OccEntityRef[];
}
/**
 * Named `verification`, not `evidence`: the `evidence` key is stripped by the
 * MCP concise projection (it elides `LineageEvent.evidence` matcher internals),
 * and this audit block must survive projection by construction.
 */
export interface EntityAnchorVerification {
    tier: 'exact-span' | 'body' | 'normalized' | 'structural' | 'lineage-events' | 'none';
    hashVersion: number;
    expectedCompared: boolean;
}
export interface EntityAnchorLocation {
    pathChanged: boolean;
    nameChanged: boolean;
    pathAtBase?: string;
    pathAtHead?: string;
}
export interface EntityAnchorChangesSince {
    /**
     * Content-changing events after the baseline, net of pure identity motion:
     * a rename whose structural shape survived does not count, a rename that
     * also changed shape does. (Unlike drift-documents' raw `logicChanged`
     * count, which would report every pure rename as a content change.)
     */
    count: number;
    strongestEvidence: EntityDriftEvidence;
    /**
     * False when in-range event-dropping gaps cover this anchor's files, the
     * match is indeterminate, or an identity-motion event was undecidable.
     */
    evidenceComplete: boolean;
}
export interface EntityAnchorBaseline {
    requested: string;
    commit: string;
    commitOrder: number;
    committedAt: string;
}
export interface EntityAnchorHonesty {
    freshness: {
        fresh: boolean;
        reasons: OccEntityFreshness['reasons'];
        workingTreeMeasured: boolean;
    };
    truncation: {
        truncated: boolean;
        reasons: EntityDiagnostic[];
        omitted: number;
    };
    evidenceGaps: EntityEvidenceGapSummary;
}
export interface EntityAnchorResolvedOutcome {
    status: 'resolved';
    id: string;
    verdict: EntityAnchorVerdict;
    unknownReason?: EntityAnchorUnknownReason;
    baseline?: EntityAnchorBaseline;
    entityAtBase?: OccEntityRef;
    entityAtHead?: OccEntityRef;
    location?: EntityAnchorLocation;
    changesSince?: EntityAnchorChangesSince;
    verification: EntityAnchorVerification;
    successor?: EntitySuccessorOutcome;
    provisional?: boolean;
    indeterminate?: boolean;
    diagnostics: EntityAnchorDiagnostic[];
    honesty: EntityAnchorHonesty;
}
export interface EntityAnchorRefusedOutcome {
    status: 'refused';
    id: string;
    code: EntityAnchorRefusalCode;
    message: string;
    diagnostics: EntityAnchorDiagnostic[];
    honesty: EntityAnchorHonesty;
}
export type EntityAnchorOutcome = EntityAnchorResolvedOutcome | EntityAnchorRefusedOutcome;
export interface EntityAnchorBatchHonesty extends EntityAnchorHonesty {
    coverage: {
        anchorsSubmitted: number;
        anchorsResolved: number;
        anchorsRefused: number;
        verdictCounts: Record<EntityAnchorVerdict, number>;
        distinctBaseCommits: number;
        baseCommitBudget: number;
        diagnosticsOmitted: number;
    };
    inputBounds: {
        maxAnchors: number;
        hardMaxAnchors: number;
        maxDistinctBaseCommits: number;
    };
    ambiguityCount: number;
}
export type VerifyEntityAnchorsResult = {
    status: 'resolved';
    anchors: EntityAnchorOutcome[];
    honesty: EntityAnchorBatchHonesty;
} | {
    status: 'error';
    code: 'invalid-options' | 'budget-exceeded';
    message: string;
    limits: {
        maxAnchors: number;
        hardMaxAnchors: number;
        maxDistinctBaseCommits: number;
    };
    actual?: {
        anchors: number;
    };
};
/**
 * How a caller names the entity to anchor. A plain object rather than a union
 * so the exactly-one-of guard sees every key the caller wrote — a union of
 * stripping object schemas would silently discard the second handle on mixed
 * input, which is the guess this surface exists to refuse.
 */
export declare const EntityAnchorCaptureHandleSchema: z.ZodObject<{
    name: z.ZodOptional<z.ZodString>;
    relativePath: z.ZodOptional<z.ZodString>;
    kind: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
        function: "function";
        file: "file";
        enum: "enum";
        type: "type";
        module: "module";
        class: "class";
        interface: "interface";
        variable: "variable";
        parameter: "parameter";
        method: "method";
        other: "other";
    }>, z.ZodEnum<{
        object: "object";
        array: "array";
        "array-item": "array-item";
        property: "property";
        section: "section";
        table: "table";
        "array-table": "array-table";
        heading: "heading";
        row: "row";
        document: "document";
    }>, z.ZodEnum<{
        test: "test";
        test_suite: "test_suite";
    }>]>>;
    containerName: z.ZodOptional<z.ZodString>;
    lineageId: z.ZodOptional<z.ZodString>;
    nodeId: z.ZodOptional<z.ZodString>;
}, z.core.$strip>;
export type EntityAnchorCaptureHandle = z.infer<typeof EntityAnchorCaptureHandleSchema>;
export interface EntityAnchorCaptured {
    lineageId: string;
    symbolKey: EntityAnchorSymbolKey;
    /**
     * Present only when capture proved the pairing: the entity is committed, its
     * working-tree bytes equal its committed head record, and the repository
     * head has not moved past the indexed head. Anything else omits the field —
     * stamping a commit whose tree never contained these hashes would store a
     * false state-at-commit claim and defer the lie to every later verify.
     */
    baseCommit?: string;
    expected: EntityAnchorExpected;
    provisional?: boolean;
    indeterminate?: boolean;
    /** Working-tree bytes differ from the committed head record. */
    uncommittedContent?: boolean;
}
export type CaptureEntityAnchorResult = {
    status: 'resolved';
    anchor: EntityAnchorCaptured;
    freshness: OccEntityFreshness;
    warnings: string[];
} | {
    status: 'not_found';
    candidates: OccEntityRef[];
    message: string;
} | {
    status: 'ambiguous';
    candidates: OccEntityRef[];
    message: string;
} | {
    status: 'error';
    code: OccEntityErrorCode;
    message: string;
};
/**
 * Project one live entity into a verifiable anchor, from one session snapshot.
 *
 * The expected tuple is a projection of the live record's hashes — never
 * `signatureHash`/`tokenCount`, and never an exact-span tier: `exactBodyHash`
 * digests the whole-diff CST span while symbol-hash's `exactSpanHash` digests
 * the live-index node span, and equating the two without a per-language proof
 * would manufacture false drift.
 */
export declare function captureEntityAnchor(input: {
    entity: LiveEntity;
    entityIndex: EntityIndex;
    freshness: OccEntityFreshness;
    /**
     * False when the live index behind `entity` could not be proved to mirror
     * the working tree (a borrowed, unmeasurable session). Both `baseCommit`
     * and `uncommittedContent` are affirmative working-tree claims and are
     * emitted only from a trusted view; an untrusted capture degrades to an
     * expected-only anchor with an explicit warning.
     */
    workingTreeTrusted?: boolean;
}): {
    anchor: EntityAnchorCaptured;
    warnings: string[];
};
type HashTier = EntityAnchorVerification['tier'];
interface HashLaneResult {
    verdict: 'fresh' | 'normalized-equal' | 'semantic-drift' | 'unknown';
    tier: HashTier;
    /** Why the lane refused, when it did. */
    unknownReason?: EntityAnchorUnknownReason;
}
export type AnchorEventContentGrade = 'changed' | 'cosmetic' | 'unchanged' | 'undecidable';
/**
 * Did this event change the entity's content, as opposed to only its identity?
 *
 * Two flag subtleties make the raw `logicChanged` bit unusable here. First, a
 * pure rename records `logicChanged: true` — the declared name is non-trivia
 * and OCC never claims a rename is a semantic no-op for callers — so for
 * identity motion (renamed/moved/reordered) the event's own structural hashes
 * decide: they are identifier-blind, and equality across the motion is real
 * evidence the shape survived (literal-only edits are invisible to that tier,
 * one more reason expected-tuple anchors are strictly stronger). Second, a
 * CST-proved comment-only change is recorded as `modified` with
 * `semanticBasis: 'comment-only-change'` and `logicChanged` unset — proved
 * cosmetic, not unverified — while any other unproven body change (whitespace
 * significance, missing grammar evidence) grades `undecidable`, never guessed.
 */
export declare function gradeEventContent(event: LineageEvent): AnchorEventContentGrade;
/** Inputs to the pure verdict derivation, so every arm is unit-testable. */
export interface AnchorVerdictInput {
    /** Committed lineage state for the anchor's lineage, when one is known. */
    lineage?: {
        status: 'live';
        atHead: OccEntityRef;
    } | {
        status: 'deleted';
    } | {
        status: 'absent';
    } | {
        status: 'outside-window';
    } | {
        status: 'version-mismatch';
    };
    /** Present when a baseline resolved and the entity was found at it. */
    atBase?: OccEntityRef;
    /** All lineage events strictly after the baseline, oldest first. */
    eventsSince?: readonly LineageEvent[];
    /** Base-side frozen body hash, when the replayed record carries a real one. */
    baseBodyHash?: string;
    /** Head-side frozen body hash from the committed head projection. */
    headBodyHash?: string;
    /** Outcome of the expected-tuple comparison, when one ran. */
    hashLane?: HashLaneResult;
    /** In-range event-dropping gaps cover this anchor's files. */
    gapsCovered: boolean;
    /** The matched entity's lineage id was synthesized by a bound-exhausted index. */
    indeterminate: boolean;
}
export interface AnchorVerdictDerivation {
    verdict: EntityAnchorVerdict;
    unknownReason?: EntityAnchorUnknownReason;
    tier: HashTier;
}
/**
 * Derive the single verdict a memory consolidator switches on.
 *
 * Precedence `deleted > semantic-drift > renamed > moved > normalized-equal >
 * fresh`, with one scoped override: proved tuple equality beats event-lane
 * content inference (an edit-and-revert is `fresh` with its events still
 * surfaced), while `renamed`/`moved` survive a byte-equal tuple because equal
 * content does not repair a broken symbol-key handle. `moved`/`renamed` are
 * net base-vs-head state — per-event flags are never a verdict condition,
 * because a rename-and-revert nets to identity.
 */
export declare function deriveAnchorVerdict(input: AnchorVerdictInput): AnchorVerdictDerivation;
/**
 * Verify caller-held anchors against lineage evidence and, when asked, live
 * hashes. OCC validates the memory and stores nothing: input is consumed,
 * never persisted, and no anchor registry exists on either side of this call.
 */
export declare function verifyEntityAnchors(options: VerifyEntityAnchorsRuntimeOptions, context: EntityAnchorVerifyContext): Promise<VerifyEntityAnchorsResult>;
export {};
