/**
 * tools/declare — what a tool author declares about its arguments, and the
 * ONE rule set that judges the declaration.
 *
 * Pattern: Map. A declaration is plain data on the `Tool` (`askOrAssume`,
 *          `period`), judged by one assert at three doors: definition
 *          (`tools/tools.ts` · `defineTool`), dispatch (`rulesOf`, because a
 *          Tool built by hand or served by a ToolProvider never passes through
 *          `defineTool`) and MCP ingest (`mcp/toolExtras.ts` ·
 *          `readToolExtras`). A malformed declaration is refused and never
 *          repaired.
 * Role:    tools/ layer leaf of the inputs layer (honesty layer 2). Imports
 *          nothing from `findings/` — the folder's one-way law.
 * Emits:   N/A.
 *
 * ## The two forms of a rule
 *
 *   - `{ assume: value }` — a value the call leaves out is FILLED BY THE
 *     LIBRARY (never by the tool) and recorded as `default`; the answer's
 *     standing then says the value was assumed.
 *   - `{ ask: question, choices? }` — a value the call leaves out is asked of
 *     the person, ONCE per batch, before anything in the batch runs, through
 *     the typed ask (`tools/inputRequest.ts`); the answer is filled and
 *     recorded as `answered` (`arguments/ask.ts`). A PRESENT value runs,
 *     recorded as the model's own — unless declared sources are armed
 *     (`.inputsLayer({ argumentSources: true })`, or `.findings({ argumentSources:
 *     true })` beside the ledger): then the model says where it
 *     came from, the library checks it (`arguments/checks.ts` · `checkSource`), and a
 *     value the check does not trace is asked about too. A choice may carry
 *     phrases the author vouches for (`{ value, said }`), matched only inside
 *     a quote the model declared.
 *
 * ## The period — `ToolPeriod`
 *
 * Which argument bounds the period the answer covers, and how its values are
 * SPELLED: `lookback` (`30m`, `24h`, `7d`, `2w`), `signed-lookback` (`-24h`),
 * `iso-range` (two ISO 8601 instants joined by `..`) or `wall-range` (two wall
 * times joined by `..`, with the zone in `zoneArgument`). Declared formats,
 * never phrases. A period on an argument with no rule is refused (adopted
 * Q13): a period argument is exactly what a rule is for.
 *
 * Since the time layer's step T5a the single-argument form is SUGAR over
 * `forms` (`time/convert.ts` · `sugarForms`): a tool declares every shape
 * its period takes — two arguments (`bounds`), one joined string, an object, a
 * `day`, a look-back with its `units` — and the facts about its source
 * (`direction`, `retention`, `maxRange`, `granularity`, `filtersToAsked`).
 * Under `.time()` the library fills a period the model left out from the
 * turn's one window, binds a sent one to the person's window, and hands the
 * tool `ctx.time` (`time/bind.ts`). Without `.time()` a period is judged
 * and read exactly as before.
 */
import { type InputValue } from './inputRequest.js';
import { PERIOD_SPELLINGS, type PeriodDirection, type PeriodFacts, type PeriodForm, type PeriodSpelling } from '../time/periodForm.js';
import { type DurationText } from '../time/duration.js';
/**
 * One allowed answer to an `ask` rule: a bare value, or a value with phrases
 * the author vouches for as meaning it (`{ value: '7d', said: ['last week'] }`).
 * The phrases are matched as whole tokens, only inside a quote the model
 * declared — never scanned for in the person's words.
 */
export type AskChoice = InputValue | {
    readonly value: InputValue;
    readonly said?: readonly string[];
};
/**
 * One argument's rule — either ask the person, or assume a declared default.
 *
 * `assume`: a value the call leaves out is filled by the library and recorded
 * as `default`. `ask`: a value the call leaves out is asked of the person once
 * per batch, before anything in the batch runs, and recorded as `answered`.
 */
