/**
 * time/ask — the one time ask (time design § 6): what a time field's
 * answer must be, why one is refused, and the choices a reading offers.
 *
 * Pattern: one judge per boundary (the `range.ts` precedent). A typed ask's
 *          `InputField.format` (`tools/inputRequest.ts`) names what the answer
 *          is; {@link checkTimeAnswer} is the ONE judge of it — at definition
 *          (a choice, a supplied value) and at the resume door (the person's
 *          answer). A refusal is a CODE with its facts; the sentence is a
 *          catalog entry (`src/locales/timeAsk.ts` · `defaultTimeAskMessages`)
 *          the app may override (`.time({ messages })`), filled here
 *          ({@link refusalReason}) — the library writes a reason only for a
 *          check the app armed by declaring the field (TQ7).
 * Role:    L0 leaf (the time layer). Imports `instant.ts`, `zone.ts`,
 *          `range.ts`, `present.ts` and the row / candidate TYPES only.
 * Emits:   N/A.
 *
 * ## What an answer must be (§ 6.1, § 6.2)
 *
 * | `format` | The answer | Refused as |
 * |----------|------------|------------|
 * | `instant` | an ISO 8601 date-time WITH its offset, strict profile (`2026-10-09T08:00-07:00`) | `not-an-instant`; `no-offset` (a date-time with no zone); `dst-gap` |
 * | `time-range` | an ISO 8601 interval `from/to` of two such instants, `from` before `to` | `not-a-range`; either end's refusal; `out-of-order` |
 * | `zone` | an IANA zone name (`America/Los_Angeles`) — never an abbreviation or a bare offset | `not-a-zone` |
 * | `time-range`, for a tool's period | the same, inside the tool's declared facts | `time-future`; `time-past`; `beyond-retention`; `over-max-range` |
 *
 * A `time-range` answer given for a tool's period is also judged against the
 * tool's declared FACTS (§ 6.2, step T5a — `convert.ts` ·
 * `periodFactProblem`), when the caller hands them with the turn's clock:
 * `time-future` (a `past` source asked for a window after now), `time-past`
 * (a `future` source asked for one that ended), `beyond-retention` (the WHOLE
 * window older than the source keeps — a partial overlap is taken) and
 * `over-max-range` (wider than the source reads at once).
 *
 * `dst-gap` is asked only when the ask knows the person's zone (the run
 * clock's, under `.time()`): a wall time that zone's clocks skip, written with
 * one of the two offsets around the change (`2026-03-08T02:30-08:00` in Los
 * Angeles) names an instant nobody's clock showed. An instant written in some
 * other offset is that instant, and is taken.
 *
 * ## The choices a reading offers (§ 6.1, § 6.3)
 *
 * `readingAsk.ts` · `timeAskOf` (split out: it renders labels through
 * `present.ts`, which only an armed agent loads) turns a `time-reading` row whose choice is `open` into one
 * field: a `format: 'zone'` field when the person named a zone the layer
 * cannot read (`PST`), else a `format: 'time-range'` field whose `enum` is
 * the candidates left (each an ISO interval) and whose `labels` render each in
 * the reader's locale, the zone named, with the end the person said. A
 * `kind: 'model'` reader's window is offered as the LIBRARY'S reading to
 * confirm ("I read “yesterday” as … — is that right?"), never as the person's
 * words (§ 5.5). So is EVERY `rule` reading (the owner's decision "Always
 * confirm", time design TQ29 — `rowsBuild.ts` · `timeReadingRows`): the choice is
 * the reading pre-filled WITH ITS ZONE ("I read “yesterday” as Thu, Oct 8,
 * 2026, PDT in America/Los_Angeles — is that right?"), so a person who meant
 * another zone's day corrects it in one answer. Free entry stays open: a
 * field is `strict` only when the app says so.
 *
 * @example
 * ```ts
 * checkTimeAnswer('time-range', '2026-10-09T08:40-07:00/2026-10-09T08:00-07:00');
 * // { problem: 'out-of-order', facts: { from: '2026-10-09T08:40-07:00', to: '2026-10-09T08:00-07:00' } }
 * checkTimeAnswer('instant', '2026-10-09T08:00'); // { problem: 'no-offset', facts: { value: '2026-10-09T08:00' } }
 * checkTimeAnswer('instant', '2026-03-08T02:30-08:00', 'America/Los_Angeles'); // { problem: 'dst-gap', … }
 * checkTimeAnswer('zone', 'PST'); // { problem: 'not-a-zone', facts: { value: 'PST' } }
 * refusalReason([checkTimeAnswer('zone', 'PST')!], defaultTimeAskMessages);
 * // '“PST” is not a time zone name. Name one such as America/Los_Angeles.'
 * ```
 */
