/**
 * time/clock — the run clock: a declared, recorded input, never a hidden read.
 *
 * Pattern: normalize-or-refuse at a boundary (`core/runInput.ts`'s shape): the
 *          app's `.time({ zone })` and the run's `time: { now, zone, window }`
 *          are read here into one {@link TimeClock}, or refused by name.
 * Role:    L0 leaf (the time layer's one owner). Imports `instant.ts`,
 *          `zone.ts`, `range.ts`, `reader.ts` (the reader's check) and
 *          `resolve.ts` (the policy's) only. The Agent reads the two inputs
 *          (`Agent.run`, `Agent.resume`); seed stamps the clock once per turn
 *          (`rows.ts` · `ClockRow`); the ToolCalls resume door compares a
 *          resume's `time` with the kept clock ({@link clockChange}).
 * Emits:   N/A.
 *
 * ## The laws (time design § 4)
 *
 * - **The zone is per run; the builder's is a fallback.** The run's
 *   `time.zone` wins, `.time({ zone })` is used when the run names none, and
 *   with neither the zone is UNKNOWN (G15) — never the server's zone, never a
 *   guess: the clock records `zoneSource: 'unknown'` and spells instants in
 *   {@link UNKNOWN_ZONE_SPELLING} (UTC), every reading of the person's words
 *   waits on their zone (it is asked first), and the zone they answer holds
 *   for the turns after it (`zoneSource: 'answered'`).
 * - **`now` is the app's, else the turn's start** — admitted as
 *   `nowSource: 'default'`, like any default nobody chose.
 * - **Frozen across a pause.** The clock is written once per turn. A resume
 *   that passes a different `time` keeps the frozen clock and records what was
 *   passed ({@link clockChange}); it is not refused, because an app that
 *   passes the current time on every call is doing nothing wrong.
 * - **A window set in a UI is a run input** (`time.window`), recorded with
 *   `source: 'control'` — the person's own typed value, never filed as an
 *   answer to an ask.
 *
 * @example
 * ```ts
 * const run = readRunTime({ now: '2026-10-09T15:40:00Z', zone: 'America/Los_Angeles' });
 * const draft = draftClock(run.value, readTimeOptions({}).value!);
 * // { now: '2026-10-09T15:40:00Z', zone: 'America/Los_Angeles', zoneSource: 'run' }
 * completeClock(draft as ClockDraft, Date.parse('2026-10-09T15:40:02Z'));
 * // { now: '2026-10-09T15:40:00Z', nowSource: 'app', zone: 'America/Los_Angeles', zoneSource: 'run' }
 * ```
 */
import { type InstantText } from './instant.js';
import { type TimeRange } from './range.js';
import { type ZoneName } from './zone.js';
import { type TimeReader } from './reader.js';
import { type TimePolicy } from './resolveRecord.js';
import { type TimeAskMessages } from './ask.js';
/** The run's clock, stamped once per turn (time design § 4). */
export interface TimeClock {
    /** The anchor for this turn — the app's `now`, else the turn's start. */
    readonly now: InstantText;
    /** The app passed `now`, or the library took the turn's start. */
    readonly nowSource: 'app' | 'default';
    /**
     * The person's zone for this run — an IANA name. Under `zoneSource:
     * 'unknown'` it is `'UTC'`: the zone instants are SPELLED in, never the
     * person's.
     */
    readonly zone: ZoneName;
    /**
     * The run's `time.zone`, else the `.time({ zone })` fallback; with neither,
     * the zone the person answered in an earlier turn of this conversation
     * (`'answered'`), else `'unknown'` (G15).
     */
    readonly zoneSource: 'run' | 'builder' | 'answered' | 'unknown';
}
/**
 * The zone a clock with no known zone spells its instants in (G15) — named
 * as unknown wherever it is shown, never read as the person's.
 */
export declare const UNKNOWN_ZONE_SPELLING: string;
/**
 * The run's time input — `agent.run({ message, time })`, or the options bag of
 * `run`, `followUp`, `resume` and `resumeOnError`. Every key is optional; a
 * run with no zone here needs the builder's fallback.
 *
 * @example
 * ```ts
 * await agent.run({ message: 'errors since 8?', time: { now: sentAt, zone: 'America/Los_Angeles' } });
 * ```
 */