export type ArgumentRule = {
    readonly ask: string;
    readonly choices?: readonly AskChoice[];
} | {
    readonly assume: InputValue;
};
/** Per argument name, its rule. Arguments with no rule run free. */
export type AskOrAssume = Readonly<Record<string, ArgumentRule>>;
export type { PeriodSpelling, PeriodForm, PeriodFacts } from '../time/periodForm.js';
export { PERIOD_SPELLINGS };
/**
 * Which arguments set the period a tool's answer covers, how their values are
 * spelled, and the facts about the source. The one period shape's TOOL half;
 * the result half (`DeclaredPeriod`: what a read queried and what the store
 * holds) belongs to the result doors.
 *
 * Two ways to name the shape, never both: today's single argument
 * (`argument` + `spelling`, or `accepts` for several spellings, and
 * `zoneArgument` beside a `wall-range`), which is sugar over the general
 * `forms` — every shape the tool accepts, in preference order.
 *
 * @example
 * ```ts
 * period: { argument: 'window', spelling: 'lookback' }  // '2h', '24h', '7d'
 * period: {
 *   forms: [{ kind: 'bounds',
 *             from: { argument: 'start_time', as: 'epoch-ms' },
 *             to:   { argument: 'end_time',   as: 'epoch-ms', edge: 'exclusive' } }],
 *   direction: 'past', retention: '30d',
 * }
 * ```
 */
export interface ToolPeriod {
    readonly argument?: string;
    readonly spelling?: PeriodSpelling;
    /** Every single-argument spelling the argument takes, in preference order. */
    readonly accepts?: readonly PeriodSpelling[];
    /** The argument that carries the zone of a `wall-range`. */
    readonly zoneArgument?: string;
    readonly forms?: readonly PeriodForm[];
    /** A `wall` / `date` / `day` form with no zone argument reads in the app's `.time({ zone })` — explicit, never implied. */
    readonly wallZone?: 'app';
    /** Which side of now the source can hold; absent: not checked. */
    readonly direction?: PeriodDirection;
    /** The oldest data the source keeps (`30d`). */
    readonly retention?: DurationText;
    /** The widest window the tool accepts at once (`24h`). */
    readonly maxRange?: DurationText;
    /** The source's smallest step (`1m`). */
    readonly granularity?: DurationText;
    /** The tool reads `ctx.time.asked` and drops rows outside it. */
    readonly filtersToAsked?: boolean;
}
/** The JSON Schema types a ruled argument may have — flat primitives only (v1). */
export declare const RULED_TYPES: readonly string[];
/** An `ask` question's bound — the typed ask's own (`tools/inputRequest.ts`). */
export declare const ASK_QUESTION_CHARS = 4096;
/** Choices per `ask` rule. */
export declare const MAX_CHOICES = 100;
/** One `said` phrase's length. */
export declare const SAID_PHRASE_CHARS = 120;
/** `said` phrases per choice. */
export declare const MAX_SAID_PHRASES = 16;
/** Arguments that may carry `ask` on one tool — the typed ask's field limit. */
export declare const MAX_ASK_ARGUMENTS = 32;
/**
 * The ONE owner of "this argument is missing from this call": no own key, or
 * a value that is `undefined`, `null`, or a string that is empty after
 * trimming. Deterministic; never a reading of what the value means.
 *
 * @example
 * ```ts
 * isMissing({ service: 'checkout' }, 'window');      // true — no key
 * isMissing({ window: '  ' }, 'window');             // true — blank string
 * isMissing({ window: '2h' }, 'window');             // false
 * ```
 */
export declare function isMissing(args: Readonly<Record<string, unknown>>, argument: string): boolean;
/**
 * Whether two argument values are the same value: same JavaScript type, and
 * the same token sequence under the evidence module's normaliser
 * (`lib/normalize.ts` · `tokenize`, `canonicalForm` — one owner of "the
 * same value", so `41,200` ≡ `41200` here exactly as at the evidence gate). A
 * value with no token after normalisation equals nothing, not even itself: it
 * cannot be checked, and "cannot be checked" is never "equal".
 */