import { type PeriodFacts } from './periodForm.js';
import { type InstantText } from './instant.js';
import { type ZoneName } from './zone.js';
/** What a time field's answer is (time design § 6.1). The value stays a string on the wire. */
export type TimeFormat = 'instant' | 'time-range' | 'zone';
export declare const TIME_FORMATS: readonly TimeFormat[];
/** Whether `value` names a {@link TimeFormat}. */
export declare function isTimeFormat(value: unknown): value is TimeFormat;
/** Why a time answer was refused — a code; the sentence is the catalog's. */
export type TimeAnswerProblem = 'not-an-instant' | 'no-offset' | 'not-a-range' | 'out-of-order' | 'dst-gap' | 'not-a-zone' | 'time-future' | 'time-past' | 'beyond-retention' | 'over-max-range';
/** One refused answer: the code and the facts its sentence names (the value as given, capped). */
export interface TimeAnswerRefusal {
    readonly problem: TimeAnswerProblem;
    readonly facts: Readonly<Record<string, string>>;
}
export declare const quoted: (value: string) => string;
/** A tool's declared facts and the turn's clock — what a `time-range` answer for that tool's period is judged against. */
export interface ToolTimeFacts {
    readonly facts: PeriodFacts;
    readonly now: InstantText;
}
/**
 * Why `value` is not a well-formed answer of `format`, or `undefined` when it
 * is one. `zone` — the person's zone, when the ask knows it (the run clock's)
 * — arms the DST-gap check; without it the answer is judged for shape, order
 * and offset only. `tool` — a tool's declared facts and the clock — judges a
 * well-formed `time-range` against them too.
 */
export declare function checkTimeAnswer(format: TimeFormat, value: string, zone?: ZoneName, tool?: ToolTimeFacts): TimeAnswerRefusal | undefined;
/**
 * Every sentence the time ask can put before a person — the keys of the
 * catalog (`src/locales/timeAsk.ts`). `answer.*` is a refusal's reason, one
 * per {@link TimeAnswerProblem}; `ask.*` a question; `choice.confirm` the
 * label on a reading to confirm — every reading the armed reader made.
 * Placeholders are `{{name}}`; the label also takes `zone`.
 */
export declare const TIME_ASK_MESSAGE_KEYS: readonly ["answer.not-an-instant", "answer.no-offset", "answer.not-a-range", "answer.out-of-order", "answer.dst-gap", "answer.not-a-zone", "answer.time-future", "answer.time-past", "answer.beyond-retention", "answer.over-max-range", "ask.which", "ask.confirm", "ask.zone", "ask.zone-unknown", "choice.confirm"];
export type TimeAskMessageKey = (typeof TIME_ASK_MESSAGE_KEYS)[number];
/** A whole catalog: one sentence per key. */
export type TimeAskMessages = Readonly<Record<TimeAskMessageKey, string>>;
/**
 * The app's overrides (`.time({ messages })`) read — every key one the
 * catalog has, every value a non-blank sentence of at most 4096 characters —
 * or a problem in words.
 */
export declare function readTimeAskMessages(value: unknown): {
    readonly value: Partial<TimeAskMessages>;
} | {
    readonly problem: string;
};
/** A catalog sentence with its `{{name}}` placeholders filled; a placeholder with no fact is left as written. */
export declare function fillMessage(template: string, facts: Readonly<Record<string, string>>): string;
/**
 * The reason a re-ask carries (`InputRefusal.reason`): one catalog sentence
 * per refused field, in field order, joined by a space — at most 4096
 * characters, the refusal's own bound.
 */
export declare function refusalReason(refusals: readonly TimeAnswerRefusal[], messages: TimeAskMessages): string;
//# sourceMappingURL=ask.d.ts.map