/**
 * startRuleClaim — WHO CLAIMS A PHRASE. The one place that answers it.
 *
 * Two check-ups ask the same question of a graph's start rules and want
 * opposite answers:
 *
 *   • `skillExamples.ts` declares a phrase and asserts THIS rule claims it;
 *   • `skillNeverRoutes.ts` declares a phrase and asserts NO rule claims it.
 *
 * The question underneath is identical — run the compiled conditions over one
 * concrete phrase, on the context a turn's first iteration really hands a start
 * rule, and see who says yes. Two copies of that would drift the moment one of
 * them learned something about the router the other did not, and the two would
 * then disagree about the same graph. So it lives here, once, and the modules
 * that report keep only their own sentences.
 *
 * Nothing here decides SEVERITY or writes a message — that is the reporting
 * module's job, because the same "no" means different things to a positive and
 * a negative assertion. This module only runs predicates and names conditions.
 *
 * Zone: PURE CORE (no engine, no loop). Pinned by
 * `test/injection-engine/skill-graph-fence.test.ts`.
 */
import type { InjectionContext } from './types.js';
import { type SkillMatchData } from './skillMatch.js';
/**
 * The slice of an entry declaration a claim question reads — structural, so
 * `skillGraph.ts`'s module-private `EntryDecl` satisfies it unchanged (the same
 * trick `skillIntent.ts` uses).
 */
export interface StartRuleDecl {
    readonly id: string;
    /** The compiled condition (from `match:`) or the author's `when`. Absent on
     *  an unconditional entry and on an intent rule (no sync predicate). */
    readonly when?: (ctx: InjectionContext) => boolean;
    /** The serializable matcher behind `when`, when declared as data — quoted
     *  back in the messages, and the one way to spot the intent arm. */
    readonly match?: SkillMatchData;
}
/**
 * Run one entry's condition over one phrase, on a COLD-START context — the
 * context a turn's first iteration really hands a start rule: iteration 1, the
 * phrase as `userMessage`, no history, no cursor, no tool results. A throw is
 * reported as `'threw'` and treated as a no-match by every caller, which is
 * exactly what the cursor resolver does with it at run time (so a claim made
 * here stays true of the run).
 *
 * An entry with NO condition matches everything: that is the cold walk's law
 * (`if (!e.when) return { to: e.id }`), not a shortcut.
 */
export declare function runsOn(entry: StartRuleDecl, phrase: string): 'match' | 'no-match' | 'threw';
/** The one context every predicate in a phrase check is judged on. */
export declare function coldContext(userMessage: string): InjectionContext;
/** The one context every predicate here is judged on, spelled out for the
 *  reader of a message — a check that names its own inputs can be argued with;
 *  one that hides them can only be guessed at. Kept as ONE string so every
 *  message describes the SAME context {@link coldContext} really builds. */
export declare const COLD_CONTEXT_PHRASE: string;
/** One claimant of a phrase: the entry, and its position in declaration order.
 *  (Named Claimant since 9.58.0 — `Claim<T>` on the `/maps` door is the
 *  honesty primitive, a different thing; one name, one meaning.) */
export interface Claimant {
    readonly entry: StartRuleDecl;
    readonly index: number;
}
/** How a rule's condition is named in a message: the data matcher quoted back,
 *  the honest word for opaque code — or, for an entry that declares neither,
 *  what having no condition MEANS. Naming a `when` predicate an unconditional
 *  entry does not have is how a report describes a graph nobody wrote. */
export declare function describeCondition(entry: StartRuleDecl): string;
/**
 * The two claimant sets, mirroring the TWO start laws (see `skillExamples.ts`'s
 * header for the whole statement) rather than re-inventing either:
 *
 *   • COLD WALK (`makeResolveCursor`, the default mount): every non-intent
 *     entry, unconditional ones included — they claim everything from their
 *     position onward.
 *   • CASCADE tier 1 (`firstRuleMatch`, mounted by `.classify()` OR by
 *     `continuity: 'conversation'`): the CONDITIONAL non-intent entries only —
 *     an unconditional entry is a default, not a rule.
 *
 * Intent entries appear in NEITHER: they compile to no sync predicate at all,
 * and the classifier judges them at run time with a scorer this pass does not
 * run.
 */
export interface ClaimLaws {
    /** First claimant under the declaration-order cold walk, or undefined. */
    readonly underColdWalk: (phrase: string) => Claimant | undefined;
    /** First claimant under the turn-start cascade's tier 1, or undefined. */
    readonly underCascade: (phrase: string) => Claimant | undefined;
}
/** Build both laws' claim finders over one entry list, in declaration order. */
export declare function claimLaws(entries: readonly StartRuleDecl[]): ClaimLaws;
