/**
 * codeRegions — the fenced code blocks of an answer, read by one linear pass,
 * closed where a CommonMark renderer closes them.
 *
 * Pattern: pure leaf. Imports nothing — it does not know the gate exists. The
 *          one reader of "which bytes of this answer sit inside a fenced
 *          block", asked by the script match (`../scripts/match.ts`) under
 *          `.namesAndNumbersFromEvidence({ code: 'match' })`. Under the
 *          default `code: 'check'` it is never called.
 * Role:    core/ layer (the evidence gate's folder), no state, no events.
 *
 * ## Why it must agree with the renderer
 *
 * A region that matches a submission is exempt from the evidence check. If
 * this reader saw a block where a renderer shows prose, a model could submit a
 * program holding a sentence, show it fenced so that the sentence renders
 * outside the block, and the sentence would never be checked. So the reader
 * closes a block exactly where CommonMark closes it. Where a renderer could
 * pair fences another way, it stops reading blocks altogether.
 *
 * ## The grammar (design: docs/design/2026-10-script-artifact.md § 5.1–5.2, aligned with CommonMark)
 *
 * The answer is read line by line. A line ends at an LF, a CR or a CRLF, as
 * CommonMark ends it.
 *
 * - An OPENING fence starts at column 0 with three or more backticks, or three
 *   or more tildes, then an optional info string, and ENDS IN A LINE ENDING.
 *   A backtick fence's info string may not contain a backtick.
 * - The CLOSING fence uses the same character and is at least as long. As in
 *   CommonMark, it may be indented by up to three spaces and is followed only
 *   by spaces.
 * - The CONTENT is exactly the bytes between the opening line's line ending
 *   and the ONE line ending before the closing line: every space, tab, CR and
 *   code point as written. Before the closing line, an LF is the wrapper's (a
 *   CR before it is content), and so is a lone CR. A closing fence on the line
 *   right after the opening one gives an empty block (content `''`).
 * - A fence that never closes is NOT a region: the text from it to the end is
 *   prose.
 * - At most {@link MAX_CODE_REGIONS} regions are read; the rest are prose and
 *   counted in `dropped`.
 *
 * ## Where reading stops (`stoppedAt`)
 *
 * The reader models CommonMark's top level only. It does not model list
 * items, block quotes, HTML blocks or the extensions renderers add. At the
 * first line where a renderer could pair fences another way, reading STOPS.
 * No region is read from there on: everything after that point is prose and
 * checked.
 *
 * Outside a block, reading stops at:
 * - a fence indented by one to three spaces. It is either a list item's fence,
 *   which the item scopes, or an indented fence, whose content a renderer
 *   strips (and "as written" and "with the indentation removed" are two
 *   different programs);
 * - a line that may start an HTML block (up to three spaces, `<`, then a
 *   letter, `/`, `!` or `?`). Inside an HTML block, a fence is not a fence;
 * - a line opening display math (`$$`), the block extension chat renderers
 *   commonly add. Inside display math, a fence is not a fence;
 * - a byte-order mark at the very start, which some renderers drop and some
 *   keep.
 *
 * Inside a block, reading stops at:
 * - a closing run followed by a TAB. CommonMark 0.30 closes the block there
 *   and 0.29 does not, so the block is read (it is code either way) and
 *   reading stops after it;
 * - a run of the block's own fence character, anywhere in its content, as long
 *   as its opening fence. A renderer laxer than CommonMark could close the
 *   block there, so the block is prose and reading stops at its opening line.
 *   The library's own wrapper never writes such a block
 *   (`../scripts/wrapper.ts` · `fenceFor`: the longest run + 1).
 *
 * Nothing here normalizes anything: no trimming, no line-ending rewrite, no
 * Unicode normalization. A region is the program a reader would copy.
 *
 * ## Linear by construction
 *
 * The text is model output, so the pass is linear in it (the
 * `lib/linearText.ts` law, pinned by `test/security/linear-scanners.test.ts`).
 * Each line is read ONCE, character by character, from where the last one
 * ended: its indentation, its fence run, the rest of it and its line ending.
 * No regular expression runs over the answer.
 *
 * @example
 * ```ts
 * const { regions } = codeRegionsOf('Total:\n```python\nprint(1)\n```\nDone.');
 * regions[0].content; // 'print(1)'
 * regions[0].block;   // 1
 * codeRegionsOf('```\na\n  ```\nRevenue was 4321.').regions[0].content; // 'a'
 * ```
 */
/** Regions read per answer; the rest are prose and counted (`dropped`). Design § 4.4. */
export declare const MAX_CODE_REGIONS = 32;
/** One fenced block, as the answer wrote it. */
export interface CodeRegion {
    /** 1-based position among the regions READ, in answer order. */
    readonly block: number;
    /** Index of the opening fence line's first character. */
    readonly start: number;
    /** Index just past the closing fence line (past its line ending when it has one). */
    readonly end: number;
    /** The bytes between the wrapper's two line endings — the program as written. */
    readonly content: string;
    /** The opening line's info string, as written (spaces excluded at the ends). */
    readonly info: string;
}
/** Every region of one answer, and how many more there were. */
export interface CodeRegions {
    readonly regions: readonly CodeRegion[];
    /** Regions past {@link MAX_CODE_REGIONS}: read as prose, never matched. */
    readonly dropped: number;
    /**
     * Where reading stopped, when it did: the index of the first character no
     * region is read from. Everything from here on is prose. Absent when the
     * whole answer was read.
     */
    readonly stoppedAt?: number;
    /**
     * The opening run of a fence still open at the END (`'```'`, `'~~~~'`) —
     * the block a renderer is still inside there. The fence is prose for the
     * match; a writer that appends after this text closes it first
     * (`../scripts/attachment.ts` · `attachmentBoundary`). Never set with
     * `stoppedAt`: after a stop the reader does not know what is open.
     */
    readonly openFence?: string;
}
/**
 * The fenced code regions of `text`, in order, how many past the cap, and where
 * reading stopped. Pure and linear; `max` defaults to {@link MAX_CODE_REGIONS}.
 */
export declare function codeRegionsOf(text: string, max?: number): CodeRegions;
