UNPKG

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.

83 lines (75 loc) 4.21 kB
/** * # react/frame-fields — reading the json Rendering HONESTLY (ADR-0052 §3/§4) * * Shared helpers for the `/react` components. They read the typed Frame `json` Rendering * ({@link ../frame/render-json.ts}) the way a Rendering must: an UNKNOWN Field is UNKNOWN (never a * zero, never interpolated), and a `MODEL` Field must PROVE its receipt (source + model version + * confidence) or it is REFUSED — the honest-chart claim is that the chart invents nothing and hides * no provenance, so a `MODEL` Field arriving without its receipt is a fail-closed error, not a badge * we quietly drop. * * ## Isolation (ADR-0052 §3, a HARD requirement — the trust substrate ships this) * Every engine import here is `import type` — ERASED at build. The `/react` runtime graph reaches * NOTHING in the engine (no tokenizer, no sha256, no Bun/node built-in); the only runtime coupling is * the optional `react` peer, resolved by the components, not this module. The two runtime CONSTANTS * that must agree with the engine — the {@link UNKNOWN} marker and the arm-id registry * ({@link ./arms.ts}) — are declared locally and pinned to the engine's TYPES at typecheck, so a * drift reds `bun run typecheck` rather than shipping a browser bundle that disagrees with the wire. */ import type { FieldJson, JsonUnknown, Maybe } from "../frame/render-json.ts"; /** * The explicit UNKNOWN marker, pinned to the engine's {@link JsonUnknown} at typecheck. The engine * carries a null/absent Field across the `json` wire as this literal (never an omitted key, never a * defaulted `0`); the components compare against THIS constant to decide "gap, not candle". The * annotation is the drift guard: if the engine ever changes its marker string, `"UNKNOWN"` stops * being assignable to {@link JsonUnknown} and this line reds — a type-only coupling, zero runtime edge. */ export const UNKNOWN: JsonUnknown = "UNKNOWN"; /** Is this {@link Maybe} value the explicit UNKNOWN marker (⇒ render a GAP, never a value)? */ export function isUnknown<T>(v: Maybe<T>): v is JsonUnknown { return v === UNKNOWN; } /** The finite value of a {@link Maybe}, or `null` when it is UNKNOWN — a `null` is the caller's cue to * leave a GAP (never substitute `0`, never interpolate a neighbour). */ export function valueOr<T>(v: Maybe<T>, fallback: null = null): T | null { return isUnknown(v) ? fallback : v; } /** Raised when a `MODEL` Field arrives WITHOUT its receipt — the honest chart refuses to draw a * model-derived value it cannot attribute (fail-closed, ADR-0052 §3). */ export class HonestChartError extends Error { constructor(message: string) { super(message); this.name = "HonestChartError"; } } /** A `MODEL` Field's receipt, extracted once it has been proven honest. */ export interface FieldReceipt { readonly source: string; readonly modelVer: string; readonly confidence: number; } /** * Prove a `MODEL` {@link FieldJson} carries its full receipt (source + modelVer + confidence), or * THROW — mirroring the engine's seam-side honesty gate ({@link ../frame/types.ts assertClaimHonest}) * on the reading side, because a `json` Rendering can be hand-built by a consumer and arrive * degraded. Returns the receipt so the badge renders it. Fail-closed: a `MODEL` value with no receipt * is never silently rendered as if honest. */ export function assertModelReceipt(field: FieldJson, label: string): FieldReceipt { if (field.attribution !== "MODEL") { throw new HonestChartError( `${label} is attributed ${field.attribution}, not MODEL — only a MODEL Field carries a receipt`, ); } const { source, modelVer, confidence } = field; if (typeof source !== "string" || source === "") { throw new HonestChartError(`MODEL ${label} is missing its \`source\` receipt`); } if (typeof modelVer !== "string" || modelVer === "") { throw new HonestChartError(`MODEL ${label} is missing its \`modelVer\` receipt`); } if (typeof confidence !== "number" || !Number.isFinite(confidence)) { throw new HonestChartError(`MODEL ${label} is missing a finite \`confidence\` receipt`); } return { source, modelVer, confidence }; }