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.

59 lines (58 loc) 3.88 kB
/** * # frame/founder-registry — the (seat × frameKind) → founder View mapping (ADR-0041 §2 / A1, kestrel-wa0j.26) * * A **founder View** is the graded SEED a pod seat reads at a given frame kind — a hypothesis entering * the ADR-0029 tournament, NEVER a blessed default (ADR-0041 §2: the null is that a pane HURTS until a * both-poles matched set says otherwise). This module is the small, semantic map from a {@link SeatId} * at a frame kind to the NAME of its founder View; the View DATA itself comes from * {@link ./founder-views.generated.ts FOUNDER_VIEWS} (parsed from the golden corpus source, never a * hand-duplicated pane list). Two layers, cleanly split: * - the **mapping** here is the seat-doctrine knowledge (which seat reads which named screen when); * - the **panes** are single-sourced from `tests/golden/accept/founder-seat-views.kestrel`. * * ## The seed mapping (docs/views/founder-seat-views.md) * - `strategist` at `OPEN` → `strategist-open` — the frontier framer orients at the open. * - `watcher` at `WAKE` → `watcher-wake` — the fast reflex reads WHAT MOVED (delta leads). * - `pm` at `WAKE` → `scan-fire` — the PM's discovery half reads one name deep on a scan. * * Both `watcher-wake` and `scan-fire` are WAKE-kind Views distinguished by SEAT, not frame kind — which * is exactly why the cell key carries a role axis (a pane's sign is role-dependent, ADR-0041 §2). * * ## Honest absence (never a silent default) * An (seat × frameKind) pair with no founder seed — a strategist at WAKE, a watcher at OPEN, a PM at * OPEN — resolves to `undefined` HERE, and {@link ./pane-catalog.ts resolveView} falls through to the * phase default for it. Absence is a first-class value (ADR-0041 §3 absent-not-hidden), never a * fabricated seed. This is a pure lookup — no clock, no RNG, fail-closed on an unknown View name. */ import { FOUNDER_VIEWS } from "./founder-views.generated.js"; /** The seed mapping: `${seat}/${frameKind}` → the founder View NAME. An absent key = honest absence * (falls through to the phase default at resolution). The View DATA is looked up in * {@link FOUNDER_VIEWS} — this table holds only names, so it can never duplicate a pane list. */ const FOUNDER_VIEW_NAME_BY_SEAT_FRAME = { "strategist/OPEN": "strategist-open", "watcher/WAKE": "watcher-wake", "pm/WAKE": "scan-fire", }; /** * The founder {@link ViewSelection} a seat reads at a frame kind, or `undefined` when the seat has no * founder seed for that frame (honest absence → the caller falls through to the phase default). Pure. * * FAIL-CLOSED: a mapping that names a View absent from the generated {@link FOUNDER_VIEWS} throws * rather than returning `undefined` — that is a generator/mapping drift (a founder View was renamed or * dropped from the golden without updating this table), not honest absence, and it must never be * silently swallowed into a phase-default fallback. */ export function founderViewFor(seat, frameKind) { const name = FOUNDER_VIEW_NAME_BY_SEAT_FRAME[`${seat}/${frameKind}`]; if (name === undefined) return undefined; // honest absence — no founder seed for this (seat × frameKind) const view = FOUNDER_VIEWS[name]; if (view === undefined) { throw new Error(`founder registry maps ${seat}/${frameKind} → "${name}", but that View is absent from the generated FOUNDER_VIEWS ` + `(regenerate: bun scripts/gen-founder-view-registry.ts). This is registry/golden drift, never honest absence.`); } return view; } /** The full set of (seat × frameKind) pairs that carry a founder seed — the mapping's key set, exposed * so tests (and any census) enumerate the seeds without re-hardcoding them. */ export const FOUNDER_SEED_KEYS = Object.keys(FOUNDER_VIEW_NAME_BY_SEAT_FRAME);