/** * `` — a config that checks its own output. * * ── What is worth asserting ────────────────────────────────────────────────── * * Not what the config already states. You wrote `percent="70"` and you assert * 70% — you have tested that TDC can count. * * What the config does NOT state is where the value is. You write * `percent="70"`, a `parent=` filter removes rows, and the share of the rows * that survive is 41%. Nothing errors. That is the failure this project is built * around, and the one an assertion has to catch. * * ── Three existing mechanisms, no new language ─────────────────────────────── * * `that=` is the `if=` expression language, unchanged. The numbers come from * ``, which already computes a whole-run answer in all five * implementations. `says=` is the sentence the reader gets — required, because an * assertion that fires with only its expression to show makes the reader work out * what it was for. * * ── The rule that keeps it honest ──────────────────────────────────────────── * * Every name the expression reads must be WHOLE-RUN CONSTANT. Without that, * `that="Amount > 100"` reads row 0 and reports on one row out of a thousand — a * check that passed because it barely looked, wearing a badge that says * "verified". So a per-row column is refused by name. * * Which names an expression reads is discovered by handing the evaluator a scope * that records what it is asked for: no parser change, and the same trick works * in every port, because all five evaluate through a scope function. * * ── No flag ────────────────────────────────────────────────────────────────── * * An assertion runs because it is written. A flag that must be remembered means * the default is a check nobody ran, and a config that looks verified and is not * is worse than one with no check at all. * * It costs no new engine consequence either: an assertion reads `stat` columns, * and `stat` already routes the config to the in-memory engine, out loud. */ import type { SequenceRegistry, SequenceSpec } from './types.js'; /** One `` as written. Exactly one of `that` and `each` is filled. */ export interface AssertSpec { /** The `if=`-style expression that must hold ONCE, over whole-run values. */ readonly that: string; /** The `if=`-style expression that must hold on EVERY row. */ readonly each: string; /** The sentence a reader gets when it does not. */ readonly says: string; } /** The whole-run assertions — the ones `checkAssertions` answers. */ export declare function wholeRunAsserts(asserts: readonly AssertSpec[]): readonly AssertSpec[]; /** The per-row assertions — the ones the render loop answers, row by row. */ export declare function perRowAsserts(asserts: readonly AssertSpec[]): readonly AssertSpec[]; /** A run whose output did not hold up its own config's claim. */ export declare class AssertionError extends Error { readonly name = "AssertionError"; } /** * Check every assertion against the finished run. * * Throws on the first one that does not hold, with the author's sentence and the * value of every column the expression read — so the reader sees the 41% rather * than only the word "false". */ export declare function checkAssertions(asserts: readonly AssertSpec[], registry: SequenceRegistry, specs: readonly SequenceSpec[], count: number): void; /** * Check every per-row assertion against ONE row. * * Called from the row loop both engines share, so a `each=` assertion costs the * same and means the same whether the run is held in memory or streamed. It is * the `if=` language over the same scope `if=` itself gets — this row's columns * and the row built-ins — so nothing new had to be learnt to write one. * * The run stops at the FIRST row that fails. On a streaming engine the rows * before it are already written, and saying "stops at the first" is honest where * "checks the whole file first" could not be true of every engine. */ export declare function checkRowAssertions(perRow: readonly AssertSpec[], registry: SequenceRegistry, row: number): void; //# sourceMappingURL=assert.d.ts.map