/**
 * time/convert — a tool's period FORMS (time design § 7.1) and the EXACT
 * conversions of one range into them (§ 7.2), with the inverse a binding reads.
 *
 * Pattern: one table per direction. A tool declares every SHAPE its period
 *          takes (`PeriodForm` — two arguments, one joined string, an object,
 *          a day, a look-back); the library converts a resolved range into the
 *          first form that holds it EXACTLY ({@link convertExact}) and reads a
 *          sent value back into a range ({@link readBack}). Both cross the
 *          argument boundary of § 3.3 through `range.ts` (`boundInto` /
 *          `boundFrom` for a `to` bound; `lookbackRange` for a look-back) —
 *          never inline.
 * Role:    L0 leaf (the time layer). Imports `instant.ts`, `duration.ts`,
 *          `range.ts`, `zone.ts` and `periodForm.ts` — the declaration half
 *          (the shapes, the sugar, each form's own rules, a declared value's
 *          spelling, the tool's facts), split out for the synchronous doors
 *          (`tools/declare.ts`, `ask.ts`, `rows.ts`) and re-exported
 *          here. Asked by `bind.ts` (the fill and the binding) and `drift.ts`,
 *          which only an armed agent loads.
 * Emits:   N/A.
 *
 * ## The sugar (§ 7.1)
 *
 * | Sugar | Means |
 * |-------|-------|
 * | `{ argument, spelling: 'lookback' }` | `{ kind: 'lookback', argument, signed: false }` |
 * | `spelling: 'signed-lookback'` | the same with `signed: true` |
 * | `spelling: 'iso-range'` | `{ kind: 'joined', argument, as: 'iso', joiner: '..', edge: 'inclusive' }` |
 * | `'wall-range'` + `zoneArgument` | `{ kind: 'joined', argument, as: 'wall', joiner: '..', edge: 'inclusive', zone: { argument } }` |
 * | `accepts: [a, b]` | `[sugar(a), sugar(b)]` |
 *
 * ## The exact rows (§ 7.2) — what {@link convertExact} sends
 *
 * | Asked | Form | Sent | Note |
 * |-------|------|------|------|
 * | a look-back | `lookback` | the same length, the sign added or removed, respelled in the form's `units` | none when no unit of `units` spells it |
 * | a look-back | `bounds` / `joined` / `object` | `[now − L, now)` in that `as` | |
 * | a range | `bounds` / `joined` / `object`, `as` `iso` · `epoch-ms` · `epoch-s` | the range; a `to` bound per its `edge` | `epoch-s` rounds outward to whole seconds: `rounded` |
 * | a range | `as: 'wall'` / `'date'` + a zone | the wall times (dates) in the zone | exact only when the tool reads back the same instants (no doubled hour; a date only at midnights) |
 * | a whole day | `day` | that day | any other range is not exact — see the inexact rows |
 * | a range ending at now (within `granularity`) | `lookback` | the smallest spelling in `units` that covers `from` | `rounded` when it is longer |
 *
 * Every other row of § 7.2 is not exact, and {@link convertExact} answers
 * `undefined` for it.
 *
 * ## The inexact rows (§ 7.2, step T5b) — what {@link convertWidened} sends
 *
 * | Asked | Form | Sent | Reads |
 * |-------|------|------|-------|
 * | a range inside one calendar day (in the form's zone) | `day` | that day | the whole day — the rest of it is `extra` |
 * | a range ending before now (past the tool's step) | `lookback` | the covering look-back from now, in the form's units | `[now − L, now]` — the gap after the range (and any rounding before it) is `extra` |
 *
 * A form whose read would be wider than the tool's `maxRange` is skipped.
 * The refusals are tests the binding asks: a range across days when every
 * form is a `day` ({@link spansDaysForDayOnly}), a sent wall time the zone
 * skips ({@link wallGapArgument}), and the facts ({@link periodFactProblem};
 * a range only partly older than `retention` runs —
 * {@link partlyBeyondRetention}).
 *
 * ## Precision and the inclusive edge
 *
 * An ISO or wall bound is written to the second when the instant is a whole
 * second, else to the millisecond; an inclusive `to` is "the last instant
 * inside at that precision" (`to − 1 s`, or `to − 1 ms`). Read back, a bound's
 * precision is how it was written: minutes (`to + 1 min`), seconds, or a
 * fraction (`+ 1 ms`). An epoch bound's precision is its unit; a date's is
 * the calendar day in the zone.
 *
 * @example
 * ```ts
 * const forms = sugarForms({ argument: 'window', spelling: 'iso-range' });
 * convertExact(
 *   { range: { from: '2026-10-09T08:00:00-07:00', to: '2026-10-09T08:41:00-07:00' } },
 *   forms,
 *   { now: '2026-10-09T15:40:00Z', zone: 'America/Los_Angeles', granularityMs: 60_000 },
 * );
 * // { form: 0, values: { window: '2026-10-09T08:00:00-07:00..2026-10-09T08:40:59-07:00' } }
 * ```
 */