export declare function sameArgumentValue(a: unknown, b: unknown): boolean;
/**
 * Whether `value` is spelled the way `spelling` declares. `lookback` is a
 * positive integer and a unit (`m`, `h`, `d`, `w`); `signed-lookback` the
 * same with a leading minus; `iso-range` two ISO 8601 instants WITH a zone,
 * joined by `..`, each a day that exists (`2026-02-30` and hour `24` are
 * refused — `Date.parse` used to roll them forward). A format check, never a
 * conversion: nothing is ever turned into a duration, and no instant is
 * compared with "now".
 */
export declare function parsesUnderSpelling(value: unknown, spelling: PeriodSpelling): boolean;
/**
 * Convert a period value between the two spellings the library converts —
 * `lookback` ↔ `signed-lookback`, by adding or removing the leading minus.
 * Nothing is ever turned into a duration; an `iso-range` is never converted.
 * `undefined` when the value does not parse under `from`. The one owner: the
 * batch ask's shared period field (`arguments/ask.ts` · `periodsShareField`) and the
 * declared-sources check's earlier answer in another spelling (`arguments/checks.ts` ·
 * `checkSource`, `matched: 'spelling'`) both convert through it.
 */
export declare function convertSpelling(value: InputValue, from: PeriodSpelling, to: PeriodSpelling): InputValue | undefined;
declare class DeclarationRefused extends Error {
}
/** Forms per period — a tool spells its period in a handful of shapes, never dozens. */
export declare const MAX_PERIOD_FORMS = 8;
/**
 * Judge a tool's `askOrAssume` and `period`, at definition — and again at
 * dispatch (`rulesOf`) and at MCP ingest, by this same function. Throws an
 * `Error` naming the tool and the argument; returns nothing on a declaration
 * this version can apply. Both absent → a no-op.
 *
 * Refused: a rule on an argument the schema does not offer, whose type is not
 * exactly one of `string`, `number`, `integer`, `boolean`, or that is a `wants`
 * argument; a rule with both forms, neither, or an unknown key; a blank or
 * over-long question; empty, over-long or repeating choices; a choice or an
 * `assume` value the property's OWN schema rejects (never the root `required`);
 * a malformed `said` phrase; more than 32 `ask` arguments; a period on an
 * argument with no rule, an unknown spelling, or a declared value not spelled
 * that way.
 *
 * @example
 * ```ts
 * assertAskOrAssume('search_logs', { window: { assume: '2h' } }, undefined, schema);  // ok
 * assertAskOrAssume('search_logs', { window: { ask: 'Which period?', choices: ['1h', '24h'] } },
 *   undefined, schema);                                                           // ok
 * assertAskOrAssume('search_logs', { window: { assume: '9h' } }, undefined, schema);  // throws
 * ```
 */
export declare function assertAskOrAssume(toolName: string, askOrAssume: unknown, period: unknown, inputSchema: Readonly<Record<string, unknown>> | undefined, wants?: Readonly<Record<string, string>>): void;
/** One declared choice's phrases — words the author vouches for as meaning that value. */
export interface ChoicePhrases {
    readonly value: InputValue;
    readonly said: readonly string[];
}
/** What an `ask` rule declares, as the layer reads it. */
export interface RuledAsk {
    /** The author's question — the ask field's `description`. */
    readonly question: string;
    /** The author's choices' values, in declared order — the field's `enum`. Absent: a free field. */
    readonly choices?: readonly InputValue[];
    /**
     * The choices that declare `said` phrases, in declared order — matched as
     * whole tokens only inside a quote the model declared (`arguments/checks.ts` ·
     * `checkSource`, `matched: 'phrase'`), never scanned for in the person's
     * words. Absent when no choice declares any.
     */
    readonly phrases?: readonly ChoicePhrases[];
}
/** One ruled argument of a tool, as the layer reads it. */
export interface RuledArgument {
    readonly argument: string;
    readonly rule: 'ask' | 'assume';
    /** The declared default — present on an `assume` rule. */
    readonly assume?: InputValue;
    /** The question and the choices — present on an `ask` rule. */
    readonly ask?: RuledAsk;
    /** The property's JSON Schema type — one of `RULED_TYPES`, judged at definition. */
    readonly type: 'string' | 'number' | 'integer' | 'boolean';
    /** Set on the argument `Tool.period` names. */
    readonly period?: true;
}
/** A tool's rules, read and judged. */
export interface ToolRules {
    readonly ruled: readonly RuledArgument[];
    readonly period?: ToolPeriod;
}
/**
 * Every form a tool's period takes, the sugar read (`time/convert.ts` ·
 * `sugarForms`) — empty when it declares none, or names an argument and no
 * spelling.
 */
