kestrel.markets
Version:
A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.
165 lines • 12 kB
TypeScript
/**
* # frame/paradigm-ledger — the FOUR-STATE paradigm cell ledger (ADR-0041 §3, kestrel-wa0j.30)
*
* ADR-0041 §3 makes every `(pane × sort-value-bundle)` cell exactly one of four states:
* • **ATTESTED** — materializes byte-identically today (and is monotone forever — the ratchet).
* • **LATENT** — not yet, but a NAMED train will land it (a LATENT refusal names its train).
* • **DEFECTIVE** — never, for a WRITTEN reason, with a SANCTIONED PERIPHRASIS.
* • **UNATTESTED** — outside the closed roster (the closed-world default; never enumerated).
*
* This module is the SINGLE SOURCE of that table. It ships in `src/` (the package's `files`
* excludes `tests/`), so production refusal constructors ({@link ./refusals.ts}) can read it — a
* LATENT refusal pulls its train from HERE, never a second hand-kept list. The committed sidecar
* `tests/golden/pane-paradigm.json` is this data SERIALIZED (generated by
* `scripts/gen-paradigm-ledger.ts`, staleness-checked in `tests/frame.paradigm-ledger.test.ts`) —
* the repo's generate-golden-from-source pattern (cf. `gen-detmath-golden.ts`), so the JSON can
* never drift from this module.
*
* ## Totality (ADR-0041 §3: "a total function over a known grid")
* {@link resolveCellState} is a TOTAL function over `pane × {@link PARADIGM_ROSTER}`: every cell
* resolves to exactly one state. The listed {@link PARADIGM_CELLS} carry the non-UNATTESTED states;
* every unlisted cell is UNATTESTED by the closed-world rule. `tests/frame.paradigm-ledger.test.ts`
* asserts totality (no cell unclassified) and binds the ATTESTED rows to the live catalog signatures.
*
* ## Forward-compatibility with scheme conditioning (wa0j.44 — NOT implemented here)
* A cell's state may later be CONDITIONED on a registry attribute (instrumentClass / SessionScheme):
* `prior-context` is DEFECTIVE under a SessionScheme with no close boundary but ATTESTED under one
* with a close — ONE paradigm, two conditioned cells (ADR-0041 §3). The cell KEY carries an OPTIONAL
* {@link CellConditioning}; every current cell OMITS it (= unconditioned, applies to all schemes).
* wa0j.44 adds scheme-conditioned cells by ADDING a more-specific conditioned cell — it NEVER
* re-keys an existing unconditioned one. Pinning the optional field into the key shape NOW (while the
* ledger is small) is the empty-ledger lesson (wa0j.52 / instrumentClass): an axis added to an
* established key is an evidence-splitting migration; an optional axis reserved up front is additive.
*/
import { type BoundaryKind, type SessionScheme } from "./session-scheme.ts";
/** The four paradigm states (ADR-0041 §3). */
export declare const PARADIGM_STATES: readonly ["ATTESTED", "LATENT", "DEFECTIVE", "UNATTESTED"];
export type ParadigmState = (typeof PARADIGM_STATES)[number];
/** A state a LISTED cell may carry — UNATTESTED is the closed-world default and is NEVER listed
* (listing it would enumerate the open world the closed-world rule exists to avoid). */
export type ListedState = Exclude<ParadigmState, "UNATTESTED">;
/**
* The CLOSED sort roster (ADR-0041 §1/§3) — the ground index sorts a pane argument may address. It
* is closed at any instant and opened ONLY by the sort-introduction ceremony (five artifacts in one
* commit). Train 1A's LIVE subset is {@link LIVE_SORTS}; the rest are pinned into the roster but
* DEFERRED (their slots arrive with later trains). A value OUTSIDE this roster is UNATTESTED and
* refused by name.
*/
export declare const PARADIGM_ROSTER: readonly ["Instrument", "LevelName", "Window", "Count", "SessionOrdinal", "ExpiryOrdinal", "Band"];
export type RosterSort = (typeof PARADIGM_ROSTER)[number];
/** The LIVE subset of {@link PARADIGM_ROSTER} the catalog materializes (has a catalog slot for).
* Train 1A opened `LevelName` / `Window` / `Count`; Train 1B opened `SessionOrdinal` (`tape d-N`) and
* `ExpiryOrdinal` (`chain e-N`) by the sort-introduction ceremony (ADR-0041 §3). */
export declare const LIVE_SORTS: readonly RosterSort[];
/**
* A registry attribute a cell's paradigm state may be CONDITIONED on (ADR-0041 §3 / kestrel-wa0j.44).
* ABSENT on every current cell (= unconditioned; the state holds for every instrumentClass /
* SessionScheme). Reserved in the key shape NOW so wa0j.44 conditions cells additively — see the
* module header. NOT populated here (wa0j.44 is explicitly out of scope for wa0j.30).
*/
export interface CellConditioning {
readonly instrumentClass?: string;
readonly sessionScheme?: string;
}
/**
* One LISTED `(pane × sort)` cell of the ledger. UNATTESTED cells are never listed (closed-world).
* Per-state required fields (enforced by {@link validateParadigmCell}):
* • ATTESTED → `form` (the taught canonical View form that materializes it).
* • LATENT → `train` (the named deferred train — ADR-0041 §3: a LATENT refusal names its train).
* • DEFECTIVE → `reason` + `periphrasis` (the written reason + the sanctioned periphrasis).
*/
export interface ParadigmCell {
readonly pane: string;
readonly sort: RosterSort;
readonly state: ListedState;
readonly form?: string;
readonly train?: string;
readonly reason?: string;
readonly periphrasis?: string;
readonly conditioning?: CellConditioning;
}
/** Where the first production DEFECTIVE cell arrives (documented — ADR-0041 §3). It has LANDED with
* kestrel-wa0j.44 as a SCHEME-CONDITIONED cell (see {@link SCHEME_CONDITIONED_CELLS}); no cell in the
* UNCONDITIONED `(pane × sort)` space is DEFECTIVE (the ratchet's equity-rth bytes stay pinned). */
export declare const DEFECTIVE_FIRST_ARRIVAL: string;
/**
* The SessionOrdinal boundary each pane's read REQUIRES (ADR-0041 §3 conditioning). A pane listed here
* is DEFECTIVE under any {@link ../frame/session-scheme.ts SessionScheme} that does NOT carry the
* required boundary, and ATTESTED-as-today under one that does — ONE paradigm, conditioned on the
* registry attribute (never two paradigms).
* • `prior-context` anchors to the prior CLOSE (the `d-1` close boundary of the SessionOrdinal
* stream), so it requires `close`.
* • `tape` (Train 1B) addresses a PRIOR SESSION (`tape d-N`, N≥1); a prior session must be delimited
* by a session `close`, so a scheme with no close (a perp's rolling UTC day) has no prior-session
* address at all — `tape × SessionOrdinal` is scheme-conditioned DEFECTIVE there (the builder
* renders the sanctioned periphrasis, anchor to the declared rolling extreme, never an invented
* session), and ATTESTED-as-today under a close-bearing scheme (equity-rth, the default). Note this
* is the CONDITIONED overlay on the UNCONDITIONED ATTESTED `tape × SessionOrdinal` cell — exactly
* the prior-context pattern (one paradigm, two conditioned cells).
* Flipping a declaration is the red-capability lever: retarget the required boundary and the conditioned
* cell + the production refusal follow. This is the SINGLE SOURCE of the requirement —
* {@link resolveCellState}, {@link schemeConditionedDefect}, and the census all read it.
*/
export declare const PANE_BOUNDARY_REQUIREMENT: Readonly<Record<string, BoundaryKind>>;
/** The roster sort a boundary-conditioned cell is keyed on: `SessionOrdinal` — the monotone boundary
* stream `d-N` indexes (ADR-0041 §1). A close/open boundary IS a SessionOrdinal address. */
export declare const CONDITIONED_SORT: RosterSort;
/** The sanctioned periphrasis for a boundary-conditioned DEFECTIVE cell (ADR-0041 §3 exemplar). */
export declare const CONDITIONED_PERIPHRASIS = "anchor to the declared rolling extreme";
/**
* The scheme-conditioned DEFECTIVE cell for `(pane × scheme)`, or `undefined` when the pane has no
* boundary requirement OR the scheme CARRIES the required boundary (then the pane is ATTESTED-as-today,
* not DEFECTIVE). Generated from {@link PANE_BOUNDARY_REQUIREMENT} × the scheme's boundary declaration —
* the production refusal ({@link ./refusals.ts}) and the census both read this one function, so they
* can never quote a different reason/periphrasis than the cell states.
*/
export declare function schemeConditionedDefect(pane: string, scheme: SessionScheme): ParadigmCell | undefined;
/**
* Every scheme-conditioned DEFECTIVE cell in the v1 grid (ADR-0041 §3) — the Cartesian product of the
* boundary-requiring panes × the schemes that LACK their required boundary. This is the production
* DEFECTIVE set (the census surfaces it); it is DELIBERATELY separate from {@link PARADIGM_CELLS} (the
* unconditioned grid) so the unconditioned census + conformance ratchet keep the equity-rth bytes
* pinned. Regenerating the sidecar re-derives this from the tables — it can never drift.
*/
export declare const SCHEME_CONDITIONED_CELLS: readonly ParadigmCell[];
/** Every LISTED cell (ATTESTED + LATENT + DEFECTIVE). Unlisted cells are UNATTESTED (closed-world). */
export declare const PARADIGM_CELLS: readonly ParadigmCell[];
/**
* The LATENT train each `views.kestrel` destination pane form is waiting on (ADR-0041 §3), keyed by
* pane id. This is the SINGLE SOURCE that `tests/frame.inflection-burndown.test.ts` reads — the
* burn-down no longer keeps its own copy. Distinct projection from {@link PARADIGM_CELLS}: those
* classify `(pane × roster-sort)`; this names the train for the destination-corpus FORMS (mostly
* new, not-yet-admitted sorts — named level-SETs, tape style/overlay/strip, macro/vol sub-selectors).
*/
export declare const DESTINATION_BACKLOG: Readonly<Record<string, string>>;
/** True iff `sort` is a member of the closed {@link PARADIGM_ROSTER}. */
export declare function isRosterSort(sort: string): sort is RosterSort;
/**
* The TOTAL four-state resolution (ADR-0041 §3). A listed unconditioned cell carries its state; every
* other `(pane × sort)` is UNATTESTED by the closed-world rule. Total by construction: it returns a
* {@link ParadigmState} for EVERY input, never throws, never `undefined` — the property the ledger
* test asserts over the whole `pane × roster` grid.
*
* **Scheme conditioning (kestrel-wa0j.44).** When a {@link CellConditioning} supplying a
* `sessionScheme` is passed AND the pane declares a {@link PANE_BOUNDARY_REQUIREMENT} on the
* {@link CONDITIONED_SORT}, the state is conditioned on the registry attribute — ONE paradigm, two
* conditioned cells: DEFECTIVE when the scheme LACKS the required boundary (a no-close perp), ATTESTED
* (as-today) when it carries it (equity-rth). The UNCONDITIONED call (no `conditioning`) is unchanged —
* the pane's conditioned axis is invisible to the unconditioned census + the conformance ratchet, so
* the equity-rth bytes stay pinned.
*/
export declare function resolveCellState(pane: string, sort: string, conditioning?: CellConditioning): ParadigmState;
/** The named LATENT train for a destination-corpus pane form, or `undefined` if the pane is not in
* the backlog (ADR-0041 §3: a LATENT refusal names its train — pulled from HERE by the constructor). */
export declare function latentTrainFor(pane: string): string | undefined;
/** The ATTESTED cells (the conformance-ratchet seed — monotone forever, ADR-0041 §3). */
export declare function attestedCells(): readonly ParadigmCell[];
/**
* Validate ONE cell against the paradigm-cell schema, returning a list of human-readable errors
* (empty ⇒ valid). Enforces the per-state required fields (ADR-0041 §3) so a DEFECTIVE cell can
* never omit its reason/periphrasis, an ATTESTED cell can never omit its form, etc. Executable mirror
* of `tests/golden/pane-paradigm.schema.json`; used by the totality test AND the DEFECTIVE
* schema-example test (which proves the state is supported without a fake production entry).
*/
export declare function validateParadigmCell(cell: unknown): string[];
//# sourceMappingURL=paradigm-ledger.d.ts.map