import { type DurationText } from './duration.js';
import { type InstantText } from './instant.js';
import { sameRange, type TimeRange } from './range.js';
export { sameRange };
import { type ZoneName } from './zone.js';
import { type PeriodFacts, type PeriodForm, type TimeRefusal } from './periodForm.js';
export { BOUND_AS, DEFAULT_GRANULARITY_MS, FACT_UNITS, FORM_KINDS, formArguments, formFacts, formIssue, formMaxRange, isBoundValue, needsZone, parsesUnderForm, PERIOD_SPELLINGS, periodFactProblem, primaryArgument, sugarForm, sugarForms, TIME_REFUSALS, toolFacts, } from './periodForm.js';
export type { Bound, BoundAs, FormArgument, PeriodDirection, PeriodFactProblem, PeriodFacts, PeriodForm, PeriodShapes, PeriodSpelling, TimeRefusal, ToBound, ZoneArgument, } from './periodForm.js';
/** What a conversion knows beyond the window: the turn's clock, the zones, the tool's step. */
export interface ConvertContext {
    /** The turn's clock (§ 4) — a look-back ends here. */
    readonly now: InstantText;
    /** The zone a wall or date form is written in and its zone argument is sent: the window's. */
    readonly zone: ZoneName;
    /** The app's `.time({ zone })` — the zone of a form that declares `wallZone: 'app'` and no zone argument. */
    readonly appZone?: ZoneName;
    /** The tool's `granularity` in milliseconds, else {@link DEFAULT_GRANULARITY_MS}. */
    readonly granularityMs: number;
}
/** The window to convert: its half-open range and, when it was said as one, its look-back. */
export interface WindowToConvert {
    readonly range: TimeRange;
    /** The look-back length the window was said as (`smhdw`), ending at the clock's `now`. */
    readonly lookback?: DurationText;
}
/** One exact conversion: the form used (its index), the argument values, and whether it rounded outward. */
export interface Conversion {
    readonly form: number;
    readonly values: Readonly<Record<string, unknown>>;
    readonly rounded?: true;
}
/**
 * The first form (in declared order) that holds `window` EXACTLY — the exact
 * rows of § 7.2 — as the argument values to send, or `undefined` when no form
 * does. A form that would widen, shift or drop part of the window is never
 * chosen here.
 */
export declare function convertExact(window: WindowToConvert, forms: readonly PeriodForm[], ctx: ConvertContext): Conversion | undefined;
/**
 * One conversion that holds MORE than the window: the form, the values, the
 * range the tool reads with them (`sent`, half-open) and the parts of it the
 * window did not ask for (`extra` — one or two ranges, in time order).
 */
export interface WidenedConversion extends Conversion {
    readonly sent: TimeRange;
    readonly extra: readonly TimeRange[];
}
/**
 * The first form (in declared order) that holds `window` by READING MORE than
 * it — the inexact rows of § 7.2: a range inside one calendar day → that day
 * (`day`); a range ending before now → the covering look-back from now
 * (`lookback`). `widestMs` (the tool's `maxRange`) skips a form whose read
 * would be wider than the tool reads at once. Asked only after
 * {@link convertExact} found no exact form.
 */
export declare function convertWidened(window: WindowToConvert, forms: readonly PeriodForm[], ctx: ConvertContext, widestMs?: number): WidenedConversion | undefined;
/**
 * Whether every form is a `day` and the window spans more than one calendar
 * day in the form's zone — the row § 7.2 refuses before dispatch: one call per
 * day is the model's choice, not the library's.
 */
