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.

69 lines 5.24 kB
/** * # frame/seat — the pod SEAT roster: the closed `role` axis of the TemplateRecord cell key * (ADR-0041 §2, Amendment A1 / kestrel-wa0j.52) * * A **Seat** is a role in the pod org, fixed by the deliberation budget it can afford (CONTEXT.md * "Seat"): a PM allocates + discovers, a Strategist frames + authors, a Watcher manages + escalates. * ADR-0041 §2 makes `role` a first-class axis of the evidence cell key **because a pane's sign is * role-dependent** — a restraint pane can be passivity for the strategist (whose authored exit * already prices the fakeout) yet correct for the watcher managing a stop-less trap. Pooling grades * across seats is therefore ill-typed, and the roster is the schema of that phantom index. * * ## Why the roster is pinned NOW, closed, while the ledger is empty (kestrel-wa0j.52) * ADR-0041 §2 pins `instrumentClass` NOW on the argument that a cell-key axis VALUE added after the * first TemplateRecord is an evidence-splitting migration. Amendment A1 applies the SAME argument to * the `role` axis's VALUE ROSTER: the ledger currently writes `role ∈ {strategist, watcher}`, but the * PM-seat percepts (scan-fire read-why, the aggregates cockpit) are beaded, and if `pm` is added to * the roster after pm-cell grading starts under a workaround key, the evidence splits exactly the way * the ADR forbids. So the roster is pinned to the full seat set **`{pm, strategist, watcher}`** now, * CLOSED — opened only by ceremony — while it costs one enum value and zero migration. * * ## What is NOT a seat (the seat-vs-mechanism distinction, kestrel-wa0j.52 reconciliation) * `risk` is the **L0 layer**, not a seat — strictly subtractive (clamps/vetoes, never opens risk), * its rendered surface the kernel safety block; a `riskmgr` persona is a Brief style on a seat, not a * seat. `Trigger` is a non-LLM reflex TIER with no judgment cells to grade. `Historian` works * off-tape on the policy (Brief) channel, not perception. `risk` stays a ceremony-addable VALUE if an * auditing/reading agent seat is ever earned — adding a value later does not split evidence (old * records stay keyed; a new value opens new cells by ceremony), which is exactly why only the AXIS * (not each value) had to be pinned pre-ledger, and the seat roster is pinned to what shipped doctrine * names today. * * ## Distinct from the cost-tier `Tier` ({@link ../session/harness/roster.ts}) * `harness/roster.ts` has its own `Tier = "strategist" | "watcher"` — the **serving-lane cost tier** * (few-expensive-turns vs the large zero-cash fan-out). That is a DIFFERENT concept from this pod * SEAT: the values overlap but the axes do not. This module owns the pod-org role axis; nothing here * imports the cost tier and nothing there should import this. */ /** * The closed pod-seat roster — the `role` axis of the TemplateRecord cell key (ADR-0041 §2 / A1). * CLOSED at any instant; opened only by ceremony (a later `risk` reading-seat would be added HERE, * with its own cells + matched sets). This array is the ONE source; {@link SeatId} is its element type * and {@link isSeatId} its runtime guard, so the type and the runtime roster can never drift. */ export declare const SEAT_IDS: readonly ["pm", "strategist", "watcher"]; /** A pod seat — the closed `role` axis of the evidence cell key (ADR-0041 §2, Amendment A1). */ export type SeatId = (typeof SEAT_IDS)[number]; /** Runtime membership in the closed {@link SEAT_IDS} roster. Fail-closed callers use this to REFUSE an * unknown role rather than coerce it (the ledger keys on the role — an unknown value must never be * silently admitted into a cell, ADR-0041 §2 no-coercion). Pure. */ export declare function isSeatId(value: unknown): value is SeatId; /** * The **founder-View opt-in policy** — the config axis that decides whether a driver consults a seat's * founder View at all (ADR-0041 §2 / A1, kestrel-wa0j.26). Founder Views are graded SEEDS, never * blessed defaults, so they are OFF unless a config OPTS IN: * - `phase-default` — the frame kind's default panes (byte-identical to before the role axis); the * driver passes NO seat, so `resolveView` never reaches the founder branch. This is the default. * - `founder` — the driver passes the acting tier's seat into `resolveView`, so a seat with a * founder seed for the frame reads it (a DIFFERENT experimental subject → a distinct ConfigId). * * A `founder` run is a distinct grid column BECAUSE the agent perceives different screens; it folds * into `deriveConfigId` automatically (like `clockHonest`/`cachePolicy`), never an a57.14 envelope * field. Absent on a config ⇒ `phase-default` semantics ⇒ that config's ConfigId is byte-identical to * before this axis existed (the drop-undefined canonicalizer). */ export type SeatViewsPolicy = "founder" | "phase-default"; /** Assert a value is a member of the closed seat roster, or THROW naming the roster (never a silent * default — the same fail-closed discipline the parser and the pane catalog carry). Returns the * value narrowed to {@link SeatId}. */ export declare function assertSeatId(value: unknown): SeatId; //# sourceMappingURL=seat.d.ts.map