import { z } from 'zod';
/**
 * Why an entity or file was judged to be a test.
 *
 * A recorded reason is not decoration: affected-test discovery is only
 * trustworthy if a caller can see *why* something was counted, and a
 * misclassified helper is otherwise indistinguishable from a real test in the
 * output.
 */
export declare const OccTestReasonCodeSchema: z.ZodEnum<{
    "test-directory": "test-directory";
    "test-filename": "test-filename";
    "test-symbol-name": "test-symbol-name";
    "test-container": "test-container";
    "test-import": "test-import";
    "test-call": "test-call";
    "test-block": "test-block";
    "test-attribute": "test-attribute";
    "custom-directory": "custom-directory";
    "custom-pattern": "custom-pattern";
}>;
export type OccTestReasonCode = z.infer<typeof OccTestReasonCodeSchema>;
export declare const OccTestReasonSchema: z.ZodObject<{
    code: z.ZodEnum<{
        "test-directory": "test-directory";
        "test-filename": "test-filename";
        "test-symbol-name": "test-symbol-name";
        "test-container": "test-container";
        "test-import": "test-import";
        "test-call": "test-call";
        "test-block": "test-block";
        "test-attribute": "test-attribute";
        "custom-directory": "custom-directory";
        "custom-pattern": "custom-pattern";
    }>;
    detail: z.ZodString;
    confidence: z.ZodNumber;
    source: z.ZodEnum<{
        symbol: "symbol";
        path: "path";
        content: "content";
        graph: "graph";
    }>;
}, z.core.$strip>;
export type OccTestReason = z.infer<typeof OccTestReasonSchema>;
export declare const OccTestSignalSchema: z.ZodObject<{
    isTest: z.ZodBoolean;
    confidence: z.ZodNumber;
    reasons: z.ZodArray<z.ZodObject<{
        code: z.ZodEnum<{
            "test-directory": "test-directory";
            "test-filename": "test-filename";
            "test-symbol-name": "test-symbol-name";
            "test-container": "test-container";
            "test-import": "test-import";
            "test-call": "test-call";
            "test-block": "test-block";
            "test-attribute": "test-attribute";
            "custom-directory": "custom-directory";
            "custom-pattern": "custom-pattern";
        }>;
        detail: z.ZodString;
        confidence: z.ZodNumber;
        source: z.ZodEnum<{
            symbol: "symbol";
            path: "path";
            content: "content";
            graph: "graph";
        }>;
    }, z.core.$strip>>;
}, z.core.$strip>;
export type OccTestSignal = z.infer<typeof OccTestSignalSchema>;
export interface TestRecognitionConfig {
    /** Extra directory segment names, matched as whole path segments. */
    directories?: readonly string[];
    /** Extra filename globs (`*` matches within one segment). */
    filePatterns?: readonly string[];
    /** Extra anchored regex sources matched against the symbol name. */
    symbolPatterns?: readonly string[];
    /**
     * Extra framework entry points that open a test block, beyond the built-in
     * BDD vocabulary. What keeps block recognition config-driven rather than
     * pinned to one framework.
     */
    callNames?: readonly string[];
    /** Drop the built-in conventions entirely and use only the custom ones. */
    disableDefaults?: boolean;
    /** Confidence at or above which `isTest` is true. Default 0.5. */
    minConfidence?: number;
}
/**
 * Directory segments that mark a test tree. Matched as whole segments, never
 * as substrings — `src/contest/`, `src/latest/`, and `src/attestation/` are
 * production code and must not be swept up.
 */
export declare const DEFAULT_TEST_DIRECTORIES: readonly string[];
export declare const DEFAULT_TEST_FILE_PATTERNS: readonly string[];
/**
 * Framework entry points that open a test block.
 *
 * Deliberately the BDD vocabulary rather than any one framework's API: jest,
 * vitest, mocha, jasmine, node:test, and Google Test all spell a block with one
 * of these. Exported so the parser recognizes exactly the names the recognizer
 * scores, instead of keeping a second list that can drift.
 */
export declare const TEST_CALL_NAMES: ReadonlySet<string>;
/**
 * True when a module specifier names a test framework.
 *
 * The qualifier that turns a bare-name match into evidence: `it(...)` imported
 * from `vitest` is a test, `it(...)` imported from a local module is a function
 * that happens to share the name.
 */
export declare function isTestFrameworkSpecifier(specifier: string): boolean;
export interface ClassifyTestFileInput {
    relativePath: string;
    /** Import specifiers, when the caller has a parsed file to hand. */
    importSpecifiers?: readonly string[];
    /** Callee names appearing in the file. */
    calleeNames?: readonly string[];
    /**
     * Every name the file declares or imports, with where an imported one came
     * from (absent means declared here).
     *
     * Without this, `calleeNames` is matched bare, and an ordinary module that
     * defines and calls its own `context(...)` is asserted to be a test. Omit it
     * and matching stays bare, which is the older, looser behaviour.
     */
    bindings?: readonly {
        name: string;
        specifier?: string;
    }[];
}
export interface ClassifyTestSymbolInput {
    name: string;
    /**
     * The entity's kind. Widened past `NormalizedSymbolKind` so data-format
     * entities can be classified too; no rule reads it today, but every other
     * classifier input is name- or path-shaped and this keeps the set complete.
     */
    kind: string;
    containerName?: string;
    /** True when extraction already identified this entity as a test block. */
    isTestBlock?: boolean;
    /**
     * The declaration line plus a few preceding non-blank lines. Supplied only
     * when the caller already holds the source — attribute detection is
     * impossible without it, and this module never reads the filesystem.
     */
    declarationContext?: readonly string[];
    /** Base class names from inheritance edges. */
    baseNames?: readonly string[];
}
export interface TestRecognizer {
    classifyFile(input: ClassifyTestFileInput): OccTestSignal;
    classifySymbol(input: ClassifyTestSymbolInput): OccTestSignal;
    /** File evidence inherited by an entity, merged with its own symbol evidence. */
    classifyEntity(fileSignal: OccTestSignal, symbolSignal: OccTestSignal): OccTestSignal;
}
export declare function createTestRecognizer(config?: TestRecognitionConfig): TestRecognizer;
/** Convenience predicate for callers that only have a path. */
export declare function isTestPath(relativePath: string, config?: TestRecognitionConfig): boolean;
