/** * ClaimDefinition COMPILER — v2 slice (inv.18 v2). The thesis inversion: the * `ClaimDefinition` SOURCE is now the PRIMARY artifact and the runtime is its * IMAGE. v1 (`./claim-definition.ts`) shipped a fail-closed VALIDATOR; THIS module * is the COMPILER that GENERATES the runtime artifacts FROM a source definition. * * ════════════════════════════════════════════════════════════════════════════ * THE FOUR DESIGN COMMITMENTS (the owner's pass/fail constraints) * ════════════════════════════════════════════════════════════════════════════ * * (1) SMALL, PRINCIPLED, DECLARATIVE INTERPRETER. `compileClaimDefinition` is a * set of PURE TOTAL functions, each a uniform FOLD over the schema fields. It * NEVER switches on `def.type`; the only type-specific information is the DATA * inside the def. Adding a claim type = adding a `defineClaim({...})` source — * ZERO interpreter edits. (The whole interpreter is ~one screen of folds; its * size is CONSTANT in the number of claim types.) * * (2) INVARIANTS ARE DERIVED, not handwritten. v1's INV-1..INV-8 become either * compile-time-illegal-to-express (via the `defineClaim` builder's types) or a * GENERATION RULE the compiler enforces structurally because it KNOWS slots ↔ * evidence ↔ projections. The slot→projection→evidence alignment (v1's INV-1 + * INV-7) is the SAME single DERIVED fact here: `toValueProjections` COMPUTES the * projection from `valueBinding` × the render slots, so a slot can never bind a * different key than the §5-gated binding. See `DERIVED_INVARIANTS` below. * * (3) ILLEGAL STATES UNREPRESENTABLE. The `defineClaim` const-generic builder makes * bad definitions impossible to EXPRESS rather than checked-then-rejected: * · INV-6 `requiredEvidence` is a NON-EMPTY tuple — `[]` is a type error. * · INV-7 `valueBinding.key` is typed `RequiredKeyOf` (the literal union * of the def's own `requiredEvidence` keys) — binding an un-§5-gated key is * a COMPILE error, not a runtime reject. * · INV-2 falsifier-completeness is a DISCRIMINATED union — `falsifierComplete: * true` with empty `falsifiers` is unrepresentable. * · INV-5 `provenancePolicy` is a REQUIRED field of `EvidenceRequirement` * (default-deny: there is no absent state to default). * * (4) VERSIONING DESIGNED-IN. Every source carries `version`; the compiler stamps a * disambiguated id (`type@version`) onto every artifact + the generated doc, and * exposes `isFalsifierSetMonotone` so an evidence-schema evolution can be * STRUCTURALLY checked "a newer version is only ever SAFER" (the falsifier set is * append-only across compatible versions). See `VERSIONING` below. * * (5) GENERATE, DON'T HANDWRITE. `compileClaimDefinition(def)` returns the full * `CompiledArtifacts` bundle (registry spec, value projections, render template, * the validator-wiring `ClaimDefinition`, decomposition closure, property + * mutation FIXTURES, and the doc card). A downstream generator serializes those * to GENERATED files (marked `@generated` + checksum, never hand-edited). * * HONEST scope note (the one place the design over-stated itself): the design said * "`falsifiers[].key` is typed as the requiredEvidence-key union" — that is WRONG and * contradicts the worked example, because a falsifier is BY DESIGN a DIFFERENT * (cross-) key (STORE_OPEN_NOW's falsifier `schedule:schedule_override` is NOT in * requiredEvidence). Only `valueBinding.key` (the C6 / INV-7 gate) is constrained to * the required-key union here; falsifier keys are left free (the runtime cross-key * arm is what gates them). This is the load-bearing illegal-states lever, applied * exactly where it is sound. * * PURITY: every fold is definition-load/build time — no clock, no RNG, no IO — so the * whole module is a pure function of its input. No kernel-downstream import (§R: * `adjudicate → claustrum → ibatexas`, never backward). */ import { type EvidenceRequirement, type SourceIntegrity } from "./evidence-requirement.js"; import type { ClaimKind, ValueBinding } from "./soundness.js"; import type { ClaimDefinition, RenderTemplate, ValidationFailureCode, ValueProjection } from "./claim-definition.js"; /** A NON-EMPTY readonly tuple. Makes `[]` a TYPE error (INV-4/INV-6 unrepresentable). */ export type NonEmpty = readonly [T, ...T[]]; /** * A source render slot. The contributor names a FIELD only on a proposition; the * backing `claimType` is IMPLIED = the def's own type, and the projection back to the * §5-gated evidence key is COMPUTED by the compiler (INV-1 derived) — so a slot can * never reference an un-gated key. `lit`/`prop` are the convenience constructors. */ export type SourceSlot = { readonly kind: "LITERAL"; readonly text: string; } | { readonly kind: "PROPOSITION"; readonly field: string; }; /** Convenience constructor: a static-text slot. Pure. */ export declare const lit: (text: string) => SourceSlot; /** * Convenience constructor: a PROPOSITION slot naming a FIELD only (claimType is * implied = self; the projection to the §5-gated key is derived). Pure. */ export declare const prop: (field: string) => SourceSlot; /** The render block — the `validated` (asserting) template, as source slots. */ export interface RenderSource { readonly validated: NonEmpty; } /** * The decomposition block — the §O#15 closure contribution: the span class this * type answers, the pt-BR markers that classify a request into it (DATA, not code — * constraint (1)), and the required-companion set. `requires` is a NON-EMPTY tuple, * so a `triadScoped` type that declares a decomposition can never be unreachable * (INV-4 derived). */ export interface DecompositionSource { readonly spanClass: string; readonly markers: NonEmpty; readonly requires: NonEmpty; } /** * The DISCRIMINATED falsifier stance (INV-2 unrepresentable). `falsifierComplete: * true` STRUCTURALLY REQUIRES a non-empty `falsifiers` tuple; the safe default omits * both. There is no way to express "complete with no falsifiers". */ export type FalsifierStance = { readonly falsifierComplete: true; readonly falsifiers: NonEmpty; } | { readonly falsifierComplete?: false; readonly falsifiers?: undefined; }; /** * The literal union of a definition's OWN `requiredEvidence` keys (INV-7's * type-level form). Resolved from the const-inferred `Self` so `valueBinding.key` * can be constrained to it — binding an un-§5-gated key becomes a COMPILE error. */ export type RequiredKeyOf = Self extends { readonly requiredEvidence: readonly (infer E)[]; } ? E extends { readonly key: infer K extends string; } ? K : never : never; /** The non-key, non-stance fields shared by every source definition. */ interface ClaimDefinitionSourceBase { /** The claim type name (the registry key + the template key + the closure target). */ readonly type: string; /** Claim-type version (designed-in evolution — stamped onto every artifact). */ readonly version: number; /** `read_claim | action_claim` — the §5 `c.kind` (drives C4 at runtime). */ readonly kind: ClaimKind; /** The C2 source-integrity floor each evidence must meet-or-exceed. */ readonly minSourceIntegrity: SourceIntegrity; /** The `∀ e ∈ requiredEvidence` set — NON-EMPTY tuple (INV-6 unrepresentable). */ readonly requiredEvidence: NonEmpty; /** Whether this type is Triad-scoped (a `true` carries a closure obligation, INV-4). */ readonly triadScoped?: boolean; /** Registry partitioning flag (the §D same-subject scope; projected to the spec). */ readonly customerScoped?: boolean; /** OPTIONAL render block; its proposition projections are DERIVED, never authored. */ readonly render?: RenderSource; /** OPTIONAL decomposition closure contribution. */ readonly decomposition?: DecompositionSource; } /** * The full DSL source shape — `Self`-parameterized so `valueBinding.key` is typed * as the literal union of THIS def's `requiredEvidence` keys (INV-7 at compile time). * Authored via {@link defineClaim} (a const-generic builder), NOT a bare annotation: * a plain `: ClaimDefinitionSource` annotation cannot infer the per-def key union, so * the builder is the load-bearing illegal-states-unrepresentable lever. */ export type ClaimDefinitionSource = ClaimDefinitionSourceBase & FalsifierStance & { readonly valueBinding?: { readonly key: RequiredKeyOf; readonly path?: readonly (string | number)[]; }; }; /** * The RUNTIME-facing definition shape the compiler folds consume. Structurally the * same as a source, but `valueBinding.key` is a plain `string` — the §5-gating * (INV-7 key-union) is enforced at AUTHORING time by {@link defineClaim}'s * F-bounded `RequiredKeyOf`, so once a value has been authored it flows here as an * ordinary structural record. (Using `ClaimDefinitionSource` directly here would * default `Self = unknown`, collapsing `RequiredKeyOf` to `never` and * rejecting EVERY def that declares a `valueBinding` — the param must be loosened.) * A `defineClaim(...)` result is assignable to this (literal key ⊂ string). */ export type CompilableClaimDefinition = ClaimDefinitionSourceBase & FalsifierStance & { readonly valueBinding?: { readonly key: string; readonly path?: readonly (string | number)[]; }; }; /** * The DSL ENTRYPOINT — a const-generic builder. The F-bounded `T extends * ClaimDefinitionSource` constraint feeds the inferred literal `T` back into the * source type so `valueBinding.key` must be a member of `T`'s own `requiredEvidence` * keys (INV-7), `requiredEvidence`/`falsifiers` must be non-empty (INV-4/INV-6), * and the falsifier stance must be consistent (INV-2) — ALL at COMPILE time. The * builder is the identity at runtime; it exists purely to mint those per-def types. */ export declare function defineClaim>(source: T): T; /** * The registry spec the compiler projects from a source. STRUCTURALLY identical to * the ibatexas `RegistryClaimSpec` (kept generic here so the compiler needs no * downstream import); the generated ibatexas file assigns it to `RegistryClaimSpec`. */ export interface CompiledRegistrySpec { readonly kind: ClaimKind; readonly minSourceIntegrity: SourceIntegrity; readonly requiredEvidence: readonly EvidenceRequirement[]; readonly customerScoped: boolean; readonly falsifierComplete?: boolean; readonly falsifiers?: readonly EvidenceRequirement[]; readonly valueBinding?: ValueBinding; } /** The decomposition closure contribution the compiler projects from a source. */ export interface CompiledClosure { readonly spanClass: string; readonly requires: readonly string[]; readonly markers: readonly RegExp[]; } /** * One MUTATION fixture: a structurally-corrupted `ClaimDefinition` paired with the * `ValidationFailureCode` the v1 validator MUST reject it with. The compiler * GENERATES one per applicable invariant (mirroring the v1 mutation-harness intent) * so the slice ships a proof that each invariant code fires — without hand-writing * the mutations. */ export interface MutationFixture { readonly code: ValidationFailureCode; readonly def: ClaimDefinition; } /** The property + mutation fixtures the compiler generates for a type. */ export interface CompiledFixtures { /** A definition that MUST validate (the compiled, complete definition). */ readonly valid: ClaimDefinition; /** One corrupted definition per applicable invariant (MUST reject with `code`). */ readonly mutations: readonly MutationFixture[]; } /** Everything the compiler GENERATES from ONE source definition. */ export interface CompiledArtifacts { readonly type: string; readonly version: number; /** `type@version` — stamped onto generated artifacts + the doc (versioning). */ readonly id: string; /** (1) the registry spec row. */ readonly registrySpec: CompiledRegistrySpec; /** (2) value-projector DATA (the projector itself is the generic `projectValue`). */ readonly valueProjections: readonly ValueProjection[]; /** (3) renderer binding / template wiring (claimType filled = self on every prop). */ readonly renderTemplate: RenderTemplate | undefined; /** (4) validator wiring — the generic v1 `ClaimDefinition`. */ readonly definition: ClaimDefinition; /** (7) decomposition rows (closure + span markers). */ readonly closure: CompiledClosure | undefined; /** (5) property + mutation fixtures. */ readonly fixtures: CompiledFixtures; /** (6) the generated markdown doc card. */ readonly doc: string; } /** * Compile ONE `ClaimDefinitionSource` into its full runtime IMAGE. PURE * (deterministic — no IO, clock, or RNG) but NOT total: it THROWS fail-closed on a * structurally-invalid definition — specifically a render block that declares a * PROPOSITION slot with NO `valueBinding` (the F7 guard below) — rather than emit an * artifact that fails its own validator. This mirrors the §R hard registry-load-error * pattern, and is DISTINCT from the sibling `validateClaimDefinition`, which reports * the same structural defect by RETURNING `{ ok: false }` instead of throwing. It * NEVER switches on `def.type`; adding a claim type adds a source file and ZERO * interpreter code. The returned bundle is what a downstream generator serializes to * GENERATED files (registry spec, projector data, template, validator-wiring def, * closure, fixtures, doc), each marked `@generated`. */ export declare function compileClaimDefinition(def: CompilableClaimDefinition): CompiledArtifacts; /** * STRUCTURAL evolution guard (designed-in versioning): a newer version of a type is * "only ever SAFER" IFF its falsifier set is a SUPERSET of the old one (the falsifier * set is APPEND-ONLY across compatible versions — adding a falsifier is demote-only, * it can only turn VALIDATED into UNKNOWN, the monotone-safety property the kernel * already guarantees at runtime). Removing a falsifier / loosening the floor is a * BREAKING major bump and returns `false` here. Pure; compares the compiled specs. * * This makes "a newer version is only ever safer" a DERIVED guard a CI step can run, * not a hand-review — exactly the constraint-(4) versioning stance, mechanized. */ export declare function isFalsifierSetMonotone(older: CompiledRegistrySpec, newer: CompiledRegistrySpec): boolean; export {}; //# sourceMappingURL=claim-compiler.d.ts.map