/** * The instruction-weight RATCHET: the always-loaded weight may not grow past * what the repository itself last recorded. * * WHY A RATCHET AND NOT THE BUDGET. `./instruction-weight.ts` explains why the * harness's own threshold cannot gate: real repositories sit several times over * it, and a rule that fails every repo on day one is switched off on day one. * What CAN gate is the repository's own past. The baseline is whatever the repo * weighed when it was last recorded, so a repo four times over budget starts * green — and stays green only while it does not get heavier. The measured case * this exists for: a root instruction file cut from ~4 100 lines to ~1 900, then * regrown by ~1 000 lines over ten ordinary commits, with nothing in CI to say so. * * WHY THE SUM, AGAIN. The baseline records `committedTotal`, the same number the * audit report scores: everything the harness loads without being asked that a * teammate on the same commit also loads. A per-file baseline would read text * moved into an always-loaded sibling as a shrink — the evasion the weight * module was built to see through. The per-file sizes are recorded too, but only * so a message can say WHICH file moved; the verdict is decided on the total. * * WHY A SHRINK IS A FINDING TOO. A baseline left above the tree is headroom, and * headroom is exactly where the regrowth above landed: every character up to the * old number would pass. So, like ESLint's unpruned suppressions and `betterer * ci`, a tree LIGHTER than its baseline asks for the baseline to be lowered — * one command, in the same change that made the cut. The baseline then always * equals the tree on the default branch, and any growth at all is a diff a * reviewer sees. * * WHO WRITES IT. Never `lint` on its own: a read never writes. The file is * written only by the explicit `vigiles lint --update-baseline`, the same shape * as `eslint --suppress-all` / `--prune-suppressions` and `jest -u`. Raising the * baseline is allowed and is the point: growth is not forbidden, it is made * visible as a reviewed diff of a committed file. * * Pure: parsing, comparison and formatting only. Reading and writing the file * is the caller's (`src/instruction-weight-ratchet.ts`). */ import { z } from "zod"; import type { InstructionWeight } from "./instruction-weight.js"; /** Where the baseline lives, relative to the directory `.vigilesrc.json` is read from. */ export declare const INSTRUCTION_BASELINE_FILE = ".vigiles/instruction-weight.json"; /** The command that writes the baseline — named once, quoted by every message. */ export declare const UPDATE_BASELINE_COMMAND = "vigiles lint --update-baseline"; /** Bumped only on an incompatible change to the on-disk shape. */ export declare const INSTRUCTION_BASELINE_VERSION = 1; /** * Which MEASUREMENT produced a recorded number — bumped whenever a release * changes what counts (chain membership in any adapter, how a file is sized), * even when the file shape stays the same. * * Without it, a vigiles fix that moves a file into or out of the chain moves * `committedTotal` on every consumer with a committed baseline, and they see * `grew`/`shrank` attributed to their own content. With it, they see one * "re-record" verdict that names the cause. `version` cannot do this job: it * describes the file, not the number in it. */ export declare const INSTRUCTION_WEIGHT_MEASURE = 1; declare const entrySchema: z.ZodObject<{ unit: z.ZodEnum<{ chars: "chars"; bytes: "bytes"; }>; measure: z.ZodNumber; total: z.ZodNumber; files: z.ZodRecord; }, z.core.$strict>; declare const baselineSchema: z.ZodObject<{ version: z.ZodLiteral<1>; bundles: z.ZodRecord; measure: z.ZodNumber; total: z.ZodNumber; files: z.ZodRecord; }, z.core.$strict>>; }, z.core.$strict>; /** One bundle's recorded weight. */ export type BaselineEntry = z.infer; /** The whole committed file. */ export type InstructionBaseline = z.infer; /** The file's contents, parsed once at the boundary. */ export type ParsedBaseline = { readonly kind: "ok"; readonly baseline: InstructionBaseline; } | { readonly kind: "invalid"; readonly message: string; }; export declare function parseInstructionBaseline(text: string): ParsedBaseline; /** What a measured weight would be recorded as: the SCORED files only. */ export declare function entryFor(weight: InstructionWeight): BaselineEntry; /** One file whose recorded size differs. `null` = absent on that side. */ export interface FileChange { readonly path: string; readonly from: number | null; readonly to: number | null; } /** * The comparison of a tree against its baseline. Each case is a different fact, * so each is its own member — "no baseline" is not "equal", and a baseline in * another unit is not a number to subtract. */ export type RatchetVerdict = { readonly kind: "unrecorded"; /** What `--update-baseline` would write. */ readonly current: BaselineEntry; } | { readonly kind: "unit-changed"; readonly recorded: BaselineEntry["unit"]; readonly current: BaselineEntry["unit"]; } | { readonly kind: "measure-changed"; readonly recorded: number; readonly current: number; } | { readonly kind: "held"; readonly total: number; readonly unit: BaselineEntry["unit"]; } | { readonly kind: "grew" | "shrank"; readonly from: number; readonly to: number; readonly unit: BaselineEntry["unit"]; /** Every file whose size moved, largest movement first. */ readonly changes: readonly FileChange[]; }; export declare function compareToBaseline(weight: InstructionWeight, recorded: BaselineEntry | undefined): RatchetVerdict; /** One file's size, for naming where the weight is. */ export interface FileWeight { readonly path: string; readonly size: number; } /** * A total above the opt-in absolute ceiling (`["error", { max }]`). * * Decided on the same number the ratchet records — `committedTotal`, the SCORED * files only — and in the same unit, so the two can never disagree about what * the weight is. It does not look at the baseline at all: that independence is * what makes it a ceiling and not a second ratchet. */ export interface CeilingVerdict { readonly total: number; readonly max: number; readonly unit: BaselineEntry["unit"]; /** The scored files, heaviest first — where the cut has to come from. */ readonly largest: readonly FileWeight[]; } /** `undefined` when the weight is at or under `max`, or when no ceiling is set. */ export declare function checkCeiling(weight: InstructionWeight, max: number | undefined): CeilingVerdict | undefined; /** Replace the measured bundles' entries; `null` removes one. Others are kept. */ export declare function recordEntries(previous: InstructionBaseline | undefined, measured: readonly (readonly [string, BaselineEntry | null])[]): InstructionBaseline; /** Stable text: sorted keys, two-space indent, trailing newline, no timestamp. */ export declare function serializeBaseline(baseline: InstructionBaseline): string; /** The one-paragraph message a verdict prints as, prefixed by its bundle. */ export declare function formatVerdict(verdict: RatchetVerdict, at: string): string; /** The message for a total over the ceiling, prefixed by its bundle. */ export declare function formatCeiling(verdict: CeilingVerdict, at: string): string; /** Why `--update-baseline` wrote nothing: the ceiling it would have been recorded above. */ export declare function formatRefusal(verdict: CeilingVerdict, at: string): string; /** The compile-time one-liner: weight now, against the baseline when there is one. */ export declare function formatWeightLine(verdict: RatchetVerdict): string; export {}; //# sourceMappingURL=instruction-baseline.d.ts.map