import { Refusal } from '@things-factory/shell' /* * **A twin model the kernel refuses is said by name** (ADR-0054). * * ── What went wrong (2026-10-10) ───────────────────────────────────────────── * The MES kernel refuses a model without a production declaration. The engine let that error through * as it was, so `twinReplay(miratek)` reached the screen as INTERNAL_SERVER_ERROR with the kernel's * English sentence in the shell's notice. The model was what was wrong, not the server. * * ── The rule ───────────────────────────────────────────────────────────────── * The kernel names its refusals: an error that carries a string `code` and an object `params`. The * kernel cannot reach the shell, so the host turns that into a shell `Refusal` here, adding which twin * it was. The sentence is made where the reader's language is known (`SpeakRefusals`, or the import * result's `refusal()`), under `error.`. Anything without a name passes through untouched. */ export function asModelRefusal(error: unknown, instanceId: string): unknown { if (error instanceof Refusal) return error const e = error as { code?: unknown; params?: unknown; message?: unknown } | null if (!e || typeof e.code !== 'string' || !e.code || !e.params || typeof e.params !== 'object') return error return new Refusal(e.code, { ...(e.params as Record), instanceId }, String(e.message ?? e.code)) } /** Run a step that loads or replays a model; a kernel refusal comes out as a `Refusal`. */ export function refusingModel(instanceId: string, step: () => T): T { try { return step() } catch (error) { throw asModelRefusal(error, instanceId) } }