/**
 * saidByPerson — which `role: 'user'` message a PERSON wrote, and which ones
 * this library wrote in a person's voice.
 *
 * Pattern: One predicate over one message, over a registry of frames. No
 *          imports, no state, no clock.
 * Role:    Leaf. Several layers ask the same question and must not answer it
 *          differently: the window's refusal engine (`currentRequest.ts`,
 *          which will not let a strategy drop the request), the six authors
 *          of library-written user turns (`window/notice.ts`,
 *          `window/summarize.ts`, `outputEnforcement.ts`, `evidence/gate.ts`,
 *          `stages/wrapUp.ts`, and `skillSteps.ts` for the nudge
 *          `stages/stepNudge.ts` appends — they own the sentences and take
 *          the markers from here), the three writers of request-only late
 *          lines (`arguments/serve.ts`, `evidence/figures.ts`,
 *          `stagedRefs.ts` — since G17), and — since 9.84.0 — a rule
 *          author reading `InjectionContext.history` (`saidByPerson(ctx)`).
 * Emits:   N/A.
 *
 * ## Why this is a leaf and not a private helper
 *
 * This library writes SEVEN kinds of `role: 'user'` message into `history`
 * that nobody said (and serves three more on a request only — below):
 * a compaction frame, a drop notice, a schema-check correction, an
 * evidence-check correction, a budget wrap-up instruction, a stepped-skill
 * nudge, and a message an Injection delivered. Six of the seven are read off
 * the OPENING they carry ({@link LIBRARY_AUTHORED_PREFIXES}); the delivered
 * one carries an `injectedBy` marker instead. The window layer knew two of the
 * openings and the marker; the evidence layer knew two more
 * (`evidence/frames.ts`); neither list was reachable from the routing layer at
 * all — the skill-graph fence forbids it from importing the agent loop, and
 * rightly. So a predicate reading `history` could filter some of the classes
 * and not the rest, and would match on our own bookkeeping text.
 *
 * A drop notice NAMES TOOLS ("Tool results are among them (lookup_order) …").
 * A rule watching history for a tool name therefore fired on the notice about
 * that tool's result leaving the window — pinning a skill on exactly the long
 * sessions where the notice appears, which is the opposite of what the author
 * wrote. That is a fixable bug in one place only: the rule has to be one
 * implementation both sides import, not two that agree until they do not.
 *
 * The two frames added in 9.86.0 are the same bug found again, and found by
 * counting rather than by reading: 9.84.0 registered four openings and wrote
 * "five classes" in prose, while the tree already had SEVEN producers of a
 * user-role message that reach `scope.history`. The budget wrap-up
 * (`stages/wrapUp.ts`) carried an unprefixed sentence containing "Do not
 * request tools", and the stepped-skill nudge (`stages/stepNudge.ts`) carries
 * a skill id and every unrun step's TOOL NAME — so both were credited to a
 * person, a `saidByPerson(ctx).some(m => m.content.includes(…))` rule matched
 * on them, and the window could anchor its refusal on the wrap-up frame.
 *
 * G17 found the same bug a third time, on a channel the walk had filed as
 * safe. Three more `role: 'user'` lines are served on a REQUEST and never
 * written to `history`: the time layer's late line (`arguments/serve.ts` ·
 * `timeLine`, on EVERY request under `.time()` since 9.134.1), the figures
 * dial's conclusion (`evidence/figures.ts` · `figuresConclusionLine`) and the
 * staged-refs nudge (`stagedRefs.ts` · `stagedRefsNudgeLine`). "Never in
 * history" was read as "no reader can mistake it", but a reader of the
 * REQUEST — a provider, a mock's echo, a host finding "this turn" as the last
 * user-role message the model was sent — sees the library's line LAST and
 * calls it the person's. So their openings are registered here too
 * ({@link LIBRARY_NOTE_OPENING}, {@link STAGED_DATA_FRAME_PREFIX}), and an
 * `ephemeral` message (a reliability retry's feedback, on one attempt's
 * request) is never a person's either.
 *
 * The markers live here, as a LIST rather than one constant per writing file.
 * A prefix is what the recognizer matches AND what the writer emits;
 * separating those is how a prefix silently stops being recognized, and an
 * authored frame that lands anywhere else is a hole nobody will see until a
 * rule fires on it. Adding one means adding it to
 * {@link LIBRARY_AUTHORED_PREFIXES}, and every reader is fixed at once —
 * which is why the count is no longer asserted in prose alone:
 * `test/injection-engine/userTurnProducers.test.ts` WALKS the tree for
 * every `role: 'user'` construction site and fails, with the file and line, on
 * one that is neither registered here, nor a person's own turn, nor
 * wire-only.
 */
/**
 * The fields authorship is decided from — structural, so both
 * `LLMMessage` (the wire shape) and `InjectionContext.history[n]` (the
 * read-only view a predicate gets) satisfy it unchanged.
 *
 * `injectedBy` is `unknown` here on purpose: this file only ever asks whether
 * the marker is PRESENT, and typing its interior would make a leaf that must
 * import nothing into a mirror that can drift.
 */
