/**
 * skillExamples — the EXAMPLES side of a start rule: the phrasings a rule says
 * it claims, and the three things a build-time check-up can then PROVE about
 * them by RUNNING the compiled matchers instead of comparing them.
 *
 * ## Why this exists (two field failures, one evening)
 *
 * `compareMatchers` (skillMatch.ts) answers only what matcher-vs-matcher
 * analysis can prove, and says so out loud: two DIFFERENT regex sources return
 * `undefined` ("regex intersection is not decided here — only identity is
 * provable"). That honesty left two real production failures unreportable:
 *
 *   A. SHADOWING BY DIFFERENT REGEXES — an earlier rule matching one product
 *      name sat above an inventory rule whose matcher is a longer alternation.
 *      A real phrase ("what's running on <host-looking-name>") was claimed by
 *      the earlier rule, so the later rule could never win on its own
 *      phrasings. Two different regexes: the check-up was correctly silent.
 *   B. ABSENCE — a second phrase matched NO rule at all, fell through to the
 *      model tier, and the model picked the wrong skill because an array name
 *      looked like a hostname. Not shadowing: absence. No amount of
 *      matcher-vs-matcher analysis can ever catch it.
 *
 * A declared example turns both into arithmetic. Run the compiled predicates
 * over one concrete phrase, in declaration order, exactly as the cold start
 * does — and the answer is a WITNESS, not a theory: this phrase, this rule,
 * this winner. No regex intersection is decided anywhere in this file.
 *
 * ## The tier difference (read this before writing `examples` anywhere)
 *
 * Two different lists spell the same author-facing sentence — "the phrasings
 * this rule claims" — and they have DIFFERENT RUNTIME ROLES:
 *
 *   • TIER 2, `match: { intent, examples }` — SCORING material. The classifier
 *     reads those examples AT RUN TIME to judge every new message
 *     (`skillIntent.ts`); they are part of how the graph routes.
 *   • TIER 1, a rule-level `examples: [...]` (this file) — TEST material. Read
 *     at BUILD time by the check-up and fed to nothing, ever. They do not
 *     widen, soften or otherwise touch matching: a rule with examples routes
 *     byte-identically to the same rule without them.
 *
 * One rule may not carry both lists (a teaching refusal names the difference):
 * two example lists with two different jobs under one rule is exactly the
 * confusion this note exists to prevent.
 *
 * ## The two start laws, and why one of them is only a WARNING
 *
 * Which rule claims a phrase is decided by one of TWO laws, and the graph does
 * not know which one it will be mounted under:
 *
 *   • the declaration-order COLD WALK (`makeResolveCursor`, the default mount)
 *     returns at the first entry with no condition or the first whose condition
 *     passes — so an UNCONDITIONAL entry claims every message from its position
 *     onward;
 *   • the turn-start CASCADE's tier 1 (`firstRuleMatch`, skillIntent.ts) reads
 *     the CONDITIONAL non-intent entries only — an unconditional entry is a
 *     default, not a rule, and never wins the turn there. That cascade is
 *     mounted by `.classify()` AND by `.skillGraph(g, { continuity:
 *     'conversation' })`, and continuity is an AGENT-MOUNT option that does not
 *     exist yet when this check runs.
 *
 * The two laws differ in exactly one place: whether an unconditional entry
 * claims. So when the earlier claimant is unconditional, the check-up cannot
 * say which law will apply — it reports BOTH readings as a WARNING
 * (`example-shadowed-by-default`) instead of asserting one as an ERROR. A
 * check-up that disagrees with the router is worse than no check-up: the router
 * really does start that turn on the later rule under a `continuity:
 * 'conversation'` mount. The ERROR (`example-shadowed-by-earlier`) is kept for
 * what both laws agree on.
 *
 * ## The context a rule is judged in, and what that makes provable
 *
 * Every predicate here runs on ONE context: {@link coldContext} — iteration 1,
 * the phrase as `userMessage`, empty `history`, no cursor. That is a real
 * context (the first iteration of a turn), but it is not the only one a start
 * rule ever sees: turn 2 of a conversation also starts cold in cursor terms
 * while carrying HISTORY. So:
 *
 *   • a DATA matcher (`match:`) reads `userMessage` and nothing else, so a
 *     no-match here is a no-match under every context — ERROR;
 *   • an opaque `when` may legitimately be gated on conversation state
 *     (`ctx.history.length > 0`) and claim the phrase on a later turn — the
 *     check cannot run that turn, so a no-match is a WARNING, and the message
 *     names the context it judged under rather than leaving the author to guess.
 *
 * A THROW stays an ERROR either way: a predicate must be pure and total, and
 * the context it threw on is one every turn 1 really hands it.
 *
 * ## The boundary, and why it is on the report itself
 *
 * These checks prove things about the phrases the author DECLARED and nothing
 * about phrases nobody wrote. No warning is NOT proof of coverage. That
 * sentence ships as {@link EXAMPLES_BOUNDARY} on `GraphCheckup.notes` —
 * visible wherever the graph reports its problems — because a reader who meets
 * it only in prose docs will meet a clean report first.
 *
 * ## The opposite assertion lives next door
 *
 * Everything here is POSITIVE: this rule claims this phrase. The negative form
 * — a phrase that must claim NO skill, which is the assertion that catches
 * over-triggering — is `skillNeverRoutes.ts`, declared on the GRAPH rather than
 * on a rule (a phrase that must route nowhere belongs to no skill). Both ask
 * `startRuleClaim.ts` the same question and differ only in which answer is a
 * defect; a phrase declared BOTH ways is reported there as the contradiction it
 * is.
 *
 * Composed into `graph.checkup()` by `skillGraph.ts`, exactly like
 * `skillContract`/`skillIntent`/`skillVocabulary`: this module owns the rule
 * AND its boundaries, and reports in the shared `GraphProblem` voice.
 */
