/** * The COLUMN-TYPE CONTRACT's vocabulary — what a tool may say about the * columns of the rowset it returns, and the one rule that judges the saying. * * Pattern: closed vocabulary + definition-time assert (the `resultCeiling` / * `resultClass` law: a declaration this library cannot honour fails * at `defineTool`, never at the first row of the first run). * Role: leaf. `src/integrity/` imports nothing outside itself, so the * vocabulary lives HERE and `core/tools.ts` reaches in for it — * never the other way round. * * ── Why the words are these words ─────────────────────────────────────── * They are NOT invented. `number | string | boolean | date` is the vocabulary * this ecosystem's rowset consumers already speak — a column-type union with * exactly these members is what the visualization layer sniffs its way to * today. Declaring in the consumer's own words is the `resultKind` law * (9.70.0) restated one level down: the tool's result in the CONSUMER's * vocabulary, not the framework's. * * The one member deliberately NOT carried over is `unknown`. A sniffer needs * that word — it is what "I looked at the values and could not tell" sounds * like. A DECLARATION has no use for it: an author who does not know what a * column holds should not name the column, and `columns: { x: 'unknown' }` * would be a promise about nothing that the checker would then have to * pretend to verify. * * ── Two spellings, one meaning ────────────────────────────────────────── * A column maps to a bare type (`lun: 'number'`) or to an object form * (`note: { type: 'string', nullable: true }`). That is this library's house * pattern for exactly this shape — `CostBudget` takes a bare number or * `{ usd, onExceed }`, `artifacts` takes a bare store or `{ store, placement }` * — and it is normalized ONCE, here, so every reader downstream sees one * shape and no downstream file learns that there were two. */ /** * What a declared column holds. * * | word | what a value must be | * | --- | --- | * | `number` | a JavaScript number that is FINITE — `NaN` and the infinities are a number that means "no number", and a chart handed one draws nothing | * | `string` | a JavaScript string, including the empty one (emptiness is meaning, and meaning is above this check's ceiling) | * | `boolean` | `true` or `false` — never `'true'`, never `0`, never `1` | * | `date` | a valid `Date` instance, or a string `Date.parse` accepts (an epoch NUMBER is a `number`; say so and the axis picker stops guessing) | */ export type ColumnType = 'number' | 'string' | 'boolean' | 'date'; /** The closed set, in one place, for the assert and for its own error message. */ export declare const COLUMN_TYPES: readonly ColumnType[]; /** The object spelling of one column's declaration. */ export interface ColumnDeclaration { /** What the column holds. */ readonly type: ColumnType; /** * `true` — a row of this column may legitimately carry NO VALUE (`null`, * `undefined`, or the key simply not set on that row), and such a row is * never a type violation. * * Default `false`, and the default is the strict one ON PURPOSE. The field * failure this check is built from was a value that went missing and left * an empty string behind; had the same code left a `null` behind, the * defect would have been identical and a lenient default would have waved * it through. One word turns it off, and every finding names that word — so * a legitimate null column costs a one-word edit, while a silent default * would cost the bug. * * `nullable` is a promise about VALUES. It is NOT a promise about the * column's existence: a declared column that appears in no row at all is a * `missing-column` finding whether or not it is nullable, because the * declaration named a column and the result has no such column. The valve * for "this column may or may not be there" is to not declare it — * unlisted columns are allowed and unjudged. */ readonly nullable?: boolean; } /** * What a tool declares about the columns of its rowset — column name to type. * * OPEN, NEVER CLOSED. A declaration is a promise about what it NAMES, not a * schema of everything the result may contain: a column nobody listed is * allowed and is never judged. Two reasons, and both are the same reason. * * • A closed schema punishes the wrong party. The day the backend adds a * column, every one of these tools starts filing findings about a change * that broke nothing — and a check that cries about correct behaviour is * a check people switch off, which is how the failure it exists to catch * gets back in. * • It is the rule the neighbouring boundary already keeps. * `toolArgsValidation` is permissive on keywords it does not know and * enforces `additionalProperties: false` only when an author explicitly * asks for it. Two validators at one seam disagreeing about whether * silence means "allowed" would be a worse defect than either could * catch. */ export type ToolResultColumns = Readonly>; /** One column's declaration after normalization — the ONLY shape any reader * downstream of `normalizeColumns` ever sees. */ export interface NormalizedColumn { readonly name: string; readonly type: ColumnType; readonly nullable: boolean; } /** * Both spellings into one list, in declaration order. * * Order is kept because it is the author's order, and a finding that names * columns in the order the author wrote them is a finding they can scan * against their own source. */ export declare function normalizeColumns(columns: ToolResultColumns): readonly NormalizedColumn[]; /** * Refuse a `resultColumns` this library cannot honour, at definition time — * naming the tool, the column and the fix. * * Exported beside {@link ColumnType} and called from `defineTool`, so a * misspelled type fails on the line that wrote it rather than at the first * rowset of the first armed run. Also called by the MCP ingest * (`readToolExtras`) on a bag from a server this process does not control — * which is why every read below goes through a fallback: a `null`, a number * or an array must reach the teaching refusal, never blow up on the way to * it. */ export declare function assertResultColumns(toolName: string, columns: unknown): void; //# sourceMappingURL=types.d.ts.map