export interface AuthoredMessage {
    readonly role: string;
    readonly content: string;
    readonly injectedBy?: unknown;
    /** `true` on a line composed for ONE request (`LLMMessage.ephemeral`) — never a person's turn. */
    readonly ephemeral?: unknown;
}
/** Opening of the authored notice a DROP leaves behind. Stable — tests and
 *  readers match on it. Written by `buildDropNotice`. */
export declare const DROP_NOTICE_PREFIX = "[dropped history";
/** Opening of the authored label a FOLD leaves behind. Stable — tests and
 *  readers match on it. Written by `buildSummaryMessage`. */
export declare const COMPACTED_FRAME_PREFIX = "[compacted history";
/** Opening of the authored frame a failed output validation writes. Stable —
 *  tests and readers match on it. Written by `buildCorrectiveTurn`. */
export declare const SCHEMA_CHECK_FRAME_PREFIX = "[schema check";
/** Opening of the authored frame the evidence gate writes. Stable — tests,
 *  docs and readers match on it. Written by `buildEvidenceCorrection`. */
export declare const EVIDENCE_CHECK_FRAME_PREFIX = "[evidence check";
/** Opening of the authored instruction the out-of-budget WRAP-UP call carries.
 *  Stable — tests and readers match on it. Written by `wrapUpStage`
 *  (`WRAP_UP_INSTRUCTION`). */
export declare const WRAP_UP_FRAME_PREFIX = "[budget exhausted";
/** Opening of the authored frame the stepped-skill NUDGE carries. Stable —
 *  tests and readers match on it. Written by `nudgeTeachingMessage`, appended
 *  by `buildStepNudgeStage`. */
export declare const STEP_NUDGE_FRAME_PREFIX = "[steps unrun";
/**
 * Opening of the LIBRARY NOTE — the late line this library serves LAST on a
 * request and never writes to `history`: the time layer's ONE served time line
 * (`arguments/serve.ts` · `timeLine`, which opens with it as `TIME_LINE_SOURCE`)
 * and the figures dial's conclusion (`evidence/figures.ts` ·
 * `figuresConclusionLine`). It says WHO speaks because an unmarked request-only
 * `user` line reads as the person talking — measured: 37 of 37 answers opened
 * "You're right… I apologize" after one (the T6b paid run). Stable — tests and
 * readers match on it, and it is the one copy both writers emit.
 */
export declare const LIBRARY_NOTE_OPENING = "[A note from the library that runs the tools \u2014 not from the person, and not a correction from them: when you answer, answer the person directly, as you would from the tool results alone.]";
/** Opening of the request-only STAGED-REFS nudge. Stable — tests and readers
 *  match on it. Written by `stagedRefsNudgeLine`, appended by `callLLM`. */
export declare const STAGED_DATA_FRAME_PREFIX = "[staged data";
/** Request-only findings DATA, quoted from the record rather than a person's message. */
export declare const FINDINGS_DATA_FRAME_PREFIX = "[AgentFootprint findings DATA v1]";
/**
 * Every opening this library puts on a `role: 'user'` message it wrote itself.
 *
 * The registry, not a convenience: this is the list a reader has to have ALL
 * of to answer "did a person say this?", and until 9.84.0 no reader had it —
 * the window held two entries, the evidence gate held the other two, and the
 * routing layer could reach neither. A new authored frame belongs here on the
 * day it is written.
 *
 * The two correction frames both QUOTE untrusted text after their label (a
 * validator's error, the model's own flagged values), which is exactly why
 * they are matched by PREFIX and never by anything further in. The nudge is
 * the same shape for a different reason: its body is a list of a skill's own
 * step notes and tool names, which is exactly the text a rule watches for.
 *
 * The list is frozen because it is a registry, not a scratch array: a consumer
 * holds the same object this library's own readers hold, and a `push` into it
 * would change what every reader calls a person's message.
 */
export declare const LIBRARY_AUTHORED_PREFIXES: readonly string[];
/** True when this user-role message opens with a frame this library authored. */
export declare function isLibraryAuthoredFrame(msg: AuthoredMessage | undefined): boolean;
/** True when this message is a notice a previous drop wrote. */
export declare function isDropNotice(msg: AuthoredMessage | undefined): boolean;
/** True when this message is a frame a previous fold wrote. */
export declare function isCompactedSummary(msg: AuthoredMessage | undefined): boolean;
/**
 * THE rule: true when this message is something a PERSON said.
 *
 * Deliberately narrow, and narrow in one direction: a message we are not sure
 * about is not credited to a person. The exclusions are the ways this library
 * authors a user turn — a delivery marker its own stage stamps, the
 * `ephemeral` flag on a line composed for one request, and the openings in
 * {@link LIBRARY_AUTHORED_PREFIXES} (the request-only late lines included) —
 * never a guess at prose.
 *
 * A message from a restored conversation, a hand-built window, or a person
 * typing passes every exclusion and is theirs.
 */
export declare function isSaidByPerson(msg: AuthoredMessage | undefined): boolean;