export declare function periodFormsOf(period: ToolPeriod | undefined): readonly PeriodForm[];
/**
 * The form a call's window is in, read off what the call GIVES — the first form given whole
 * (every argument but the zone), else the first form given in part; `undefined` when every
 * form is left out. A period's forms are alternatives, so this is the one reading of "which
 * form did the call take", asked by the inputs layer (`arguments/resolve.ts` · `windowUntakenOf`) and
 * inner dispatch (`toolDispatch.ts` · `refuseUnaccountedRuledArguments`).
 */
export declare function sentFormOf(forms: readonly PeriodForm[], args: Readonly<Record<string, unknown>>): number | undefined;
/**
 * The arguments of every form but `forms[taken]` that it does not also name — an
 * alternative the call did not take. Empty for a single form: one form is one window.
 */
export declare function untakenBesides(forms: readonly PeriodForm[], taken: number): ReadonlySet<string>;
/**
 * The form a call that leaves EVERY form out owes, by the rules: a form this turn's kept
 * answers fill whole (`answered`), else the first form the rules ASSUME whole — its default IS
 * the window — else the first form, asked by its own asks. Never every form at once: that
 * would ask the person for two windows, which the tool refuses.
 */
export declare function owedFormOf(forms: readonly PeriodForm[], rules: ToolRules, answered: (argument: string) => boolean): number;
/**
 * Every argument a period names — the single argument, or each form's bound,
 * object and zone arguments. What a row's `period: true` marks.
 */
export declare function periodArgumentsOf(period: ToolPeriod | undefined): ReadonlySet<string>;
/**
 * The ONE argument a period is known by — the single `argument`, else the
 * first form's first bound. The results layer's join key (a `period` row names
 * it, and joins the call's `argument` row by it).
 */
export declare function periodArgumentOf(period: ToolPeriod | undefined): string | undefined;
/** The facts a period declares about its source, only those it declares. */
export declare function periodFactsOf(period: ToolPeriod | undefined): PeriodFacts;
/** Why a tool's rules could not be read — the assert's own sentence. */
export interface RulesRefused {
    readonly refused: string;
}
/** The shape `rulesOf` reads — any object carrying the three declarations. */
export interface RuledToolLike {
    readonly schema: {
        readonly name: string;
        readonly inputSchema?: Readonly<Record<string, unknown>>;
    };
    readonly askOrAssume?: unknown;
    readonly period?: unknown;
    readonly wants?: Readonly<Record<string, string>>;
}
/**
 * A tool's rules as the inputs layer applies them, or why they cannot be read,
 * or `undefined` for a tool that declares none. Runs the SAME assert
 * `defineTool` runs, because a Tool built by hand or delivered by a
 * ToolProvider never passed through `defineTool` — and a rule that fails here
 * refuses the call; it is never repaired. Cached per tool object.
 */
export declare function rulesOf(tool: RuledToolLike | undefined): ToolRules | RulesRefused | undefined;
/** True when `rulesOf` could not read the rules. */
export declare function isRefused(value: ToolRules | RulesRefused | undefined): value is RulesRefused;
/**
 * Whether a tool's argument rules can be read and rule at least one argument
 * — the one predicate for "this tool is RULED" wherever the declared sources'
 * `_findings.from` is planted (`core/slots/buildToolsSlot.ts`, `stages/seed.ts`):
 * only such a tool's calls are checked and filed.
 */
export declare function carriesRules(tool: RuledToolLike | undefined): boolean;
/**
 * Forget every definition-time warning issued so far.
 * @internal test seam — the ledger is process-wide and warn-once.
 */
export declare function _resetDeclareWarnings(): void;
/** @internal — `DeclarationRefused` is the assert's own error class, for tests. */
export { DeclarationRefused };
//# sourceMappingURL=declare.d.ts.map