import { type StartRuleDecl } from './startRuleClaim.js';
import type { GraphProblem } from './skillGraphCheckup.js';
/**
 * The statement the check-up makes about its own reach, carried on
 * `GraphCheckup.notes` whenever any rule declared examples. Same voice as the
 * ingress ticket's "absence of a refusal is not consent": a clean report is
 * evidence about the phrases you wrote, and about nothing else.
 */
export declare const EXAMPLES_BOUNDARY: string;
/** The note added when declaration order does not decide the turn start, so
 *  only the order-independent check (self-match) could run. */
export declare const EXAMPLES_ORDER_NOT_CHECKED: string;
/**
 * The slice of an entry declaration this module reads — the shared claim shape
 * ({@link StartRuleDecl}, which owns "who claims a phrase") plus the one field
 * only this check reads. Structural, so `skillGraph.ts`'s module-private
 * `EntryDecl` satisfies it unchanged (the same trick `skillIntent.ts` uses).
 */
export interface ExampleRuleDecl extends StartRuleDecl {
    /** The phrasings this rule claims (build-time TEST material). */
    readonly examples?: readonly string[];
}
/** What {@link checkStartRuleExamples} found, plus what it wants to say about
 *  its own reach. Both empty when no rule declared examples. */
export interface ExamplesCheckup {
    readonly problems: readonly GraphProblem[];
    readonly notes: readonly string[];
}
/**
 * Validate a rule-level `examples` list at DECLARATION time, refusing every
 * shape whose check-up answer could only mislead — each refusal naming the fix:
 *
 *   • not an array / an EMPTY array — nothing to prove, and a check-up that
 *     passes in silence reads as coverage;
 *   • a non-string or blank entry — there is no phrase to run a matcher on;
 *   • examples on an UNCONDITIONAL entry — it claims every message, so every
 *     example passes by construction and proves nothing;
 *   • examples beside `match: { intent, examples }` — two lists, two jobs (see
 *     the tier note in this file's header).
 *
 * Returns a frozen copy (or `undefined` when nothing was declared), so the
 * stored list cannot drift from the validated one.
 */
export declare function validateStartRuleExamples(examples: unknown, where: string, rule: {
    readonly hasCondition: boolean;
    readonly isIntent: boolean;
}): readonly string[] | undefined;
/**
 * Run the three example properties. Pure, and byte-identically silent when no
 * rule declared examples (one `Array.some` and out).
 *
 * `orderDecides` mirrors the gate the pairwise rule checks already use
 * (`!exclusiveEntries || hasClassifier`): declaration order decides the turn
 * start under the default form and under a classifier's tier 1, and does NOT
 * under a scorer or `.entryByRead()`. Where it does not hold, only the
 * order-independent property (self-match) is claimed and a note says so.
 */
export declare function checkStartRuleExamples(input: {
    readonly entries: readonly ExampleRuleDecl[];
    readonly orderDecides: boolean;
    readonly hasClassifier: boolean;
}): ExamplesCheckup;
