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.
783 lines (722 loc) • 31 kB
text/typescript
/**
* # protocol/oversight-wire — the SNAKE_CASE wire mirror of the oversight contract (kestrel-telx.5).
*
* The oversight stream (contract §4) is served over the SAME platform HTTP/SSE dialect the
* Operation stream is: **snake_case bodies**, an **opaque STRING cursor**, a **closed `event:`
* enum**. `src/protocol/oversight.ts` is the camelCase DOMAIN contract both Renderings consume;
* this leaf is its wire face, decoded to the domain types AT THE BOUNDARY (contract §4.4). It is
* re-exported by {@link ./wire.ts} — the one import path the CLI transport
* ({@link ../cli/backend/wire.ts}) already re-exports — so there is exactly ONE definition of the
* oversight wire shapes and exactly ONE definition of the SSE vocabulary (the enum itself stays in
* `oversight.ts`; nothing here re-declares it). It lives in its own file only because it is long;
* every consumer reaches it through `wire.ts`, per the bead.
*
* ## FAIL CLOSED — a decoder is a GATE, not a cast
* Every decoder below reads `unknown` and CHECKS each required field, throwing
* {@link OversightWireError} naming the exact path. A missing / mistyped field is a loud protocol
* violation, never `undefined` smuggled into a domain type and never a silent default. Nullable
* contract fields (`fair`, `plan`, `note`, …) are decoded as EXPLICIT `null` — absent-not-hidden —
* and a `null` where the contract requires a value still reds.
*
* ## ZERO runtime dependencies (OSS-ADR-0046 + tests/protocol.boundary.test.ts)
* The only imports are intra-protocol. In particular this leaf holds NO CLI error type: it throws
* its own dependency-free {@link OversightWireError}, which the CLI client
* ({@link ../cli/backend/oversight-remote.ts}) wraps into a `CliError` with code
* `OVERSIGHT_PROTOCOL_VIOLATION` (contract §4.3 rule 1/2). Same discipline as
* {@link ../client/sse-transport.ts}: the transport/decoder layer is error-agnostic, the caller owns
* the error TAXONOMY.
*
* ## NOT in the shipped JSON Schema (slice-1 posture)
* `scripts/gen-wire-schema.ts` reflects an explicit root list (`WIRE_COMPOSITES`, the ten slice-1
* RESPONSE composites). The oversight shapes are deliberately NOT added to it: the platform route
* (§4.1) does not exist yet, and shipping a schema for a route nobody serves would be a gate whose
* stated coverage exceeds its actual coverage. Adding them is a one-line follow-up when the route
* lands.
*/
import type {
AgentTier,
AgentTierStatus,
Attribution,
AuthorTier,
Authorship,
BookView,
Caller,
CallerDetection,
CallerKind,
EngineActionKind,
EscalationReason,
KernelBrief,
KernelBudget,
KernelClaim,
KernelEngineAction,
KernelField,
KernelFill,
KernelLeg,
KernelMandate,
KernelOwnerAct,
KernelPlanState,
KernelPosition,
KernelRestingOrder,
KernelVehicleHealth,
KernelWake,
MessageAuthor,
Mode,
OrgNode,
OversightAct,
OversightActRecord,
OversightDelivery,
OversightEscalation,
OversightEvent,
OversightEventType,
OversightFrame,
OversightIdentity,
OversightKernel,
OversightMessage,
OversightTurn,
PlanLifecycle,
PlanOutcome,
PodView,
RiskEnvelope,
SpectatorFrame,
SpectatorPane,
TurnDisposition,
WakeSeverity,
} from "./oversight.ts";
import {
AGENT_TIERS,
ATTRIBUTIONS,
AUTHOR_TIERS,
CALLER_DETECTIONS,
CALLER_KINDS,
ENGINE_ACTION_KINDS,
ESCALATION_REASONS,
MESSAGE_AUTHORS,
MODES,
OVERSIGHT_ACT_KINDS,
PLAN_LIFECYCLES,
PLAN_OUTCOMES,
TURN_DISPOSITIONS,
WAKE_SEVERITIES,
} from "./oversight.ts";
import type { Scope } from "./index.ts";
import type { FailureClass, OperationId, SessionDiagnostic, SessionId, TurnBody, TurnEntry } from "./session.ts";
import { FAILURE_CLASSES, SESSION_DIAGNOSTICS } from "./session.ts";
/* ─────────────────────────── the fail-closed reader ─────────────────────────── */
/** A wire body that does not match the contract. Dependency-free on purpose: the CLI wraps it as a
* `CliError{code:"OVERSIGHT_PROTOCOL_VIOLATION"}`, the SDK could wrap it as its own. */
export class OversightWireError extends Error {
constructor(
readonly path: string,
detail: string,
) {
super(`oversight wire: ${path} — ${detail}`);
this.name = "OversightWireError";
}
}
type Rec = Record<string, unknown>;
function kindOf(v: unknown): string {
if (v === null) return "null";
if (Array.isArray(v)) return "array";
return typeof v;
}
/** Narrow `v` to a plain object or fail closed. */
function obj(v: unknown, path: string): Rec {
if (typeof v !== "object" || v === null || Array.isArray(v)) {
throw new OversightWireError(path, `expected an object, got ${kindOf(v)}`);
}
return v as Rec;
}
function str(o: Rec, k: string, path: string): string {
const v = o[k];
if (typeof v !== "string") throw new OversightWireError(`${path}.${k}`, `expected string, got ${kindOf(v)}`);
return v;
}
function num(o: Rec, k: string, path: string): number {
const v = o[k];
if (typeof v !== "number" || !Number.isFinite(v)) {
throw new OversightWireError(`${path}.${k}`, `expected a finite number, got ${kindOf(v)}`);
}
return v;
}
function bool(o: Rec, k: string, path: string): boolean {
const v = o[k];
if (typeof v !== "boolean") throw new OversightWireError(`${path}.${k}`, `expected boolean, got ${kindOf(v)}`);
return v;
}
/** A REQUIRED nullable field: present and either the value or an explicit `null` (absent-not-hidden
* — a DROPPED key still reds; only an explicit `null` reads as UNKNOWN). */
function nullable<T>(read: (o: Rec, k: string, path: string) => T) {
return (o: Rec, k: string, path: string): T | null => {
if (!(k in o)) throw new OversightWireError(`${path}.${k}`, "required (nullable) field is absent — absent-not-hidden");
return o[k] === null ? null : read(o, k, path);
};
}
const nullStr = nullable(str);
const nullNum = nullable(num);
/** An OPTIONAL field: absent ⇒ `undefined`; present ⇒ type-checked. */
function optional<T>(read: (o: Rec, k: string, path: string) => T) {
return (o: Rec, k: string, path: string): T | undefined =>
o[k] === undefined ? undefined : read(o, k, path);
}
/** A closed vocabulary member, checked against its runtime tuple — the wire can never smuggle an
* off-enum member in as a bare string. */
function member<T extends string>(tuple: readonly T[]) {
return (o: Rec, k: string, path: string): T => {
const v = str(o, k, path);
if (!(tuple as readonly string[]).includes(v)) {
throw new OversightWireError(`${path}.${k}`, `${JSON.stringify(v)} is outside the closed vocabulary [${tuple.join(", ")}]`);
}
return v as T;
};
}
function list<T>(o: Rec, k: string, path: string, each: (v: unknown, path: string) => T): readonly T[] {
const v = o[k];
if (!Array.isArray(v)) throw new OversightWireError(`${path}.${k}`, `expected array, got ${kindOf(v)}`);
return v.map((item, i) => each(item, `${path}.${k}[${i}]`));
}
function strList(o: Rec, k: string, path: string): readonly string[] {
return list(o, k, path, (v, p) => {
if (typeof v !== "string") throw new OversightWireError(p, `expected string, got ${kindOf(v)}`);
return v;
});
}
/** A REQUIRED nullable SUB-OBJECT decoded by `dec`. */
function nullObj<T>(o: Rec, k: string, path: string, dec: (v: unknown, path: string) => T): T | null {
if (!(k in o)) throw new OversightWireError(`${path}.${k}`, "required (nullable) section is absent — absent-not-hidden");
return o[k] === null ? null : dec(o[k], `${path}.${k}`);
}
const callerKind = member<CallerKind>(CALLER_KINDS);
const callerDetection = member<CallerDetection>(CALLER_DETECTIONS);
const mode = member<Mode>(MODES);
const attribution = member<Attribution>(ATTRIBUTIONS);
const planLifecycle = member<PlanLifecycle>(PLAN_LIFECYCLES);
const planOutcome = member<PlanOutcome>(PLAN_OUTCOMES);
const wakeSeverity = member<WakeSeverity>(WAKE_SEVERITIES);
const engineActionKind = member<EngineActionKind>(ENGINE_ACTION_KINDS);
const agentTier = member<AgentTier>(AGENT_TIERS);
const authorTier = member<AuthorTier>(AUTHOR_TIERS);
const escalationReason = member<EscalationReason>(ESCALATION_REASONS);
const messageAuthor = member<MessageAuthor>(MESSAGE_AUTHORS);
const turnDisposition = member<TurnDisposition>(TURN_DISPOSITIONS);
const actKind = member(OVERSIGHT_ACT_KINDS);
const failureClass = member<FailureClass>(FAILURE_CLASSES);
const sessionDiagnostic = member<SessionDiagnostic>(SESSION_DIAGNOSTICS);
const side = member<"buy" | "sell">(["buy", "sell"]);
/* ────────────────────────────── identity (§3.1) ────────────────────────────── */
export function decodeCaller(v: unknown, path = "caller"): Caller {
const o = obj(v, path);
return {
kind: callerKind(o, "kind", path),
harness: nullStr(o, "harness", path),
detectedBy: callerDetection(o, "detected_by", path),
interactive: bool(o, "interactive", path),
};
}
export function decodeOversightIdentity(v: unknown, path = "identity"): OversightIdentity {
const o = obj(v, path);
const operation = optional(str)(o, "operation", path);
return {
caller: decodeCaller(o["caller"], `${path}.caller`),
sessionId: str(o, "session_id", path) as SessionId,
...(operation !== undefined ? { operation: operation as OperationId } : {}),
mode: mode(o, "mode", path),
// `Scope` is the platform's capability vocabulary, already pinned by the Operation dialect;
// it rides through as its string members (no oversight-local re-declaration).
scopes: strList(o, "scopes", path) as readonly Scope[],
};
}
/* ────────────────────────────── the kernel (§3.2) ──────────────────────────── */
export function decodeKernelField(v: unknown, path: string): KernelField {
const o = obj(v, path);
const source = optional(str)(o, "source", path);
const modelVer = optional(str)(o, "model_ver", path);
const confidence = optional(num)(o, "confidence", path);
const asOfSeq = optional(num)(o, "as_of_seq", path);
return {
value: num(o, "value", path),
attribution: attribution(o, "attribution", path),
...(source !== undefined ? { source } : {}),
...(modelVer !== undefined ? { modelVer } : {}),
...(confidence !== undefined ? { confidence } : {}),
...(asOfSeq !== undefined ? { asOfSeq } : {}),
};
}
export function decodeKernelLeg(v: unknown, path: string): KernelLeg {
const o = obj(v, path);
const strike = optional(num)(o, "strike", path);
const right = optional(member<"C" | "P">(["C", "P"]))(o, "right", path);
// ADR-0017: strike and right are BOTH present (an option) or BOTH absent (spot). A half-populated
// leg would render a fictional strike — refuse it.
if ((strike === undefined) !== (right === undefined)) {
throw new OversightWireError(path, "strike and right must be BOTH present (option) or BOTH absent (spot) — ADR-0017");
}
return {
symbol: str(o, "symbol", path),
...(strike !== undefined ? { strike } : {}),
...(right !== undefined ? { right } : {}),
};
}
export function decodeKernelPosition(v: unknown, path: string): KernelPosition {
const o = obj(v, path);
return {
leg: decodeKernelLeg(o["leg"], `${path}.leg`),
qty: num(o, "qty", path),
basis: num(o, "basis", path),
fair: nullNum(o, "fair", path),
unrealUsd: nullNum(o, "unreal_usd", path),
plan: nullStr(o, "plan", path),
claimOwner: nullStr(o, "claim_owner", path),
structure: nullStr(o, "structure", path),
};
}
export function decodeKernelRestingOrder(v: unknown, path: string): KernelRestingOrder {
const o = obj(v, path);
return {
ref: str(o, "ref", path),
leg: decodeKernelLeg(o["leg"], `${path}.leg`),
side: side(o, "side", path),
qty: num(o, "qty", path),
px: num(o, "px", path),
live: bool(o, "live", path),
clamped: bool(o, "clamped", path),
note: nullStr(o, "note", path),
plan: nullStr(o, "plan", path),
};
}
export function decodeKernelFill(v: unknown, path: string): KernelFill {
const o = obj(v, path);
return {
leg: decodeKernelLeg(o["leg"], `${path}.leg`),
side: side(o, "side", path),
qty: num(o, "qty", path),
px: num(o, "px", path),
plan: nullStr(o, "plan", path),
};
}
export function decodeKernelPlanState(v: unknown, path: string): KernelPlanState {
const o = obj(v, path);
return {
name: str(o, "name", path),
state: planLifecycle(o, "state", path),
outcome: "outcome" in o && o["outcome"] === null ? null : planOutcome(o, "outcome", path),
note: nullStr(o, "note", path),
blockedReason: nullStr(o, "blocked_reason", path),
};
}
export function decodeRiskEnvelope(v: unknown, path: string): RiskEnvelope {
const o = obj(v, path);
return {
remainingR: num(o, "remaining_r", path),
planEnvelope: num(o, "plan_envelope", path),
bookEnvelope: num(o, "book_envelope", path),
ownerEnvelope: num(o, "owner_envelope", path),
};
}
export function decodeKernelBudget(v: unknown, path: string): KernelBudget {
const o = obj(v, path);
return {
used: nullNum(o, "used", path),
remaining: nullNum(o, "remaining", path),
total: nullNum(o, "total", path),
maxConcurrentR: nullNum(o, "max_concurrent_r", path),
};
}
export function decodeKernelWake(v: unknown, path: string): KernelWake {
const o = obj(v, path);
return {
reason: str(o, "reason", path),
severity: wakeSeverity(o, "severity", path),
deadlineMin: nullNum(o, "deadline_min", path),
};
}
export function decodeKernelVehicleHealth(v: unknown, path: string): KernelVehicleHealth {
const o = obj(v, path);
return {
symbol: str(o, "symbol", path),
bidPresentRate: num(o, "bid_present_rate", path),
twoSided: bool(o, "two_sided", path),
staleS: num(o, "stale_s", path),
dark: bool(o, "dark", path),
};
}
export function decodeKernelEngineAction(v: unknown, path: string): KernelEngineAction {
const o = obj(v, path);
return {
id: str(o, "id", path),
kind: engineActionKind(o, "kind", path),
asofSeq: num(o, "asof_seq", path),
reason: nullStr(o, "reason", path),
};
}
export function decodeKernelOwnerAct(v: unknown, path: string): KernelOwnerAct {
const o = obj(v, path);
return { id: str(o, "id", path), kind: str(o, "kind", path), asofSeq: num(o, "asof_seq", path) };
}
export function decodeKernelClaim(v: unknown, path: string): KernelClaim {
const o = obj(v, path);
return {
field: decodeKernelField(o["field"], `${path}.field`),
claimType: member<"predictor" | "regime">(["predictor", "regime"])(o, "claim_type", path),
};
}
export function decodeKernelMandate(v: unknown, path: string): KernelMandate {
const o = obj(v, path);
return {
objective: str(o, "objective", path),
rUsd: num(o, "r_usd", path),
successCriterion: str(o, "success_criterion", path),
riskRule: str(o, "risk_rule", path),
};
}
export function decodeKernelBrief(v: unknown, path: string): KernelBrief {
const o = obj(v, path);
return { text: str(o, "text", path), hash: str(o, "hash", path), version: nullStr(o, "version", path) };
}
/** The acting kernel. EVERY section is required on the wire (absent-not-hidden, §3.2): an absent
* source section arrives as an explicit `null`/`[]`, never as a dropped key. */
export function decodeOversightKernel(v: unknown, path = "kernel"): OversightKernel {
const o = obj(v, path);
return {
mandate: nullObj(o, "mandate", path, decodeKernelMandate),
brief: nullObj(o, "brief", path, decodeKernelBrief),
wake: nullObj(o, "wake", path, decodeKernelWake),
dataHealth: list(o, "data_health", path, decodeKernelVehicleHealth),
unavailable: strList(o, "unavailable", path),
budgetEnvelope: nullObj(o, "budget_envelope", path, decodeRiskEnvelope),
ownerActs: list(o, "owner_acts", path, decodeKernelOwnerAct),
engineLog: list(o, "engine_log", path, decodeKernelEngineAction),
claims: list(o, "claims", path, decodeKernelClaim),
positions: list(o, "positions", path, decodeKernelPosition),
resting: list(o, "resting", path, decodeKernelRestingOrder),
fillsSinceLast: list(o, "fills_since_last", path, decodeKernelFill),
budget: nullObj(o, "budget", path, decodeKernelBudget),
plans: list(o, "plans", path, decodeKernelPlanState),
};
}
/* ─────────────────────────────── the org (§3.3) ────────────────────────────── */
export function decodeAuthorship(v: unknown, path: string): Authorship {
const o = obj(v, path);
return {
tier: authorTier(o, "tier", path),
model: nullStr(o, "model", path),
version: nullStr(o, "version", path),
};
}
export function decodeAgentTierStatus(v: unknown, path: string): AgentTierStatus {
const o = obj(v, path);
const s = obj(o["strategist"], `${path}.strategist`);
const w = obj(o["watcher"], `${path}.watcher`);
const e = obj(o["escalation"], `${path}.escalation`);
return {
strategist: {
model: nullStr(s, "model", `${path}.strategist`),
thesis: nullStr(s, "thesis", `${path}.strategist`),
briefHash: nullStr(s, "brief_hash", `${path}.strategist`),
lastReframeSeq: nullNum(s, "last_reframe_seq", `${path}.strategist`),
},
watcher: {
model: nullStr(w, "model", `${path}.watcher`),
lastActionSeq: nullNum(w, "last_action_seq", `${path}.watcher`),
},
escalation: {
pending: bool(e, "pending", `${path}.escalation`),
reason: "reason" in e && e["reason"] === null ? null : escalationReason(e, "reason", `${path}.escalation`),
atSeq: nullNum(e, "at_seq", `${path}.escalation`),
},
configId: nullStr(o, "config_id", path),
};
}
export function decodeBookView(v: unknown, path: string): BookView {
const o = obj(v, path);
const cov = obj(o["coverage"], `${path}.coverage`);
const st = obj(o["status"], `${path}.status`);
return {
bookId: str(o, "book_id", path),
coverage: {
symbols: strList(cov, "symbols", `${path}.coverage`),
thesis: str(cov, "thesis", `${path}.coverage`),
},
kernel: decodeOversightKernel(o["kernel"], `${path}.kernel`),
tiers: decodeAgentTierStatus(o["tiers"], `${path}.tiers`),
status: {
severity: wakeSeverity(st, "severity", `${path}.status`),
deadlineMin: nullNum(st, "deadline_min", `${path}.status`),
wakesRemaining: nullNum(st, "wakes_remaining", `${path}.status`),
coalesced: num(st, "coalesced", `${path}.status`),
},
};
}
export function decodePodView(v: unknown, path: string): PodView {
const o = obj(v, path);
const aggRaw = obj(o["aggregate"], `${path}.aggregate`);
const aggregate: Record<string, Record<string, number>> = {};
for (const [childId, facts] of Object.entries(aggRaw)) {
const f = obj(facts, `${path}.aggregate.${childId}`);
const inner: Record<string, number> = {};
for (const key of Object.keys(f)) inner[key] = num(f, key, `${path}.aggregate.${childId}`);
aggregate[childId] = inner;
}
return {
podId: str(o, "pod_id", path),
envelope: decodeRiskEnvelope(o["envelope"], `${path}.envelope`),
aggregate,
children: list(o, "children", path, decodeOrgNode),
};
}
export function decodeOrgNode(v: unknown, path: string): OrgNode {
const o = obj(v, path);
const node = member<"book" | "pod">(["book", "pod"])(o, "node", path);
return node === "book"
? { node: "book", book: decodeBookView(o["book"], `${path}.book`) }
: { node: "pod", pod: decodePodView(o["pod"], `${path}.pod`) };
}
/* ──────────────────────────── the Frame (§3.4, §4.2) ───────────────────────── */
export function decodeSpectatorPane(v: unknown, path: string): SpectatorPane {
const o = obj(v, path);
return {
paneId: str(o, "pane_id", path),
columns: strList(o, "columns", path),
rows: list(o, "rows", path, (row, rp) => {
if (!Array.isArray(row)) throw new OversightWireError(rp, `expected a row array, got ${kindOf(row)}`);
return row.map((cell, i) => {
if (cell === null || typeof cell === "string" || (typeof cell === "number" && Number.isFinite(cell))) {
return cell as string | number | null;
}
throw new OversightWireError(`${rp}[${i}]`, `expected a scalar cell (string | finite number | null), got ${kindOf(cell)}`);
});
}),
};
}
export function decodeSpectatorFrame(v: unknown, path: string): SpectatorFrame {
const o = obj(v, path);
return {
watchlist: strList(o, "watchlist", path),
// The ONE permitted wall clock in this contract (§4 invariant 4) — spectator only.
asof: str(o, "asof", path),
panes: list(o, "panes", path, decodeSpectatorPane),
};
}
export function decodeOversightMessage(v: unknown, path: string): OversightMessage {
const o = obj(v, path);
return {
seq: num(o, "seq", path),
messageId: str(o, "message_id", path),
author: messageAuthor(o, "author", path),
to: nullStr(o, "to", path),
text: str(o, "text", path),
};
}
export function decodeOversightFrame(v: unknown, path = "frame"): OversightFrame {
const o = obj(v, path);
return {
identity: decodeOversightIdentity(o["identity"], `${path}.identity`),
asofSeq: num(o, "asof_seq", path),
pod: nullObj(o, "pod", path, decodePodView),
spectator: nullObj(o, "spectator", path, decodeSpectatorFrame),
pending: nullObj(o, "pending", path, decodeOversightDelivery),
messages: list(o, "messages", path, decodeOversightMessage),
};
}
/* ─────────────────────────── the turn-stream (§3.5) ────────────────────────── */
export function decodeOversightDelivery(v: unknown, path = "delivery"): OversightDelivery {
const o = obj(v, path);
return {
sessionId: str(o, "session_id", path) as SessionId,
ordinal: num(o, "ordinal", path),
parentHash: str(o, "parent_hash", path),
// The RUNTIME's Frame address, carried verbatim — a Rendering never re-hashes the projection.
frameRoot: str(o, "frame_root", path),
bookId: str(o, "book_id", path),
tier: agentTier(o, "tier", path),
kernel: decodeOversightKernel(o["kernel"], `${path}.kernel`),
};
}
export function decodeTurnBody(v: unknown, path: string): TurnBody {
const o = obj(v, path);
const kind = member<"authored" | "stand-down" | "failure">(["authored", "stand-down", "failure"])(o, "kind", path);
switch (kind) {
case "authored":
return { kind, bytes: str(o, "bytes", path) };
case "stand-down":
return { kind, reason: str(o, "reason", path) };
case "failure":
return { kind, failureClass: failureClass(o, "failure_class", path) };
}
}
export function decodeTurnEntry(v: unknown, path: string): TurnEntry {
const o = obj(v, path);
if (o["kind"] !== "turn") throw new OversightWireError(`${path}.kind`, `expected "turn", got ${JSON.stringify(o["kind"])}`);
return {
kind: "turn",
sessionId: str(o, "session_id", path) as SessionId,
ordinal: num(o, "ordinal", path),
parentHash: str(o, "parent_hash", path),
frameRoot: str(o, "frame_root", path),
authoredSha256: str(o, "authored_sha256", path),
body: decodeTurnBody(o["body"], `${path}.body`),
entryHash: str(o, "entry_hash", path),
};
}
export function decodeOversightTurn(v: unknown, path = "turn"): OversightTurn {
const o = obj(v, path);
return {
entry: decodeTurnEntry(o["entry"], `${path}.entry`),
disposition: turnDisposition(o, "disposition", path),
authoredBy: decodeAuthorship(o["authored_by"], `${path}.authored_by`),
escalated: "escalated" in o && o["escalated"] === null ? null : escalationReason(o, "escalated", path),
};
}
export function decodeOversightEscalation(v: unknown, path = "escalation"): OversightEscalation {
const o = obj(v, path);
return {
seq: num(o, "seq", path),
bookId: str(o, "book_id", path),
// NB: dot-access `o.from`, never the bracket-quoted form — the protocol.boundary import
// scanner regex reads a quoted key of that name as an ES import specifier and false-positives.
from: decodeAuthorship(o.from, `${path}.from`),
to: authorTier(o, "to", path),
reason: escalationReason(o, "reason", path),
note: nullStr(o, "note", path),
answeredBySeq: nullNum(o, "answered_by_seq", path),
};
}
/* ──────────────────────────────── acts (§3.6) ──────────────────────────────── */
export function decodeOversightAct(v: unknown, path = "act"): OversightAct {
const o = obj(v, path);
const act = actKind(o, "act", path);
switch (act) {
case "allocate":
return { act, target: str(o, "target", path), envelopeR: num(o, "envelope_r", path) };
case "arm":
return { act, target: str(o, "target", path) };
case "de-arm":
return { act, target: str(o, "target", path), reason: str(o, "reason", path) };
case "coverage":
return {
act,
bookId: str(o, "book_id", path),
symbols: strList(o, "symbols", path),
thesis: str(o, "thesis", path), // REQUIRED: instruments alone are not coverage
};
case "fund":
return { act, ownerEnvelope: num(o, "owner_envelope", path), authorizationRef: str(o, "authorization_ref", path) };
case "de-fund":
return { act, ownerEnvelope: num(o, "owner_envelope", path) };
case "pause":
return { act, target: str(o, "target", path) };
case "veto":
return { act, target: str(o, "target", path), reason: str(o, "reason", path) };
}
}
export function decodeOversightActRecord(v: unknown, path = "record"): OversightActRecord {
const o = obj(v, path);
return {
seq: num(o, "seq", path),
actId: str(o, "act_id", path),
act: decodeOversightAct(o["act"], `${path}.act`),
authoredBy: decodeAuthorship(o["authored_by"], `${path}.authored_by`),
};
}
/* ───────────────────────────── the SSE envelope (§4) ───────────────────────── */
/**
* The oversight SSE frame's JSON `data:` payload — the mirror of {@link ./wire.ts WireOperationEvent}.
* `cursor` echoes the SSE `id:` line (an OPAQUE STRING — §4.3 rule 6: never parsed), `type` is the
* closed enum from `oversight.ts` (ONE definition — this shape re-declares nothing), and the
* type-specific body rides in `data` as snake_case.
*/
export interface WireOversightEvent {
readonly cursor: string;
readonly type: OversightEventType;
readonly session_id: string;
readonly data?: Record<string, unknown>;
}
/**
* Decode ONE typed oversight event body into the camelCase domain union (contract §4.2 table).
*
* `type` MUST already have been admitted against `isOversightEventType` (§4.3 rule 1 — the
* transport's closed-vocabulary gate); this decoder is TOTAL over the enum, so a member added to
* the enum without a case here is a compile error (the `never` exhaustiveness arm), not a silent
* pass-through.
*/
export function decodeOversightEvent(type: OversightEventType, data: unknown): OversightEvent {
const path = type;
switch (type) {
case "oversight.snapshot":
return { type, frame: decodeOversightFrame(obj(data, path)["frame"], `${path}.frame`) };
case "oversight.delivery": {
const o = obj(data, path);
return { type, seq: num(o, "seq", path), delivery: decodeOversightDelivery(o["delivery"], `${path}.delivery`) };
}
case "oversight.turn": {
const o = obj(data, path);
return { type, seq: num(o, "seq", path), turn: decodeOversightTurn(o["turn"], `${path}.turn`) };
}
case "oversight.act":
return { type, record: decodeOversightActRecord(obj(data, path)["record"], `${path}.record`) };
case "oversight.escalation":
return { type, escalation: decodeOversightEscalation(obj(data, path)["escalation"], `${path}.escalation`) };
case "oversight.message":
return { type, message: decodeOversightMessage(obj(data, path)["message"], `${path}.message`) };
case "oversight.journal": {
const o = obj(data, path);
return {
type,
seq: num(o, "seq", path),
bookId: str(o, "book_id", path),
authoredBy: decodeAuthorship(o["authored_by"], `${path}.authored_by`),
text: str(o, "text", path),
};
}
case "oversight.diagnostic": {
const o = obj(data, path);
return { type, diagnostic: sessionDiagnostic(o, "diagnostic", path), ordinal: num(o, "ordinal", path) };
}
case "oversight.finalized": {
const o = obj(data, path);
return {
type,
seq: num(o, "seq", path),
sessionId: str(o, "session_id", path) as SessionId,
tipHash: str(o, "tip_hash", path),
artifacts: strList(o, "artifacts", path),
};
}
case "oversight.failed":
return { type, reason: str(obj(data, path), "reason", path) };
default: {
// fail closed: an enum member with no decoder is a protocol drift, never a silent default.
const never: never = type;
throw new OversightWireError("type", `no decoder for ${JSON.stringify(never)}`);
}
}
}
/**
* The BUS-BACKED `seq` of a decoded event, or `null` for the two members that carry none
* (`oversight.snapshot` — a projection; `oversight.diagnostic` — nothing landed; `oversight.failed`
* — the stream is dying). This is the input to §4.3 rule 4 (monotone seq): the rule can only apply
* where the contract says a `seq` exists, so the extraction lives HERE, beside the shapes, rather
* than being re-derived by each client.
*/
export function busSeqOf(e: OversightEvent): number | null {
switch (e.type) {
case "oversight.delivery":
case "oversight.turn":
case "oversight.journal":
case "oversight.finalized":
return e.seq;
case "oversight.act":
return e.record.seq;
case "oversight.escalation":
return e.escalation.seq;
case "oversight.message":
return e.message.seq;
case "oversight.snapshot":
case "oversight.diagnostic":
case "oversight.failed":
return null;
default: {
const never: never = e;
throw new OversightWireError("event", `unhandled event ${JSON.stringify(never)}`);
}
}
}