export interface RunTime {
    /**
     * The turn's anchor — the MESSAGE's time, so a replay or a late resume
     * reads "yesterday" the same way. An ISO 8601 instant with a zone (upper
     * case `T` and `Z`, no leap second), or a `Date`. Omitted: the turn's start,
     * recorded `nowSource: 'default'`.
     */
    readonly now?: string | Date;
    /** The person's IANA zone for this run (`'America/Los_Angeles'`). Never an abbreviation. */
    readonly zone?: string;
    /**
     * A window set in a UI — a brushed chart range, a range picker — as a
     * half-open `{ from, to }` of instants. Recorded with `source: 'control'`.
     */
    readonly window?: TimeRange;
}
/** The builder's `.time(options)` — the fallback zone, the reader and its policy (time design § 11). */
export interface TimeOptions {
    /**
     * The fallback zone for a run that names none. Omitted with no run zone
     * either: the zone is unknown — never the server's — and the person is
     * asked it before any time they wrote is read (G15).
     */
    readonly zone?: string;
    /**
     * The strategy that reads the person's words into time parts (`TimeReader`).
     * No default: without one, the person's words are not read — no
     * `time-reading` row is filed.
     */
    readonly reader?: TimeReader;
    /**
     * How the library picks among a reading's candidates (needs `reader`).
     * `dateOrder` (default `'ask'`): a numeric date's orders become choices,
     * or the one order your people write (`'MDY'`, `'DMY'`, `'YMD'`), recorded
     * as assumed. `year` (default `'ask'`): a date said without a year is
     * asked, or `'current'` — the clock's year, recorded as assumed.
     */
    readonly policy?: {
        readonly dateOrder?: TimePolicy['dateOrder'];
        readonly year?: TimePolicy['year'];
    };
    /**
     * Your words for the time ask (`defaultTimeAskMessages` keys → sentence):
     * the reason a refused time answer is re-asked with, the ask's questions,
     * the label on a reading to confirm. A key you leave out keeps the default.
     */
    readonly messages?: Partial<TimeAskMessages>;
}
/** {@link RunTime} as read: every value checked and kept as written, a `Date` spelled in UTC. */
export interface ReadRunTime {
    readonly now?: InstantText;
    readonly zone?: ZoneName;
    readonly window?: TimeRange;
}
/** {@link TimeOptions} as read — the policy's defaults filled in when a reader is armed. */
export interface ReadTimeOptions {
    readonly zone?: ZoneName;
    readonly reader?: TimeReader;
    readonly policy?: TimePolicy;
    /** The app's catalog overrides — every key one the catalog has. */
    readonly messages?: Partial<TimeAskMessages>;
}
/** What a turn's clock is before seed knows the turn's start. */
export interface ClockDraft {
    readonly now?: InstantText;
    readonly zone: ZoneName;
    /** `'unknown'`: neither the run nor the builder named a zone — `zone` is the UTC spelling. */
    readonly zoneSource: 'run' | 'builder' | 'unknown';
    readonly window?: TimeRange;
}
/** A read answer: the value, or a problem named in words. */
export type Read<T> = {
    readonly value: T;
} | {
    readonly problem: string;
};
/**
 * The run's `time` input, checked. `undefined` reads as "nothing passed".
 * Refused, by name: a non-object, an unknown key, a zone that is not an IANA
 * name, a `now` that is not an instant with a zone, a `window` that is not two
 * strict instants with `from` before `to`.
 */
export declare function readRunTime(value: unknown): Read<ReadRunTime | undefined>;
/**
 * The builder's `.time(options)`, checked. `undefined` reads as `{}` — the
 * layer armed with no fallback zone, so every run names its own.
 */
export declare function readTimeOptions(value: unknown): Read<ReadTimeOptions>;
/**
 * The turn's clock as far as the run's inputs decide it. With no zone from
 * the run or the builder the zone is UNKNOWN (G15): `zoneSource: 'unknown'`,
 * instants spelled in {@link UNKNOWN_ZONE_SPELLING} — never the server's
 * zone, never a guess (seed reads a zone the person answered in an earlier
 * turn, `stages/timeLayer.ts` · `stampClock`).
 */
export declare function draftClock(run: ReadRunTime | undefined, options: ReadTimeOptions): ClockDraft;
/**
 * The clock, once the turn's start is known: `now` is the app's, else that
 * start. `answeredZone` — the zone the person answered in an earlier turn —
 * is read only when the draft's zone is unknown, and is then the turn's zone
 * (`zoneSource: 'answered'`).
 */
export declare function completeClock(draft: ClockDraft, turnStartMs: number, answeredZone?: ZoneName): TimeClock;
/** What a resume passed that differs from the kept clock, and the kept values it would have replaced. */
export interface ClockChange {
    readonly passed: ReadRunTime;
    readonly kept: {
        readonly now: InstantText;
        readonly zone: ZoneName;
        readonly window?: TimeRange;
    };
}
/**
 * The difference between a resume's `time` and the turn's frozen clock, or
 * `undefined` when every value passed equals the kept one (a key not passed
 * is no difference). `now` compares as text: a resume passing the same
 * instant in another spelling is recorded, because the record keeps spellings.
 *
 * @example
 * ```ts
 * clockChange({ now: '2026-10-09T16:10:00Z' }, { now: '2026-10-09T15:40:00Z', zone: 'UTC' });
 * // { passed: { now: '2026-10-09T16:10:00Z' }, kept: { now: '2026-10-09T15:40:00Z', zone: 'UTC' } }
 * ```
 */
export declare function clockChange(passed: ReadRunTime, kept: {
    readonly now: InstantText;
    readonly zone: ZoneName;
    readonly window?: TimeRange;
}): ClockChange | undefined;
//# sourceMappingURL=clock.d.ts.map