/**
 * Ownership contract for the one mutation-score floor that lives in two files.
 *
 * `.lisa.config.json` (`quality.mutation.strykerThresholds`) owns the value;
 * `stryker.conf.json` (`thresholds`) is where Stryker reads it. Every other
 * sync artifact is written wholesale (`pointer: ""`), so a hand-edit to one of
 * those is obviously wrong and gets overwritten. `stryker.conf.json` is the
 * only partial binding in the registry: editing 17 of its 18 keys is correct
 * and editing the 18th is silently wrong — which is exactly the file that
 * drifted (CodySwannGT/lisa#2968).
 *
 * This module is deliberately named after that single instance rather than
 * generalised. A framework for a one-instance problem is a bigger mistake than
 * the instance; if a second partial binding is ever added, the registry test
 * that pins "exactly one partial binding" fails and forces the decision then.
 *
 * Two controls live here:
 *
 * 1. {@link describeMutationFloorDivergence} — the message the config sync
 *    fails with when the two floors disagree with nothing recording why. Sync
 *    refuses in BOTH directions: writing the config value can raise the floor
 *    above the score the codebase actually measures (reddening the mutation
 *    gate on unchanged code), and absorbing the file value would silently
 *    lower a declared floor.
 *
 *    A divergence someone deliberately chose is a different case, and blocking
 *    it would make the guard the thing that gets deleted. When
 *    `_thresholdsDivergence` records BOTH live numbers and a reason, sync
 *    proceeds, leaves the enforced floor alone, and reports that it is
 *    honouring a recorded divergence — visible, not blocking. A declaration
 *    that has gone stale against either live value is no longer a record of a
 *    decision, so it stops exempting anything.
 * 2. {@link checkMutationFloorOwnership} — the executable form of the
 *    ownership statement carried in `stryker.conf.json` itself, so that a
 *    hand-edit of `thresholds` fails a test instead of relying on a comment
 *    being read.
 * @module sync/stryker-thresholds-ownership
 */
import { type JsonValue } from "./json-path.js";
/** Config key that owns the mutation-score floor. */
export declare const MUTATION_FLOOR_CONFIG_KEY = "quality.mutation.strykerThresholds";
/** Config file that owns the mutation-score floor. */
export declare const MUTATION_FLOOR_CONFIG_FILE = ".lisa.config.json";
/** Artifact file that mirrors the mutation-score floor. */
export declare const MUTATION_FLOOR_ARTIFACT_FILE = "stryker.conf.json";
/** Dot path of the mirrored floor inside the artifact file. */
export declare const MUTATION_FLOOR_ARTIFACT_POINTER = "thresholds";
/** Artifact key stating, in the file itself, who owns `thresholds`. */
export declare const MUTATION_FLOOR_OWNER_FIELD = "_thresholdsOwner";
/** Artifact key declaring a deliberate, temporary, fully-recorded divergence. */
export declare const MUTATION_FLOOR_DIVERGENCE_FIELD = "_thresholdsDivergence";
/**
 * Whether a registry binding is the single config-owned mutation floor.
 * @param key - Registry entry key being synced
 * @param file - Artifact file the binding writes
 * @param pointer - Dot path inside that file
 * @returns True for the one guarded binding
 */
export declare function isMutationFloorBinding(key: string, file: string, pointer: string): boolean;
/**
 * Build the operator-readable divergence diagnosis, naming both values and the
 * file each came from.
 * @param configValue - Floor declared in the config
 * @param artifactValue - Floor enforced by the artifact
 * @returns Multi-line failure message
 */
export declare function describeMutationFloorDivergence(configValue: unknown, artifactValue: unknown): string;
/** Config sync refused to write because the two mutation floors disagree. */
export declare class MutationFloorDivergenceError extends Error {
    /** Floor declared in the config. */
    readonly configValue: unknown;
    /** Floor enforced by the artifact on disk. */
    readonly artifactValue: unknown;
    /**
     * Build the refusal carrying both floors.
     * @param configValue - Floor declared in the config
     * @param artifactValue - Floor enforced by the artifact
     */
    constructor(configValue: unknown, artifactValue: unknown);
}
/** A deliberate, fully-recorded divergence between the two floors. */
export interface MutationFloorDeclaration {
    /** Why the two floors are allowed to differ, and what resolves it. */
    readonly reason: string;
    /** Floor this file enforces. */
    readonly enforced: JsonValue;
    /** Floor the owning config key declares. */
    readonly declared: JsonValue;
}
/**
 * Read `_thresholdsDivergence` when it still records the live numbers.
 * @param strykerConf - Parsed `stryker.conf.json`
 * @param onDisk - Floor this file currently enforces
 * @param configValue - Floor the owning config key currently declares
 * @returns The declaration, or undefined when absent, incomplete, or stale
 */
export declare function readMutationFloorDeclaration(strykerConf: unknown, onDisk: unknown, configValue: unknown): MutationFloorDeclaration | undefined;
/**
 * Build the line sync prints when it honours a recorded divergence.
 * @param declaration - The current, matching divergence declaration
 * @returns Operator-readable single-line detail
 */
export declare function describeHonouredMutationFloorDivergence(declaration: MutationFloorDeclaration): string;
/**
 * Check the ownership statement carried by `stryker.conf.json` itself.
 * @param strykerConf - Parsed `stryker.conf.json`
 * @param configValue - Floor declared in the owning config key
 * @returns One problem string per violation; empty when the file is in step
 */
export declare function checkMutationFloorOwnership(strykerConf: unknown, configValue: unknown): readonly string[];
//# sourceMappingURL=stryker-thresholds-ownership.d.ts.map