export declare function spansDaysForDayOnly(window: WindowToConvert, forms: readonly PeriodForm[], ctx: ConvertContext): boolean;
/** A window a tool can read — the conversion to send — or the reason it cannot, before dispatch. */
export type ToolConversion = {
    /** Exact, or — when no form holds the window exactly — WIDENED (it carries `sent` and `extra`). */
    readonly conversion: Conversion | WidenedConversion;
    /** The window starts before the source's oldest data and ends after it: it dispatches, marked. */
    readonly partlyBeyondRetention?: true;
} | {
    readonly refused: TimeRefusal;
};
/**
 * Whether one tool can read one window, and how — the ONE answer every door
 * that puts a person's window into a tool asks (the fill, the time ask's
 * answer and its choices, the served line): the tool's facts first
 * ({@link periodFactProblem}), then the first form that holds it exactly
 * ({@link convertExact}), then the first that holds it by reading MORE
 * ({@link convertWidened} — `maxRange` skips a read too wide), then `multi-day`
 * for a `day`-only tool ({@link spansDaysForDayOnly}), and otherwise
 * `no-form-holds`: no declared form can read it at all (a look-back ends at
 * now, so it cannot reach a window still running; a covering look-back wider
 * than `maxRange` is not read). Never the tool's own default in its place.
 *
 * @example
 * ```ts
 * const lookbackOnly = [{ kind: 'lookback', argument: 'window', signed: false }] as const;
 * const ctx = { now: '2026-10-09T15:40:00Z', zone: 'America/Los_Angeles', granularityMs: 60_000 };
 * const yesterday = { from: '2026-10-08T00:00:00-07:00', to: '2026-10-09T00:00:00-07:00' };
 * convertForTool({ range: yesterday }, lookbackOnly, {}, ctx);
 * // { conversion: { form: 0, values: { window: '1960m' }, sent: …, extra: [ …the gap after it… ] } }
 * convertForTool({ range: yesterday }, lookbackOnly, { maxRange: '24h' }, ctx);
 * // { refused: 'no-form-holds' } — reaching 8 Oct from now takes a look-back wider than 24h
 * ```
 */
export declare function convertForTool(window: WindowToConvert, forms: readonly PeriodForm[], facts: PeriodFacts | undefined, ctx: ConvertContext): ToolConversion;
/**
 * The first argument of `form` whose sent value is a wall time the zone
 * SKIPS (a spring-forward gap) — the tool would read a time that never
 * happened; refused before dispatch (§ 7.2). `undefined` when the form reads
 * no wall bound, the zone is unknown, or every wall value exists.
 */
export declare function wallGapArgument(args: Readonly<Record<string, unknown>>, form: PeriodForm, ctx: {
    readonly appZone?: ZoneName;
}): string | undefined;
/**
 * Whether {@link readBack} cannot read `args` for want of a zone alone — a
 * wall or date form whose zone argument is not in the call yet and no app
 * zone stands in. A caller that finds every bound present and still gets no
 * range tells "the zone is still to come" (this) from "the bounds name no
 * window" (misspelled, a wall time the zone skips, `from` not before `to`).
 */
export declare function readBackLacksZone(args: Readonly<Record<string, unknown>>, form: PeriodForm, ctx: {
    readonly appZone?: ZoneName;
}): boolean;
/**
 * The half-open range the arguments of `form` name — the § 3.3 conversion back
 * from each bound — or `undefined` when they do not name one (missing,
 * misspelled, a wall time the zone doubles or skips, `from` not before `to`).
 * A look-back is read at the turn's clock (`lookbackRange`). The range is
 * spelled in UTC: compare it as instants ({@link sameRange}).
 */
export declare function readBack(args: Readonly<Record<string, unknown>>, form: PeriodForm, ctx: {
    readonly now: InstantText;
    readonly appZone?: ZoneName;
}): TimeRange | undefined;
/**
 * The absolute range a look-back window was sent as to a bounds form —
 * `[now − L, now)`, which reads back one millisecond shorter than the
 * look-back's own `[now − L, now]` — so a binding recognises either.
 */
export declare function lookbackAsBounds(now: InstantText, lookback: DurationText): TimeRange | undefined;
/** The tool's step in milliseconds — its `granularity`, else one minute (§ 7.4). */
export declare function granularityMsOf(facts: PeriodFacts | undefined): number;
/**
 * Whether a half-open range is PARTLY older than what the source keeps — it
 * starts before `now − retention` and ends after it. It dispatches as asked
 * (§ 7.2); the result's `held` decides `partly-held`. `false` when the tool
 * declares no `retention`.
 */
export declare function partlyBeyondRetention(range: TimeRange, facts: PeriodFacts, now: InstantText): boolean;
/** The widest window the tool reads at once (`maxRange`) in milliseconds, when it declares one. */
export declare function widestMsOf(facts: PeriodFacts | undefined): number | undefined;
//# sourceMappingURL=convert.d.ts.map