@almadar/core 10.101.0 → 10.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/expression.ts","../src/types/identity.ts","../src/types/json.ts","../src/types/field.ts","../src/types/asset.ts","../src/types/entity.ts","../src/types/effect.ts","../src/types/user.ts","../src/types/effect-result.ts","../src/types/bus.ts","../src/fixtures.ts"],"names":["z"],"mappings":"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","file":"fixtures.js","sourcesContent":["/**\n * S-Expression Types\n *\n * Defines the S-Expression type system for guards, effects, and computed values.\n * S-expressions are JSON arrays where the first element is an operator string.\n *\n * @example\n * // Guard: health > 0\n * [\">\", \"@entity.health\", 0]\n *\n * // Effect: set x to x + vx\n * [\"set\", \"@entity.x\", [\"+\", \"@entity.x\", \"@entity.vx\"]]\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport type { RuntimeValue } from './json.js';\n\n// ============================================================================\n// S-Expression Type\n// ============================================================================\n\n/**\n * S-Expression type - recursive structure representing expressions.\n *\n * An S-expression is either:\n * - A literal value (string, number, boolean, null)\n * - An object literal (for payload data, props, etc.)\n * - A binding reference (string starting with @)\n * - A call expression (array with operator as first element)\n */\n/** Object literal branch of an S-expression atom (payload data, props, etc.). */\nexport interface SExprObject {\n [key: string]: SExpr;\n}\nexport type SExprAtom = string | number | boolean | null | SExprObject;\nexport type SExpr = SExprAtom | SExpr[];\n\n/**\n * Expression type - S-expressions only.\n * Used for guards, computed values, and effect expressions.\n *\n * NOTE: Legacy string format is no longer supported.\n * All expressions must be S-expression arrays.\n */\nexport type Expression = SExpr;\n\n// ============================================================================\n// S-Expression Schema (Zod)\n// ============================================================================\n\n/**\n * Recursive schema for s-expr-shaped DATA in literal positions (object\n * values, effect arguments). Unlike `SExprSchema`, arrays may be empty or\n * non-operator-headed — literal data lists (`children: []`, `tiles: [...]`)\n * are valid here; only call positions get the operator-head refine.\n */\nexport const SExprDataSchema: z.ZodType<SExpr> = z.lazy(() =>\n z.union([SExprAtomSchema, z.array(SExprDataSchema)]),\n);\n\n/**\n * Schema for atomic S-expression values (non-array)\n * Includes objects for payload data, props, etc.\n */\nexport const SExprAtomSchema: z.ZodType<SExprAtom> = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.record(SExprDataSchema), // Objects for payload data\n]);\n\n/**\n * Recursive schema for S-expressions.\n * Validates that arrays have at least one element and first element is a string (operator).\n */\nexport const SExprSchema: z.ZodType<SExpr> = z.lazy(() =>\n z.union([\n SExprAtomSchema,\n z\n .array(z.lazy(() => SExprSchema))\n .min(1)\n .refine(\n (arr) => typeof arr[0] === 'string',\n { message: 'S-expression array must have a string operator as first element' }\n ),\n ])\n);\n\n/**\n * Schema for Expression type - S-expressions only.\n * S-expressions are arrays with operator as first element.\n *\n * NOTE: Legacy string format is no longer supported.\n */\nexport const ExpressionSchema: z.ZodType<Expression> = SExprSchema;\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard for S-expression detection.\n * 100% reliable - structural check, no regex or keyword matching.\n *\n * @param value - Value to check\n * @returns true if value is an S-expression (array with string operator)\n */\nexport function isSExpr(value: RuntimeValue): value is SExpr[] {\n return (\n Array.isArray(value) &&\n value.length > 0 &&\n typeof value[0] === 'string'\n );\n}\n\n/**\n * Type guard for S-expression atoms (non-array values).\n * \n * Validates that a value is an S-expression atom (literal value).\n * Includes null, strings, numbers, booleans, and objects. Used to\n * distinguish atomic values from S-expression calls (arrays).\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is an S-expression atom, false otherwise\n *\n * @example\n * isSExprAtom('hello'); // returns true\n * isSExprAtom(42); // returns true\n * isSExprAtom(null); // returns true\n * isSExprAtom({ key: 'value' }); // returns true\n * isSExprAtom(['+', 1, 2]); // returns false\n */\nexport function isSExprAtom(value: RuntimeValue): value is SExprAtom {\n if (value === null) return true;\n if (Array.isArray(value)) return false;\n const type = typeof value;\n return type === 'string' || type === 'number' || type === 'boolean' || type === 'object';\n}\n\n/**\n * Checks if a value is a binding reference.\n * \n * Validates that a string is a binding reference (starts with @).\n * Bindings reference runtime values like @entity.health, @payload.amount, @now.\n * Used for identifying bindings in S-expressions and validation.\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is a binding reference, false otherwise\n *\n * @example\n * isBinding('@entity.health'); // returns true\n * isBinding('@payload.amount'); // returns true\n * isBinding('not-a-binding'); // returns false\n * isBinding(123); // returns false\n */\nexport function isBinding(value: RuntimeValue): value is string {\n return typeof value === 'string' && value.startsWith('@');\n}\n\n/**\n * Checks if a value is a valid S-expression call (array with operator).\n * \n * Alias for isSExpr() - validates S-expression call structure.\n * Used to distinguish between S-expression calls and atom values.\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is a valid S-expression call, false otherwise\n *\n * @example\n * isSExprCall(['+', 1, 2]); // returns true\n * isSExprCall(['set', '@entity.health', 100]); // returns true\n * isSExprCall('not-a-call'); // returns false\n */\nexport function isSExprCall(value: RuntimeValue): value is SExpr[] {\n return isSExpr(value);\n}\n\n// ============================================================================\n// Binding Parsing\n// ============================================================================\n\n/**\n * Parsed binding reference\n */\nexport interface ParsedBinding {\n /** Type of binding: core (@entity, @payload, @state, @now) or entity (@EntityName) */\n type: 'core' | 'entity';\n /** The root binding name (entity, payload, state, now, or EntityName) */\n root: string;\n /** Path segments after the root (e.g., ['health'] for @entity.health) */\n path: string[];\n /** Full original binding string */\n original: string;\n}\n\n/**\n * Core bindings that are always available.\n * Phase 4.5 adds: config, computed, trait (for behavior support).\n * `user` is the authenticated user / agent context (see binding.ts) and is\n * read-only in guards/effects/ticks — atoms reference `@user.id` and\n * `@user.role` for ownership / role-based gating.\n * `callsitePayload` is the call-site-captured event payload emitted by the\n * compiler's inline-trait hoisting; the runtime BindingResolver resolves it\n * at the composing effect.\n * `pages` / `currentTheme` are render-resolved schema sigils (effect-only,\n * see `orbital-rust/crates/orbital-compiler/src/phases/resolve.rs`):\n * substituted from the host orbital's schema (`@pages` → its `NavItem[]`\n * nav array, `@currentTheme` → its `data-theme` key) before codegen — they\n * never survive as live bindings past that substitution pass.\n */\nexport const CORE_BINDINGS = ['entity', 'payload', 'state', 'now', 'config', 'computed', 'trait', 'user', 'callsitePayload', 'pages', 'currentTheme'] as const;\nexport type CoreBinding = (typeof CORE_BINDINGS)[number];\n\n/**\n * Parses a binding reference into its components.\n * \n * Deconstructs a binding string (e.g., '@entity.health') into its constituent\n * parts: type, root, path, and original string. Does NOT use regex - uses\n * structured string operations for reliability and maintainability.\n * \n * @param {string} binding - Binding string starting with @\n * @returns {ParsedBinding | null} Parsed binding object or null if invalid\n * \n * @example\n * parseBinding('@entity.health'); // returns { type: 'core', root: 'entity', path: ['health'], original: '@entity.health' }\n * parseBinding('@User.name'); // returns { type: 'entity', root: 'User', path: ['name'], original: '@User.name' }\n * parseBinding('not-a-binding'); // returns null\n */\nexport function parseBinding(binding: string): ParsedBinding | null {\n if (!binding.startsWith('@')) {\n return null;\n }\n\n // Remove @ prefix\n const withoutPrefix = binding.slice(1);\n\n // Split by dots\n const parts = withoutPrefix.split('.');\n\n if (parts.length === 0 || parts[0] === '') {\n return null;\n }\n\n const root = parts[0];\n const path = parts.slice(1);\n\n // Determine if core binding or entity reference\n const isCore = (CORE_BINDINGS as readonly string[]).includes(root);\n\n return {\n type: isCore ? 'core' : 'entity',\n root,\n path,\n original: binding,\n };\n}\n\n/**\n * Validate a binding reference format.\n *\n * @param binding - Binding string to validate\n * @returns true if valid binding format\n */\nexport function isValidBinding(binding: string): boolean {\n const parsed = parseBinding(binding);\n if (!parsed) return false;\n\n // Core bindings: @entity, @payload, @state, @now (optionally with path)\n // @state and @now don't have paths\n if (parsed.type === 'core') {\n if (parsed.root === 'state' || parsed.root === 'now') {\n return parsed.path.length === 0;\n }\n // @entity and @payload can have paths\n return true;\n }\n\n // Entity bindings: @EntityName.field - must have at least one path segment\n return parsed.path.length > 0;\n}\n\n// ============================================================================\n// S-Expression Utilities\n// ============================================================================\n\n/**\n * Get the operator from an S-expression call.\n *\n * @param expr - S-expression array\n * @returns The operator string or null if not a valid call\n */\nexport function getOperator(expr: SExpr): string | null {\n if (!isSExpr(expr)) return null;\n return expr[0] as string;\n}\n\n/**\n * Get the arguments from an S-expression call.\n *\n * @param expr - S-expression array\n * @returns Array of arguments (empty if not a valid call)\n */\nexport function getArgs(expr: SExpr): SExpr[] {\n if (!isSExpr(expr)) return [];\n return expr.slice(1);\n}\n\n/**\n * Create an S-expression call.\n *\n * @param operator - The operator string\n * @param args - Arguments to the operator\n * @returns S-expression array\n */\nexport function sexpr(operator: string, ...args: SExpr[]): SExpr[] {\n return [operator, ...args];\n}\n\n/**\n * Walk an S-expression tree and apply a visitor function to each node.\n *\n * @param expr - S-expression to walk\n * @param visitor - Function to call on each node\n */\nexport function walkSExpr(\n expr: SExpr,\n visitor: (node: SExpr, parent: SExpr[] | null, index: number) => void,\n parent: SExpr[] | null = null,\n index: number = 0\n): void {\n visitor(expr, parent, index);\n\n if (isSExpr(expr)) {\n for (let i = 0; i < expr.length; i++) {\n walkSExpr(expr[i], visitor, expr, i);\n }\n }\n}\n\n/**\n * Collect all bindings referenced in an S-expression.\n *\n * @param expr - S-expression to analyze\n * @returns Array of binding strings found\n */\nexport function collectBindings(expr: SExpr): string[] {\n const bindings: string[] = [];\n\n walkSExpr(expr, (node) => {\n if (isBinding(node)) {\n bindings.push(node);\n }\n });\n\n return bindings;\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type SExprInput = z.input<typeof SExprSchema>;\nexport type ExpressionInput = z.input<typeof ExpressionSchema>;\n\n// ============================================================================\n// Runtime Evaluation Types\n// ============================================================================\n\n/** Evaluation context for guards and s-expressions. Recursive. */\nexport interface EvalContext {\n [key: string]: string | number | boolean | Date | null | string[] | EvalContext | undefined;\n}\n\n/**\n * A single value carried by an event payload field. The top-level payload\n * is always an object; the VALUES in that object can be primitives, nested\n * objects, or arrays of the same. Arrays are allowed so real-world emits\n * like `{ files: [{ name, size, type }, ...] }` or `{ selected: string[] }`\n * are typed natively instead of forcing consumers to wrap at every call.\n *\n * `Date` is included so `EntityRow` (whose values are `FieldValue`, which\n * includes `Date`) is assignable to a payload field without a cast —\n * emitted entity rows flow through the bus without boundary widening.\n */\nexport type EventPayloadValue =\n | string\n | number\n | boolean\n | Date\n | null\n | undefined\n | EventPayload\n | readonly EventPayloadValue[];\n\n/**\n * Typed event payload. Object-shaped so it's assignable to the bus's\n * `EventPayload` parameter without casts.\n */\nexport interface EventPayload {\n [key: string]: EventPayloadValue;\n}\n\n/**\n * Runtime guard for `EventPayloadValue` — narrows interpreter-produced\n * `unknown` values at typed substrate boundaries (e.g. `TraceContext.emit`).\n */\nexport function isEventPayloadValue(value: RuntimeValue): value is EventPayloadValue {\n if (value === null || value === undefined) return true;\n const kind = typeof value;\n if (kind === 'string' || kind === 'number' || kind === 'boolean') return true;\n if (value instanceof Date) return true;\n if (Array.isArray(value)) return value.every((item: RuntimeValue) => isEventPayloadValue(item));\n if (kind === 'object' && value !== null && typeof value === 'object') {\n return Object.values(value).every((item: RuntimeValue) => isEventPayloadValue(item));\n }\n return false;\n}\n\n/** Zod twin of `EventPayloadValue` — the one runtime validator for a bus-emit payload slot. */\nexport const EventPayloadValueSchema: z.ZodType<EventPayloadValue> = z.lazy(() =>\n z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.date(),\n z.null(),\n z.undefined(),\n EventPayloadSchema,\n z.array(EventPayloadValueSchema),\n ]),\n);\n\n/** Zod twin of `EventPayload` — the wire shape of a bus event's `payload`. */\nexport const EventPayloadSchema: z.ZodType<EventPayload> = z.lazy(() => z.record(EventPayloadValueSchema));\n\n/**\n * Allowed leaf value for `LogMeta`. Mirrors `EventPayloadValue` shape so\n * the same row/list data flows through logs without manual flattening,\n * with `Error` added since structured logs carry exception detail.\n */\nexport type LogMetaValue =\n | string\n | number\n | boolean\n | Date\n | null\n | undefined\n | Error\n | LogMeta\n | readonly LogMetaValue[];\n\n/** Structured log/event metadata. Recursive to support nested log data. */\nexport interface LogMeta {\n [key: string]: LogMetaValue;\n}\n","/**\n * Identity model (Almadar Rabit V4, Phase 1 — types only).\n *\n * Branded, prefix-tagged node ids + a workspace-scoped name ledger. Ids are\n * the durable edge keys of the identity-keyed schema graph; the ledger is the\n * sole name↔id map (names are display labels, one row per rename). This module\n * is pure: no I/O, no side effects. Minting is the only impurity (clock +\n * crypto randomness for the ULID suffix).\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Branded id types\n// ============================================================================\n\ntype Branded<K extends string> = string & { readonly __idBrand: K };\n\nexport type OrbitalId = Branded<'OrbitalId'>;\nexport type EntityId = Branded<'EntityId'>;\nexport type TraitId = Branded<'TraitId'>;\nexport type EventId = Branded<'EventId'>;\nexport type PageId = Branded<'PageId'>;\nexport type ServiceId = Branded<'ServiceId'>;\nexport type ThemeId = Branded<'ThemeId'>;\nexport type PaletteEntryId = Branded<'PaletteEntryId'>;\n\n/** Node kind ↔ id-prefix table. The single source of truth for every prefix. */\nconst ID_PREFIXES = {\n orbital: 'orb_',\n entity: 'ent_',\n trait: 'trt_',\n event: 'evt_',\n page: 'pag_',\n service: 'svc_',\n theme: 'thm_',\n palette: 'pal_',\n} as const;\n\nexport type IdKind = keyof typeof ID_PREFIXES;\n\n/** Compile-time map from kind to its branded id type. */\nexport interface IdForKind {\n orbital: OrbitalId;\n entity: EntityId;\n trait: TraitId;\n event: EventId;\n page: PageId;\n service: ServiceId;\n theme: ThemeId;\n palette: PaletteEntryId;\n}\n\n/**\n * The one controlled brand assertion in this module. A prefix-checked string\n * is asserted into its branded form here and nowhere else.\n */\nfunction brand<Id extends string>(value: string): Id {\n return value as Id;\n}\n\n// ============================================================================\n// Kind guards + constructors (one shared factory, eight kinds)\n// ============================================================================\n\ninterface IdKindApi<Id extends string> {\n readonly prefix: string;\n is(value: string): value is Id;\n as(value: string): Id;\n}\n\nfunction makeIdKind<Id extends string>(kind: IdKind): IdKindApi<Id> {\n const prefix = ID_PREFIXES[kind];\n const is = (value: string): value is Id =>\n value.startsWith(prefix) && value.length > prefix.length;\n const as = (value: string): Id => {\n if (!is(value)) {\n throw new Error(\n `Expected ${kind} id (prefix \"${prefix}\"), got: ${JSON.stringify(value)}`,\n );\n }\n return brand<Id>(value);\n };\n return { prefix, is, as };\n}\n\nconst orbitalKind = makeIdKind<OrbitalId>('orbital');\nconst entityKind = makeIdKind<EntityId>('entity');\nconst traitKind = makeIdKind<TraitId>('trait');\nconst eventKind = makeIdKind<EventId>('event');\nconst pageKind = makeIdKind<PageId>('page');\nconst serviceKind = makeIdKind<ServiceId>('service');\nconst themeKind = makeIdKind<ThemeId>('theme');\nconst paletteKind = makeIdKind<PaletteEntryId>('palette');\n\nexport const isOrbitalId = orbitalKind.is;\nexport const asOrbitalId = orbitalKind.as;\nexport const isEntityId = entityKind.is;\nexport const asEntityId = entityKind.as;\nexport const isTraitId = traitKind.is;\nexport const asTraitId = traitKind.as;\nexport const isEventId = eventKind.is;\nexport const asEventId = eventKind.as;\nexport const isPageId = pageKind.is;\nexport const asPageId = pageKind.as;\nexport const isServiceId = serviceKind.is;\nexport const asServiceId = serviceKind.as;\nexport const isThemeId = themeKind.is;\nexport const asThemeId = themeKind.as;\nexport const isPaletteEntryId = paletteKind.is;\nexport const asPaletteEntryId = paletteKind.as;\n\n/**\n * The id-prefix for a node kind (`'entity' → 'ent_'`). The JS mirror of the\n * Rust `IdKind::prefix`. Single source of truth is {@link ID_PREFIXES}.\n */\nexport function idPrefix(kind: IdKind): string {\n return ID_PREFIXES[kind];\n}\n\n/**\n * The node kind an id's prefix denotes, or `null` for an unrecognized /\n * bare-prefix string. The JS mirror of the Rust `id_kind_of`. Prefixes are\n * mutually non-overlapping, so match order is irrelevant.\n */\nexport function idKindOf(id: string): IdKind | null {\n for (const kind of Object.keys(ID_PREFIXES) as IdKind[]) {\n const prefix = ID_PREFIXES[kind];\n if (id.startsWith(prefix) && id.length > prefix.length) return kind;\n }\n return null;\n}\n\n// ============================================================================\n// Minting — prefix + ULID\n// ============================================================================\n\nconst CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(len: number): Uint8Array {\n const g = globalThis as { crypto?: { getRandomValues?: (a: Uint8Array) => Uint8Array } };\n if (g.crypto?.getRandomValues) {\n return g.crypto.getRandomValues(new Uint8Array(len));\n }\n throw new Error('mintId: no crypto.getRandomValues available in this runtime');\n}\n\nfunction encodeTime(now: number): string {\n let value = now;\n let out = '';\n for (let i = 0; i < TIME_LEN; i++) {\n const mod = value % 32;\n out = CROCKFORD[mod] + out;\n value = (value - mod) / 32;\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n const bytes = randomBytes(RANDOM_LEN);\n let out = '';\n for (let i = 0; i < RANDOM_LEN; i++) {\n out += CROCKFORD[bytes[i] & 31];\n }\n return out;\n}\n\n/** A 26-char Crockford-base32 ULID: 48-bit ms timestamp + 80 bits of randomness. */\nfunction ulid(): string {\n return encodeTime(Date.now()) + encodeRandom();\n}\n\n/** Mint a fresh, opaque, kind-tagged id: `<prefix><ULID>`. */\nexport function mintId<K extends IdKind>(kind: K): IdForKind[K] {\n return brand<IdForKind[K]>(ID_PREFIXES[kind] + ulid());\n}\n\n// ============================================================================\n// Deterministic derivation — JS twin of Rust `derive_id`\n// ============================================================================\n\nconst U64_MASK = (1n << 64n) - 1n;\nconst BODY_TIME_MASK = (1n << 50n) - 1n;\nconst BODY_RANDOM_MASK = (1n << 80n) - 1n;\nconst FNV_PRIME_64 = 0x100000001b3n;\nconst FNV_OFFSET_1 = 0xcbf29ce484222325n;\nconst FNV_OFFSET_2 = (0x100000001b3n ^ 0xdeadbeefn) & U64_MASK;\n\n/** SplitMix64 — a small, well-distributed non-cryptographic mixer. */\nfunction splitmix64(x: bigint): bigint {\n let z = (x + 0x9e3779b97f4a7c15n) & U64_MASK;\n z = ((z ^ (z >> 30n)) * 0xbf58476d1ce4e5b9n) & U64_MASK;\n z = ((z ^ (z >> 27n)) * 0x94d049bb133111ebn) & U64_MASK;\n return (z ^ (z >> 31n)) & U64_MASK;\n}\n\n/** FNV-1a 64-bit over `data` starting from `offset`. */\nfunction fnv1a64(data: Uint8Array, offset: bigint): bigint {\n let h = offset & U64_MASK;\n for (const b of data) {\n h = (h ^ BigInt(b)) & U64_MASK;\n h = (h * FNV_PRIME_64) & U64_MASK;\n }\n return h;\n}\n\n/** Emit the low `nChars * 5` bits of `value` as base32, most-significant char first. */\nfunction pushBase32(value: bigint, nChars: number): string {\n let v = value;\n const chars = new Array<string>(nChars);\n for (let i = nChars - 1; i >= 0; i--) {\n chars[i] = CROCKFORD[Number(v & 0x1fn)];\n v >>= 5n;\n }\n return chars.join('');\n}\n\n/**\n * Deterministically derive a child id rooted in `parentId` — no entropy, no\n * clock, so re-deriving from the same inputs never churns. JS twin of the\n * Rust `derive_id` in `orbital-core/src/identity.rs`; used ONLY for synthetic\n * nodes produced by deterministic materialization (orbital-import\n * prefixing), never for author-facing fresh ids (use {@link mintId} there).\n */\nexport function deriveId(parentId: string, discriminator: string): string {\n const kind = idKindOf(parentId) ?? 'trait';\n const encoder = new TextEncoder();\n const parentBytes = encoder.encode(parentId);\n const discBytes = encoder.encode(discriminator);\n const data = new Uint8Array(parentBytes.length + 1 + discBytes.length);\n data.set(parentBytes, 0);\n data[parentBytes.length] = 0x1f;\n data.set(discBytes, parentBytes.length + 1);\n\n const h1 = splitmix64(fnv1a64(data, FNV_OFFSET_1));\n const h2 = splitmix64(fnv1a64(data, FNV_OFFSET_2));\n const timeBits = (((h1 << 64n) | h2) & BODY_TIME_MASK);\n const randBits = (((h2 << 64n) | h1) & BODY_RANDOM_MASK);\n\n return ID_PREFIXES[kind] + pushBase32(timeBits, 10) + pushBase32(randBits, 16);\n}\n\n// ============================================================================\n// Identity ledger\n// ============================================================================\n\n/** Ledger row kind. `palette` entries are manifest ids, not name-ledger rows. */\nexport type LedgerKind =\n | 'orbital'\n | 'entity'\n | 'trait'\n | 'event'\n | 'page'\n | 'service'\n | 'theme';\n\n/**\n * One ledger row: the workspace's name history for a single node id.\n *\n * For kind `'event'` the row is minted per-(trait, declared event) per the\n * Phase-0 freeze — the owning trait is recorded in `parent`; a call-site event\n * rename is a one-row edit on this same id (the baked-vs-current key namespaces\n * collapse into `bakedName` vs `curName`).\n */\nexport interface LedgerEntry {\n id: string;\n kind: LedgerKind;\n bakedName: string;\n curName: string;\n renames: ReadonlyArray<{ from: string; to: string; at: string }>;\n owner: 'std' | 'io' | 'workspace';\n /** Owning trait for kind `'event'` (per-trait event-id namespace). */\n parent?: TraitId;\n}\n\nexport interface IdentityLedger {\n schemaVersion: 1;\n entries: Record<string, LedgerEntry>;\n}\n\n/** Resolve a name to its id via exact `curName` match within `kind`, else null. */\nexport function ledgerResolveName(\n ledger: IdentityLedger,\n kind: LedgerKind,\n name: string,\n): string | null {\n for (const [id, entry] of Object.entries(ledger.entries)) {\n if (entry.kind === kind && entry.curName === name) return id;\n }\n return null;\n}\n\n/** Immutable rename: returns a new ledger with the id's `curName` + `renames` updated. */\nexport function ledgerRename(\n ledger: IdentityLedger,\n id: string,\n to: string,\n at: string,\n): IdentityLedger {\n const entry = ledger.entries[id];\n if (entry === undefined) return ledger;\n const updated: LedgerEntry = {\n ...entry,\n curName: to,\n renames: [...entry.renames, { from: entry.curName, to, at }],\n };\n return { ...ledger, entries: { ...ledger.entries, [id]: updated } };\n}\n\n/** Current display name for an id, or null when the id is not in the ledger. */\nexport function ledgerCurName(ledger: IdentityLedger, id: string): string | null {\n return ledger.entries[id]?.curName ?? null;\n}\n\n// ============================================================================\n// Zod schemas — the `.orb` load-time activation surface (Rabit V4, Phase 4)\n// ============================================================================\n\n/**\n * Prefix-checked, kind-tagged id schemas. Each narrows a validated string to\n * its branded id type via the module's own kind guard, so a schema that reads\n * `TraitIdSchema.optional()` yields `TraitId | undefined` with no cast. The\n * guard is the single source of prefix truth (`ID_PREFIXES`); the schema is a\n * thin zod wrapper over it.\n */\nexport const OrbitalIdSchema = z\n .string()\n .refine(isOrbitalId, { message: `Expected an orbital id (prefix \"${ID_PREFIXES.orbital}\")` });\nexport const EntityIdSchema = z\n .string()\n .refine(isEntityId, { message: `Expected an entity id (prefix \"${ID_PREFIXES.entity}\")` });\nexport const TraitIdSchema = z\n .string()\n .refine(isTraitId, { message: `Expected a trait id (prefix \"${ID_PREFIXES.trait}\")` });\nexport const EventIdSchema = z\n .string()\n .refine(isEventId, { message: `Expected an event id (prefix \"${ID_PREFIXES.event}\")` });\nexport const PageIdSchema = z\n .string()\n .refine(isPageId, { message: `Expected a page id (prefix \"${ID_PREFIXES.page}\")` });\nexport const ServiceIdSchema = z\n .string()\n .refine(isServiceId, { message: `Expected a service id (prefix \"${ID_PREFIXES.service}\")` });\nexport const ThemeIdSchema = z\n .string()\n .refine(isThemeId, { message: `Expected a theme id (prefix \"${ID_PREFIXES.theme}\")` });\nexport const PaletteEntryIdSchema = z\n .string()\n .refine(isPaletteEntryId, { message: `Expected a palette-entry id (prefix \"${ID_PREFIXES.palette}\")` });\n\nexport const LedgerKindSchema = z.enum([\n 'orbital',\n 'entity',\n 'trait',\n 'event',\n 'page',\n 'service',\n 'theme',\n]);\n\nexport const LedgerEntrySchema = z.object({\n id: z.string(),\n kind: LedgerKindSchema,\n bakedName: z.string(),\n curName: z.string(),\n renames: z.array(\n z.object({ from: z.string(), to: z.string(), at: z.string() }),\n ),\n owner: z.enum(['std', 'io', 'workspace']),\n parent: TraitIdSchema.optional(),\n});\n\nexport const IdentityLedgerSchema = z.object({\n schemaVersion: z.literal(1),\n entries: z.record(LedgerEntrySchema),\n});\n","/**\n * JSON primitives — the universal \"data crossed a boundary\" type.\n *\n * Every value that arrives over the wire from an LLM (tool-call args),\n * from disk (workspace files), or from an HTTP body before\n * domain-specific validation is a `JsonValue`. Narrow with a typed\n * predicate (`is`-guard) at the boundary; don't widen back to `unknown`.\n *\n * `JsonObject` and `ToolArgs` are aliases for the common\n * `Record<string, JsonValue>` shape. `ToolArgs` is the name the\n * agent surface uses for LLM-emitted tool-call arguments; `JsonObject`\n * is the general-purpose alias. They are the same type — the alias\n * exists so call sites read at the right semantic level.\n *\n * Why not `Record<string, unknown>`? Two reasons. (1) `unknown` widens\n * back to anything, which defeats the purpose of typing the boundary.\n * (2) The `@almadar/eslint-plugin/no-record-string-unknown` rule blocks\n * the wider form — `JsonValue`-based records are the typed answer.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\n\n/**\n * Recursive JSON value union — every shape JSON can carry.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/**\n * JSON object — keyed string→JsonValue. The wire form of arbitrary\n * structured data. Replaces `Record<string, unknown>` at typed\n * boundaries (LLM emits, file reads, HTTP bodies).\n */\nexport type JsonObject = { [key: string]: JsonValue };\n\n/** Zod schema for JsonValue — the one boundary validator for parsed-JSON slots. */\nexport const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(JsonValueSchema), z.record(JsonValueSchema)]),\n);\n\n/**\n * LLM tool-call arguments — same shape as `JsonObject`, named for the\n * agent-surface call site. Each tool's `execute(args: ToolArgs)`\n * receives this and narrows via an `is`-guard predicate before any\n * field access.\n */\nexport type ToolArgs = JsonObject;\n\n/**\n * Universal type-guard input — every runtime value shape a predicate can\n * be handed, enumerated instead of `unknown` (the repo bans `unknown`\n * even at guard boundaries). Primitives cover every `typeof` result;\n * `object` covers arrays, records, class instances, and functions.\n */\nexport type RuntimeValue =\n | string\n | number\n | bigint\n | boolean\n | symbol\n | Date\n | null\n | undefined\n | object;\n\n/**\n * Type guard: is the given value a JSON primitive (non-array,\n * non-object)? Used by walkers that decide whether to recurse.\n */\nexport function isJsonPrimitive(\n value: JsonValue,\n): value is string | number | boolean | null {\n return (\n value === null\n || typeof value === 'string'\n || typeof value === 'number'\n || typeof value === 'boolean'\n );\n}\n\n/**\n * Type guard: is the given value a JSON object (non-array, non-null)?\n */\nexport function isJsonObject(value: JsonValue): value is JsonObject {\n return (\n value !== null\n && typeof value === 'object'\n && !Array.isArray(value)\n );\n}\n\n/**\n * Type guard: is the given value a JSON array?\n */\nexport function isJsonArray(value: JsonValue): value is JsonValue[] {\n return Array.isArray(value);\n}\n","/**\n * Field Types for Orbital Units\n *\n * Extracted from schema/data-entities.ts for the orbitals module.\n * These types define the field structure within orbital entities.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport type { EntityId } from './identity.js';\nimport { EntityIdSchema } from './identity.js';\nimport type { JsonValue, RuntimeValue } from './json.js';\nimport { JsonValueSchema } from './json.js';\n\n// ============================================================================\n// Field Types\n// ============================================================================\n\n/**\n * Supported field types for entity fields.\n *\n * @example\n * { name: 'status', type: 'enum', values: ['draft', 'published'] }\n * { name: 'authorId', type: 'relation', relation: { entity: 'User', cardinality: 'one' } }\n */\nexport type FieldType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'date'\n | 'timestamp'\n | 'datetime'\n // Semantic string domains. `.lolo` already types `date`/`datetime` rather\n // than annotating them, so these belong in the type system for the same\n // reason: a field's domain is a declared fact, not a decoration. They\n // replaced the optional `format` property, which had zero producers.\n | 'email'\n | 'url'\n | 'phone'\n | 'uuid'\n | 'image'\n // Promoted value types (2026-08-20). `money` is numeric at rest - the\n // declared type (never a field-name heuristic) drives currency inputs\n // and formatting. `file` is the canonical struct value\n // {name, url, mimeType, sizeBytes} - an uploaded artifact, not a\n // validated string; `url` is a data: URI in mock mode.\n | 'money'\n | 'file'\n | 'array'\n | 'object'\n | 'enum'\n | 'relation'\n | 'trait'\n | 'slot'\n | 'pattern'\n // Renderable UI content — a pattern node (or array of them), the same\n // shape `render-ui` effects carry (`PatternNode` in render-ui-edit.ts).\n // First-class so view-fragment fields stop hiding behind `object`/`json`.\n | 'node'\n // Event-name reference — a string at rest, but the TYPE marks it as an\n // event key rather than free text (Phase B / SCAN-EVENT-KNOB-2). Legal\n // on struct-alias fields consumed by config knobs (e.g. `ItemAction.event`).\n | 'event'\n // Closed scalar transport union (`ControlValue`) and tagged struct union\n // (`type DrawItem = DrawShape | DrawText`) — real .lolo/.orb types the\n // Rust compiler accepts; the TS mirror must carry them or generated\n // factories fail DTS (docs/Almadar_LOLO_Gaps.md L-6).\n | 'scalar'\n | 'union';\n\n/** Every `FieldType`, as a runtime array. Downstream imports this instead of\n * re-listing the union — five copies had already drifted apart. */\nexport const FIELD_TYPES = [\n 'string',\n 'number',\n 'boolean',\n 'date',\n 'timestamp',\n 'datetime',\n 'email',\n 'url',\n 'phone',\n 'uuid',\n 'image',\n 'money',\n 'file',\n 'array',\n 'object',\n 'enum',\n 'relation',\n 'trait',\n 'slot',\n 'pattern',\n 'node',\n 'event',\n 'scalar',\n 'union',\n] as const satisfies readonly FieldType[];\n\n/** The semantic string domains — constrained strings, validatable by value. */\nexport const SEMANTIC_STRING_TYPES = ['email', 'url', 'phone', 'uuid', 'image'] as const;\n\nexport type SemanticStringType = (typeof SEMANTIC_STRING_TYPES)[number];\n\n/** Is this a semantic string domain (as opposed to a bare `string`)? */\nexport function isSemanticStringType(type: FieldType): type is SemanticStringType {\n return (SEMANTIC_STRING_TYPES as readonly string[]).includes(type);\n}\n\nexport const FieldTypeSchema = z.enum(FIELD_TYPES);\n\n/** Words legal in a `.lolo`/`.orb` TYPE POSITION that are not entity field\n * types (config/param/return annotations, primitives with no field-level\n * meaning, etc.) — declared so the i18n `types` vocabulary section is\n * `FIELD_TYPES ∪ TYPE_POSITION_ONLY` exactly, not a hand-maintained superset\n * held together by a one-directional pinned test (see G-i18n-5). */\nexport const TYPE_POSITION_ONLY = [\n 'Map',\n 'SExpr',\n 'any',\n 'asset',\n 'bool',\n 'component',\n 'duration',\n 'entity',\n 'float',\n 'icon',\n 'int',\n 'null',\n 'secret',\n 'void',\n] as const;\n\n// ============================================================================\n// Relation Configuration\n// ============================================================================\n\n/**\n * Cardinality for relation fields.\n * Matches Rust compiler's Cardinality enum.\n */\nexport type RelationCardinality = \n | 'one' \n | 'many' \n | 'one-to-many' \n | 'many-to-one' \n | 'many-to-many';\n\nexport const RelationCardinalitySchema = z.enum([\n 'one',\n 'many',\n 'one-to-many',\n 'many-to-one',\n 'many-to-many',\n]);\n\n/**\n * Configuration for relation fields (foreign keys).\n * Matches Rust compiler's RelationDefinition format.\n */\nexport type RelationConfig = {\n /** Target entity name (e.g., 'User', 'Task') - matches Rust's `entity` field */\n entity: string;\n /** V4 dual-carry id sibling of `entity` — optional until the Phase-7 flip. */\n entityId?: EntityId;\n /** Field on target entity (defaults to 'id') */\n field?: string;\n /** \n * Cardinality: one, many, one-to-many, many-to-one, many-to-many\n * Matches Rust compiler's cardinality format\n */\n cardinality?: RelationCardinality;\n /** Delete behavior */\n onDelete?: 'cascade' | 'nullify' | 'restrict';\n /** \n * Foreign key field name (for legacy compatibility).\n * @deprecated Use field instead\n */\n foreignKey?: string;\n /**\n * Target entity name (for legacy compatibility).\n * @deprecated Use entity instead\n */\n target?: string;\n /**\n * Cardinality type alias (for legacy compatibility).\n * @deprecated Use cardinality instead\n */\n type?: RelationCardinality;\n};\n\nexport const RelationConfigSchema = z.object({\n entity: z.string().min(1, 'Target entity is required'),\n entityId: EntityIdSchema.optional(),\n field: z.string().optional(),\n cardinality: RelationCardinalitySchema.optional(),\n onDelete: z.enum(['cascade', 'nullify', 'restrict']).optional(),\n // Legacy compatibility fields\n foreignKey: z.string().optional(),\n target: z.string().optional(),\n type: RelationCardinalitySchema.optional(),\n}).transform((data) => {\n // Normalize legacy format to standard format\n const normalized: RelationConfig = {\n entity: data.entity || data.target || '',\n entityId: data.entityId,\n cardinality: data.cardinality || data.type,\n field: data.field,\n onDelete: data.onDelete,\n };\n return normalized;\n});\n\nexport type RelationConfigInput = z.input<typeof RelationConfigSchema>;\n\n// ============================================================================\n// Field Format\n// ============================================================================\n\n/**\n * Value rules for the semantic string domains — one owner, so the seeders, the\n * validators and the verifiers cannot drift apart on what counts as valid.\n *\n * These replaced the old optional `format` property, which had zero producers\n * anywhere in the repo and no Rust counterpart at all: `format` was unreachable\n * from `.lolo`, so every consumer fell back to guessing from field names.\n */\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@.]+\\.[^\\s@]+$/;\nconst URL_RE = /^https?:\\/\\/[^\\s]+$/;\nconst PHONE_RE = /^[+]?[\\d\\s().-]{7,}$/;\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function isEmailValue(value: string): boolean {\n return EMAIL_RE.test(value);\n}\n\nexport function isUrlValue(value: string): boolean {\n return URL_RE.test(value);\n}\n\nexport function isPhoneValue(value: string): boolean {\n return PHONE_RE.test(value);\n}\n\nexport function isUuidValue(value: string): boolean {\n return UUID_RE.test(value);\n}\n\n// ============================================================================\n// File value — the canonical struct a `file`-typed field holds at rest.\n// ONE owner for the shape; mirrors `file_value_fields()` in orbital-core\n// (ir/render.rs) and the codegen zod emitter.\n// ============================================================================\n\n/** The value a `file`-typed entity field holds: an uploaded artifact.\n * `url` is a `data:` URI in mock/playground mode (size-ceilinged by the\n * mock adapter) or an object-storage URL in production. */\nexport type FileValue = {\n name: string;\n url: string;\n mimeType: string;\n sizeBytes: number;\n};\n\n/** Zod schema for {@link FileValue}. */\nexport const FileValueSchema = z.object({\n name: z.string(),\n url: z.string(),\n mimeType: z.string(),\n sizeBytes: z.number(),\n});\n\n/** Is `value` a well-formed {@link FileValue}? The `file` twin of\n * `isSemanticStringValue` — the seeder's output must satisfy this. */\nexport function isFileValue(value: unknown): value is FileValue {\n return FileValueSchema.safeParse(value).success;\n}\n\n/** Does `value` satisfy the declared semantic domain? `image` is a URL. */\nexport function isSemanticStringValue(type: SemanticStringType, value: string): boolean {\n switch (type) {\n case 'email':\n return isEmailValue(value);\n case 'url':\n case 'image':\n return isUrlValue(value);\n case 'phone':\n return isPhoneValue(value);\n case 'uuid':\n return isUuidValue(value);\n }\n}\n\n// ============================================================================\n// Entity Field — discriminated union by `type`\n// ============================================================================\n\n/**\n * Field-type tags that don't carry a type-dependent payload. The base\n * `EntityField` shape applies as-is.\n */\ntype ScalarFieldType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'date'\n | 'timestamp'\n | 'datetime'\n | 'email'\n | 'url'\n | 'phone'\n | 'uuid'\n | 'image'\n | 'money'\n | 'file'\n | 'trait'\n | 'slot'\n | 'pattern'\n | 'node'\n | 'event'\n // Closed scalar transport union (`ControlValue`) — a real .lolo/.orb type\n // the compiler accepts in payloads and map values; the TS mirror must carry\n // it or generated factories fail DTS (docs/Almadar_LOLO_Gaps.md L-6).\n | 'scalar';\n\n/** Fields shared across every variant. */\ntype EntityFieldBase = {\n /**\n * Field name (camelCase). Optional for nested item/property descriptors\n * where the name is implied by the parent (`items`, `properties[k]`).\n * Mirrors Rust's `FieldDefinition.name: Option<String>`.\n */\n name?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Primary-key marker. Mirrors Rust's `FieldDefinition.primary_key`\n * (serde `primaryKey`). */\n primaryKey?: boolean;\n /** Default value — parsed from `.orb`, always JSON-shaped. */\n default?: JsonValue;\n /** Minimum value (for number) or length (for string) */\n min?: number;\n /** Maximum value or length */\n max?: number;\n /** Object property schemas keyed by property name (for object type).\n * Mirrors Rust's `FieldDefinition.properties: Option<HashMap<String,\n * FieldDefinition>>`. Populated by the lolo lowerer when a field /\n * config slot's type expression resolves to a struct shape\n * (`TypeExpr::Object`), including named-type aliases like `[MetricSpec]`. */\n properties?: Record<string, EntityField>;\n /** Runtime-managed widget state (authored `@intrinsic` in `.lolo`). Exempt\n * from the explicit-binding rule and never a domain-data bind target. */\n intrinsic?: boolean;\n /** Human/semantic description (authored `@description \"...\"` in `.lolo`).\n * Authoring/build-time metadata — factory-signature catalog, embeddings,\n * curation field-matching; the runtime ignores it. */\n description?: string;\n /** User-vocabulary synonyms (authored `@synonyms \"...\"` in `.lolo`).\n * Free text feeding catalog search / curation field-matching. */\n synonyms?: string;\n /** Declared mock value(s) (authored `@mock \"...\"` in `.lolo`), used\n * LITERALLY by the seeder (`sampleValue.ts`, `seed.rs`) — never mapped\n * through a domain-name lookup table. Comma-separated is an explicit\n * candidate list rotated by row index (`@mock \"Acme Corp, Globex Inc\"`);\n * no comma is a single literal value, index-suffixed per row\n * (`@mock \"person-name\"` -> \"person-name-1\", \"person-name-2\", ...). */\n mock?: string;\n /**\n * The imported entity this field was merged from on a rebind (sibling\n * pull / entity contract). Absent on author-declared fields — a merged\n * field's `required` is the ATOM's own write contract, never the host\n * writer's.\n */\n mergedFrom?: string;\n};\n\n/**\n * Scalar / structural fields — no type-dependent payload required.\n * `values?` is permitted as an OPTIONAL UI/validation hint (e.g. lolo's\n * `'a' | 'b' | 'c'` string-union sugar lowers to `type: 'string', values:\n * [...]`). Only `EnumEntityField` MANDATES values.\n */\nexport type ScalarEntityField = EntityFieldBase & {\n type: ScalarFieldType;\n /** Optional vocabulary hint for scalar fields (e.g. string unions\n * authored as `'a'|'b'|'c'` in lolo). Not required at this variant. */\n values?: string[];\n};\n\n/** `type: 'enum'` REQUIRES the closed vocabulary in `values`. */\nexport type EnumEntityField = EntityFieldBase & {\n type: 'enum';\n /** Closed string vocabulary the field accepts. */\n values: string[];\n};\n\n/** `type: 'relation'` REQUIRES the relation target binding. */\nexport type RelationEntityField = EntityFieldBase & {\n type: 'relation';\n /** Relation target binding (entity + cardinality). */\n relation: RelationConfig;\n};\n\n/**\n * `type: 'union'` — a TAGGED union of struct variants (`.lolo`\n * `type DrawItem = DrawShape | DrawText`). `values` carries the variant NAMES\n * in declaration order; `properties` (from the base shape) carries each\n * variant's shape keyed by that name. The discriminator is the variant's own\n * literal-typed tag field, so selection is data-driven. Recursion is carried\n * BY NAME: a variant referring back to the union gets `values` with no\n * `properties` (mirrors `FieldType::Union` in orbital-core).\n */\nexport type UnionEntityField = EntityFieldBase & {\n type: 'union';\n /** Variant type names in declaration order. */\n values: string[];\n};\n\n/** `type: 'array'` — element schema in `items` strongly preferred but\n * optional for legacy compatibility with codegen-emitted scalar-array\n * fields (e.g. `{type: 'array', default: []}`). The lolo lowerer + Rust\n * validator catch typed-element-required cases downstream. */\nexport type ArrayEntityField = EntityFieldBase & {\n type: 'array';\n /** Element schema for the array. */\n items?: EntityField;\n};\n\n/**\n * `type: 'object'` — a fixed-key struct (fields in `properties`) OR a\n * dynamic-key map (`Map K V` in `.lolo`; the uniform value schema lives in\n * `items`, mirroring an array's element schema). A distinct variant so `items`\n * is statically allowed only on object/array fields, never on scalars.\n */\nexport type ObjectEntityField = EntityFieldBase & {\n type: 'object';\n /** Uniform value schema for a dynamic-key map (`Map K V`). */\n items?: EntityField;\n};\n\n/**\n * Entity field definition — discriminated union by `type`. Each variant\n * statically enforces its dependent payload (`values` for enum,\n * `relation` for relation, `items` for array) so TS / Zod / JSON Schema\n * consumers all agree on the dependency, not just the Rust validator.\n *\n * @example\n * { name: 'status', type: 'enum', values: ['draft', 'published'] }\n * { name: 'authorId', type: 'relation', relation: { entity: 'User', cardinality: 'one' } }\n * { name: 'tags', type: 'array', items: { type: 'string' } }\n */\nexport type EntityField =\n | ScalarEntityField\n | EnumEntityField\n | RelationEntityField\n | UnionEntityField\n | ArrayEntityField\n | ObjectEntityField;\n\n/**\n * Alias map for legacy/loose field-type spellings. Preprocessed into the\n * canonical `FieldType` enum before zod validates. Without this, agent-produced\n * schemas using `text`/`int`/`float`/`ts` were rejected at parse time — this\n * normalizes them so the rest of the pipeline sees only canonical types.\n */\nconst FIELD_TYPE_ALIASES: Record<string, FieldType> = {\n text: 'string',\n int: 'number',\n float: 'number',\n ts: 'timestamp',\n};\n\n/**\n * Zod schema for `EntityField`. Preprocess normalizes:\n * - legacy `type` aliases (text → string, int → number, etc.)\n * - legacy `enum: string[]` alias → `values: string[]`\n *\n * Branches on `type` so TS narrows the parsed output to the matching\n * discriminated-union variant.\n */\n// The third type param stays `unknown`: zod v3 bakes `unknown` into\n// `z.preprocess`'s input type, and the recursion needs the explicit annotation.\nexport const EntityFieldSchema: z.ZodType<EntityField, z.ZodTypeDef, unknown> = z.lazy(() => {\n const baseFieldShape = {\n name: z.string().min(1, 'Field name is required').optional(),\n required: z.boolean().optional(),\n primaryKey: z.boolean().optional(),\n default: JsonValueSchema.optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n properties: z.record(EntityFieldSchema).optional(),\n intrinsic: z.boolean().optional(),\n description: z.string().optional(),\n synonyms: z.string().optional(),\n mock: z.string().optional(),\n mergedFrom: z.string().optional(),\n };\n\n /** Build a scalar variant schema. `values?` is permitted as a hint;\n * only the enum variant mandates a non-empty values array. */\n function scalarVariant<T extends ScalarFieldType>(t: T) {\n return z.object({\n ...baseFieldShape,\n type: z.literal(t),\n values: z.array(z.string()).optional(),\n });\n }\n\n return z.preprocess(\n (input) => {\n if (\n input === null ||\n typeof input !== 'object' ||\n !('type' in input) ||\n typeof (input as { type?: RuntimeValue }).type !== 'string'\n ) {\n return input;\n }\n const obj = input as { type: string; enum?: RuntimeValue; values?: RuntimeValue };\n const next: { type: string; enum?: RuntimeValue; values?: RuntimeValue } = { ...obj };\n const aliased = FIELD_TYPE_ALIASES[obj.type];\n if (aliased !== undefined) next.type = aliased;\n // Fold legacy `enum: string[]` into `values: string[]`.\n if (next.enum !== undefined && next.values === undefined) {\n next.values = next.enum;\n }\n delete next.enum;\n return next;\n },\n z.discriminatedUnion('type', [\n scalarVariant('string'),\n scalarVariant('number'),\n scalarVariant('boolean'),\n scalarVariant('date'),\n scalarVariant('timestamp'),\n scalarVariant('datetime'),\n scalarVariant('email'),\n scalarVariant('url'),\n scalarVariant('phone'),\n scalarVariant('uuid'),\n scalarVariant('image'),\n scalarVariant('trait'),\n scalarVariant('slot'),\n scalarVariant('pattern'),\n scalarVariant('node'),\n scalarVariant('event'),\n scalarVariant('money'),\n scalarVariant('file'),\n scalarVariant('scalar'),\n // Enum variant — REQUIRES non-empty values.\n z.object({\n ...baseFieldShape,\n type: z.literal('enum'),\n values: z.array(z.string()).min(1, 'Enum field requires a non-empty `values` array'),\n }),\n // Union variant — tagged struct union; values = variant names,\n // per-variant shapes in `properties` (absent on named recursion).\n z.object({\n ...baseFieldShape,\n type: z.literal('union'),\n values: z.array(z.string()).min(1, 'Union field requires a non-empty `values` array'),\n }),\n // Relation variant — REQUIRES relation config.\n z.object({\n ...baseFieldShape,\n type: z.literal('relation'),\n relation: RelationConfigSchema,\n }),\n // Array variant — items optional to match relaxed TS shape.\n z.object({\n ...baseFieldShape,\n type: z.literal('array'),\n items: EntityFieldSchema.optional(),\n }),\n // Object variant — fixed-key struct (`properties`) or dynamic-key\n // map (`Map K V`, uniform value schema in `items`).\n z.object({\n ...baseFieldShape,\n type: z.literal('object'),\n items: EntityFieldSchema.optional(),\n values: z.array(z.string()).optional(),\n }),\n ]),\n );\n});\n\nexport type EntityFieldInput = z.input<typeof EntityFieldSchema>;\n\n// ============================================================================\n// Type Aliases (for cleaner imports)\n// ============================================================================\n\n/** Alias for EntityField - preferred name */\nexport type Field = EntityField;\n\n/** Alias for EntityFieldSchema - preferred name */\nexport const FieldSchema = EntityFieldSchema;\n","/**\n * Asset Types for Semantic Asset References\n *\n * Defines types for abstracting asset paths into semantic references.\n * Assets are resolved from SemanticAssetRef to actual paths at compile time.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Entity Roles\n// ============================================================================\n\n/**\n * Entity roles in game contexts\n */\nexport const ENTITY_ROLES = [\n 'player',\n 'enemy',\n 'npc',\n 'item',\n 'tile',\n 'projectile',\n 'effect',\n 'ui',\n 'decoration',\n 'vehicle',\n] as const;\n\nexport type EntityRole = (typeof ENTITY_ROLES)[number];\n\nexport const EntityRoleSchema = z.enum(ENTITY_ROLES);\n\n// ============================================================================\n// Visual Styles\n// ============================================================================\n\n/**\n * Visual art styles for games\n */\nexport const VISUAL_STYLES = ['pixel', 'vector', 'hd', '1-bit', 'isometric'] as const;\n\nexport type VisualStyle = (typeof VISUAL_STYLES)[number];\n\nexport const VisualStyleSchema = z.enum(VISUAL_STYLES);\n\n// ============================================================================\n// Asset Dimension + Aspect (render metadata carried with the asset / the need)\n// ============================================================================\n\n/**\n * Whether the asset is a 2D sprite/image or a 3D model. Set by the consuming\n * canvas: the same entity role is a 2D sprite-sheet on a tile board and a 3D\n * rigged model on a 3D board.\n */\nexport const ASSET_DIMENSIONS = ['2d', '3d'] as const;\n\nexport type AssetDimension = (typeof ASSET_DIMENSIONS)[number];\n\nexport const AssetDimensionSchema = z.enum(ASSET_DIMENSIONS);\n\n/**\n * Rendering aspect ratio of an asset: square (tiles/sprites/portraits/icons),\n * 16:9 (scene backdrops), 5:7 (cards), 8:1 (effect frame strips),\n * 4:1 (wide paddles/bars), 5:3 (wide scenes), 1:2 (tall banners).\n */\nexport const ASSET_ASPECTS = ['1:1', '16:9', '5:7', '8:1', '4:1', '5:3', '1:2'] as const;\n\nexport type AssetAspect = (typeof ASSET_ASPECTS)[number];\n\nexport const AssetAspectSchema = z.enum(ASSET_ASPECTS);\n\n// ============================================================================\n// Animation Name + Sheet Direction\n// ============================================================================\n\n/**\n * Animation names matching a sprite sheet's row layout. Canonical home for\n * this vocabulary — `@almadar/ui`'s `spriteAnimationTypes.ts` re-exports it\n * rather than redeclaring, so board `.lolo` config and the render library\n * agree on one enum.\n */\nexport const ANIMATION_NAMES = ['idle', 'walk', 'skate', 'jump', 'fall', 'attack', 'hit', 'death'] as const;\n\nexport type AnimationName = (typeof ANIMATION_NAMES)[number];\n\nexport const AnimationNameSchema = z.enum(ANIMATION_NAMES);\n\n/**\n * Sheet file directions (physical PNG files a sprite sheet ships as).\n * Legacy hand-drawn packs ship only se/sw and mirror-flip for ne/nw (a cheat\n * that shows the face while walking away); 3D-baked sheets ship all four real\n * directions — the renderer prefers a real sheet and keeps the flip only as\n * the legacy fallback.\n */\nexport const SPRITE_DIRECTIONS = ['se', 'sw', 'ne', 'nw'] as const;\n\nexport type SpriteDirection = (typeof SPRITE_DIRECTIONS)[number];\n\nexport const SpriteDirectionSchema = z.enum(SPRITE_DIRECTIONS);\n\n/**\n * Camera projections a baked sprite sheet can ship. `iso` is directional\n * (se/sw physical sheets, ne/nw by mirror); `front`/`top`/`perspective` are\n * single fixed-camera sheets (the mesh reference-sheet camera vocabulary).\n */\nexport const SHEET_PROJECTIONS = ['iso', 'front', 'back', 'top', 'perspective'] as const;\n\nexport type SheetProjection = (typeof SHEET_PROJECTIONS)[number];\n\nexport const SheetProjectionSchema = z.enum(SHEET_PROJECTIONS);\n\n// ============================================================================\n// Animation Definition\n// ============================================================================\n\n/**\n * Definition for a single named animation within a sprite sheet: which row\n * it occupies, how many frames it has, and its playback rate. This is the\n * shape actually consumed by `@almadar/ui`'s sprite-sheet renderer\n * (`spriteAnimation.ts`'s `frameRect`/`getCurrentFrameFromDef`) — moved here\n * verbatim rather than reconciled with a differently-shaped guess, since\n * `@almadar/ui`'s version is the one with real production consumers.\n */\nexport interface AnimationDef {\n /** Row index in the sprite sheet (0-based; each animation occupies one row). */\n row: number;\n /** Number of frames in this animation. */\n frames: number;\n /** Frames per second. */\n frameRate: number;\n /** Whether the animation loops. */\n loop: boolean;\n}\n\nexport const AnimationDefSchema = z.object({\n row: z.number().int().nonnegative(),\n frames: z.number().int().positive(),\n frameRate: z.number().positive(),\n loop: z.boolean(),\n});\n\n// ============================================================================\n// Sprite Sheet Atlas\n// ============================================================================\n\n/**\n * Parsed sprite-sheet atlas JSON — the contract a `spriteSheet`-role `Asset.url`\n * resolves to when fetched (see `Asset.url` usage in `@almadar/ui`'s\n * `useUnitSpriteAtlas`). A unit's `sprite?: Asset` stays the static single-pose\n * image; `spriteSheet?: Asset` is a SEPARATE reference whose URL points at a\n * `SpriteSheetAtlas`-shaped JSON manifest (e.g. `.../guardian-sprite-sheet.json`),\n * not a PNG. Frame-cutting geometry lives here, not inlined onto `Asset` — an\n * `Asset` traveling through `render-ui` every tick stays small.\n */\nexport interface SpriteSheetAtlas {\n /** Unit archetype key. */\n unit?: string;\n /** Visual type key. */\n type?: string;\n /** Width of a single frame in pixels. */\n frameWidth: number;\n /** Height of a single frame in pixels. */\n frameHeight: number;\n /** Number of columns (frames per row). */\n columns: number;\n /** Number of rows (animations). */\n rows: number;\n /** Directions present as physical PNG files. */\n directions: SpriteDirection[];\n /** Relative PNG sheet paths per direction. */\n sheets: Partial<Record<SpriteDirection, string>>;\n /** Animation row layout keyed by animation name. Unit sheets use the canonical `AnimationName` rows; one-shot fx sheets declare their own names (e.g. `burst`) — the manifest is authoritative for its rows. */\n animations: Partial<Record<string, AnimationDef>>;\n /**\n * Per-projection sheet PNGs (additive; absent on legacy atlases). `iso`\n * mirrors `sheets` (directional se/sw); the fixed cameras carry one sheet\n * each. `sheets` remains the iso back-compat alias — writers emit both.\n */\n projections?: {\n iso?: Partial<Record<SpriteDirection, string>>;\n front?: string;\n back?: string;\n top?: string;\n perspective?: string;\n };\n}\n\nexport const SpriteSheetAtlasSchema = z.object({\n unit: z.string().optional(),\n type: z.string().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n directions: z.array(SpriteDirectionSchema),\n sheets: z.record(SpriteDirectionSchema, z.string()),\n animations: z.record(z.string(), AnimationDefSchema),\n projections: z\n .object({\n iso: z.record(SpriteDirectionSchema, z.string()).optional(),\n front: z.string().optional(),\n back: z.string().optional(),\n top: z.string().optional(),\n perspective: z.string().optional(),\n })\n .optional(),\n});\n\n// ============================================================================\n// Texture Atlas — named-subrect packed sheet (the industry standard)\n// ============================================================================\n\n/**\n * One named sub-rectangle inside a packed sheet. Mirrors the ShoeBox /\n * TexturePacker `<SubTexture>` element every Kenney `Spritesheet/*.xml` ships\n * (`x`/`y`/`width`/`height` = the rect in the sheet PNG; `frameX`/`frameY`/\n * `frameWidth`/`frameHeight` = the trim/pad offsets for sprites packed with\n * transparent edges removed — optional, present only on trimmed atlases).\n */\nexport interface SubTexture {\n x: number;\n y: number;\n width: number;\n height: number;\n frameX?: number;\n frameY?: number;\n frameWidth?: number;\n frameHeight?: number;\n}\n\nexport const SubTextureSchema = z.object({\n x: z.number().nonnegative(),\n y: z.number().nonnegative(),\n width: z.number().positive(),\n height: z.number().positive(),\n frameX: z.number().optional(),\n frameY: z.number().optional(),\n frameWidth: z.number().positive().optional(),\n frameHeight: z.number().positive().optional(),\n});\n\n/**\n * A packed sheet + its named sub-rectangles — the canonical parse target for a\n * Kenney `Spritesheet/*.xml` atlas. A STATIC tile/prop/UI Asset references one\n * of these: `{ url: <sheet.png>, atlas: <this.json>, sprite: \"grass.png\" }` →\n * the renderer fetches the sheet + atlas ONCE and blits the named sub-rect,\n * instead of loading N individual PNGs. (Animated actors use `SpriteSheetAtlas`\n * instead; a uniform-grid tile page uses `Tilesheet`.)\n */\nexport interface TextureAtlas {\n /** Relative path to the sheet PNG the sub-rects index into (the atlas's own `imagePath`). */\n imagePath: string;\n /** Sub-rectangles keyed by their atlas name (e.g. `\"grass.png\"`). */\n subTextures: Record<string, SubTexture>;\n}\n\nexport const TextureAtlasSchema = z.object({\n imagePath: z.string(),\n subTextures: z.record(z.string(), SubTextureSchema),\n});\n\n// ============================================================================\n// Tilesheet — uniform-grid packed page (cut by index)\n// ============================================================================\n\n/**\n * A uniform-grid tile page — the shape a Kenney `Tilesheet/` sheet takes (e.g.\n * Pirate Pack: \"each tile is 64×64, no margin\"). Tiles are cut by `(col,row)`\n * index rather than by named rect. `names` is present only when a sibling\n * `.xml`/`.txt` supplies an index→name list; otherwise a tile is addressed by\n * its `\"col,row\"` (or flat index) via `Asset.sprite`.\n */\nexport interface Tilesheet {\n /** Relative path to the tile sheet PNG. */\n imagePath: string;\n /** Width of one tile cell in pixels. */\n tileWidth: number;\n /** Height of one tile cell in pixels. */\n tileHeight: number;\n /** Number of columns in the grid. */\n columns: number;\n /** Number of rows in the grid. */\n rows: number;\n /** Outer margin before the first tile, in pixels (default 0). */\n margin?: number;\n /** Gap between adjacent tiles, in pixels (default 0). */\n spacing?: number;\n /** Optional index→name labels when a descriptor supplies them. */\n names?: string[];\n}\n\nexport const TilesheetSchema = z.object({\n imagePath: z.string(),\n tileWidth: z.number().positive(),\n tileHeight: z.number().positive(),\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n margin: z.number().nonnegative().optional(),\n spacing: z.number().nonnegative().optional(),\n names: z.array(z.string()).optional(),\n});\n\n// ============================================================================\n// Semantic Asset Reference\n// ============================================================================\n\n/**\n * Semantic reference to an asset (not a hardcoded path).\n * Resolved to actual paths at compile time via asset maps.\n */\nexport type SemanticAssetRef = {\n /**\n * Entity role — a free string. Core no longer constrains the vocabulary to\n * `EntityRole` (that enum stays an exported shared reference for the asset\n * tool + renderer); genre boards may use their own roles (`boss`, `tower`, …).\n */\n role: string;\n /** Sub-category within role (hero, slime, coin, etc.) */\n category: string;\n /** Required animations for this entity */\n animations?: string[];\n /** Visual style preference */\n style?: VisualStyle;\n /** Variant identifier (for multiple versions) */\n variant?: string;\n /** 2D sprite vs 3D model — the rendering dimension the consuming canvas needs. */\n dimension?: AssetDimension;\n /** Rendering aspect ratio (square sprite/portrait/tile, 16:9 backdrop, 5:7 card, 8:1 fx-strip). */\n aspect?: AssetAspect;\n};\n\nexport const SemanticAssetRefSchema = z.object({\n role: z.string().min(1),\n category: z.string().min(1),\n animations: z.array(z.string()).optional(),\n style: VisualStyleSchema.optional(),\n variant: z.string().optional(),\n dimension: AssetDimensionSchema.optional(),\n aspect: AssetAspectSchema.optional(),\n});\n\n// ============================================================================\n// Asset — the UNIFIED asset type\n// ============================================================================\n\n/**\n * The single asset type: a `SemanticAssetRef` (role/dimension/animations/aspect/style)\n * WITH its resolved URL folded in. Used everywhere an asset is referenced — a lolo\n * board `assetManifest` (`Map string Asset`), every `@almadar/ui` game prop, the\n * asset-workflow's resolved/pool assets, and the inspector picker. Replaces the bare\n * `AssetUrl`-string asset field so the render metadata travels WITH the asset (no\n * pixel-dimension or filename heuristics needed to know sheet-vs-frame / 2d-vs-3d).\n */\nexport interface Asset extends SemanticAssetRef {\n /** The resolved asset URL. When `atlas`/`sprite` are set this is the SHEET png; otherwise a standalone image. */\n url: AssetUrl;\n /**\n * Optional atlas JSON (a `TextureAtlas` or `Tilesheet`) that slices `url`.\n * When present with `sprite`, the renderer fetches sheet + atlas once and\n * blits one sub-rect instead of loading a standalone PNG. Absent → `url` is\n * a plain whole-image asset (the existing, non-atlas path).\n */\n atlas?: AssetUrl;\n /**\n * The sub-texture selector within `atlas`: a `SubTexture` name for a\n * `TextureAtlas` (e.g. `\"grass.png\"`), or a `\"col,row\"`/flat index for a\n * `Tilesheet`. Only meaningful alongside `atlas`.\n */\n sprite?: string;\n /** Optional display name (inspector picker). */\n name?: string;\n /** Optional thumbnail URL (inspector picker grid). */\n thumbnailUrl?: string;\n /** Authored generation subject (visualDNA) for asset-workflow regeneration. */\n prompt?: string;\n /** Authored per-animation frame choreography — the exact pose per frame, the only pose source for animated slots. */\n choreography?: Record<string, string[]>;\n}\n\nexport const AssetSchema = SemanticAssetRefSchema.extend({\n url: z.string(),\n atlas: z.string().optional(),\n sprite: z.string().optional(),\n name: z.string().optional(),\n thumbnailUrl: z.string().optional(),\n prompt: z.string().optional(),\n choreography: z.record(z.string(), z.array(z.string())).optional(),\n});\n\n// ============================================================================\n// Asset Catalog\n// ============================================================================\n\n/**\n * Single browsable asset in the inspector picker catalog.\n * Backs the asset/icon pickers — a flat list the inspector renders for\n * the user to choose from when a config field's type is `'asset'`.\n */\nexport interface AssetCatalogEntry {\n /** Resolvable URL to the asset. */\n url: string;\n /** Display name for the asset. */\n name: string;\n /** Grouping category within the catalog. */\n category: string;\n /** Asset kind the picker dispatches on. */\n kind: 'image' | 'spritesheet' | 'audio' | 'scene' | 'portrait' | 'model' | 'other';\n /** Optional thumbnail URL for grid previews. */\n thumbnailUrl?: string;\n /** 2D sprite vs 3D model — the asset's actual rendering dimension. */\n dimension?: AssetDimension;\n /** The asset's actual rendering aspect ratio. */\n aspect?: AssetAspect;\n}\n\nexport const AssetCatalogEntrySchema = z.object({\n url: z.string(),\n name: z.string(),\n category: z.string(),\n kind: z.enum(['image', 'spritesheet', 'audio', 'scene', 'portrait', 'model', 'other']),\n thumbnailUrl: z.string().optional(),\n dimension: AssetDimensionSchema.optional(),\n aspect: AssetAspectSchema.optional(),\n});\n\n/**\n * Flat list of browsable assets surfaced by the inspector pickers.\n */\nexport type AssetCatalog = AssetCatalogEntry[];\n\nexport const AssetCatalogSchema = z.array(AssetCatalogEntrySchema);\n\n/**\n * Asset-reference URL marker. A plain alias over `string` — the value is a\n * resolvable asset URL — but the named type lets the pattern-sync tool\n * (`tools/almadar-pattern-sync/parser.ts`) detect a component prop as an asset\n * field (tagged `asset`) the same way `EventKey`/`LucideIcon` are detected by\n * type identity. Components annotate image/url props as `AssetUrl` (`src`,\n * `backgroundImage`, `avatar`, …); the generator emits a `string` config knob\n * declared as the `asset` config type, which the property inspector dispatches\n * an AssetPicker on. Not branded — asset urls originate from user data, so cast\n * friction would buy nothing; the value is the marker the tool finds.\n */\nexport type AssetUrl = string;\n\n// ============================================================================\n// ScenePos — neutral scene coordinate\n// ============================================================================\n\n/**\n * A neutral position in scene space: 2D (`x`,`y`) or optionally 3D (`x`,`y`,`z`).\n * The single coordinate type shared by every drawable descriptor and camera pose\n * across the 2D and 3D canvas hosts, so a scene composes from the same `{x,y,z?}`\n * regardless of projection or painter. Logical, not pixel — the host's projector\n * maps a `ScenePos` to screen space.\n */\nexport interface ScenePos {\n x: number;\n y: number;\n z?: number;\n}\n\nexport const ScenePosSchema = z.object({\n x: z.number(),\n y: z.number(),\n z: z.number().optional(),\n});\n\n// ============================================================================\n// Camera — neutral camera pose shared by the 2D and 3D canvas hosts\n// ============================================================================\n\n/**\n * Camera behaviors, unifying the former per-host vocab (2D `camera` string +\n * 3D `cameraMode`). `isometric`/`top-down`/`front` are fixed framings (`front` =\n * the straight-on flat elevation — side-scroller / reference-sheet view);\n * `follow`/`chase` track a target; `perspective` is the 3D dramatic framing.\n */\nexport const CAMERA_MODES = ['isometric', 'perspective', 'top-down', 'front', 'follow', 'chase'] as const;\n\nexport type CameraMode = (typeof CAMERA_MODES)[number];\n\nexport const CameraModeSchema = z.enum(CAMERA_MODES);\n\n/**\n * A neutral camera pose shared by the 2D and 3D canvas hosts, so `type: canvas`\n * carries one camera object regardless of painter. `pos`/`target` are `ScenePos`\n * (logical scene space, not pixels); `zoom` scales the view (the former `scale`);\n * `fov` is the 3D field of view; `mode` selects the framing/tracking behavior.\n * Every field is optional — an omitted camera means the host's default framing.\n */\nexport interface Camera {\n pos?: ScenePos;\n target?: ScenePos;\n zoom?: number;\n fov?: number;\n mode?: CameraMode;\n /** Orbit the mode's framing position around the vertical axis through the target, in radians (3D hosts only). */\n azimuth?: number;\n /** Orbit height angle above the ground plane, in radians (3D hosts only). */\n elevation?: number;\n}\n\nexport const CameraSchema = z.object({\n pos: ScenePosSchema.optional(),\n target: ScenePosSchema.optional(),\n zoom: z.number().optional(),\n fov: z.number().optional(),\n mode: CameraModeSchema.optional(),\n azimuth: z.number().optional(),\n elevation: z.number().optional(),\n});\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type SemanticAssetRefInput = z.input<typeof SemanticAssetRefSchema>;\nexport type AnimationDefInput = z.input<typeof AnimationDefSchema>;\nexport type AssetCatalogEntryInput = z.input<typeof AssetCatalogEntrySchema>;\nexport type SpriteSheetAtlasInput = z.input<typeof SpriteSheetAtlasSchema>;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Creates a semantic asset key from role and category.\n * \n * Generates a unique asset identifier by combining role and category\n * with a colon separator. Used for asset management and lookup.\n * \n * @param {EntityRole} role - Entity role (e.g., 'player', 'enemy')\n * @param {string} category - Asset category (e.g., 'sprite', 'animation')\n * @returns {string} Asset key in format 'role:category'\n * \n * @example\n * createAssetKey('player', 'sprite'); // returns 'player:sprite'\n * createAssetKey('enemy', 'animation'); // returns 'enemy:animation'\n */\nexport function createAssetKey(role: EntityRole, category: string): string {\n return `${role}:${category}`;\n}\n\n/**\n * Parses an asset key into role and category components.\n * \n * Deconstructs an asset key string (format 'role:category') into its\n * constituent parts. Returns null if the key format is invalid.\n * \n * @param {string} key - Asset key in format 'role:category'\n * @returns {{ role: string; category: string } | null} Parsed components or null\n * \n * @example\n * parseAssetKey('player:sprite'); // returns { role: 'player', category: 'sprite' }\n * parseAssetKey('enemy:animation'); // returns { role: 'enemy', category: 'animation' }\n * parseAssetKey('invalid'); // returns null\n */\nexport function parseAssetKey(key: string): { role: string; category: string } | null {\n const parts = key.split(':');\n if (parts.length !== 2) return null;\n return { role: parts[0], category: parts[1] };\n}\n\n/**\n * Gets common animations for an entity role.\n * \n * Returns an array of default animation names appropriate for the\n * specified entity role. Used for asset configuration and validation.\n * \n * @param {EntityRole} role - Entity role\n * @returns {string[]} Array of default animation names\n * \n * @example\n * getDefaultAnimationsForRole('player'); // returns ['idle', 'run', 'jump', 'fall', 'attack', 'hurt', 'die']\n * getDefaultAnimationsForRole('enemy'); // returns ['idle', 'walk', 'attack', 'hurt', 'die']\n */\nexport function getDefaultAnimationsForRole(role: EntityRole): string[] {\n switch (role) {\n case 'player':\n return ['idle', 'run', 'jump', 'fall', 'attack', 'hurt', 'die'];\n case 'enemy':\n return ['idle', 'walk', 'attack', 'hurt', 'die'];\n case 'npc':\n return ['idle', 'walk', 'talk'];\n case 'item':\n return ['idle', 'collected'];\n case 'tile':\n return ['static'];\n case 'projectile':\n return ['fly', 'hit', 'expire'];\n case 'effect':\n return ['play'];\n case 'ui':\n return ['normal', 'hover', 'pressed', 'disabled'];\n case 'decoration':\n return ['idle'];\n case 'vehicle':\n return ['idle', 'move', 'brake'];\n default:\n return ['idle'];\n }\n}\n\n/**\n * Validates that an asset reference has required animations.\n * \n * Checks if an asset reference contains all required animations.\n * Returns an error message if validation fails, or null if valid.\n * \n * @param {SemanticAssetRef} assetRef - Asset reference to validate\n * @param {string[]} requiredAnimations - Required animation names\n * @returns {string | null} Error message or null if valid\n * \n * @example\n * validateAssetAnimations(assetRef, ['idle', 'run']); // returns null if valid\n * validateAssetAnimations(assetRef, ['missing-animation']); // returns error message\n */\nexport function validateAssetAnimations(\n assetRef: SemanticAssetRef,\n requiredAnimations: string[]\n): { valid: boolean; missing: string[] } {\n const provided = assetRef.animations || [];\n const missing = requiredAnimations.filter((anim) => !provided.includes(anim));\n return { valid: missing.length === 0, missing };\n}\n\n// ============================================================================\n// Sprite Sheet Layout — the canonical unit sheet convention (owner-approved\n// \"Sheet convergence\": 8 cols x 5 rows @ 256px, dark charcoal background).\n// `tools/asset-workflow`'s `spritesheet-bake.ts` (SPRITE_LAYOUT) and\n// `prompt-composer.ts` derive from this; this is the single source.\n// ============================================================================\n\nexport const SPRITE_SHEET_LAYOUT = {\n frameWidth: 256,\n frameHeight: 256,\n columns: 8,\n rows: 5,\n background: '#20202E',\n} as const;\n\nexport type SpriteSheetLayout = typeof SPRITE_SHEET_LAYOUT;\n\n/**\n * The canonical unit animation row table (idle/walk/attack/hit/death), one\n * row per `AnimationName`, in sheet-row order. Mirrors\n * `tools/asset-workflow/src/spritesheet-bake.ts`'s `SPRITE_LAYOUT`.\n */\nexport const DEFAULT_UNIT_ANIMATION_ROWS: ReadonlyArray<{ name: AnimationName } & AnimationDef> = [\n { name: 'idle', row: 0, frames: 4, loop: true, frameRate: 6 },\n { name: 'walk', row: 1, frames: 8, loop: true, frameRate: 10 },\n { name: 'attack', row: 2, frames: 6, loop: false, frameRate: 12 },\n { name: 'hit', row: 3, frames: 3, loop: false, frameRate: 8 },\n { name: 'death', row: 4, frames: 6, loop: false, frameRate: 8 },\n] as const;\n\n/**\n * Builds the canonical unit `SpriteSheetAtlas` from `SPRITE_SHEET_LAYOUT` +\n * `DEFAULT_UNIT_ANIMATION_ROWS` for a given set of direction sheets. Directions\n * default to whichever keys `sheets` actually carries (legacy se/sw-only packs\n * included), or the caller can force a specific set via `opts.directions`.\n */\nexport function defaultUnitAtlas(\n sheets: SpriteSheetAtlas['sheets'],\n opts?: { directions?: SpriteDirection[] }\n): SpriteSheetAtlas {\n const directions = opts?.directions ?? SPRITE_DIRECTIONS.filter((direction) => sheets[direction] !== undefined);\n const animations: Partial<Record<string, AnimationDef>> = {};\n for (const { name, ...def } of DEFAULT_UNIT_ANIMATION_ROWS) {\n animations[name] = def;\n }\n return {\n frameWidth: SPRITE_SHEET_LAYOUT.frameWidth,\n frameHeight: SPRITE_SHEET_LAYOUT.frameHeight,\n columns: SPRITE_SHEET_LAYOUT.columns,\n rows: SPRITE_SHEET_LAYOUT.rows,\n directions,\n sheets,\n animations,\n };\n}\n\n// ============================================================================\n// Manifest Entry — the kflow-assets `manifest.json` row shape. Core is the\n// owner; `tools/asset-workflow`'s `ExtendedManifestEntry` converges onto this\n// (mirrors `tools/asset-workflow/src/asset-schema.ts`'s `CanvasAffinity`,\n// `FrameSpec`, `AssetLicense`, `SourceCatalog` literal unions).\n// ============================================================================\n\nexport const MANIFEST_ENTRY_KINDS = ['model', 'image', 'spritesheet', 'audio', 'json'] as const;\n\nexport type ManifestEntryKind = (typeof MANIFEST_ENTRY_KINDS)[number];\n\nexport const ManifestEntryKindSchema = z.enum(MANIFEST_ENTRY_KINDS);\n\n// ============================================================================\n// Game audio\n// ============================================================================\n\n/**\n * One entry of a game's sound manifest, keyed by logical cue name. Core owns\n * the shape so both the render substrate (`useGameAudio` / the `game-audio-cue`\n * pattern) and the generated `.lolo` factories resolve the SAME declaration —\n * a hook-local interface is invisible to the pattern extractor and lowers to a\n * shapeless `object`, which the `.lolo` type system rejects outright.\n */\nexport interface SoundEntry {\n /** Single path, or several to pick from at random on each play. */\n path: string | string[];\n /** Volume 0-1, multiplied by the master volume. */\n volume?: number;\n /** Whether this sound loops (background music). */\n loop?: boolean;\n /** Concurrent Audio instances kept in the pool. */\n poolSize?: number;\n /** Start automatically on the first user interaction. */\n autostart?: boolean;\n /** Use crossfade transitions when played as music. */\n crossfade?: boolean;\n /** Crossfade duration in milliseconds. */\n crossfadeDurationMs?: number;\n}\n\nexport const SoundEntrySchema = z.object({\n path: z.union([z.string(), z.array(z.string())]),\n volume: z.number().optional(),\n loop: z.boolean().optional(),\n poolSize: z.number().optional(),\n autostart: z.boolean().optional(),\n crossfade: z.boolean().optional(),\n crossfadeDurationMs: z.number().optional(),\n});\n\n/** A game's sound manifest: logical cue name → its definition. */\nexport type AudioManifest = Record<string, SoundEntry>;\n\nexport const AudioManifestSchema = z.record(z.string(), SoundEntrySchema);\n\nexport const MANIFEST_CANVAS_AFFINITIES = ['isometric', 'hex', 'flat', 'side', '3d', 'none'] as const;\n\nexport type ManifestCanvasAffinity = (typeof MANIFEST_CANVAS_AFFINITIES)[number];\n\nexport const ManifestCanvasAffinitySchema = z.enum(MANIFEST_CANVAS_AFFINITIES);\n\nexport const MANIFEST_SOURCE_CATALOGS = ['kenny', 'kekec-assets', 'iram-assets', 'trait-wars-assets', 'kflow-assets'] as const;\n\nexport type ManifestSourceCatalog = (typeof MANIFEST_SOURCE_CATALOGS)[number];\n\nexport const ManifestSourceCatalogSchema = z.enum(MANIFEST_SOURCE_CATALOGS);\n\nexport const MANIFEST_ASSET_LICENSES = ['CC0', 'proprietary'] as const;\n\nexport type ManifestAssetLicense = (typeof MANIFEST_ASSET_LICENSES)[number];\n\nexport const ManifestAssetLicenseSchema = z.enum(MANIFEST_ASSET_LICENSES);\n\n/**\n * Path of the sheet's `atlas.json` relative to the pack's `shared/` root\n * (`riya-platformer/units/riya/atlas.json`) — the executable frame truth for\n * unit sheets whose rows are not uniform.\n */\nexport type ManifestAtlasRef = string;\n\n/** Tile/sprite-sheet frame layout for a manifest row, an atlas reference, else `null`. */\nexport type ManifestFrameSpec =\n | { kind: 'iso-tile'; w: number; h: number }\n | { kind: 'sprite-sheet'; frame: number; cols: number; rows: number }\n | ManifestAtlasRef\n | null;\n\nexport const ManifestFrameSpecSchema = z.union([\n z.object({ kind: z.literal('iso-tile'), w: z.number(), h: z.number() }),\n z.object({ kind: z.literal('sprite-sheet'), frame: z.number(), cols: z.number(), rows: z.number() }),\n z.string().min(1),\n z.null(),\n]);\n\n/**\n * One row of `almadar-assets/kflow-assets/manifest.json`. Core owns this\n * shape; `tools/asset-workflow`'s `ExtendedManifestEntry` converges onto it.\n */\nexport interface ManifestEntry {\n url: string;\n name: string;\n category: string;\n kind: ManifestEntryKind;\n width: number;\n height: number;\n canvasAffinity: ManifestCanvasAffinity;\n genreAffinity: string[];\n swapClass: string;\n sourceCatalog: ManifestSourceCatalog;\n frameSpec: ManifestFrameSpec;\n /** Provenance-extended field: present on the promote/register path only. */\n license?: ManifestAssetLicense;\n}\n\nexport const ManifestEntrySchema = z.object({\n url: z.string(),\n name: z.string(),\n category: z.string(),\n kind: ManifestEntryKindSchema,\n width: z.number(),\n height: z.number(),\n canvasAffinity: ManifestCanvasAffinitySchema,\n genreAffinity: z.array(z.string()),\n swapClass: z.string(),\n sourceCatalog: ManifestSourceCatalogSchema,\n frameSpec: ManifestFrameSpecSchema,\n license: ManifestAssetLicenseSchema.optional(),\n});\n\nexport type ManifestEntryInput = z.input<typeof ManifestEntrySchema>;\n\n// ============================================================================\n// Manifest -> Asset Catalog adapter\n// ============================================================================\n\nconst ASSET_CATALOG_ENTRY_KINDS: readonly AssetCatalogEntry['kind'][] = [\n 'image',\n 'spritesheet',\n 'audio',\n 'scene',\n 'portrait',\n 'model',\n 'other',\n];\n\nconst MODEL_URL_EXTENSIONS = ['.glb', '.gltf'];\nconst AUDIO_URL_EXTENSIONS = ['.mp3', '.ogg', '.wav'];\n\nfunction urlEndsWithAny(url: string, extensions: readonly string[]): boolean {\n const lower = url.toLowerCase();\n return extensions.some((extension) => lower.endsWith(extension));\n}\n\n/**\n * Declared, order-sensitive rule for deriving the catalog `kind` from a\n * manifest row: `frameSpec`/`kind==='spritesheet'` beats extension, which\n * beats the manifest's own `kind`. No filename-keyword guessing.\n */\nfunction deriveManifestAssetKind(entry: ManifestEntry): AssetCatalogEntry['kind'] {\n if (typeof entry.frameSpec === 'string' || entry.frameSpec?.kind === 'sprite-sheet' || entry.kind === 'spritesheet') return 'spritesheet';\n if (entry.kind === 'model' || urlEndsWithAny(entry.url, MODEL_URL_EXTENSIONS)) return 'model';\n if (entry.kind === 'audio' || urlEndsWithAny(entry.url, AUDIO_URL_EXTENSIONS)) return 'audio';\n if (entry.kind === 'image') return 'image';\n return 'other';\n}\n\nfunction parseAssetAspectRatio(aspect: AssetAspect): number {\n const [w, h] = aspect.split(':').map(Number);\n return w / h;\n}\n\nconst ASSET_ASPECT_RATIO_TOLERANCE = 0.01;\n\n/**\n * The asset's aspect only when width/height are both known (> 0) and their\n * ratio matches exactly one `ASSET_ASPECTS` entry within 1%; otherwise\n * omitted (never guessed).\n */\nfunction deriveManifestAssetAspect(width: number, height: number): AssetAspect | undefined {\n if (width <= 0 || height <= 0) return undefined;\n const ratio = width / height;\n for (const aspect of ASSET_ASPECTS) {\n const expected = parseAssetAspectRatio(aspect);\n if (Math.abs(ratio / expected - 1) <= ASSET_ASPECT_RATIO_TOLERANCE) return aspect;\n }\n return undefined;\n}\n\nconst ABSOLUTE_URL_PATTERN = /^[a-z][a-z0-9+.-]*:\\/\\//i;\n\n/** Prefixes a relative manifest url with `cdnPrefix`; leaves an absolute url untouched. */\nfunction resolveManifestUrl(url: string, cdnPrefix?: string): string {\n if (!cdnPrefix || ABSOLUTE_URL_PATTERN.test(url)) return url;\n const prefix = cdnPrefix.endsWith('/') ? cdnPrefix : `${cdnPrefix}/`;\n const rest = url.startsWith('/') ? url.slice(1) : url;\n return `${prefix}${rest}`;\n}\n\n/**\n * Adapts kflow-assets manifest rows into the inspector picker's\n * `AssetCatalog`. The ONE deterministic derivation the Kura assets server\n * route (`GET /api/assets/catalog`) and any other manifest consumer share.\n */\nexport function manifestToAssetCatalog(entries: ReadonlyArray<ManifestEntry>, opts?: { cdnPrefix?: string }): AssetCatalog {\n return entries.map((entry) => {\n const kind = deriveManifestAssetKind(entry);\n const dimension: AssetDimension = entry.canvasAffinity === '3d' ? '3d' : '2d';\n const aspect = deriveManifestAssetAspect(entry.width, entry.height);\n const url = resolveManifestUrl(entry.url, opts?.cdnPrefix);\n const catalogEntry: AssetCatalogEntry = {\n url,\n name: entry.name,\n category: entry.category,\n kind,\n dimension,\n };\n if (aspect !== undefined) catalogEntry.aspect = aspect;\n if (kind === 'image' || kind === 'spritesheet') catalogEntry.thumbnailUrl = url;\n return catalogEntry;\n });\n}\n\n// ============================================================================\n// Asset query grammar — Unity-style `t:<kind>` / `l:<label>` + free text.\n// The ONE grammar `parseAssetQuery`/`matchAssetQuery` implement; every\n// consumer (the Kura assets server route, the client's `asset-query.ts`)\n// imports these instead of re-parsing.\n// ============================================================================\n\nconst ASSET_QUERY_TYPE_PREFIX = 't:';\nconst ASSET_QUERY_LABEL_PREFIX = 'l:';\n\nfunction isAssetCatalogEntryKind(value: string): value is AssetCatalogEntry['kind'] {\n return ASSET_CATALOG_ENTRY_KINDS.some((kind) => kind === value);\n}\n\ninterface ParsedAssetQuery {\n text: string;\n kind?: AssetCatalogEntry['kind'];\n labels: string[];\n /** A `t:` token whose value is not a known `AssetCatalogEntry['kind']` — the query matches nothing. */\n unknownKind: boolean;\n}\n\nfunction parseAssetQueryTokens(q: string): ParsedAssetQuery {\n const tokens = q.trim().length > 0 ? q.trim().split(/\\s+/) : [];\n const textParts: string[] = [];\n const labels: string[] = [];\n let kind: AssetCatalogEntry['kind'] | undefined;\n let unknownKind = false;\n for (const token of tokens) {\n if (token.startsWith(ASSET_QUERY_TYPE_PREFIX)) {\n const value = token.slice(ASSET_QUERY_TYPE_PREFIX.length);\n if (isAssetCatalogEntryKind(value)) kind = value;\n else unknownKind = true;\n } else if (token.startsWith(ASSET_QUERY_LABEL_PREFIX)) {\n const value = token.slice(ASSET_QUERY_LABEL_PREFIX.length);\n if (value.length > 0) labels.push(value);\n } else {\n textParts.push(token);\n }\n }\n return { text: textParts.join(' '), kind, labels, unknownKind };\n}\n\n/**\n * Parses a `t:<kind>` / `l:<label>` / free-text asset search query. An\n * unrecognized `t:` value is dropped from the returned `kind` (there is no\n * value of `AssetCatalogEntry['kind']` to report) — `matchAssetQuery`, which\n * shares this same tokenizer internally, is the authority that turns it into\n * \"matches nothing\".\n */\nexport function parseAssetQuery(q: string): { text: string; kind?: AssetCatalogEntry['kind']; labels: string[] } {\n const parsed = parseAssetQueryTokens(q);\n return parsed.kind === undefined ? { text: parsed.text, labels: parsed.labels } : { text: parsed.text, kind: parsed.kind, labels: parsed.labels };\n}\n\n/**\n * Matches one catalog entry against a `t:`/`l:`/free-text query. `l:` labels\n * are ANDed against `entry.category` (exact, case-insensitive); free text is\n * an ANDed case-insensitive substring over `name`+`category`. An unrecognized\n * `t:` kind matches nothing.\n */\nexport function matchAssetQuery(entry: AssetCatalogEntry, q: string): boolean {\n const parsed = parseAssetQueryTokens(q);\n if (parsed.unknownKind) return false;\n if (parsed.kind !== undefined && entry.kind !== parsed.kind) return false;\n for (const label of parsed.labels) {\n if (entry.category.toLowerCase() !== label.toLowerCase()) return false;\n }\n if (parsed.text.length > 0) {\n const haystack = `${entry.name} ${entry.category}`.toLowerCase();\n if (!haystack.includes(parsed.text.toLowerCase())) return false;\n }\n return true;\n}\n","/**\n * Entity Types for Orbital Units\n *\n * Defines the OrbitalEntity type - the nucleus of an Orbital Unit.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { EntityIdSchema } from './identity.js';\nimport type { EntityId } from './identity.js';\nimport { EntityFieldSchema, type EntityField, type FileValue } from './field.js';\nimport { SemanticAssetRefSchema, type SemanticAssetRef } from './asset.js';\nimport { JsonValueSchema, type RuntimeValue } from './json.js';\nimport { SExprSchema, type SExpr } from './expression.js';\n\n// ============================================================================\n// Entity Persistence\n// ============================================================================\n\n/**\n * Entity persistence types.\n *\n * - persistent: Stored in database (has collection)\n * - runtime: Exists only at runtime (not persisted)\n */\nexport type EntityPersistence = 'persistent' | 'runtime';\n\nexport const EntityPersistenceSchema = z.enum([\n 'persistent',\n 'runtime',\n]);\n\n// ============================================================================\n// Orbital Entity\n// ============================================================================\n\n/**\n * OrbitalEntity - the nucleus of an Orbital Unit.\n *\n * This is a simplified entity definition optimized for orbital composition.\n * Collection names are derived automatically from persistence type if not provided.\n */\nexport type OrbitalEntity = {\n /** V4 dual-carry id sibling of `name` — optional until the Phase-7 flip. */\n id?: EntityId;\n\n /** Entity name (PascalCase, e.g., \"Task\", \"User\") */\n name: string;\n\n /** Entity persistence type (defaults to 'persistent' if not specified) */\n persistence?: EntityPersistence;\n\n /** Whether this entity's state is shared across all bound traits (vs per-trait copy). Orthogonal to persistence. */\n shared?: boolean;\n\n /**\n * Whether this entity types the ambient `@user` viewer. Orthogonal to both\n * `persistence` and `shared`: `[persistent: people, identity]` is an\n * app-owned user directory, `[runtime, identity]` the provider-supplied\n * current viewer. At most one per composed program.\n */\n identity?: boolean;\n\n /**\n * `@read` — a per-row predicate (`@entity` = candidate row, `@user` =\n * viewer) ANDed with any call-site `filter:`. The un-bypassable twin of\n * `filter:`, enforced once for every trait that fetches this entity.\n */\n read_policy?: SExpr;\n\n /** `@create` — `@entity` binds the incoming data about to become a row. */\n create_policy?: SExpr;\n\n /** `@update` — `@entity` binds the existing row before mutation. */\n update_policy?: SExpr;\n\n /** `@delete` — same binding shape as `@update`. */\n delete_policy?: SExpr;\n\n /**\n * `@<op> none \"<reason>\"` — a directive's omission, DECLARED.\n *\n * Runtime behaviour is identical to leaving the directive out (an absent\n * policy is allow-all). It records that the author concluded no per-row\n * predicate can express the rule — usually because visibility depends on a\n * DIFFERENT entity, which a per-row predicate cannot join across. Without\n * it a lint must flag considered and forgotten omissions alike, and a lint\n * that flags correct code is one people learn to ignore.\n */\n access_waivers?: {\n read?: string;\n create?: string;\n update?: string;\n delete?: string;\n };\n\n /** Collection name (auto-derived if not provided for persistent entities) */\n collection?: string;\n\n /** Entity fields */\n fields: EntityField[];\n\n /** Pre-authored instances (seed data or static reference data) */\n instances?: EntityRow[];\n\n /** Auto-add createdAt/updatedAt timestamps */\n timestamps?: boolean;\n\n /** Soft delete support */\n softDelete?: boolean;\n\n /** Human-readable description */\n description?: string;\n\n /** Visual prompt for AI generation */\n visual_prompt?: string;\n\n /** Semantic asset reference for visual representation (games) */\n assetRef?: SemanticAssetRef;\n};\n\nexport const OrbitalEntitySchema = z.object({\n name: z.string().min(1, 'Entity name is required'),\n // V4 arena id (`EntityDefinition.id`); declared so the strip-mode zod gate\n // carries an imported entity's id through instead of erasing it.\n id: EntityIdSchema.optional(),\n persistence: EntityPersistenceSchema.default('persistent'),\n shared: z.boolean().optional(),\n // Must stay in step with the Rust serde field (`EntityDefinition.identity`,\n // orbital-core/src/schema/types.rs). `z.object()` STRIPS unknown keys rather\n // than rejecting them, so a Rust-only field works on the compiled path and\n // silently vanishes on the interpreter path.\n identity: z.boolean().optional(),\n // Same \"must stay in step with Rust serde\" hazard as `identity` above —\n // these four mirror `EntityDefinition.{read,create,update,delete}_policy`.\n // Rust has no `rename_all` on this struct, so the wire key IS snake_case\n // (unlike this file's other camelCase fields, which are Rust-side-absent\n // and so never hit this cross-language constraint — see `visual_prompt`\n // just below for the existing precedent).\n read_policy: SExprSchema.optional(),\n create_policy: SExprSchema.optional(),\n update_policy: SExprSchema.optional(),\n delete_policy: SExprSchema.optional(),\n // Snake_case for the same cross-language reason as the four policies above.\n access_waivers: z\n .object({\n read: z.string().optional(),\n create: z.string().optional(),\n update: z.string().optional(),\n delete: z.string().optional(),\n })\n .optional(),\n collection: z.string().optional(),\n fields: z.array(EntityFieldSchema).min(1, 'At least one field is required'),\n instances: z.array(z.record(JsonValueSchema)).optional(),\n timestamps: z.boolean().optional(),\n softDelete: z.boolean().optional(),\n description: z.string().optional(),\n visual_prompt: z.string().optional(),\n assetRef: SemanticAssetRefSchema.optional(),\n});\n\nexport type OrbitalEntityInput = z.input<typeof OrbitalEntitySchema>;\n\n// ============================================================================\n// Type Aliases (for cleaner imports)\n// ============================================================================\n\n/** Alias for OrbitalEntity - preferred name */\nexport type Entity = OrbitalEntity;\n\n/** Alias for OrbitalEntitySchema - preferred name */\nexport const EntitySchema = OrbitalEntitySchema;\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Derives the collection name for a persistent entity.\n * \n * Generates the database collection name by converting the entity name\n * to lowercase and adding an 's' suffix (simple pluralization).\n * Returns undefined for non-persistent (runtime) entities.\n * \n * @param {OrbitalEntity} entity - Entity to derive collection name for\n * @returns {string | undefined} Collection name or undefined for non-persistent entities\n * \n * @example\n * deriveCollection({ name: 'User', persistence: 'persistent' }); // returns 'users'\n * deriveCollection({ name: 'Task', persistence: 'runtime' }); // returns undefined\n */\nexport function deriveCollection(entity: OrbitalEntity): string | undefined {\n if (entity.persistence !== 'persistent') {\n return undefined;\n }\n // Lowercase + 's' suffix (simple pluralization)\n return entity.name.toLowerCase() + 's';\n}\n\n/**\n * Checks if an entity is runtime-only (not persisted).\n * \n * Type guard to determine if an entity exists only at runtime\n * and is not stored in the database.\n * \n * @param {OrbitalEntity} entity - Entity to check\n * @returns {boolean} True if entity is runtime-only, false otherwise\n * \n * @example\n * isRuntimeEntity({ persistence: 'runtime' }); // returns true\n * isRuntimeEntity({ persistence: 'persistent' }); // returns false\n */\nexport function isRuntimeEntity(entity: OrbitalEntity): boolean {\n return entity.persistence === 'runtime';\n}\n\n/**\n * Checks whether an entity's persistence mode allows `persistence` /\n * `collection` overrides at the factory call site.\n *\n * Only `persistent` entities (explicit or default) support these overrides.\n * Runtime entities are fixed; callers must not expose `persistence` or\n * `collection` params for them.\n *\n * @param persistence - The entity persistence mode (undefined = default persistent)\n * @returns True when overrides are allowed, false otherwise\n *\n * @example\n * persistenceModeAllowsOverrides('persistent'); // returns true\n * persistenceModeAllowsOverrides('runtime'); // returns false\n * persistenceModeAllowsOverrides(undefined); // returns true (default persistent)\n */\nexport function persistenceModeAllowsOverrides(\n persistence: EntityPersistence | undefined,\n): boolean {\n return persistence === 'persistent' || persistence === undefined;\n}\n\n// ============================================================================\n// Entity Instance Data (Runtime)\n// ============================================================================\n\n/**\n * A single field value at runtime.\n * Union of all possible types from FieldType: string, number, boolean, date, array, nested.\n * The nested-record branch's index signature tolerates `undefined` so that\n * TypeScript optional properties (`x?: string`, carrying `string | undefined`)\n * on EntityRow extenders typecheck without ceremony. At JSON serialization\n * time `undefined` is equivalent to \"key absent\" and never appears on the\n * wire; the inclusion here is a pure type-surface accommodation.\n */\nexport type FieldValue = string | number | boolean | Date | null | string[] | FieldValue[] | { [key: string]: FieldValue | undefined };\n\n/** Zod twin of `FieldValue` — the one runtime validator for a stored field slot. */\nexport const FieldValueSchema: z.ZodType<FieldValue> = z.lazy(() =>\n z.union([z.string(), z.number(), z.boolean(), z.date(), z.null(), z.array(FieldValueSchema), z.record(FieldValueSchema.optional())]),\n);\n\n/**\n * What a FORM CONTROL puts on the event bus — the closed set of shapes an\n * Input / Select / Checkbox / Date / multi-select / file field actually\n * produces.\n *\n * A TRANSPORT type, deliberately distinct from `FieldValue`, and the separation\n * is the point. `FieldValue` conflated two jobs: what a control emits, and what\n * an entity field holds. The second never needed it — an entity field always\n * has one declared type (`email : email!`, `age : number`) — so the openness\n * only travelled outward, degrading every generated `.lolo` payload to a\n * shapeless `object`.\n *\n * NOT recursive, and the variants are enumerated from what is actually emitted\n * rather than guessed. `FileValue` is here because the compiler put it here: a\n * scalar-only draft failed against the file field, which hands\n * `Form.handleChange` a `{ name, url, mimeType, sizeBytes }` record.\n *\n * The rule is Aeson's — enumerate the shapes that occur, keep the open type at\n * the boundary, convert on the way in. In `.lolo` that boundary is the\n * `(set @entity.X ?value)` of the receiving transition, where the entity\n * field's own declared type does the checking.\n */\nexport type ControlValue = string | number | boolean | null | string[] | FileValue;\n\n/**\n * Runtime guard for `FieldValue` — narrows interpreter-produced `unknown`\n * values at typed substrate boundaries (e.g. `IntegrationContext.http` body).\n */\nexport function isFieldValue(value: RuntimeValue): value is FieldValue {\n if (value === null) return true;\n const kind = typeof value;\n if (kind === 'string' || kind === 'number' || kind === 'boolean') return true;\n if (value instanceof Date) return true;\n if (Array.isArray(value)) return value.every((item: RuntimeValue) => isFieldValue(item));\n if (kind === 'object' && value !== null && typeof value === 'object') {\n return Object.values(value).every((item: RuntimeValue) => item === undefined || isFieldValue(item));\n }\n return false;\n}\n\n/**\n * One instance of an entity with actual field values.\n * The shape is determined by the Entity definition at schema time.\n *\n * @example\n * // Entity defines: Patient { fullName: string, age: number, active: boolean }\n * // EntityRow is: { id: \"p1\", fullName: \"Sarah\", age: 34, active: true }\n */\nexport type EntityRow = { id?: string } & Record<string, FieldValue | undefined>;\n\n/** Zod twin of `EntityRow` — the one runtime validator for an `@entity` wire row. */\nexport const EntityRowSchema: z.ZodType<EntityRow> = z\n .object({ id: z.string().optional() })\n .catchall(FieldValueSchema.optional());\n\n/**\n * A field-TYPED `EntityRow` — the SINGLE entity type, refined with a concrete\n * field SHAPE `S`. Non-optional members of `S` are REQUIRED, each with its real\n * type; the result stays `& EntityRow`, so the index signature is intact and\n * every other field is still field-open — any domain entity that provides those\n * fields satisfies it.\n *\n * One declaration, two jobs: (1) TypeScript enforces the bound entity has the\n * fields WITH their types (a behavior binding a thinner/mistyped entity fails to\n * typecheck); and (2) pattern-sync reads the same type and writes the entity\n * prop's field shape (`properties` + `requiredFields`) onto the registry, so\n * lolo-ui emits a COMPLETE `entity { … }` (every field, typed + demo-seeded) and\n * the `ORB_X_ENTITY_PROP_CONTRACT` validator rejects an incompatible bind at\n * `orbital validate`. (A raw `EntityRow & { rating: number }` intersection is\n * equivalent for one-off shapes.)\n *\n * @example\n * // HeroOrganism renders entity.title / entity.subtitle:\n * entity?: EntityWith<{ title: string; subtitle?: string }>;\n * // entity.title → string (required)\n * // entity.subtitle → string | undefined (optional)\n * // entity.other → FieldValue | undefined (still field-open)\n */\n// `S extends object` (not `Record<string, FieldValue>`) so a plain `interface`\n// row shape satisfies it — interfaces lack the implicit index signature `Record`\n// requires. FieldValue-compatibility is still enforced structurally: `& EntityRow`\n// intersects every field with the `FieldValue | undefined` index signature, so a\n// non-FieldValue field (e.g. a React `LucideIcon`) collapses to `never` at use.\nexport type EntityWith<S extends object> = EntityRow & S;\n\n/**\n * Collection of entity instances keyed by entity name.\n * Used by OrbPreview mockData, OrbitalServerRuntime state, data grids, etc.\n *\n * @example\n * const data: EntityData = {\n * Patient: [{ id: \"1\", fullName: \"Sarah\", age: 34 }],\n * QueueEntry: [{ id: \"1\", patientName: \"Sarah\", waitMinutes: 12 }],\n * };\n */\nexport type EntityData = Record<string, EntityRow[]>;\n","/**\n * Effect Types (Self-Contained)\n *\n * Defines effect types for trait transitions and ticks.\n * Effects are S-expressions (arrays) that describe actions to perform.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { type SExpr, type Expression, type EventPayload, SExprDataSchema } from './expression.js';\nimport type { RuntimeValue, JsonValue } from './json.js';\nimport { type ServiceParams } from './service.js';\nimport { type EntityRow, type FieldValue } from './entity.js';\n\n// ============================================================================\n// UI Slots\n// ============================================================================\n\n/**\n * Known UI slots where content can be rendered\n */\nexport const UI_SLOTS = [\n // App slots\n 'main',\n 'sidebar',\n 'modal',\n 'drawer',\n 'overlay',\n 'center',\n 'toast',\n 'floating',\n 'system', // For invisible system components (InputListener, CollisionDetector)\n 'content',\n 'screen',\n // Game HUD slots\n 'hud',\n 'hud-top',\n 'hud-bottom',\n 'hud.health',\n 'hud.score',\n 'hud.inventory',\n 'hud.stamina',\n // Game overlay slots\n 'overlay.inventory',\n 'overlay.dialogue',\n 'overlay.menu',\n 'overlay.pause',\n] as const;\n\nexport type UISlot = (typeof UI_SLOTS)[number];\n\nexport const UISlotSchema = z.enum(UI_SLOTS);\n\n// ============================================================================\n// Pattern Config (for render-ui effects)\n// ============================================================================\n\n// Import pattern types for local use and re-export for consumers\nimport type {\n PatternType,\n PatternConfig,\n PatternProps,\n PatternPropsMap,\n AnyPatternConfig,\n} from '../patterns/index.js';\n\n/**\n * Type-safe pattern configuration for render-ui effects.\n *\n * Re-exported from @almadar/patterns. Generated from patterns-registry.json.\n *\n * @example\n * // Type-safe with specific pattern type\n * const config: PatternConfig<'entity-table'> = {\n * patternType: 'entity-table',\n * columns: ['name', 'email'], // ✅ Required prop\n * entity: 'User',\n * };\n *\n * // Error: Property 'columns' is missing (required prop)\n * const bad: PatternConfig<'entity-table'> = { patternType: 'entity-table' };\n *\n * // Error: 'fake-pattern' is not assignable to PatternType\n * const invalid: PatternConfig = { patternType: 'fake-pattern' };\n */\nexport type {\n PatternType,\n PatternConfig,\n PatternProps,\n PatternPropsMap,\n AnyPatternConfig,\n};\n\n// ============================================================================\n// Service Config (for call-service effects)\n// ============================================================================\n\n/**\n * Configuration extracted from call-service effects\n */\nexport type CallServiceConfig = {\n service: string;\n action: string;\n endpoint?: string;\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n params?: ServiceParams;\n onSuccess?: string;\n onError?: string;\n};\n\n// ============================================================================\n// Typed Effect Tuples\n// ============================================================================\n\n/**\n * A binding reference to a render tree stored elsewhere — a trait `config`\n * knob or a payload field — e.g. `\"@config.bodyContent\"`. Resolved to a pattern\n * node at render time. This is how an atom renders a tree that contains data\n * bindings (`entity: \"@payload.data\"`, `fields: \"@config.fields\"`): the tree is\n * a permissive `TraitConfigValue` stored in `config` (a binding string is not a\n * valid `AnyPatternConfig` prop value), and the render-ui effect points at it.\n * Worked example: `std-browse`'s loaded transition is `['render-ui', 'main',\n * '@config.bodyContent']`. The Rust validator accepts this form; this variant\n * lets the TS effect type express it.\n */\nexport type RenderBinding = `@${string}`;\n\n/**\n * A binding reference resolving to a {@link UISlot} at inline time — a trait\n * `config` knob holding the slot name, e.g. `\"@config.reviewSlot\"`. Mirrors\n * {@link RenderBinding} for the SLOT position: the compiler's inline phase\n * substitutes the config value before anything renders, and the Rust\n * validator accepts the pre-substitution form (worked example:\n * `std-approval-gate`'s review queue renders into `@config.reviewSlot`).\n * This variant lets the TS effect type express the template-layer form.\n */\nexport type SlotBinding = `@config.${string}`;\n\n/**\n * Template-layer pattern node: a render tree whose discriminant and/or props\n * are still bindings (`type: '@config.viewPattern'`, `title: '@config.title'`)\n * or loose nested descriptors the compiler's inline phase resolves. The\n * resolved layer is {@link AnyPatternConfig}; this variant lets generated\n * behavior descriptors (std-ts) carry the pre-substitution form the Rust\n * validator accepts (worked example: `std-graphs` renders\n * `{ type: '@config.viewPattern', chartType: '@config.chartType', … }`).\n */\nexport type TemplatePatternConfig = { type: PatternType | RenderBinding } & Record<string, JsonValue>;\n\n/**\n * Render UI effect - displays a pattern in a UI slot.\n * @example ['render-ui', 'main', { patternType: 'entity-table', columns: ['name'] }]\n * @example ['render-ui', 'main', '@config.bodyContent'] // a {@link RenderBinding} target\n * @example ['render-ui', '@config.reviewSlot', { patternType: 'entity-table' }] // a {@link SlotBinding} slot\n */\nexport type RenderUIEffect =\n | ['render-ui', UISlot | SlotBinding, AnyPatternConfig]\n | ['render-ui', UISlot | SlotBinding, AnyPatternConfig, ResolvedPatternProps]\n | ['render-ui', UISlot | SlotBinding, TemplatePatternConfig]\n | ['render-ui', UISlot | SlotBinding, RenderBinding]\n | ['render-ui', UISlot | SlotBinding, null];\n\n/**\n * Lambda expression for per-item rendering in data-grid/data-list.\n * The compiler generates: {(paramName: Record<string, unknown>) => (<>JSX</>)}\n * where @{paramName}.field bindings reference the current iteration item.\n *\n * @example [\"fn\", \"item\", { \"type\": \"stack\", \"children\": [{ \"type\": \"typography\", \"content\": \"@item.title\" }] }]\n */\nexport type RenderItemLambda = ['fn', string, AnyPatternConfig];\n\n/**\n * Dynamic-collection children entry: renders one child per item of a collection\n * expression, authored inline in a `children:` position and kept verbatim as IR\n * (no new node kind). The collection expression is an {@link SExpr} evaluated at\n * render time; the {@link RenderItemLambda} body is instantiated per item with\n * the lambda param bound as an `@item`-scope binding. Both execution paths lower\n * onto the one lambda + `@item` + splice machinery.\n *\n * @example [\"array/map\", \"@entity.tasks\", [\"fn\", \"item\", { \"type\": \"typography\", \"content\": \"@item.title\" }]]\n */\nexport type RenderChildrenMap = ['array/map', SExpr, RenderItemLambda];\n\n/**\n * Trailing options object on navigate effects. `crumb` labels the navigation\n * stack entry the client pushes for the target page (e.g. the record title a\n * list router has in `?row` at push time); without it the entry falls back to\n * the target page's declared/derived label.\n */\nexport type NavigateOptions = { crumb?: string | SExpr };\n\n/**\n * Navigate effect - navigates to an internal page path or an external URL.\n * @example ['navigate', '/tasks'] or ['navigate', '/tasks/:id', { id: '123' }]\n * @example ['navigate', 'https://example.com']\n * @example ['navigate', '/contracts/42', { id: '42' }, { crumb: '@payload.row.title' }]\n */\nexport type NavigateEffect =\n | ['navigate', string | SExpr]\n | ['navigate', string | SExpr, Record<string, string | SExpr>]\n | ['navigate', string | SExpr, Record<string, string | SExpr>, NavigateOptions];\n\n/**\n * Navigate-back effect - pops the current entry off the orbital-scoped\n * navigation stack and navigates to the previous one. The stack is\n * client-session state (cold loads are seeded from declared page-path\n * prefixes), so an ancestor always exists on nested paths; the validator\n * rejects `navigate-back` reachable only from pages with no path ancestor.\n * @example ['navigate-back']\n */\nexport type NavigateBackEffect = ['navigate-back'];\n\n/**\n * Emit effect - emits an event, optionally with payload.\n * @example ['emit', 'SAVE'] or ['emit', 'PLAYER_DIED', { playerId: '@entity.id' }]\n * @example ['emit', 'FILTER_CHANGED', '@entity.filters']\n */\nexport type EmitEffect = ['emit', string] | ['emit', string, EventPayload | string];\n\n/**\n * `emit:` config block attached to async / reactive data operators.\n *\n * Each key names an event the runtime should fire on the bus when the\n * effect reaches the corresponding lifecycle point. The set of keys an\n * operator actually supports is enforced by the compiler validator:\n *\n * | Operator | Supported keys |\n * |------------------|---------------------------|\n * | `fetch` | `success`, `failure` |\n * | `persist` | `success`, `failure` |\n * | `call-service` | `success`, `failure` |\n * | `set` | `success` |\n * | `ref` | `on_change`, `failure` |\n * | `os/watch-*` | `on_message`, `failure` |\n *\n * Payload convention:\n * - `success` / `on_change` → the effect's result (fetched entity, new value)\n * - `failure` → `{ error: string, code?: string }`\n * - `on_message` → the incoming message (os/watch-* streams)\n *\n * See `docs/Almadar_Std_Gaps.md` §3.1 for the close-the-circuit design.\n */\nexport interface EmitConfig {\n /** Fires after a one-shot async effect resolves successfully. */\n success?: string;\n /** Fires when the effect throws; payload is `{ error: string }`. */\n failure?: string;\n /** Reactive-subscription event (per update for `ref`). */\n on_change?: string;\n /** Per-event fire for `os/watch-*` streams. */\n on_message?: string;\n}\n\n/**\n * Set effect - sets a binding to a value.\n *\n * Two forms are supported to match the runtime's `set` handler signature\n * `(targetId, field, value)`:\n *\n * - 3-element binding form (legacy / std behaviors): ['set', '@entity.field', value]\n * - 4-element target form (canonical runtime): ['set', entityId, fieldName, value]\n *\n * The 4-element form is what `OrbitalServerRuntime`'s set handler\n * dispatches directly (`update(entityType, targetId, { field: value })`).\n * Prefer the 4-element form when authoring schemas in TypeScript that\n * load directly into the runtime.\n *\n * @example ['set', '@entity.health', 100] // 3-element\n * @example ['set', '@entity.id', 'health', 100] // 4-element\n * @example ['set', '@entity.id', 'count', ['+', '@entity.count', 1]]\n */\nexport type SetEffect =\n | ['set', string, SExpr]\n | ['set', string, string, SExpr];\n\n/**\n * Trailing config object on persist effects. When present, it carries the\n * `emit` map specifying which events to fire on persist success/failure.\n * Mirrors what the runtime's `EffectExecutor` reads at the 5th tuple\n * position. See `(persist create Entity @payload.data { emit: { success:\n * \"Saved\", failure: \"SaveFailed\" } })` in `.lolo` source.\n */\nexport type PersistEmitConfig = {\n emit?: { success?: string; failure?: string };\n};\n\n/**\n * Persist effect data argument: an entity row literal (field map), a\n * binding string referencing a row in scope (e.g. `@payload.data`,\n * `@entity`), or an expression form that evaluates to a row (e.g.\n * `[\"object/merge\", \"@payload.data\", { sender: \"@user.id\" }]`). At\n * runtime, binding strings and expressions resolve to `EntityRow` values\n * before the persist op runs — both paths evaluate the expression first.\n */\nexport type PersistRowInput = { id?: string | SExpr } & Record<string, FieldValue | SExpr | undefined>;\n\nexport type PersistData = EntityRow | PersistRowInput | string | SExpr[];\n\n/**\n * One EVALUATED operation of the runtime path's `[\"persist\", \"batch\", [...ops]]`\n * form, as `EffectExecutor` hands it to `handlers.persist('batch', '', { operations })`\n * and both server persist handlers execute it. The row is optional on\n * create/update (an absent row persists `{}`), exactly as the handlers always\n * tolerated. The compiled path has no batch persist — ledger §169.\n */\nexport type PersistBatchOperation =\n | ['create', string, EntityRow?]\n | ['update', string, string, EntityRow?]\n | ['delete', string, string];\n\nfunction isRowObject(value: RuntimeValue): value is EntityRow {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date);\n}\n\n/** The ONE structural check for a batch operation — every consumer narrows through it. */\nexport function isPersistBatchOperation(value: RuntimeValue): value is PersistBatchOperation {\n if (!Array.isArray(value) || typeof value[1] !== 'string') return false;\n switch (value[0]) {\n case 'create':\n return value.length === 2 || (value.length === 3 && isRowObject(value[2]));\n case 'update':\n return typeof value[2] === 'string' && (value.length === 3 || (value.length === 4 && isRowObject(value[3])));\n case 'delete':\n return value.length === 3 && typeof value[2] === 'string';\n default:\n return false;\n }\n}\n\n/**\n * Persist effect - creates, updates, deletes, or clears entities.\n *\n * Each operation accepts an optional trailing `PersistEmitConfig` so the\n * runtime can fire success / failure events when the operation completes.\n *\n * @example ['persist', 'create', 'Task', { title: '@payload.title' }]\n * @example ['persist', 'update', '@entity.entityType', '@payload.data']\n * @example ['persist', 'create', 'Task', '@payload.data', { emit: { success: 'TaskCreated' } }]\n */\nexport type PersistEffect =\n | ['persist', 'create', string, PersistData]\n | ['persist', 'create', string, PersistData, PersistEmitConfig]\n | ['persist', 'update', string, PersistData]\n | ['persist', 'update', string, PersistData, PersistEmitConfig]\n | ['persist', 'delete', string]\n | ['persist', 'delete', string, PersistData]\n | ['persist', 'delete', string, PersistData, PersistEmitConfig]\n | ['persist', 'clear', string]\n | ['persist', 'clear', string, PersistData]\n | ['persist', 'clear', string, PersistData, PersistEmitConfig];\n\n/**\n * Call service effect - invokes an external service.\n *\n * Two shapes are accepted:\n *\n * 1. Flat form (what the runtime reads and every .orb file uses):\n * `['call-service', serviceName, action, params?]` — args[0]=service,\n * args[1]=action, args[2]=params. This is the canonical form; the\n * runtime's EffectExecutor decodes exactly these positions.\n *\n * 2. Legacy config-object form (kept for the `callService()` helper):\n * `['call-service', serviceName, CallServiceConfig]` — retained so\n * older call sites using the builder helper continue to typecheck.\n *\n * @example ['call-service', 'llm', 'generate', { userPrompt: '@entity.inputText' }]\n * @example ['call-service', 'llm', 'generate', { userPrompt: '...' }, { emit: { success: 'OK', failure: 'ERR' } }]\n * @example ['call-service', 'WeatherAPI', { service: 'weather', action: 'get', onSuccess: 'OK' }]\n */\nexport type CallServiceEffect =\n | ['call-service', string, string]\n | ['call-service', string, string, ServiceParams]\n | ['call-service', string, string, ServiceParams, PersistEmitConfig]\n | ['call-service', string, CallServiceConfig];\n\n/**\n * Spawn effect - creates a new entity instance (games).\n * @example ['spawn', 'Bullet', { x: '@entity.x', y: '@entity.y' }]\n */\nexport type SpawnEffect = ['spawn', string] | ['spawn', string, EntityRow];\n\n/**\n * Despawn effect - removes an entity instance (games).\n * @example ['despawn', '@entity.id']\n */\nexport type DespawnEffect = ['despawn', string];\n\n/**\n * Do effect - executes multiple effects in sequence.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['do', ['set', '@entity.x', 0], ['set', '@entity.y', 0]]\n */\nexport type DoEffect = ['do', ...SExpr[]];\n\n/**\n * Options accepted by `fetch` / `ref` / `deref` effects. Mirrors what\n * `OrbitalServerRuntime`'s fetch handler reads at runtime: `id`, `filter`,\n * `limit`, `offset`, `include`, plus the trailing `emit:` map for\n * success/failure event names.\n */\nexport type FetchOptions = {\n /** Fetch a single entity by ID */\n id?: string;\n /** Filter expression (S-expression) */\n filter?: SExpr;\n /** Maximum number of entities to return. The template layer may carry a\n * binding (`'@config.pageSize'`) or a computed S-expression — the\n * compiler's inline phase resolves it to a number. */\n limit?: number | RenderBinding | SExpr[];\n /** Number of entities to skip — same template-layer forms as `limit`. */\n offset?: number | RenderBinding | SExpr[];\n /** Relations to populate (entity field names). The template layer may\n * carry a binding (`'@config.include'`) — same as `limit`/`offset`, the\n * compiler's inline phase resolves it to the concrete list. */\n include?: string[] | RenderBinding;\n /** Lifecycle events to emit on resolve / reject */\n emit?: { success?: string; failure?: string };\n};\n\n/**\n * Fetch effect - retrieves entity data (server-side).\n * @example ['fetch', 'User'] or ['fetch', 'User', { id: '@payload.userId' }]\n */\nexport type FetchEffect = ['fetch', string] | ['fetch', string, FetchOptions];\n\n/** Options for `fetch-stream` — mirror of the compiler's `OirEffect::FetchStream`\n * (`orbital-core/src/ir/effects.rs`) and the runtime's `fetchStream` handler. */\nexport type FetchStreamOptions = {\n id?: string | SExpr;\n filter?: SExpr;\n /** `on_message` fires per chunk; `success` on completion. */\n emit?: { on_message?: string; success?: string; failure?: string };\n};\n\n/**\n * Fetch-stream effect - streams entity rows (server-side), one `on_message`\n * emit per chunk. The compiled path (`OirEffect::FetchStream`) and the\n * runtime (`EffectExecutor` `'fetch-stream'`) both execute it.\n * @example ['fetch-stream', 'Message', { filter: ['=', '@entity.roomId', '@payload.roomId'], emit: { on_message: 'CHUNK' } }]\n */\nexport type FetchStreamEffect = ['fetch-stream', string] | ['fetch-stream', string, FetchStreamOptions];\n\n/**\n * Result returned by a fetch / ref / deref handler.\n *\n * `rows` carries the entity (or entities) that survived `filter` AND\n * pagination (`offset`/`limit`). `total` is the count of rows that\n * matched the filter BEFORE pagination, so paginating consumers can\n * compute `totalPages = ceil(total / pageSize)` without a second\n * round-trip. Single-entity fetches by id return `total: 1` (or `0`\n * if not found, in which case the handler returns `null` instead).\n */\nexport interface FetchResult {\n rows: EntityRow | EntityRow[];\n total: number;\n}\n\n/**\n * If effect - conditional effect execution.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['if', ['>', '@entity.health', 0], ['emit', 'ALIVE'], ['emit', 'DEAD']]\n */\nexport type IfEffect = ['if', Expression, SExpr] | ['if', Expression, SExpr, SExpr];\n\n/**\n * When effect - conditional effect similar to if but without else.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['when', ['>', '@entity.health', 0], ['emit', 'ALIVE']]\n */\nexport type WhenEffect = ['when', Expression, SExpr];\n\n/**\n * Let effect - creates local bindings for effects.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['let', ['temp', ['get', '@payload.value']], ['set', '@entity.value', 'temp']]\n */\nexport type LetEffect = ['let', [string, SExpr][], ...SExpr[]];\n\n/**\n * Log effect - logs a message for debugging.\n * @example ['log', 'User created:', '@entity.name']\n */\nexport type LogEffect = ['log', ...SExpr[]];\n\n/**\n * Wait effect - delays execution.\n * @example ['wait', 1000] - wait 1 second\n */\nexport type WaitEffect = ['wait', number];\n\n// ============================================================================\n// Resource Effects (reactive entity subscriptions and atomic operations)\n// ============================================================================\n\n/**\n * Ref effect - creates a reactive entity subscription.\n * Returns a reactive reference that auto-updates when the entity changes.\n * @example ['ref', '@entity.health'] - reactive subscription to health\n * @example ['ref', 'User', { id: '@payload.userId' }] - reactive ref to specific user\n */\nexport type RefEffect =\n | ['ref', string]\n | ['ref', string, FetchOptions];\n\n/**\n * Deref effect - snapshot read of an entity value.\n * Returns the current value without subscribing to changes.\n * @example ['deref', '@entity.health'] - read current health value\n * @example ['deref', 'User', { id: '@payload.userId' }] - read specific user snapshot\n */\nexport type DerefEffect =\n | ['deref', string]\n | ['deref', string, FetchOptions];\n\n/**\n * Swap! effect - atomic compare-and-swap on an entity field.\n * Only updates if the current value matches the expected value.\n * @example ['swap!', '@entity.health', ['fn', ['old'], ['-', 'old', '@payload.damage']]]\n * @example ['swap!', '@entity.counter', ['+', '@entity.counter', 1]]\n */\nexport type SwapEffect = ['swap!', string, SExpr];\n\n/**\n * Options accepted by `watch` effects. Mirrors what the runtime reads when\n * registering the change callback: `debounce` and the trailing `emit:` map.\n */\nexport type WatchOptions = {\n /** Debounce duration in milliseconds */\n debounce?: number;\n /** Lifecycle events to emit on update / failure */\n emit?: { on_message?: string; failure?: string };\n};\n\n/**\n * Watch effect - registers a callback for entity changes.\n * Emits an event whenever the watched binding changes.\n * @example ['watch', '@entity.health', 'HEALTH_CHANGED']\n * @example ['watch', '@entity.status', 'STATUS_UPDATED', { debounce: 100 }]\n */\nexport type WatchEffect =\n | ['watch', string, string]\n | ['watch', string, string, WatchOptions];\n\n/**\n * Atomic effect - groups multiple effects into an atomic transaction.\n * All effects either succeed together or are rolled back.\n * @example ['atomic', ['set', '@entity.x', 10], ['set', '@entity.y', 20]]\n * @example ['atomic', ['persist', 'update', 'User', { balance: 100 }], ['emit', 'BALANCE_UPDATED']]\n */\nexport type AtomicEffect = ['atomic', ...SExpr[]];\n\n// ============================================================================\n// ML Effects (from almadar-std/modules/nn, tensor, train)\n// ============================================================================\n\n/**\n * One layer in an NN architecture description. The set of valid layer kinds\n * lives in `almadar-std/modules/nn`; here we keep the wire shape generic\n * enough for the cross-package runtime + Python bridge to round-trip.\n */\nexport type NnLayer = {\n type: string;\n [key: string]: string | number | boolean | number[] | string[] | undefined;\n};\n\n/**\n * Hyperparameters for `train` and `evaluate`. Recursive to allow nested\n * optimizer / scheduler config blocks without falling back to `unknown`.\n */\nexport type NnConfig = {\n [key: string]: string | number | boolean | string[] | number[] | NnConfig | undefined;\n};\n\n/**\n * Forward-pass config: `input` is a binding string (`@payload.input`), and\n * `on-complete` names the event to fire when the prediction lands.\n */\nexport type ForwardConfig = {\n architecture: NnLayer[];\n input: string;\n 'on-complete'?: string;\n config?: NnConfig;\n};\n\n/**\n * Training-loop config. `dataset` is a binding string referencing the rows\n * to train on. Optimizer / loss / scheduler land inside `config`.\n */\nexport type TrainConfig = {\n architecture: NnLayer[];\n dataset: string;\n config?: NnConfig;\n 'on-complete'?: string;\n};\n\n/**\n * Evaluation config. `metrics` lists named metrics the Python backend\n * computes (`accuracy`, `precision`, ...).\n */\nexport type EvaluateConfig = {\n architecture: NnLayer[];\n dataset: string;\n metrics: string[];\n config?: NnConfig;\n 'on-complete'?: string;\n};\n\n/**\n * Forward effect - runs a neural network forward pass (Python backend).\n * @example ['forward', 'primary', { architecture: [...], input: '@payload.input', 'on-complete': 'PREDICTION_READY' }]\n */\nexport type ForwardEffect = ['forward', string, ForwardConfig];\n\n/**\n * Train effect - runs a training loop (Python backend).\n * @example ['train', { architecture: [...], dataset: '@entity.data', config: { epochs: 10 }, 'on-complete': 'TRAINING_DONE' }]\n */\nexport type TrainEffect = ['train', TrainConfig];\n\n/**\n * Evaluate effect - runs model evaluation (Python backend).\n * @example ['evaluate', { architecture: [...], dataset: '@entity.testData', metrics: ['accuracy'], 'on-complete': 'EVAL_DONE' }]\n */\nexport type EvaluateEffect = ['evaluate', EvaluateConfig];\n\n/**\n * Checkpoint save effect - saves model weights.\n * @example ['checkpoint/save', '/path/to/model.pt', '@entity.weights']\n */\nexport type CheckpointSaveEffect = ['checkpoint/save', string, SExpr];\n\n/**\n * Checkpoint load effect - loads model weights.\n * @example ['checkpoint/load', '/path/to/model.pt']\n */\nexport type CheckpointLoadEffect = ['checkpoint/load', string];\n\n// ============================================================================\n// Agent Effects (from agent/* operator namespace)\n// ============================================================================\n\n/**\n * Agent effect - invokes an agent/* operator.\n * Covers all 22 operators in the std-agent category.\n * @example ['agent/memorize', 'use data-grid for tables', 'preference']\n * @example ['agent/recall', 'user preferences']\n * @example ['agent/generate', 'Summarize this schema']\n */\nexport type AgentEffect = [`agent/${string}`, ...SExpr[]];\n\n/**\n * OS effect - invokes an os/* operator.\n *\n * Covers reactive subscriptions to OS / network resources:\n * - `os/watch-http`, `os/watch-ws`, `os/watch-sse` — long-lived streams\n * that fire `on_message` / `failure` events through a trailing\n * `EmitConfig` block (see `EmitConfig` for the supported keys).\n * - `os/read-file`, `os/exec`, etc. — one-shot OS operations.\n *\n * @example ['os/watch-http', 'wss://push.example.com', { emit: { on_message: 'PUSH_RECEIVED', failure: 'PUSH_DISCONNECTED' } }]\n * @example ['os/read-file', '/etc/hosts']\n */\nexport type OsEffect = [`os/${string}`, ...SExpr[]];\n\n/**\n * Browser effect - invokes a browser/* device operator (client host path).\n * User-initiated, async, resolves via the standard trailing emit envelope.\n * Concrete operators (browser/open-file-picker, browser/clipboard-read,\n * browser/clipboard-write, browser/geolocation-current) and their arity /\n * payload shapes live in @almadar/std BROWSER_OPERATORS.\n * @example ['browser/open-file-picker', { multiple: false }, { emit: { success: 'FILES_PICKED', failure: 'PICK_CANCELLED' } }]\n */\nexport type BrowserEffect = [`browser/${string}`, ...SExpr[]];\n\n/**\n * LLM effect - invokes an llm/* operator (agent path).\n * @example ['llm/generate', '@entity.request', { emit: { success: 'PLANNED', failure: 'PLAN_FAILED' } }]\n */\nexport type LlmEffect = [`llm/${string}`, ...SExpr[]];\n\n/**\n * Behavior effect - invokes a behavior/* operator (agent path).\n * @example ['behavior/instantiate', '@entity.plan', { emit: { failure: 'BUILD_FAILED' } }]\n */\nexport type BehaviorEffect = [`behavior/${string}`, ...SExpr[]];\n\n/**\n * Validate effect - invokes a validate/* operator (agent path).\n * @example ['validate/validate', '@entity.schema', { emit: { failure: 'INVALID' } }]\n */\nexport type ValidateEffect = [`validate/${string}`, ...SExpr[]];\n\n/**\n * Remaining agent-path operator effects: session/* (workspace session ops),\n * compose/* (schema composition), trace/* (trace emission), memory/*\n * (agent memory), application/* (app lifecycle). Expression-only namespaces\n * (array/, math/, object/, str/, …) are deliberately NOT effect heads.\n * @example ['session/write-spec', '@entity.spec']\n * @example ['compose/compose-all', { emit: { failure: 'COMPOSE_FAILED' } }]\n */\nexport type SessionEffect = [`session/${string}`, ...SExpr[]];\nexport type ComposeEffect = [`compose/${string}`, ...SExpr[]];\nexport type TraceEffect = [`trace/${string}`, ...SExpr[]];\nexport type MemoryEffect = [`memory/${string}`, ...SExpr[]];\nexport type ApplicationEffect = [`application/${string}`, ...SExpr[]];\n\n// ============================================================================\n// Async Effects (from almadar-std/modules/async)\n// ============================================================================\n\n/**\n * Async delay effect - wait then execute effects.\n * @example ['async/delay', 2000, ['emit', 'TIMEOUT']]\n */\nexport type AsyncDelayEffect = ['async/delay', number | string, ...Effect[]];\n\n/**\n * Async debounce effect - debounce then execute effect.\n * @example ['async/debounce', 300, ['emit', 'SEARCH_COMPLETE']]\n * @example ['async/debounce', '@entity.debounceMs', ['emit', 'SEARCH_COMPLETE']]\n */\nexport type AsyncDebounceEffect = ['async/debounce', number | string, SExpr];\n\n/**\n * Async throttle effect - throttle then execute effect.\n * @example ['async/throttle', 100, ['emit', 'SCROLL_HANDLED']]\n * @example ['async/throttle', '@entity.throttleMs', ['emit', 'SCROLL_HANDLED']]\n */\nexport type AsyncThrottleEffect = ['async/throttle', number | string, SExpr];\n\n/**\n * Async interval effect - execute effect at intervals.\n * @example ['async/interval', 1000, ['emit', 'TICK']]\n * @example ['async/interval', '@entity.intervalMs', ['emit', 'POLL_TICK']]\n */\nexport type AsyncIntervalEffect = ['async/interval', number | string, SExpr];\n\n/**\n * Async race effect - first effect to complete wins.\n * @example ['async/race', ['call', 'api1'], ['call', 'api2']]\n */\nexport type AsyncRaceEffect = ['async/race', ...Effect[]];\n\n/**\n * Async all effect - wait for all effects to complete.\n * @example ['async/all', ['call', 'api1'], ['call', 'api2']]\n */\nexport type AsyncAllEffect = ['async/all', ...Effect[]];\n\n/**\n * Async sequence effect - execute effects in sequence.\n * @example ['async/sequence', ['call', 'validate'], ['call', 'save']]\n */\nexport type AsyncSequenceEffect = ['async/sequence', ...Effect[]];\n\n/**\n * Union of all typed effects.\n * Provides compile-time validation for common effect types.\n */\nexport type TypedEffect =\n | RenderUIEffect\n | NavigateEffect\n | NavigateBackEffect\n | EmitEffect\n | SetEffect\n | PersistEffect\n | CallServiceEffect\n | SpawnEffect\n | DespawnEffect\n | DoEffect\n | FetchEffect\n | FetchStreamEffect\n | IfEffect\n | WhenEffect\n | LetEffect\n | LogEffect\n | WaitEffect\n | RefEffect\n | DerefEffect\n | SwapEffect\n | WatchEffect\n | AtomicEffect\n | AsyncDelayEffect\n | AsyncDebounceEffect\n | AsyncThrottleEffect\n | AsyncIntervalEffect\n | AsyncRaceEffect\n | AsyncAllEffect\n | AsyncSequenceEffect\n | ForwardEffect\n | TrainEffect\n | EvaluateEffect\n | CheckpointSaveEffect\n | CheckpointLoadEffect\n | AgentEffect\n | OsEffect\n | BrowserEffect\n | LlmEffect\n | BehaviorEffect\n | ValidateEffect\n | SessionEffect\n | ComposeEffect\n | TraceEffect\n | MemoryEffect\n | ApplicationEffect;\n\n// ============================================================================\n// Effect Type (Strictly Typed)\n// ============================================================================\n\n/**\n * Effect type - typed S-expression format.\n *\n * Effects are strongly typed tuples that enforce:\n * - Valid effect operators (render-ui, emit, set, persist, navigate, call-service)\n * - Valid UISlots for render-ui\n * - Valid PatternTypes and props for render-ui\n * - Correct argument types for each effect\n *\n * Available typed effects:\n * - RenderUIEffect: ['render-ui', UISlot, PatternConfig]\n * - NavigateEffect: ['navigate', path] or ['navigate', path, params]\n * - EmitEffect: ['emit', eventName] or ['emit', eventName, payload]\n * - SetEffect: ['set', binding, value]\n * - PersistEffect: ['persist', operation, entity, data?]\n * - CallServiceEffect: ['call-service', serviceName, config]\n *\n * @example\n * [\"set\", \"@entity.health\", 100]\n * [\"emit\", \"PLAYER_DIED\", { \"playerId\": \"@entity.id\" }]\n * [\"render-ui\", \"main\", { \"patternType\": \"entity-table\", \"columns\": [\"name\"] }]\n * [\"call-service\", \"WeatherAPI\", { \"action\": \"getWeather\", \"onSuccess\": \"OK\" }]\n * [\"navigate\", \"/tasks\"]\n * [\"persist\", \"create\", \"Task\", { \"title\": \"@payload.title\" }]\n */\nexport type Effect = TypedEffect;\n\n/**\n * The effects a server reports an outcome for on\n * `OrbitalEventResponse.effectResults` (`ServerEffectResult.effect`). Every\n * member is checked against the effect heads above at compile time, so a\n * name that is not an effect cannot be listed and a new server-reported\n * effect is added HERE only — the wire type, its zod twin and the\n * `events-wire` fixture case all derive from this array.\n */\nexport const SERVER_REPORTED_EFFECTS = [\n 'set',\n 'persist',\n 'call-service',\n 'fetch',\n 'fetch-stream',\n 'ref',\n 'deref',\n 'swap!',\n 'atomic',\n 'emit',\n] as const satisfies readonly Effect[0][];\n\nexport type ServerReportedEffect = (typeof SERVER_REPORTED_EFFECTS)[number];\n\n/** A namespaced effect head (`trace/emit`, `memory/store`, `llm/…`) — what a\n * `substrate` result's `name` carries. Derived from the union, never listed. */\nexport type NamespacedEffectName = Extract<Effect[0], `${string}/${string}`>;\n\n/**\n * Schema for Effect - validates S-expression format. Arguments validate as\n * s-expr-shaped DATA (`SExprDataSchema`) — literal data arrays (empty or\n * non-operator-headed) are valid argument values; the operator-head refine\n * applies to the effect itself, not to every argument.\n */\nexport const EffectSchema = z.array(SExprDataSchema).min(1).refine(\n (arr) => typeof arr[0] === 'string',\n { message: 'Effect must be an S-expression with a string operator as first element' }\n);\n\nexport type EffectInput = z.input<typeof EffectSchema>;\n\n/**\n * Type guard to check if a value is a valid Effect (S-expression).\n * \n * Validates that a value conforms to the Effect structure. Effects are\n * represented as arrays where the first element is a string (effect type)\n * and subsequent elements are parameters. Used for runtime validation\n * of effect structures.\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is a valid Effect, false otherwise\n *\n * @example\n * isEffect(['set', '@entity.health', 100]); // returns true\n * isEffect('not-an-effect'); // returns false\n * isEffect([]); // returns false\n */\nexport function isEffect(value: RuntimeValue): value is Effect {\n return Array.isArray(value) && value.length > 0 && typeof value[0] === 'string';\n}\n\n/**\n * Alias for isEffect (for clarity when working with S-expressions)\n */\nexport const isSExprEffect = isEffect;\n\n// ============================================================================\n// Effect Builder Helpers\n// ============================================================================\n\n/**\n * Creates a set effect for state updates.\n * \n * Generates an effect that sets a binding to a value. Used in state\n * machine transitions to update entity fields, UI state, or other\n * mutable data.\n * \n * @param {string} binding - Target binding (e.g., '@entity.health')\n * @param {SExpr} value - Value to set (can be literal or expression)\n * @returns {Effect} Set effect array\n * \n * @example\n * set('@entity.health', 100); // returns [\"set\", \"@entity.health\", 100]\n * set('@state.loading', false); // returns [\"set\", \"@state.loading\", false]\n */\nexport function set(binding: string, value: SExpr): Effect {\n return ['set', binding, value];\n}\n\n/**\n * Creates an emit effect for event dispatching.\n * \n * Generates an effect that emits an event with optional payload.\n * Used in state machine transitions to trigger events that can be\n * handled by other traits, services, or external systems.\n * \n * @param {string} event - Event name to emit\n * @param {EventPayload} [payload] - Optional event payload\n * @returns {Effect} Emit effect array\n * \n * @example\n * emit('PLAYER_DIED', { playerId: '@entity.id' }); // returns [\"emit\", \"PLAYER_DIED\", { playerId: \"@entity.id\" }]\n * emit('GAME_STARTED'); // returns [\"emit\", \"GAME_STARTED\"]\n */\nexport function emit(event: string, payload?: EventPayload): Effect {\n return payload ? ['emit', event, payload] : ['emit', event];\n}\n\n/**\n * Creates a navigation effect for page routing.\n * \n * Generates an effect that navigates to a specified path with optional\n * parameters. Used in state machine transitions to change pages or\n * update URL parameters.\n * \n * @param {string} path - Target path (e.g., '/tasks')\n * @param {Record<string, string>} [params] - Optional URL parameters\n * @returns {NavigateEffect} Navigation effect array\n * \n * @example\n * navigate('/tasks'); // returns [\"navigate\", \"/tasks\"]\n * navigate('/user', { id: '123' }); // returns [\"navigate\", \"/user\", { id: \"123\" }]\n */\nexport function navigate(path: string): NavigateEffect;\nexport function navigate(path: string, params: Record<string, string>): NavigateEffect;\nexport function navigate(path: string, params: Record<string, string>, options: NavigateOptions): NavigateEffect;\nexport function navigate(path: string, params?: Record<string, string>, options?: NavigateOptions): NavigateEffect {\n if (params && options) return ['navigate', path, params, options];\n return params ? ['navigate', path, params] : ['navigate', path];\n}\n\n/**\n * Creates a navigate-back effect: pop the orbital's navigation stack and\n * navigate to the previous entry.\n *\n * @example\n * navigateBack(); // returns [\"navigate-back\"]\n */\nexport function navigateBack(): NavigateBackEffect {\n return ['navigate-back'];\n}\n\n/**\n * Create a render-ui effect\n * @example [\"render-ui\", \"main\", { \"patternType\": \"entity-table\", \"columns\": [\"name\"] }]\n */\nexport function renderUI(\n target: UISlot,\n pattern: AnyPatternConfig\n): RenderUIEffect;\nexport function renderUI(\n target: UISlot,\n pattern: AnyPatternConfig,\n props: ResolvedPatternProps\n): RenderUIEffect;\nexport function renderUI(\n target: UISlot,\n pattern: AnyPatternConfig,\n props?: ResolvedPatternProps\n): RenderUIEffect {\n return props\n ? ['render-ui', target, pattern, props]\n : ['render-ui', target, pattern];\n}\n\n/**\n * Create a persist effect\n * @example [\"persist\", \"create\", \"Task\", { \"title\": \"@payload.title\" }]\n */\nexport function persist(\n action: 'create' | 'update',\n entity: string,\n data: PersistData\n): PersistEffect;\nexport function persist(\n action: 'delete' | 'clear',\n entity: string,\n data?: PersistData\n): PersistEffect;\nexport function persist(\n action: 'create' | 'update' | 'delete' | 'clear',\n entity: string,\n data?: PersistData\n): PersistEffect {\n if (action === 'create' || action === 'update') {\n return ['persist', action, entity, data!] as PersistEffect;\n }\n return data\n ? ['persist', action, entity, data] as PersistEffect\n : ['persist', action, entity] as PersistEffect;\n}\n\n/**\n * Create a call-service effect\n * @example [\"call-service\", \"stripe\", { \"service\": \"stripe\", \"action\": \"charge\", \"onSuccess\": \"OK\", \"onError\": \"ERR\" }]\n */\nexport function callService(\n serviceName: string,\n config: CallServiceConfig\n): CallServiceEffect {\n return ['call-service', serviceName, config];\n}\n\n/**\n * Create a spawn effect (games)\n * @example [\"spawn\", \"Bullet\", { \"x\": \"@entity.x\", \"y\": \"@entity.y\" }]\n */\nexport function spawn(entity: string): SpawnEffect;\nexport function spawn(entity: string, initialState: EntityRow): SpawnEffect;\nexport function spawn(entity: string, initialState?: EntityRow): SpawnEffect {\n return initialState ? ['spawn', entity, initialState] : ['spawn', entity];\n}\n\n/**\n * Create a despawn effect (games)\n * @example [\"despawn\", \"@entity.id\"]\n */\nexport function despawn(entityId: string): DespawnEffect {\n return ['despawn', entityId];\n}\n\n/**\n * Create a do effect (multiple effects)\n * @example [\"do\", [\"set\", \"@entity.x\", 0], [\"set\", \"@entity.y\", 0]]\n */\nexport function doEffects(...effects: SExpr[]): DoEffect {\n return ['do', ...effects];\n}\n\n/**\n * Create a fetch effect (server-side data retrieval)\n * @example [\"fetch\", \"User\"] - fetch all users\n * @example [\"fetch\", \"User\", { \"id\": \"@payload.userId\" }] - fetch by ID\n * @example [\"fetch\", \"User\", { \"filter\": [\"=\", \"@entity.status\", \"active\"], \"limit\": 10 }]\n */\nexport function fetch(entity: string): FetchEffect;\nexport function fetch(entity: string, options: FetchOptions): FetchEffect;\nexport function fetch(entity: string, options?: FetchOptions): FetchEffect {\n return options ? ['fetch', entity, options] : ['fetch', entity];\n}\n\n// ============================================================================\n// Resource Effect Builder Helpers\n// ============================================================================\n\n/**\n * Create a ref effect (reactive entity subscription).\n *\n * @param {string} binding - Binding or entity name to subscribe to\n * @param {FetchOptions} [selector] - Optional selector for specific entity\n * @returns {RefEffect} Ref effect array\n *\n * @example\n * ref('@entity.health'); // returns [\"ref\", \"@entity.health\"]\n * ref('User', { id: '@payload.userId' }); // returns [\"ref\", \"User\", { id: \"@payload.userId\" }]\n */\nexport function ref(binding: string): RefEffect;\nexport function ref(binding: string, selector: FetchOptions): RefEffect;\nexport function ref(binding: string, selector?: FetchOptions): RefEffect {\n return selector ? ['ref', binding, selector] : ['ref', binding];\n}\n\n/**\n * Create a deref effect (snapshot read).\n *\n * @param {string} binding - Binding or entity name to read\n * @param {FetchOptions} [selector] - Optional selector for specific entity\n * @returns {DerefEffect} Deref effect array\n *\n * @example\n * deref('@entity.health'); // returns [\"deref\", \"@entity.health\"]\n * deref('User', { id: '@payload.userId' }); // returns [\"deref\", \"User\", { id: \"@payload.userId\" }]\n */\nexport function deref(binding: string): DerefEffect;\nexport function deref(binding: string, selector: FetchOptions): DerefEffect;\nexport function deref(binding: string, selector?: FetchOptions): DerefEffect {\n return selector ? ['deref', binding, selector] : ['deref', binding];\n}\n\n/**\n * Create a swap! effect (atomic compare-and-swap).\n *\n * @param {string} binding - Binding to atomically update\n * @param {SExpr} transform - Transformation expression applied to the current value\n * @returns {SwapEffect} Swap effect array\n *\n * @example\n * swap('@entity.counter', ['+', '@entity.counter', 1]);\n * // returns [\"swap!\", \"@entity.counter\", [\"+\", \"@entity.counter\", 1]]\n */\nexport function swap(binding: string, transform: SExpr): SwapEffect {\n return ['swap!', binding, transform];\n}\n\n/**\n * Create a watch effect (entity change callback).\n *\n * @example\n * watch('@entity.health', 'HEALTH_CHANGED');\n * watch('@entity.status', 'STATUS_UPDATED', { debounce: 100 });\n */\nexport function watch(binding: string, event: string): WatchEffect;\nexport function watch(binding: string, event: string, options: WatchOptions): WatchEffect;\nexport function watch(binding: string, event: string, options?: WatchOptions): WatchEffect {\n return options\n ? ['watch', binding, event, options]\n : ['watch', binding, event];\n}\n\n/**\n * Create an atomic effect (transaction group).\n *\n * @param {...SExpr[]} effects - Effects to execute atomically\n * @returns {AtomicEffect} Atomic effect array\n *\n * @example\n * atomic(['set', '@entity.x', 10], ['set', '@entity.y', 20]);\n * // returns [\"atomic\", [\"set\", \"@entity.x\", 10], [\"set\", \"@entity.y\", 20]]\n */\nexport function atomic(...effects: SExpr[]): AtomicEffect {\n return ['atomic', ...effects];\n}\n\n// ============================================================================\n// Runtime Pattern Types\n// ============================================================================\n\n/** Resolved pattern props for render-ui effects at runtime. Recursive for nested pattern configs. */\nexport type ResolvedPatternProps = {\n [prop: string]:\n | string\n | number\n | boolean\n | null\n | undefined\n | ResolvedPatternProps\n | RenderChildrenMap\n | Array<ResolvedPatternProps | RenderChildrenMap>;\n};\n\n/**\n * Zod twin of `PatternConfig`/`AnyPatternConfig` — validates the WIRE SHAPE\n * (a plain object, or `null` for an unset render-ui target) only. Per-pattern\n * prop shape (the hundreds of generated `PatternPropsMap` variants) is\n * enforced by the patterns registry at `orb validate` / lolo parse time, not\n * re-validated here — a second, drifting copy of that registry is exactly\n * the duplicate this schema must not become.\n */\nexport const PatternConfigSchema: z.ZodType<AnyPatternConfig | null> = z.custom<AnyPatternConfig | null>(\n (value) => value === null || (typeof value === 'object' && value !== null && !Array.isArray(value)),\n { message: 'Expected a pattern config object or null' },\n);\n\n/** Zod twin of `ResolvedPatternProps` — validates the wire shape (a plain object) only, see {@link PatternConfigSchema}. */\nexport const ResolvedPatternPropsSchema: z.ZodType<ResolvedPatternProps> = z.custom<ResolvedPatternProps>(\n (value) => typeof value === 'object' && value !== null && !Array.isArray(value),\n { message: 'Expected a resolved pattern props object' },\n);\n\n/** A node in a render-ui effect tree. */\nexport interface RenderUINode {\n type: string;\n props?: ResolvedPatternProps;\n /** Static child nodes and/or dynamic-collection map entries. A\n * {@link RenderChildrenMap} entry expands at render time into resolved\n * `RenderUINode`s, so components always receive a flat, fully-resolved list. */\n children?: Array<RenderUINode | RenderChildrenMap>;\n content?: string;\n entity?: string;\n renderItem?: RenderUINode;\n}\n\n","/**\n * Authenticated user context — what `@user.x` resolves against.\n *\n * The canonical shape for the `user` binding root, shared by both execution\n * paths: the JS interpreter resolves `@user.id` through\n * `EvaluationContext.user`, and the compiled shell emits `user?.id` against the\n * `UserContext` its `@app/shared` re-exports from here.\n *\n * `id` is the field the behavior library reads for ownership scoping and `role`\n * the field it reads for capability gating. Auth providers that name the subject\n * `uid` must normalize at their boundary — {@link normalizeUserContext} does that.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { FieldValueSchema, type FieldValue } from './entity.js';\n\n/** Authenticated user / agent identity behind `@user.x` bindings. */\nexport interface UserContext {\n /** Stable subject identifier. `@user.id` — the ownership key. */\n id: string;\n /** `@user.email` */\n email?: string;\n /** `@user.name` — display name. */\n name?: string;\n /** `@user.role` — single role string, compared against a policy's allowed list. */\n role?: string;\n /** `@user.permissions` — fine-grained capability strings. */\n permissions?: string[];\n /** Additional provider claims, readable as `@user.<claim>`. */\n [key: string]: FieldValue | undefined;\n}\n\n/**\n * The identity of an unauthenticated viewer. A resolvable object rather than\n * `undefined` so a role predicate evaluates to a definite `false` instead of\n * comparing against nothing.\n */\nexport const ANONYMOUS_USER: UserContext = {\n id: 'anonymous',\n role: 'anonymous',\n permissions: [],\n};\n\n/** Provider-shaped identity claims, before normalization. */\nexport interface RawUserClaims {\n id?: string;\n uid?: string;\n email?: string | null;\n name?: string;\n displayName?: string | null;\n role?: string;\n permissions?: string[];\n [key: string]: FieldValue | undefined;\n}\n\n/** Zod twin of `RawUserClaims` — the wire shape of `OrbitalEventRequest.user`. */\nexport const RawUserClaimsSchema: z.ZodType<RawUserClaims> = z\n .object({\n id: z.string().optional(),\n uid: z.string().optional(),\n email: z.string().nullable().optional(),\n name: z.string().optional(),\n displayName: z.string().nullable().optional(),\n role: z.string().optional(),\n permissions: z.array(z.string()).optional(),\n })\n .catchall(FieldValueSchema.optional());\n\n/** Claim keys {@link normalizeUserContext} derives rather than copies verbatim. */\nconst DERIVED_CLAIM_KEYS: readonly string[] = ['id', 'name', 'displayName', 'email'];\n\n/**\n * Normalize provider claims into a {@link UserContext}.\n *\n * Firebase (and most OIDC providers) name the subject `uid` and the display name\n * `displayName`, while every `.lolo` behavior reads `@user.id` / `@user.name`.\n * Without this normalization `@user.id` is `undefined` against a fully\n * authenticated request and every ownership filter silently matches no rows.\n * `uid` is preserved so `@user.uid` keeps working.\n *\n * Returns `undefined` for absent or subject-less claims so callers can\n * distinguish \"no auth ran\" from \"anonymous\"; use {@link ANONYMOUS_USER} where a\n * definite identity is required.\n */\nexport function normalizeUserContext(\n claims: RawUserClaims | null | undefined,\n): UserContext | undefined {\n if (!claims) return undefined;\n const id = claims.id ?? claims.uid;\n if (typeof id !== 'string' || id.length === 0) return undefined;\n\n const user: UserContext = { id };\n for (const [key, value] of Object.entries(claims)) {\n if (value === undefined || DERIVED_CLAIM_KEYS.includes(key)) continue;\n user[key] = value;\n }\n\n const name = claims.name ?? claims.displayName;\n if (typeof name === 'string' && name.length > 0) user.name = name;\n if (typeof claims.email === 'string' && claims.email.length > 0) user.email = claims.email;\n\n return user;\n}\n\n/**\n * Turn a row of an app's `[identity]` entity into a viewer.\n *\n * There is no separate persona shape: an identity row IS the persona\n * (`Almadar_LOLO_Identity.md` §4.3), so this only guards the one field the\n * behavior library requires — a non-empty string `id` — and passes every other\n * declared field through as a `@user.<field>` claim. Rows without a usable id\n * yield `undefined` rather than a persona nobody can own rows as.\n */\nexport function personaFromIdentityRow(\n row: Record<string, FieldValue | undefined>,\n): UserContext | undefined {\n const id = row['id'];\n if (typeof id !== 'string' || id.length === 0) return undefined;\n const persona: UserContext = { id };\n for (const [key, value] of Object.entries(row)) {\n if (key === 'id' || value === undefined) continue;\n persona[key] = value;\n }\n return persona;\n}\n\n/**\n * The viewer a host presents when nothing named one.\n *\n * Without this, `@user` is `Null` in headless verify and preview, so every\n * `viewerName: @user.name` binding renders blank and the account menu never\n * appears — an app that cannot say who you are. Worse, an ownership filter that\n * works and one that is broken both render an empty table.\n *\n * `role` is deliberately EMPTY, not a guess. A default of `admin` would silently\n * flip which branch renders at the 38 `@user.role` comparisons in the corpus;\n * an empty role matches no literal, exactly as `Null` did, so this fixes\n * \"undefined at runtime\" without changing a single guard outcome.\n */\nexport const DEFAULT_VIEWER: UserContext = {\n id: 'viewer-1',\n name: 'Dev Viewer',\n email: 'viewer@example.com',\n role: '',\n};\n\n/**\n * The viewer to present an app as when nothing named one.\n *\n * `DEFAULT_VIEWER` is synthetic — `viewer-1` is in no app's roster — so under it\n * every ownership predicate (`@entity.<owner> == @user.id`) matches zero rows and\n * a correctly-scoped app renders empty tables everywhere. That is indistinguishable\n * on screen from a broken filter, which is exactly the failure DEFAULT_VIEWER's own\n * comment warns about.\n *\n * So when the app declares an `[identity]` roster, the default viewer is a REAL\n * member of it. `DEFAULT_VIEWER` remains the fallback for apps that declare no\n * identity entity, where there is nobody to be.\n *\n * Both execution paths share this rule; the Rust twin is\n * `orbital-core::runtime::persona::resolve_default_viewer`.\n */\nexport function resolveDefaultViewer(roster: readonly UserContext[]): UserContext {\n return roster.length > 0 ? (roster[0] as UserContext) : DEFAULT_VIEWER;\n}\n\n/** Look a persona up in a roster by id, or by role when no id matches. */\nexport function findPersonaInRoster(\n roster: readonly UserContext[],\n idOrRole: string,\n): UserContext | undefined {\n return (\n roster.find((p) => p.id === idOrRole) ??\n roster.find((p) => p.role === idOrRole)\n );\n}\n\n/**\n * Resolve a persona spec — a bare id/role (`Person Id 3`, `moderator`) or a full\n * JSON `UserContext` — into a viewer. This is the `ALMADAR_PERSONA` contract,\n * shared by every host that presents an app as somebody.\n *\n * The roster is the app's OWN declared personas — the seeded rows of its\n * `[identity]` entity (`Almadar_LOLO_Identity.md` §4.3) — supplied by the host\n * that has them in hand (the runtime's live store on the interpreter path, the\n * schema-derived seed rows on the compiled path). There is no global roster:\n * an app without an `[identity]` entity resolves only JSON-form specs.\n *\n * Throws on anything unresolvable rather than returning `undefined`: \"no persona\"\n * and \"persona silently ignored\" look identical on screen, so a bad spec must\n * fail at boot instead of rendering as nobody.\n */\nexport function resolvePersonaSpec(spec: string, roster: readonly UserContext[]): UserContext {\n const raw = spec.trim();\n if (!raw.startsWith('{')) {\n const declared = findPersonaInRoster(roster, raw);\n if (!declared) {\n const known = roster.map((p) => `${p.id}/${p.role ?? '-'}`).join(', ');\n throw new Error(\n `Persona \"${raw}\" is not a declared persona id or role. ` +\n (roster.length > 0\n ? `Known: ${known}`\n : 'This app declares no [identity] entity, so only the JSON persona form is accepted.'),\n );\n }\n return declared;\n }\n let claims: RawUserClaims;\n try {\n claims = JSON.parse(raw);\n } catch {\n throw new Error(`Persona is not valid JSON: ${raw}`);\n }\n const user = normalizeUserContext(claims);\n if (!user) {\n throw new Error(`Persona needs an \"id\" (or \"uid\"): ${raw}`);\n }\n return user;\n}\n\n// ============================================================================\n// Dev identity token\n// ============================================================================\n\n/**\n * Marks a bearer token as a mocked dev identity rather than a real ID token.\n * The prefix is deliberately unmistakable: a server accepts these ONLY behind an\n * explicit dev opt-in, so a production deployment rejects them like any other\n * malformed token.\n */\nexport const DEV_TOKEN_PREFIX = 'almadar-dev.';\n\n/**\n * Encode a viewer as a dev bearer token.\n *\n * Carries the WHOLE identity, not just the subject: real Firebase claims have no\n * `role`, so a server that only reads `uid` leaves every `@user.role` gate inert\n * even for a signed-in user. URI-encoded JSON keeps the token header-safe (no\n * spaces or delimiters) and works unchanged in Node and the browser.\n */\nexport function encodeDevIdentityToken(user: UserContext): string {\n return DEV_TOKEN_PREFIX + encodeURIComponent(JSON.stringify(user));\n}\n\n/**\n * Decode a dev bearer token back into a viewer, or `undefined` if it is not one\n * / is malformed — callers fail closed rather than inventing an identity.\n */\nexport function decodeDevIdentityToken(token: string): UserContext | undefined {\n if (!token.startsWith(DEV_TOKEN_PREFIX)) return undefined;\n try {\n const claims: RawUserClaims = JSON.parse(\n decodeURIComponent(token.slice(DEV_TOKEN_PREFIX.length)),\n );\n return normalizeUserContext(claims);\n } catch {\n return undefined;\n }\n}\n","/**\n * Server-side effect result — the wire shape a server-executed effect\n * (`SERVER_REPORTED_EFFECTS` in `effect.ts`) reports back to the client,\n * closing the circuit on `OrbitalEventResponse.effectResults`.\n *\n * Promoted from `@almadar/runtime`'s `ServerEffectHandlers.ts` (the JS\n * interpreter's own definition, canonical per `CLAUDE.md`'s \"converge on\n * the TypeScript implementation\" ruling) so `@almadar/core` owns the one\n * shape both execution paths report against.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { EntityRowSchema, type EntityRow } from './entity.js';\nimport { SERVER_REPORTED_EFFECTS, type ServerReportedEffect, type NamespacedEffectName } from './effect.js';\nimport { EventPayloadValueSchema, type EventPayloadValue } from './expression.js';\n\n/**\n * Result entry recorded for each effect invocation. Mirrors the server\n * runtime's `EffectResult`. Callers who want telemetry pass an array that\n * the factory appends to; otherwise it's unused.\n */\nexport interface ServerBatchSummary {\n operations: EntityRow[];\n completedCount: number;\n totalCount: number;\n}\n\n/** Zod twin of `ServerBatchSummary`. */\nexport const ServerBatchSummarySchema: z.ZodType<ServerBatchSummary> = z.object({\n operations: z.array(EntityRowSchema),\n completedCount: z.number(),\n totalCount: z.number(),\n});\n\nexport interface ServerEffectResult {\n /**\n * The reported effect's head (`SERVER_REPORTED_EFFECTS`, derived from the\n * effect union in `effect.ts`), or `\"substrate\"` — the one wire grouping\n * for the namespaced operators (`trace/*`, `memory/*`, `session/*`,\n * `behavior/*`, `compose/*`), whose head rides `name`.\n */\n effect: ServerReportedEffect | \"substrate\";\n action?: string;\n entityType?: string;\n /** The invoked namespaced operator (e.g. `\"memory/store\"`), set only on `effect: \"substrate\"`. */\n name?: NamespacedEffectName;\n /** Entity row for CRUD/set/swap, the batch summary for `persist batch`, the raw service/substrate result. */\n data?: EntityRow | ServerBatchSummary | EventPayloadValue;\n success: boolean;\n /**\n * Set when a persist failed because an access policy rejected it or the\n * write resolved no row key — mirrors `OrbitalServerRuntime.EffectResult`\n * so the offline-preview and real-server persist paths report the same\n * denial discriminator to the verification trace.\n */\n denied?: true;\n error?: string;\n /** Coded failure reason for a persist that resolved no target row. */\n code?: \"not-found\" | \"no-row-key\";\n}\n\n/** Zod twin of `ServerEffectResult`. */\nexport const ServerEffectResultSchema: z.ZodType<ServerEffectResult> = z.object({\n effect: z.union([z.enum(SERVER_REPORTED_EFFECTS), z.literal(\"substrate\")]),\n action: z.string().optional(),\n entityType: z.string().optional(),\n name: z.custom<NamespacedEffectName>((v) => typeof v === \"string\" && /^[^/]+\\/.+$/.test(v)).optional(),\n data: z.union([EntityRowSchema, ServerBatchSummarySchema, EventPayloadValueSchema]).optional(),\n success: z.boolean(),\n denied: z.literal(true).optional(),\n error: z.string().optional(),\n code: z.enum([\"not-found\", \"no-row-key\"]).optional(),\n});\n","/**\n * Bus Event Types (framework concept)\n *\n * Canonical event shape for Almadar's cross-package event bus. Hoisted into\n * `@almadar/core` so `@almadar/ui`, `@almadar/runtime`, and generated code\n * all agree on the same structure. Replaces the previously divergent\n * `KFlowEvent` (ui) and `RuntimeEvent` (runtime) definitions.\n *\n * @packageDocumentation\n */\n\nimport { z } from \"zod\";\nimport { EventPayloadSchema, type EventPayload } from \"./expression.js\";\nimport { OrbitalIdSchema, TraitIdSchema, EventIdSchema, type OrbitalId, type TraitId, type EventId } from \"./identity.js\";\nimport { EntityRowSchema, type EntityRow } from \"./entity.js\";\nimport { PatternConfigSchema, ResolvedPatternPropsSchema, type PatternConfig, type ResolvedPatternProps } from \"./effect.js\";\nimport { RawUserClaimsSchema, type RawUserClaims } from \"./user.js\";\nimport { ServerEffectResultSchema, type ServerEffectResult } from \"./effect-result.js\";\n\n/**\n * Declared event key. A trait's event names (INIT, SAVE, CLOSE,\n * CONFIRM_REMOVE, ...) flow through the orbital schema and the UI as\n * strings; this alias marks \"this string is a declared event key, not\n * arbitrary text.\"\n *\n * Component props typed as `EventKey` are detected by the pattern-sync\n * tool (`tools/almadar-pattern-sync/parser.ts`) via a TS-type lookup and\n * marked as `kind: \"event\"` in the patterns registry\n * (`@almadar/patterns`). Consumers of the registry — the Rust compiler's\n * inline phase and the `@almadar/runtime` preprocess — read that marker\n * to apply call-site `events: { OLD: NEW }` renames to render-ui trees\n * without name-matching heuristics.\n *\n * Plain alias over `string`. Not branded because event keys originate\n * from user data at runtime (orb schema literals, bus emits), so cast\n * friction would buy nothing. The value of the alias is at the type\n * surface — it's a marker the pattern-sync tool can find via\n * `getSymbolAtLocation`.\n */\nexport type EventKey = string;\n\n/**\n * Phantom-typed brand for declarative bus-emit props on UI components.\n *\n * Used by component authors to BOTH mark a prop as a bus-event reference\n * AND document the payload shape that the component will fire onto the\n * bus when that prop is bound. Authors write:\n *\n * // Tabs.tsx\n * export interface TabsProps {\n * tabChangeEvent?: EventEmit<{ tabId: string }>;\n * }\n *\n * Consumers see only the structural `string` (no UX impact: passing a\n * literal `\"TAB_CHANGED\"` keeps working). The phantom `P` parameter\n * carries the bus-payload schema at the type level for pattern-sync to\n * extract.\n *\n * Pattern-sync (`tools/almadar-pattern-sync/parser.ts`) detects this\n * brand via TS type-lookup (mirrors how it detects `EventKey`) and\n * writes two registry fields per prop:\n * - `kind: \"event-ref\"` — the discriminant rules read in lolo / orb\n * validator to know \"this prop's string value is a bus event name.\"\n * - `emitPayloadSchema` — the structural shape of `P`, serialized as\n * the same JSON-Schema-shaped record Almadar uses for trait\n * `payloadSchema`. Validator rules cross-check this against the\n * trait's declared `emits { EVENT { ... } }` payload to catch mismatches\n * at parse / validate time instead of runtime.\n *\n * Example payload bus emission inside the component (no wrapper —\n * `EventEmit<P>` erases to `string`):\n *\n * if (tabChangeEvent) eventBus.emit(`UI:${tabChangeEvent}`, { tabId });\n *\n * The brand is structurally an unused optional readonly property; TS\n * never asks for it at construction, so authors and consumers never\n * see it.\n */\nexport type EventEmit<P> = string & { readonly __emitPayload?: P };\n\n/**\n * Phantom-typed brand for declarative bus-listen props on UI components.\n *\n * Mirror of `EventEmit<P>`. Used by future patterns where a UI component\n * subscribes to a bus event and forwards its payload upward via prop\n * (e.g. an editor pattern that listens for `EXTERNAL_RESET` and exposes\n * the consumed payload to the parent). Pattern-sync detects this brand\n * the same way as `EventEmit<P>` and writes:\n * - `kind: \"event-listen\"` (or a sub-discriminant of `event-ref`)\n * - `listenPayloadSchema` with the structural shape of `P`\n *\n * Validator rules use this to verify the trait the prop is bound to\n * actually emits a payload of the expected shape.\n *\n * Reserved for symmetry; no @almadar/ui component uses it as of this\n * commit. Add usages incrementally as patterns require them.\n */\nexport type EventListen<P> = string & { readonly __listenPayload?: P };\n\n// NOTE: The phantom entity-inlet brands `EntityInlet`/`EntityRecord`/\n// `EntityCollection` were removed in the entity-row clean slate. There is now\n// ONE entity type — `EntityRow` (`./entity`), used directly: a single record is\n// `EntityRow`, a collection is `readonly EntityRow[]`. pattern-sync detects an\n// entity prop by the `EntityRow` type identity and derives record-vs-collection\n// from array-vs-not, so no brand is needed.\n\n/**\n * Identifies the origin of a bus event. Used by cross-trait listeners to\n * filter emits from specific orbitals, traits, transitions, or ticks.\n *\n * `transition` and `tick` are optional runtime-internal details; most\n * consumers only care about `orbital` and `trait`.\n */\nexport interface BusEventSource {\n orbital?: string;\n /** V4 dual-carry id sibling of `orbital` — stable across an orbital rename. */\n orbitalId?: OrbitalId;\n trait?: string;\n /** V4 dual-carry id sibling of `trait` — stable across a trait rename. */\n traitId?: TraitId;\n /** V4 dual-carry id of the emitted event — stable across an event rename. */\n eventId?: EventId;\n transition?: string;\n tick?: string;\n /**\n * True when the orbital bridge re-broadcasts an event onto the bus\n * (any source — both echoes of the dispatched event and server-side\n * cascade emits via `(emit X)` / `fetch.emit.success`). Cross-trait\n * listeners filter on this flag so the click-time qualified emit\n * (which has no `fromBridge`) doesn't double-fire alongside the\n * post-server bridge confirmation. See `dispatched` for the narrower\n * \"echo of the just-dispatched event\" signal.\n */\n fromBridge?: boolean;\n /**\n * True ONLY for bridge echoes the receiving tab already processed, so\n * the originating trait's self-subscription skips them instead of\n * re-dispatching its own echo (infinite loop / double execution).\n * Set by path 1 of useOrbitalBridge (compiled shell — echo of the\n * just-dispatched event; server-side cascade emits there carry\n * `fromBridge: true` but NOT `dispatched`, so they still reach the\n * source trait's transition handler, e.g. `loading -> browsing` on a\n * fetch's `emit.success`) and by ServerBridge (runtime path — stamped\n * on exactly one response-cascade echo per event the dispatch delivered\n * locally on the bare key, `stampLocallyDeliveredEchoes`; server-only\n * results stay unstamped). Cross-trait `listens` never filter on this\n * flag, so their delivery is unaffected. Push-leg events from OTHER\n * tabs (multiplayer) are never stamped.\n */\n dispatched?: boolean;\n /**\n * The client that originated the dispatch whose effects emitted this\n * event (from `OrbitalEventRequest.clientId`); absent for headless\n * dispatches (ticks, circuit-router probes, walkers). The server-side\n * listens fan-out skips client-originated cascade emits — under dual\n * execution the originating client relays every cascade hop through the\n * bridge itself, so the server dispatching the same hop double-ran it\n * (one Send persisted two rows). Headless topology keeps the fan-out:\n * there is no client to drive the circuit.\n */\n originClientId?: string;\n}\n\n// The third type param is `object` on schemas nesting a branded-id\n// `.refine(<type predicate>)` field: the refine's parsed INPUT is a plain\n// `string`, not the branded output type, so the input/output-equal default\n// `z.ZodType<T>` mis-typechecks. `object` is what the wire actually carries\n// (a JSON body) — never `unknown`.\n\n/** Zod twin of `BusEventSource`. */\nexport const BusEventSourceSchema: z.ZodType<BusEventSource, z.ZodTypeDef, object> = z.object({\n orbital: z.string().optional(),\n orbitalId: OrbitalIdSchema.optional(),\n trait: z.string().optional(),\n traitId: TraitIdSchema.optional(),\n eventId: EventIdSchema.optional(),\n transition: z.string().optional(),\n tick: z.string().optional(),\n fromBridge: z.boolean().optional(),\n dispatched: z.boolean().optional(),\n originClientId: z.string().optional(),\n});\n\n/**\n * An event flowing on the bus.\n *\n * The `source` field is structured so cross-trait listeners can match\n * `event.source?.orbital === 'X' && event.source?.trait === 'Y'` without\n * parsing a delimiter.\n */\nexport interface BusEvent {\n /** Event type identifier (e.g., 'CartItemLoaded', 'TASK_COMPLETED') */\n type: EventKey;\n /** Optional structured payload */\n payload?: EventPayload;\n /** Timestamp when the event was emitted */\n timestamp: number;\n /** Optional origin info for filtering */\n source?: BusEventSource;\n}\n\n/** Bus event listener callback. */\nexport type BusEventListener = (event: BusEvent) => void;\n\n/** Returned by `on()` / `once()` to detach a listener. */\nexport type Unsubscribe = () => void;\n\n/**\n * One event a transition's effects emitted, carried back to the client to\n * re-dispatch (in order) so the state machine advances through the\n * cascade without server-side recursion. Named/shaped to match the\n * generated compiled-path `EmittedEvent` (orbital-shell-typescript's\n * `shared/types.ts`) so the two execution paths agree on one shape.\n */\nexport interface EmittedEvent {\n event: string;\n payload?: EventPayload;\n source?: BusEventSource;\n}\n\n/** Zod twin of `EmittedEvent`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const EmittedEventSchema: z.ZodType<EmittedEvent, z.ZodTypeDef, object> = z.object({\n event: z.string(),\n payload: EventPayloadSchema.optional(),\n source: BusEventSourceSchema.optional(),\n});\n\n// ============================================================================\n// Client-effect wire grammar\n// ============================================================================\n\n/**\n * Client-side effect tuple shipped in `OrbitalEventResponse.clientEffects`.\n * Restricted to the effect kinds the client knows how to apply to the\n * UI: render-ui (slot mutation, including the `toast` slot that carries\n * what used to be the separate notify effect) and navigate (route change).\n * Server-only effects (persist, set, fetch, ...) execute on the server and\n * surface their results via `effectResults` and `emittedEvents`, not here.\n *\n * Shape note: the wire form is broader than `RenderUIEffect` /\n * `NavigateEffect` from `@almadar/core/types/effect.ts` in two places — the\n * runtime appends an interpolated `props` object plus an optional `priority`\n * slot to render-ui (slot 4 + 5), and `navigate`'s optional argument may\n * surface as `undefined` rather than absent. The local union spells those\n * variants out explicitly so consumers (ServerBridge.tsx parser, debugger\n * inspector) get accurate completions instead of `unknown[]`.\n *\n * `slot` is a plain `string` in this wire shape (not `UISlot`'s literal\n * union) because the runtime forwards the raw string from the trait's\n * `(render-ui slot ...)` SExpr without re-validating against the registry —\n * registry validation lives in `orbital validate` / `lolo` parse, not here.\n */\nexport type ClientRenderUITuple =\n | ['render-ui', string, PatternConfig | null]\n | ['render-ui', string, PatternConfig | null, ResolvedPatternProps]\n | ['render-ui', string, PatternConfig | null, ResolvedPatternProps | undefined, number | undefined];\n\nexport type ClientNavigateTuple =\n | ['navigate', string]\n | ['navigate', string, Record<string, string> | undefined]\n | ['navigate', string, Record<string, string> | undefined, { crumb?: string }];\n\nexport type ClientNavigateBackTuple = ['navigate-back'];\n\nexport type ClientEffectTuple =\n | ClientRenderUITuple\n | ClientNavigateTuple\n | ClientNavigateBackTuple;\n\n/** Zod twin of `ClientRenderUITuple` — one variant per fixed arity (3/4/5), unioned. */\nexport const ClientRenderUITupleSchema = z.union([\n z.tuple([z.literal('render-ui'), z.string(), PatternConfigSchema]),\n z.tuple([z.literal('render-ui'), z.string(), PatternConfigSchema, ResolvedPatternPropsSchema]),\n z.tuple([\n z.literal('render-ui'),\n z.string(),\n PatternConfigSchema,\n ResolvedPatternPropsSchema.optional(),\n z.number().optional(),\n ]),\n]);\n\n/** Zod twin of `ClientNavigateTuple` — one variant per fixed arity (2/3/4), unioned. */\nexport const ClientNavigateTupleSchema = z.union([\n z.tuple([z.literal('navigate'), z.string()]),\n z.tuple([z.literal('navigate'), z.string(), z.record(z.string()).optional()]),\n z.tuple([\n z.literal('navigate'),\n z.string(),\n z.record(z.string()).optional(),\n z.object({ crumb: z.string().optional() }),\n ]),\n]);\n\n/** Zod twin of `ClientNavigateBackTuple`. */\nexport const ClientNavigateBackTupleSchema = z.tuple([z.literal('navigate-back')]);\n\n/** Zod twin of `ClientEffectTuple`. */\nexport const ClientEffectTupleSchema: z.ZodType<ClientEffectTuple> = z.union([\n ClientRenderUITupleSchema,\n ClientNavigateTupleSchema,\n ClientNavigateBackTupleSchema,\n]);\n\n// ============================================================================\n// Event dispatch wire (single owner — canonical = the TS runtime)\n// ============================================================================\n\n/**\n * Client → server event dispatch request. The single upstream owner of\n * this shape — both the JS interpreter (`@almadar/runtime`'s\n * `OrbitalEventRequest`) and the compiled path's generated `EventRequest`\n * (orbital-shell-typescript's `shared/types.ts`, mirrored 1:1 in\n * `orbital-core`) carry the same fields, so the two execution paths cannot\n * drift.\n */\nexport interface OrbitalEventRequest {\n event: string;\n /**\n * V4 dual-carry id sibling of `event` — the fired event's id, when known\n * (e.g. threaded from a `listens[].triggersId`). Optional; absent means\n * the state machine dispatches by name only (legacy).\n */\n eventId?: EventId;\n payload?: EventPayload;\n entityId?: string;\n /**\n * Scoped-listen delivery: dispatch to THIS trait only. A listens-matched\n * trigger is addressed to the listening trait; without this, a trigger\n * renamed to INIT broadcast orbital-wide and re-ran every trait's\n * initializer (R-SCOPED-LISTEN-INIT-RENAME-FREEZE re-fire cascade).\n */\n targetTrait?: string;\n /** Provider claims for `@user` bindings, normalized by `normalizeUserContext`. */\n user?: RawUserClaims;\n /** Per-tab client identity (UUID) — excludes this request's origin from live-broadcast delivery. */\n clientId?: string;\n /**\n * Broadcast-class marker (T6, docs/Almadar_Tick_Loop.md §3a): the name of\n * the tick that emitted this event. Tick-stamped dispatches are\n * latest-state broadcasts — the client fires them without awaiting the\n * response, and the server relays them to OTHER tabs coalesced\n * (newest-per-key) at a snapshot rate instead of 1:1.\n */\n tick?: string;\n /** Emitting trait for a tick-stamped dispatch — builds the relay's BusEventSource (sourceless emits are dropped client-side). */\n sourceTrait?: string;\n /**\n * Stateless addressing: the traits this dispatch runs against, each with\n * the scope it dispatches `from` (a single-element array is the common\n * case; a listens fan-out that crosses traits carries more than one). The\n * compiled server is stateless-per-trait too (`handlers.rs:510-532` seeds\n * state from `currentState`) — this generalizes that mechanism instead of\n * the retired single `currentState`/`fields` pair.\n */\n traits?: Array<{ trait: string; from: string }>;\n /**\n * The dispatching traits' current `@entity` frames (declared defaults <\n * fetched row < `[shared]` frame), keyed by trait name. The server layers\n * each row over the one it resolves via `resolveEntityView` so guards and\n * effects read the same values the client does.\n */\n entityByTrait?: Record<string, EntityRow>;\n /** The orbital/behavior name this dispatch targets, for stateless multi-orbital addressing. */\n behavior?: string;\n}\n\n/** Structured reason one trait (or the whole dispatch) did not transition. */\nexport type TransitionRejectionCode =\n | 'no-matching-transition'\n | 'guard-rejected'\n | 'no-dispatchable-traits';\n\n/**\n * Why a dispatched trait (or the whole request) did not transition —\n * G-RUNTIME-023. `statesDeclaringEvent` lists the states whose transition\n * table DOES declare the event, which makes a stale client-supplied `from`\n * self-explanatory in a stateless response.\n */\nexport interface TransitionRejection {\n code: TransitionRejectionCode;\n trait?: string;\n from?: string;\n event?: string;\n statesDeclaringEvent?: string[];\n transition?: string;\n guard?: unknown;\n}\n\n/**\n * Server → client event dispatch response. Mirrors the compiled path's\n * generated `EventResponse` (orbital-shell-typescript's `shared/types.ts`,\n * mirrored 1:1 in `orbital-core`'s `effects/response.rs`) — canonical = the\n * TS runtime's `OrbitalEventResponse` (`@almadar/runtime`'s\n * `OrbitalServerRuntime.ts`).\n */\nexport interface OrbitalEventResponse {\n success: boolean;\n transitioned: boolean;\n /** Whole-orbital state snapshot, keyed by trait name. */\n states: Record<string, string>;\n /**\n * Events emitted during processing, in declaration order. ALWAYS present\n * (`[]` when none) — the compiled Hono path used to omit this field on a\n * no-cascade response, which forced every consumer to optional-chain a\n * field that is really always there.\n *\n * Each entry carries a `source: BusEventSource` so the client-side\n * ServerBridge can re-broadcast on the qualified `UI:Orbital.Trait.EVENT`\n * bus key. Without source the re-broadcast skips the entry and downstream\n * listeners (e.g. ContactBrowse waiting for ContactLoaded after a fetch)\n * never fire — the dashboard-layout that ContactLoaded renders disappears.\n */\n emittedEvents: EmittedEvent[];\n /** Fetched/queried entity collections this response carries, keyed by entity name. */\n data?: Record<string, EntityRow[]>;\n /**\n * `@entity` fields this transition's server-side `set` effects wrote,\n * post-effect, keyed by trait name — the response-side twin of the\n * request's `entityByTrait`. The client merges them over its own effect\n * results (server wins).\n */\n entityByTrait?: Record<string, EntityRow>;\n /** Client-side effects to execute (render-ui, navigate). */\n clientEffects?: ClientEffectTuple[];\n /**\n * Same effects as `clientEffects`, paired with the producing trait name.\n * Consumers that need per-trait attribution (e.g. `<TraitFrame>` resolving\n * `@trait.X` bindings) read from this field; legacy consumers ignore it\n * and continue with the flat `clientEffects` array unchanged.\n *\n * Same length and ordering as `clientEffects`; entries are 1:1 by index.\n */\n clientEffectsByTrait?: Array<{ traitName: string; effect: ClientEffectTuple }>;\n /** Results from server-side effects (persist, call-service, set). */\n effectResults?: ServerEffectResult[];\n /** Guard that failed, addressed as `\"<Trait>.<event>\"`, for debugging. */\n guardFailed?: string;\n /**\n * Structured per-trait / per-request rejection reasons (G-RUNTIME-023) —\n * present only when nothing transitioned. Supersedes the `guardFailed`\n * string (kept for backcompat) with a machine-readable shape.\n */\n rejections?: TransitionRejection[];\n /**\n * Names of traits DROPPED from a stateless cascade because the cross-trait\n * worklist hit its safety-valve cap (G-RUNTIME-027) — the response's\n * states/effects/entity rows are INCOMPLETE for these traits. Absent when\n * the whole worklist ran. Surfaced so the truncation is observable\n * (previously the tail of any page over ~20 traits silently never\n * executed).\n */\n cascadeTruncated?: string[];\n error?: string;\n}\n\n/** Zod twin of `OrbitalEventRequest`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const OrbitalEventRequestSchema: z.ZodType<OrbitalEventRequest, z.ZodTypeDef, object> = z.object({\n event: z.string(),\n eventId: EventIdSchema.optional(),\n payload: EventPayloadSchema.optional(),\n entityId: z.string().optional(),\n targetTrait: z.string().optional(),\n user: RawUserClaimsSchema.optional(),\n clientId: z.string().optional(),\n tick: z.string().optional(),\n sourceTrait: z.string().optional(),\n traits: z.array(z.object({ trait: z.string(), from: z.string() })).optional(),\n entityByTrait: z.record(EntityRowSchema).optional(),\n behavior: z.string().optional(),\n});\n\n/** Zod twin of `OrbitalEventResponse`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const OrbitalEventResponseSchema: z.ZodType<OrbitalEventResponse, z.ZodTypeDef, object> = z.object({\n success: z.boolean(),\n transitioned: z.boolean(),\n states: z.record(z.string()),\n emittedEvents: z.array(EmittedEventSchema),\n data: z.record(z.array(EntityRowSchema)).optional(),\n entityByTrait: z.record(EntityRowSchema).optional(),\n clientEffects: z.array(ClientEffectTupleSchema).optional(),\n clientEffectsByTrait: z\n .array(z.object({ traitName: z.string(), effect: ClientEffectTupleSchema }))\n .optional(),\n effectResults: z.array(ServerEffectResultSchema).optional(),\n guardFailed: z.string().optional(),\n rejections: z\n .array(\n z.object({\n code: z.enum(['no-matching-transition', 'guard-rejected', 'no-dispatchable-traits']),\n trait: z.string().optional(),\n from: z.string().optional(),\n event: z.string().optional(),\n statesDeclaringEvent: z.array(z.string()).optional(),\n transition: z.string().optional(),\n guard: z.unknown().optional(),\n }),\n )\n .optional(),\n cascadeTruncated: z.array(z.string()).optional(),\n error: z.string().optional(),\n});\n\n// ============================================================================\n// Live broadcast wire (server → other connected clients)\n// ============================================================================\n\n/**\n * One persist-envelope success emit, handed to the live-broadcast sink\n * (`OrbitalServerRuntime.setLiveBroadcastSink`) and relayed to every OTHER\n * connected client. Fired only from the `persist` effect's `emit:{success}`\n * envelope (batch and single-op) — never from the generic emit funnel — so\n * transport layers can fan it out without matching on event names. Promoted\n * from `@almadar/runtime`'s own `LiveBroadcastItem` (canonical per Program\n * A's \"converge on the TS runtime\" ruling) so `orbital-server`'s `GET\n * /api/events` broadcast mirrors the same shape.\n */\nexport interface LiveBroadcastItem {\n event: string;\n payload?: EventPayload;\n source: BusEventSource;\n /** `clientId` of the request that produced this emit; excluded from delivery by the transport. */\n originClientId?: string;\n}\n\n/** Zod twin of `LiveBroadcastItem`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const LiveBroadcastItemSchema: z.ZodType<LiveBroadcastItem, z.ZodTypeDef, object> = z.object({\n event: z.string(),\n payload: EventPayloadSchema.optional(),\n source: BusEventSourceSchema,\n originClientId: z.string().optional(),\n});\n\n/** @deprecated use {@link OrbitalEventRequest}. Kept until every referrer migrates (Program A wave A8). */\nexport type EventDispatchRequest = OrbitalEventRequest;\n\n/** @deprecated use {@link OrbitalEventRequestSchema}. */\nexport const EventDispatchRequestSchema = OrbitalEventRequestSchema;\n\n/** @deprecated use {@link OrbitalEventResponse}. Kept until every referrer migrates (Program A wave A8). */\nexport type EventDispatchResponse = OrbitalEventResponse;\n\n/** @deprecated use {@link OrbitalEventResponseSchema}. */\nexport const EventDispatchResponseSchema = OrbitalEventResponseSchema;\n","/**\n * Event-wire fixtures (Program A, §156, wave A2) — the ONE recorded fixture\n * set every server and client test loads: vitest in `@almadar/runtime` /\n * `@almadar/ui` / `almadar-playground-runtime`, `cargo test` in\n * `orbital-core` / `orbital-server` / `orbital-client` and the native\n * (Android/iOS) shell decoders, the Hono codegen contract test, and `orb\n * verify --server`. Generated by `scripts/generate-event-wire-fixtures.ts`\n * (`pnpm run build:fixtures`, wired into `build`) into\n * `fixtures/events-wire/<case>/{request,response}.json` (+ `stream.json` for\n * `sse-stream`, `live-push.json` for `live-push`), each already validated\n * against the zod schemas at generation time.\n *\n * Node-only (reads from disk with `node:fs`) — this module is exported ONLY\n * from the `@almadar/core/fixtures` subpath, never the main entry, so\n * browser bundles (`@almadar/ui`, the playground client, both of which the\n * root workspace Vite pre-bundles `@almadar/core` through) never pull in\n * `node:fs`. Mirrors the `@almadar/core/mock` subpath precedent for\n * Node/build-only surface area.\n *\n * @packageDocumentation\n */\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { z } from 'zod';\n\nimport {\n type OrbitalEventRequest,\n type OrbitalEventResponse,\n type ClientEffectTuple,\n type EmittedEvent,\n type LiveBroadcastItem,\n OrbitalEventRequestSchema,\n OrbitalEventResponseSchema,\n ClientEffectTupleSchema,\n EmittedEventSchema,\n LiveBroadcastItemSchema,\n} from './types/bus.js';\nimport type { JsonValue } from './types/json.js';\n\n/**\n * One SSE stream item, as written by the `POST .../events?stream=true`\n * endpoint's `onPush` calls plus its final write — see `stream.json`'s\n * generator comment (`scripts/generate-event-wire-fixtures.ts`) for the\n * exact source lines. Not part of `types/bus.ts`: the enclosing envelope is\n * `@almadar/server`'s `SSEEvent<T>` transport shape, downstream of core.\n */\nexport interface SSEStreamItem {\n type: 'event' | 'effect' | 'complete' | 'error';\n data: EmittedEvent | ClientEffectTuple | OrbitalEventResponse | { message: string };\n timestamp: number;\n}\n\n/** Zod twin of `SSEStreamItem` — validates at generation AND on load. Input\n * slot is `object` for the reason given at `BusEventSourceSchema`. */\nexport const SSEStreamItemSchema: z.ZodType<SSEStreamItem, z.ZodTypeDef, object> = z.union([\n z.object({ type: z.literal('event'), data: EmittedEventSchema, timestamp: z.number() }),\n z.object({ type: z.literal('effect'), data: ClientEffectTupleSchema, timestamp: z.number() }),\n z.object({ type: z.literal('complete'), data: OrbitalEventResponseSchema, timestamp: z.number() }),\n z.object({ type: z.literal('error'), data: z.object({ message: z.string() }), timestamp: z.number() }),\n]);\n\n/** One loaded fixture case — the files actually present under `<case>/`. */\nexport interface EventWireFixture {\n request?: OrbitalEventRequest;\n response?: OrbitalEventResponse;\n stream?: SSEStreamItem[];\n livePush?: LiveBroadcastItem;\n}\n\n/**\n * Case names under `fixtures/events-wire/`, in sync with\n * `scripts/generate-event-wire-fixtures.ts` (a generator-time assertion\n * fails the build if the two lists diverge).\n */\nexport const EVENT_WIRE_FIXTURE_CASES: readonly string[] = [\n 'cascade-emitted-events',\n 'client-effects-by-trait',\n 'effect-results',\n 'effect-results-every-kind',\n 'guard-rejected',\n 'live-push',\n 'navigate-1',\n 'navigate-2',\n 'navigate-3',\n 'navigate-back',\n 'render-ui-3',\n 'render-ui-4',\n 'render-ui-5',\n 'render-ui-clear',\n 'sse-stream',\n 'stateless-traits',\n];\n\n// `src/fixtures.ts` and its built output `dist/fixtures.js` are both exactly\n// one path segment below the package root, so a single `..` resolves\n// correctly whether this module runs from source (tests, via tsx/vitest) or\n// from the published `dist/`.\nconst PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');\n\nfunction readJsonIfExists(path: string): JsonValue | undefined {\n try {\n const json: JsonValue = JSON.parse(readFileSync(path, 'utf8'));\n return json;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;\n throw error;\n }\n}\n\n/** Reads `<caseDir>/<file>` and validates it through its schema — the load is\n * typed by the parse, never by a cast. */\nfunction loadValidated<T>(caseDir: string, file: string, schema: z.ZodType<T, z.ZodTypeDef, object>): T | undefined {\n const json = readJsonIfExists(join(caseDir, file));\n return json === undefined ? undefined : schema.parse(json);\n}\n\n/**\n * Loads one case of the recorded event-wire fixture set from disk, relative\n * to the package root (works both from `packages/almadar-core` source and\n * from an installed `node_modules/@almadar/core`, since `fixtures/` ships\n * alongside `dist/` — see `package.json` `files`).\n */\nexport function loadEventWireFixture(caseName: string): EventWireFixture {\n if (!EVENT_WIRE_FIXTURE_CASES.includes(caseName)) {\n throw new Error(`Unknown event-wire fixture case: \"${caseName}\". Known cases: ${EVENT_WIRE_FIXTURE_CASES.join(', ')}`);\n }\n const caseDir = join(PACKAGE_ROOT, 'fixtures', 'events-wire', caseName);\n return {\n request: loadValidated(caseDir, 'request.json', OrbitalEventRequestSchema),\n response: loadValidated(caseDir, 'response.json', OrbitalEventResponseSchema),\n stream: loadValidated(caseDir, 'stream.json', z.array(SSEStreamItemSchema)),\n livePush: loadValidated(caseDir, 'live-push.json', LiveBroadcastItemSchema),\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/types/expression.ts","../src/types/identity.ts","../src/types/json.ts","../src/types/field.ts","../src/types/asset.ts","../src/types/entity.ts","../src/types/effect.ts","../src/types/user.ts","../src/types/effect-result.ts","../src/types/bus.ts","../src/fixtures.ts"],"names":["z"],"mappings":"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","file":"fixtures.js","sourcesContent":["/**\n * S-Expression Types\n *\n * Defines the S-Expression type system for guards, effects, and computed values.\n * S-expressions are JSON arrays where the first element is an operator string.\n *\n * @example\n * // Guard: health > 0\n * [\">\", \"@entity.health\", 0]\n *\n * // Effect: set x to x + vx\n * [\"set\", \"@entity.x\", [\"+\", \"@entity.x\", \"@entity.vx\"]]\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport type { RuntimeValue } from './json.js';\n\n// ============================================================================\n// S-Expression Type\n// ============================================================================\n\n/**\n * S-Expression type - recursive structure representing expressions.\n *\n * An S-expression is either:\n * - A literal value (string, number, boolean, null)\n * - An object literal (for payload data, props, etc.)\n * - A binding reference (string starting with @)\n * - A call expression (array with operator as first element)\n */\n/** Object literal branch of an S-expression atom (payload data, props, etc.). */\nexport interface SExprObject {\n [key: string]: SExpr;\n}\nexport type SExprAtom = string | number | boolean | null | SExprObject;\nexport type SExpr = SExprAtom | SExpr[];\n\n/**\n * Expression type - S-expressions only.\n * Used for guards, computed values, and effect expressions.\n *\n * NOTE: Legacy string format is no longer supported.\n * All expressions must be S-expression arrays.\n */\nexport type Expression = SExpr;\n\n// ============================================================================\n// S-Expression Schema (Zod)\n// ============================================================================\n\n/**\n * Recursive schema for s-expr-shaped DATA in literal positions (object\n * values, effect arguments). Unlike `SExprSchema`, arrays may be empty or\n * non-operator-headed — literal data lists (`children: []`, `tiles: [...]`)\n * are valid here; only call positions get the operator-head refine.\n */\nexport const SExprDataSchema: z.ZodType<SExpr> = z.lazy(() =>\n z.union([SExprAtomSchema, z.array(SExprDataSchema)]),\n);\n\n/**\n * Schema for atomic S-expression values (non-array)\n * Includes objects for payload data, props, etc.\n */\nexport const SExprAtomSchema: z.ZodType<SExprAtom> = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.record(SExprDataSchema), // Objects for payload data\n]);\n\n/**\n * Recursive schema for S-expressions.\n * Validates that arrays have at least one element and first element is a string (operator).\n */\nexport const SExprSchema: z.ZodType<SExpr> = z.lazy(() =>\n z.union([\n SExprAtomSchema,\n z\n .array(z.lazy(() => SExprSchema))\n .min(1)\n .refine(\n (arr) => typeof arr[0] === 'string',\n { message: 'S-expression array must have a string operator as first element' }\n ),\n ])\n);\n\n/**\n * Schema for Expression type - S-expressions only.\n * S-expressions are arrays with operator as first element.\n *\n * NOTE: Legacy string format is no longer supported.\n */\nexport const ExpressionSchema: z.ZodType<Expression> = SExprSchema;\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard for S-expression detection.\n * 100% reliable - structural check, no regex or keyword matching.\n *\n * @param value - Value to check\n * @returns true if value is an S-expression (array with string operator)\n */\nexport function isSExpr(value: RuntimeValue): value is SExpr[] {\n return (\n Array.isArray(value) &&\n value.length > 0 &&\n typeof value[0] === 'string'\n );\n}\n\n/**\n * Type guard for S-expression atoms (non-array values).\n * \n * Validates that a value is an S-expression atom (literal value).\n * Includes null, strings, numbers, booleans, and objects. Used to\n * distinguish atomic values from S-expression calls (arrays).\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is an S-expression atom, false otherwise\n *\n * @example\n * isSExprAtom('hello'); // returns true\n * isSExprAtom(42); // returns true\n * isSExprAtom(null); // returns true\n * isSExprAtom({ key: 'value' }); // returns true\n * isSExprAtom(['+', 1, 2]); // returns false\n */\nexport function isSExprAtom(value: RuntimeValue): value is SExprAtom {\n if (value === null) return true;\n if (Array.isArray(value)) return false;\n const type = typeof value;\n return type === 'string' || type === 'number' || type === 'boolean' || type === 'object';\n}\n\n/**\n * Checks if a value is a binding reference.\n * \n * Validates that a string is a binding reference (starts with @).\n * Bindings reference runtime values like @entity.health, @payload.amount, @now.\n * Used for identifying bindings in S-expressions and validation.\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is a binding reference, false otherwise\n *\n * @example\n * isBinding('@entity.health'); // returns true\n * isBinding('@payload.amount'); // returns true\n * isBinding('not-a-binding'); // returns false\n * isBinding(123); // returns false\n */\nexport function isBinding(value: RuntimeValue): value is string {\n return typeof value === 'string' && value.startsWith('@');\n}\n\n/**\n * Checks if a value is a valid S-expression call (array with operator).\n * \n * Alias for isSExpr() - validates S-expression call structure.\n * Used to distinguish between S-expression calls and atom values.\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is a valid S-expression call, false otherwise\n *\n * @example\n * isSExprCall(['+', 1, 2]); // returns true\n * isSExprCall(['set', '@entity.health', 100]); // returns true\n * isSExprCall('not-a-call'); // returns false\n */\nexport function isSExprCall(value: RuntimeValue): value is SExpr[] {\n return isSExpr(value);\n}\n\n// ============================================================================\n// Binding Parsing\n// ============================================================================\n\n/**\n * Parsed binding reference\n */\nexport interface ParsedBinding {\n /** Type of binding: core (@entity, @payload, @state, @now) or entity (@EntityName) */\n type: 'core' | 'entity';\n /** The root binding name (entity, payload, state, now, or EntityName) */\n root: string;\n /** Path segments after the root (e.g., ['health'] for @entity.health) */\n path: string[];\n /** Full original binding string */\n original: string;\n}\n\n/**\n * Core bindings that are always available.\n * Phase 4.5 adds: config, computed, trait (for behavior support).\n * `user` is the authenticated user / agent context (see binding.ts) and is\n * read-only in guards/effects/ticks — atoms reference `@user.id` and\n * `@user.role` for ownership / role-based gating.\n * `callsitePayload` is the call-site-captured event payload emitted by the\n * compiler's inline-trait hoisting; the runtime BindingResolver resolves it\n * at the composing effect.\n * `pages` / `currentTheme` are render-resolved schema sigils (effect-only,\n * see `orbital-rust/crates/orbital-compiler/src/phases/resolve.rs`):\n * substituted from the host orbital's schema (`@pages` → its `NavItem[]`\n * nav array, `@currentTheme` → its `data-theme` key) before codegen — they\n * never survive as live bindings past that substitution pass.\n */\nexport const CORE_BINDINGS = ['entity', 'payload', 'state', 'now', 'config', 'computed', 'trait', 'user', 'callsitePayload', 'pages', 'currentTheme'] as const;\nexport type CoreBinding = (typeof CORE_BINDINGS)[number];\n\n/**\n * Parses a binding reference into its components.\n * \n * Deconstructs a binding string (e.g., '@entity.health') into its constituent\n * parts: type, root, path, and original string. Does NOT use regex - uses\n * structured string operations for reliability and maintainability.\n * \n * @param {string} binding - Binding string starting with @\n * @returns {ParsedBinding | null} Parsed binding object or null if invalid\n * \n * @example\n * parseBinding('@entity.health'); // returns { type: 'core', root: 'entity', path: ['health'], original: '@entity.health' }\n * parseBinding('@User.name'); // returns { type: 'entity', root: 'User', path: ['name'], original: '@User.name' }\n * parseBinding('not-a-binding'); // returns null\n */\nexport function parseBinding(binding: string): ParsedBinding | null {\n if (!binding.startsWith('@')) {\n return null;\n }\n\n // Remove @ prefix\n const withoutPrefix = binding.slice(1);\n\n // Split by dots\n const parts = withoutPrefix.split('.');\n\n if (parts.length === 0 || parts[0] === '') {\n return null;\n }\n\n const root = parts[0];\n const path = parts.slice(1);\n\n // Determine if core binding or entity reference\n const isCore = (CORE_BINDINGS as readonly string[]).includes(root);\n\n return {\n type: isCore ? 'core' : 'entity',\n root,\n path,\n original: binding,\n };\n}\n\n/**\n * Validate a binding reference format.\n *\n * @param binding - Binding string to validate\n * @returns true if valid binding format\n */\nexport function isValidBinding(binding: string): boolean {\n const parsed = parseBinding(binding);\n if (!parsed) return false;\n\n // Core bindings: @entity, @payload, @state, @now (optionally with path)\n // @state and @now don't have paths\n if (parsed.type === 'core') {\n if (parsed.root === 'state' || parsed.root === 'now') {\n return parsed.path.length === 0;\n }\n // @entity and @payload can have paths\n return true;\n }\n\n // Entity bindings: @EntityName.field - must have at least one path segment\n return parsed.path.length > 0;\n}\n\n// ============================================================================\n// S-Expression Utilities\n// ============================================================================\n\n/**\n * Get the operator from an S-expression call.\n *\n * @param expr - S-expression array\n * @returns The operator string or null if not a valid call\n */\nexport function getOperator(expr: SExpr): string | null {\n if (!isSExpr(expr)) return null;\n return expr[0] as string;\n}\n\n/**\n * Get the arguments from an S-expression call.\n *\n * @param expr - S-expression array\n * @returns Array of arguments (empty if not a valid call)\n */\nexport function getArgs(expr: SExpr): SExpr[] {\n if (!isSExpr(expr)) return [];\n return expr.slice(1);\n}\n\n/**\n * Create an S-expression call.\n *\n * @param operator - The operator string\n * @param args - Arguments to the operator\n * @returns S-expression array\n */\nexport function sexpr(operator: string, ...args: SExpr[]): SExpr[] {\n return [operator, ...args];\n}\n\n/**\n * Walk an S-expression tree and apply a visitor function to each node.\n *\n * @param expr - S-expression to walk\n * @param visitor - Function to call on each node\n */\nexport function walkSExpr(\n expr: SExpr,\n visitor: (node: SExpr, parent: SExpr[] | null, index: number) => void,\n parent: SExpr[] | null = null,\n index: number = 0\n): void {\n visitor(expr, parent, index);\n\n if (isSExpr(expr)) {\n for (let i = 0; i < expr.length; i++) {\n walkSExpr(expr[i], visitor, expr, i);\n }\n }\n}\n\n/**\n * Collect all bindings referenced in an S-expression.\n *\n * @param expr - S-expression to analyze\n * @returns Array of binding strings found\n */\nexport function collectBindings(expr: SExpr): string[] {\n const bindings: string[] = [];\n\n walkSExpr(expr, (node) => {\n if (isBinding(node)) {\n bindings.push(node);\n }\n });\n\n return bindings;\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type SExprInput = z.input<typeof SExprSchema>;\nexport type ExpressionInput = z.input<typeof ExpressionSchema>;\n\n// ============================================================================\n// Runtime Evaluation Types\n// ============================================================================\n\n/** Evaluation context for guards and s-expressions. Recursive. */\nexport interface EvalContext {\n [key: string]: string | number | boolean | Date | null | string[] | EvalContext | undefined;\n}\n\n/**\n * A single value carried by an event payload field. The top-level payload\n * is always an object; the VALUES in that object can be primitives, nested\n * objects, or arrays of the same. Arrays are allowed so real-world emits\n * like `{ files: [{ name, size, type }, ...] }` or `{ selected: string[] }`\n * are typed natively instead of forcing consumers to wrap at every call.\n *\n * `Date` is included so `EntityRow` (whose values are `FieldValue`, which\n * includes `Date`) is assignable to a payload field without a cast —\n * emitted entity rows flow through the bus without boundary widening.\n */\nexport type EventPayloadValue =\n | string\n | number\n | boolean\n | Date\n | null\n | undefined\n | EventPayload\n | readonly EventPayloadValue[];\n\n/**\n * Typed event payload. Object-shaped so it's assignable to the bus's\n * `EventPayload` parameter without casts.\n */\nexport interface EventPayload {\n [key: string]: EventPayloadValue;\n}\n\n/**\n * Runtime guard for `EventPayloadValue` — narrows interpreter-produced\n * `unknown` values at typed substrate boundaries (e.g. `TraceContext.emit`).\n */\nexport function isEventPayloadValue(value: RuntimeValue): value is EventPayloadValue {\n if (value === null || value === undefined) return true;\n const kind = typeof value;\n if (kind === 'string' || kind === 'number' || kind === 'boolean') return true;\n if (value instanceof Date) return true;\n if (Array.isArray(value)) return value.every((item: RuntimeValue) => isEventPayloadValue(item));\n if (kind === 'object' && value !== null && typeof value === 'object') {\n return Object.values(value).every((item: RuntimeValue) => isEventPayloadValue(item));\n }\n return false;\n}\n\n/** Zod twin of `EventPayloadValue` — the one runtime validator for a bus-emit payload slot. */\nexport const EventPayloadValueSchema: z.ZodType<EventPayloadValue> = z.lazy(() =>\n z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.date(),\n z.null(),\n z.undefined(),\n EventPayloadSchema,\n z.array(EventPayloadValueSchema),\n ]),\n);\n\n/** Zod twin of `EventPayload` — the wire shape of a bus event's `payload`. */\nexport const EventPayloadSchema: z.ZodType<EventPayload> = z.lazy(() => z.record(EventPayloadValueSchema));\n\n/**\n * Allowed leaf value for `LogMeta`. Mirrors `EventPayloadValue` shape so\n * the same row/list data flows through logs without manual flattening,\n * with `Error` added since structured logs carry exception detail.\n */\nexport type LogMetaValue =\n | string\n | number\n | boolean\n | Date\n | null\n | undefined\n | Error\n | LogMeta\n | readonly LogMetaValue[];\n\n/** Structured log/event metadata. Recursive to support nested log data. */\nexport interface LogMeta {\n [key: string]: LogMetaValue;\n}\n","/**\n * Identity model (Almadar Rabit V4, Phase 1 — types only).\n *\n * Branded, prefix-tagged node ids + a workspace-scoped name ledger. Ids are\n * the durable edge keys of the identity-keyed schema graph; the ledger is the\n * sole name↔id map (names are display labels, one row per rename). This module\n * is pure: no I/O, no side effects. Minting is the only impurity (clock +\n * crypto randomness for the ULID suffix).\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Branded id types\n// ============================================================================\n\ntype Branded<K extends string> = string & { readonly __idBrand: K };\n\nexport type OrbitalId = Branded<'OrbitalId'>;\nexport type EntityId = Branded<'EntityId'>;\nexport type TraitId = Branded<'TraitId'>;\nexport type EventId = Branded<'EventId'>;\nexport type PageId = Branded<'PageId'>;\nexport type ServiceId = Branded<'ServiceId'>;\nexport type ThemeId = Branded<'ThemeId'>;\nexport type PaletteEntryId = Branded<'PaletteEntryId'>;\n\n/** Node kind ↔ id-prefix table. The single source of truth for every prefix. */\nconst ID_PREFIXES = {\n orbital: 'orb_',\n entity: 'ent_',\n trait: 'trt_',\n event: 'evt_',\n page: 'pag_',\n service: 'svc_',\n theme: 'thm_',\n palette: 'pal_',\n} as const;\n\nexport type IdKind = keyof typeof ID_PREFIXES;\n\n/** Compile-time map from kind to its branded id type. */\nexport interface IdForKind {\n orbital: OrbitalId;\n entity: EntityId;\n trait: TraitId;\n event: EventId;\n page: PageId;\n service: ServiceId;\n theme: ThemeId;\n palette: PaletteEntryId;\n}\n\n/**\n * The one controlled brand assertion in this module. A prefix-checked string\n * is asserted into its branded form here and nowhere else.\n */\nfunction brand<Id extends string>(value: string): Id {\n return value as Id;\n}\n\n// ============================================================================\n// Kind guards + constructors (one shared factory, eight kinds)\n// ============================================================================\n\ninterface IdKindApi<Id extends string> {\n readonly prefix: string;\n is(value: string): value is Id;\n as(value: string): Id;\n}\n\nfunction makeIdKind<Id extends string>(kind: IdKind): IdKindApi<Id> {\n const prefix = ID_PREFIXES[kind];\n const is = (value: string): value is Id =>\n value.startsWith(prefix) && value.length > prefix.length;\n const as = (value: string): Id => {\n if (!is(value)) {\n throw new Error(\n `Expected ${kind} id (prefix \"${prefix}\"), got: ${JSON.stringify(value)}`,\n );\n }\n return brand<Id>(value);\n };\n return { prefix, is, as };\n}\n\nconst orbitalKind = makeIdKind<OrbitalId>('orbital');\nconst entityKind = makeIdKind<EntityId>('entity');\nconst traitKind = makeIdKind<TraitId>('trait');\nconst eventKind = makeIdKind<EventId>('event');\nconst pageKind = makeIdKind<PageId>('page');\nconst serviceKind = makeIdKind<ServiceId>('service');\nconst themeKind = makeIdKind<ThemeId>('theme');\nconst paletteKind = makeIdKind<PaletteEntryId>('palette');\n\nexport const isOrbitalId = orbitalKind.is;\nexport const asOrbitalId = orbitalKind.as;\nexport const isEntityId = entityKind.is;\nexport const asEntityId = entityKind.as;\nexport const isTraitId = traitKind.is;\nexport const asTraitId = traitKind.as;\nexport const isEventId = eventKind.is;\nexport const asEventId = eventKind.as;\nexport const isPageId = pageKind.is;\nexport const asPageId = pageKind.as;\nexport const isServiceId = serviceKind.is;\nexport const asServiceId = serviceKind.as;\nexport const isThemeId = themeKind.is;\nexport const asThemeId = themeKind.as;\nexport const isPaletteEntryId = paletteKind.is;\nexport const asPaletteEntryId = paletteKind.as;\n\n/**\n * The id-prefix for a node kind (`'entity' → 'ent_'`). The JS mirror of the\n * Rust `IdKind::prefix`. Single source of truth is {@link ID_PREFIXES}.\n */\nexport function idPrefix(kind: IdKind): string {\n return ID_PREFIXES[kind];\n}\n\n/**\n * The node kind an id's prefix denotes, or `null` for an unrecognized /\n * bare-prefix string. The JS mirror of the Rust `id_kind_of`. Prefixes are\n * mutually non-overlapping, so match order is irrelevant.\n */\nexport function idKindOf(id: string): IdKind | null {\n for (const kind of Object.keys(ID_PREFIXES) as IdKind[]) {\n const prefix = ID_PREFIXES[kind];\n if (id.startsWith(prefix) && id.length > prefix.length) return kind;\n }\n return null;\n}\n\n// ============================================================================\n// Minting — prefix + ULID\n// ============================================================================\n\nconst CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(len: number): Uint8Array {\n const g = globalThis as { crypto?: { getRandomValues?: (a: Uint8Array) => Uint8Array } };\n if (g.crypto?.getRandomValues) {\n return g.crypto.getRandomValues(new Uint8Array(len));\n }\n throw new Error('mintId: no crypto.getRandomValues available in this runtime');\n}\n\nfunction encodeTime(now: number): string {\n let value = now;\n let out = '';\n for (let i = 0; i < TIME_LEN; i++) {\n const mod = value % 32;\n out = CROCKFORD[mod] + out;\n value = (value - mod) / 32;\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n const bytes = randomBytes(RANDOM_LEN);\n let out = '';\n for (let i = 0; i < RANDOM_LEN; i++) {\n out += CROCKFORD[bytes[i] & 31];\n }\n return out;\n}\n\n/** A 26-char Crockford-base32 ULID: 48-bit ms timestamp + 80 bits of randomness. */\nfunction ulid(): string {\n return encodeTime(Date.now()) + encodeRandom();\n}\n\n/** Mint a fresh, opaque, kind-tagged id: `<prefix><ULID>`. */\nexport function mintId<K extends IdKind>(kind: K): IdForKind[K] {\n return brand<IdForKind[K]>(ID_PREFIXES[kind] + ulid());\n}\n\n// ============================================================================\n// Deterministic derivation — JS twin of Rust `derive_id`\n// ============================================================================\n\nconst U64_MASK = (1n << 64n) - 1n;\nconst BODY_TIME_MASK = (1n << 50n) - 1n;\nconst BODY_RANDOM_MASK = (1n << 80n) - 1n;\nconst FNV_PRIME_64 = 0x100000001b3n;\nconst FNV_OFFSET_1 = 0xcbf29ce484222325n;\nconst FNV_OFFSET_2 = (0x100000001b3n ^ 0xdeadbeefn) & U64_MASK;\n\n/** SplitMix64 — a small, well-distributed non-cryptographic mixer. */\nfunction splitmix64(x: bigint): bigint {\n let z = (x + 0x9e3779b97f4a7c15n) & U64_MASK;\n z = ((z ^ (z >> 30n)) * 0xbf58476d1ce4e5b9n) & U64_MASK;\n z = ((z ^ (z >> 27n)) * 0x94d049bb133111ebn) & U64_MASK;\n return (z ^ (z >> 31n)) & U64_MASK;\n}\n\n/** FNV-1a 64-bit over `data` starting from `offset`. */\nfunction fnv1a64(data: Uint8Array, offset: bigint): bigint {\n let h = offset & U64_MASK;\n for (const b of data) {\n h = (h ^ BigInt(b)) & U64_MASK;\n h = (h * FNV_PRIME_64) & U64_MASK;\n }\n return h;\n}\n\n/** Emit the low `nChars * 5` bits of `value` as base32, most-significant char first. */\nfunction pushBase32(value: bigint, nChars: number): string {\n let v = value;\n const chars = new Array<string>(nChars);\n for (let i = nChars - 1; i >= 0; i--) {\n chars[i] = CROCKFORD[Number(v & 0x1fn)];\n v >>= 5n;\n }\n return chars.join('');\n}\n\n/**\n * Deterministically derive a child id rooted in `parentId` — no entropy, no\n * clock, so re-deriving from the same inputs never churns. JS twin of the\n * Rust `derive_id` in `orbital-core/src/identity.rs`; used ONLY for synthetic\n * nodes produced by deterministic materialization (orbital-import\n * prefixing), never for author-facing fresh ids (use {@link mintId} there).\n */\nexport function deriveId(parentId: string, discriminator: string): string {\n const kind = idKindOf(parentId) ?? 'trait';\n const encoder = new TextEncoder();\n const parentBytes = encoder.encode(parentId);\n const discBytes = encoder.encode(discriminator);\n const data = new Uint8Array(parentBytes.length + 1 + discBytes.length);\n data.set(parentBytes, 0);\n data[parentBytes.length] = 0x1f;\n data.set(discBytes, parentBytes.length + 1);\n\n const h1 = splitmix64(fnv1a64(data, FNV_OFFSET_1));\n const h2 = splitmix64(fnv1a64(data, FNV_OFFSET_2));\n const timeBits = (((h1 << 64n) | h2) & BODY_TIME_MASK);\n const randBits = (((h2 << 64n) | h1) & BODY_RANDOM_MASK);\n\n return ID_PREFIXES[kind] + pushBase32(timeBits, 10) + pushBase32(randBits, 16);\n}\n\n// ============================================================================\n// Identity ledger\n// ============================================================================\n\n/** Ledger row kind. `palette` entries are manifest ids, not name-ledger rows. */\nexport type LedgerKind =\n | 'orbital'\n | 'entity'\n | 'trait'\n | 'event'\n | 'page'\n | 'service'\n | 'theme';\n\n/**\n * One ledger row: the workspace's name history for a single node id.\n *\n * For kind `'event'` the row is minted per-(trait, declared event) per the\n * Phase-0 freeze — the owning trait is recorded in `parent`; a call-site event\n * rename is a one-row edit on this same id (the baked-vs-current key namespaces\n * collapse into `bakedName` vs `curName`).\n */\nexport interface LedgerEntry {\n id: string;\n kind: LedgerKind;\n bakedName: string;\n curName: string;\n renames: ReadonlyArray<{ from: string; to: string; at: string }>;\n owner: 'std' | 'io' | 'workspace';\n /** Owning trait for kind `'event'` (per-trait event-id namespace). */\n parent?: TraitId;\n}\n\nexport interface IdentityLedger {\n schemaVersion: 1;\n entries: Record<string, LedgerEntry>;\n}\n\n/** Resolve a name to its id via exact `curName` match within `kind`, else null. */\nexport function ledgerResolveName(\n ledger: IdentityLedger,\n kind: LedgerKind,\n name: string,\n): string | null {\n for (const [id, entry] of Object.entries(ledger.entries)) {\n if (entry.kind === kind && entry.curName === name) return id;\n }\n return null;\n}\n\n/** Immutable rename: returns a new ledger with the id's `curName` + `renames` updated. */\nexport function ledgerRename(\n ledger: IdentityLedger,\n id: string,\n to: string,\n at: string,\n): IdentityLedger {\n const entry = ledger.entries[id];\n if (entry === undefined) return ledger;\n const updated: LedgerEntry = {\n ...entry,\n curName: to,\n renames: [...entry.renames, { from: entry.curName, to, at }],\n };\n return { ...ledger, entries: { ...ledger.entries, [id]: updated } };\n}\n\n/** Current display name for an id, or null when the id is not in the ledger. */\nexport function ledgerCurName(ledger: IdentityLedger, id: string): string | null {\n return ledger.entries[id]?.curName ?? null;\n}\n\n// ============================================================================\n// Zod schemas — the `.orb` load-time activation surface (Rabit V4, Phase 4)\n// ============================================================================\n\n/**\n * Prefix-checked, kind-tagged id schemas. Each narrows a validated string to\n * its branded id type via the module's own kind guard, so a schema that reads\n * `TraitIdSchema.optional()` yields `TraitId | undefined` with no cast. The\n * guard is the single source of prefix truth (`ID_PREFIXES`); the schema is a\n * thin zod wrapper over it.\n */\nexport const OrbitalIdSchema = z\n .string()\n .refine(isOrbitalId, { message: `Expected an orbital id (prefix \"${ID_PREFIXES.orbital}\")` });\nexport const EntityIdSchema = z\n .string()\n .refine(isEntityId, { message: `Expected an entity id (prefix \"${ID_PREFIXES.entity}\")` });\nexport const TraitIdSchema = z\n .string()\n .refine(isTraitId, { message: `Expected a trait id (prefix \"${ID_PREFIXES.trait}\")` });\nexport const EventIdSchema = z\n .string()\n .refine(isEventId, { message: `Expected an event id (prefix \"${ID_PREFIXES.event}\")` });\nexport const PageIdSchema = z\n .string()\n .refine(isPageId, { message: `Expected a page id (prefix \"${ID_PREFIXES.page}\")` });\nexport const ServiceIdSchema = z\n .string()\n .refine(isServiceId, { message: `Expected a service id (prefix \"${ID_PREFIXES.service}\")` });\nexport const ThemeIdSchema = z\n .string()\n .refine(isThemeId, { message: `Expected a theme id (prefix \"${ID_PREFIXES.theme}\")` });\nexport const PaletteEntryIdSchema = z\n .string()\n .refine(isPaletteEntryId, { message: `Expected a palette-entry id (prefix \"${ID_PREFIXES.palette}\")` });\n\nexport const LedgerKindSchema = z.enum([\n 'orbital',\n 'entity',\n 'trait',\n 'event',\n 'page',\n 'service',\n 'theme',\n]);\n\nexport const LedgerEntrySchema = z.object({\n id: z.string(),\n kind: LedgerKindSchema,\n bakedName: z.string(),\n curName: z.string(),\n renames: z.array(\n z.object({ from: z.string(), to: z.string(), at: z.string() }),\n ),\n owner: z.enum(['std', 'io', 'workspace']),\n parent: TraitIdSchema.optional(),\n});\n\nexport const IdentityLedgerSchema = z.object({\n schemaVersion: z.literal(1),\n entries: z.record(LedgerEntrySchema),\n});\n","/**\n * JSON primitives — the universal \"data crossed a boundary\" type.\n *\n * Every value that arrives over the wire from an LLM (tool-call args),\n * from disk (workspace files), or from an HTTP body before\n * domain-specific validation is a `JsonValue`. Narrow with a typed\n * predicate (`is`-guard) at the boundary; don't widen back to `unknown`.\n *\n * `JsonObject` and `ToolArgs` are aliases for the common\n * `Record<string, JsonValue>` shape. `ToolArgs` is the name the\n * agent surface uses for LLM-emitted tool-call arguments; `JsonObject`\n * is the general-purpose alias. They are the same type — the alias\n * exists so call sites read at the right semantic level.\n *\n * Why not `Record<string, unknown>`? Two reasons. (1) `unknown` widens\n * back to anything, which defeats the purpose of typing the boundary.\n * (2) The `@almadar/eslint-plugin/no-record-string-unknown` rule blocks\n * the wider form — `JsonValue`-based records are the typed answer.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\n\n/**\n * Recursive JSON value union — every shape JSON can carry.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/**\n * JSON object — keyed string→JsonValue. The wire form of arbitrary\n * structured data. Replaces `Record<string, unknown>` at typed\n * boundaries (LLM emits, file reads, HTTP bodies).\n */\nexport type JsonObject = { [key: string]: JsonValue };\n\n/** Zod schema for JsonValue — the one boundary validator for parsed-JSON slots. */\nexport const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(JsonValueSchema), z.record(JsonValueSchema)]),\n);\n\n/**\n * LLM tool-call arguments — same shape as `JsonObject`, named for the\n * agent-surface call site. Each tool's `execute(args: ToolArgs)`\n * receives this and narrows via an `is`-guard predicate before any\n * field access.\n */\nexport type ToolArgs = JsonObject;\n\n/**\n * Universal type-guard input — every runtime value shape a predicate can\n * be handed, enumerated instead of `unknown` (the repo bans `unknown`\n * even at guard boundaries). Primitives cover every `typeof` result;\n * `object` covers arrays, records, class instances, and functions.\n */\nexport type RuntimeValue =\n | string\n | number\n | bigint\n | boolean\n | symbol\n | Date\n | null\n | undefined\n | object;\n\n/**\n * Type guard: is the given value a JSON primitive (non-array,\n * non-object)? Used by walkers that decide whether to recurse.\n */\nexport function isJsonPrimitive(\n value: JsonValue,\n): value is string | number | boolean | null {\n return (\n value === null\n || typeof value === 'string'\n || typeof value === 'number'\n || typeof value === 'boolean'\n );\n}\n\n/**\n * Type guard: is the given value a JSON object (non-array, non-null)?\n */\nexport function isJsonObject(value: JsonValue): value is JsonObject {\n return (\n value !== null\n && typeof value === 'object'\n && !Array.isArray(value)\n );\n}\n\n/**\n * Type guard: is the given value a JSON array?\n */\nexport function isJsonArray(value: JsonValue): value is JsonValue[] {\n return Array.isArray(value);\n}\n","/**\n * Field Types for Orbital Units\n *\n * Extracted from schema/data-entities.ts for the orbitals module.\n * These types define the field structure within orbital entities.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport type { EntityId } from './identity.js';\nimport { EntityIdSchema } from './identity.js';\nimport type { JsonValue, RuntimeValue } from './json.js';\nimport { JsonValueSchema } from './json.js';\n\n// ============================================================================\n// Field Types\n// ============================================================================\n\n/**\n * Supported field types for entity fields.\n *\n * @example\n * { name: 'status', type: 'enum', values: ['draft', 'published'] }\n * { name: 'authorId', type: 'relation', relation: { entity: 'User', cardinality: 'one' } }\n */\nexport type FieldType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'date'\n | 'timestamp'\n | 'datetime'\n // Semantic string domains. `.lolo` already types `date`/`datetime` rather\n // than annotating them, so these belong in the type system for the same\n // reason: a field's domain is a declared fact, not a decoration. They\n // replaced the optional `format` property, which had zero producers.\n | 'email'\n | 'url'\n | 'phone'\n | 'uuid'\n | 'image'\n // Promoted value types (2026-08-20). `money` is numeric at rest - the\n // declared type (never a field-name heuristic) drives currency inputs\n // and formatting. `file` is the canonical struct value\n // {name, url, mimeType, sizeBytes} - an uploaded artifact, not a\n // validated string; `url` is a data: URI in mock mode.\n | 'money'\n | 'file'\n | 'array'\n | 'object'\n | 'enum'\n | 'relation'\n | 'trait'\n | 'slot'\n | 'pattern'\n // Renderable UI content — a pattern node (or array of them), the same\n // shape `render-ui` effects carry (`PatternNode` in render-ui-edit.ts).\n // First-class so view-fragment fields stop hiding behind `object`/`json`.\n | 'node'\n // Event-name reference — a string at rest, but the TYPE marks it as an\n // event key rather than free text (Phase B / SCAN-EVENT-KNOB-2). Legal\n // on struct-alias fields consumed by config knobs (e.g. `ItemAction.event`).\n | 'event'\n // Closed scalar transport union (`ControlValue`) and tagged struct union\n // (`type DrawItem = DrawShape | DrawText`) — real .lolo/.orb types the\n // Rust compiler accepts; the TS mirror must carry them or generated\n // factories fail DTS (docs/Almadar_LOLO_Gaps.md L-6).\n | 'scalar'\n | 'union';\n\n/** Every `FieldType`, as a runtime array. Downstream imports this instead of\n * re-listing the union — five copies had already drifted apart. */\nexport const FIELD_TYPES = [\n 'string',\n 'number',\n 'boolean',\n 'date',\n 'timestamp',\n 'datetime',\n 'email',\n 'url',\n 'phone',\n 'uuid',\n 'image',\n 'money',\n 'file',\n 'array',\n 'object',\n 'enum',\n 'relation',\n 'trait',\n 'slot',\n 'pattern',\n 'node',\n 'event',\n 'scalar',\n 'union',\n] as const satisfies readonly FieldType[];\n\n/** The semantic string domains — constrained strings, validatable by value. */\nexport const SEMANTIC_STRING_TYPES = ['email', 'url', 'phone', 'uuid', 'image'] as const;\n\nexport type SemanticStringType = (typeof SEMANTIC_STRING_TYPES)[number];\n\n/** Is this a semantic string domain (as opposed to a bare `string`)? */\nexport function isSemanticStringType(type: FieldType): type is SemanticStringType {\n return (SEMANTIC_STRING_TYPES as readonly string[]).includes(type);\n}\n\nexport const FieldTypeSchema = z.enum(FIELD_TYPES);\n\n/** Words legal in a `.lolo`/`.orb` TYPE POSITION that are not entity field\n * types (config/param/return annotations, primitives with no field-level\n * meaning, etc.) — declared so the i18n `types` vocabulary section is\n * `FIELD_TYPES ∪ TYPE_POSITION_ONLY` exactly, not a hand-maintained superset\n * held together by a one-directional pinned test (see G-i18n-5). */\nexport const TYPE_POSITION_ONLY = [\n 'Map',\n 'SExpr',\n 'any',\n 'asset',\n 'bool',\n 'component',\n 'duration',\n 'entity',\n 'float',\n 'icon',\n 'int',\n 'null',\n 'secret',\n 'void',\n] as const;\n\n// ============================================================================\n// Relation Configuration\n// ============================================================================\n\n/**\n * Cardinality for relation fields.\n * Matches Rust compiler's Cardinality enum.\n */\nexport type RelationCardinality = \n | 'one' \n | 'many' \n | 'one-to-many' \n | 'many-to-one' \n | 'many-to-many';\n\nexport const RelationCardinalitySchema = z.enum([\n 'one',\n 'many',\n 'one-to-many',\n 'many-to-one',\n 'many-to-many',\n]);\n\n/**\n * Configuration for relation fields (foreign keys).\n * Matches Rust compiler's RelationDefinition format.\n */\nexport type RelationConfig = {\n /** Target entity name (e.g., 'User', 'Task') - matches Rust's `entity` field */\n entity: string;\n /** V4 dual-carry id sibling of `entity` — optional until the Phase-7 flip. */\n entityId?: EntityId;\n /** Field on target entity (defaults to 'id') */\n field?: string;\n /** \n * Cardinality: one, many, one-to-many, many-to-one, many-to-many\n * Matches Rust compiler's cardinality format\n */\n cardinality?: RelationCardinality;\n /** Delete behavior */\n onDelete?: 'cascade' | 'nullify' | 'restrict';\n /** \n * Foreign key field name (for legacy compatibility).\n * @deprecated Use field instead\n */\n foreignKey?: string;\n /**\n * Target entity name (for legacy compatibility).\n * @deprecated Use entity instead\n */\n target?: string;\n /**\n * Cardinality type alias (for legacy compatibility).\n * @deprecated Use cardinality instead\n */\n type?: RelationCardinality;\n};\n\nexport const RelationConfigSchema = z.object({\n entity: z.string().min(1, 'Target entity is required'),\n entityId: EntityIdSchema.optional(),\n field: z.string().optional(),\n cardinality: RelationCardinalitySchema.optional(),\n onDelete: z.enum(['cascade', 'nullify', 'restrict']).optional(),\n // Legacy compatibility fields\n foreignKey: z.string().optional(),\n target: z.string().optional(),\n type: RelationCardinalitySchema.optional(),\n}).transform((data) => {\n // Normalize legacy format to standard format\n const normalized: RelationConfig = {\n entity: data.entity || data.target || '',\n entityId: data.entityId,\n cardinality: data.cardinality || data.type,\n field: data.field,\n onDelete: data.onDelete,\n };\n return normalized;\n});\n\nexport type RelationConfigInput = z.input<typeof RelationConfigSchema>;\n\n// ============================================================================\n// Field Format\n// ============================================================================\n\n/**\n * Value rules for the semantic string domains — one owner, so the seeders, the\n * validators and the verifiers cannot drift apart on what counts as valid.\n *\n * These replaced the old optional `format` property, which had zero producers\n * anywhere in the repo and no Rust counterpart at all: `format` was unreachable\n * from `.lolo`, so every consumer fell back to guessing from field names.\n */\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@.]+\\.[^\\s@]+$/;\nconst URL_RE = /^https?:\\/\\/[^\\s]+$/;\nconst PHONE_RE = /^[+]?[\\d\\s().-]{7,}$/;\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function isEmailValue(value: string): boolean {\n return EMAIL_RE.test(value);\n}\n\nexport function isUrlValue(value: string): boolean {\n return URL_RE.test(value);\n}\n\nexport function isPhoneValue(value: string): boolean {\n return PHONE_RE.test(value);\n}\n\nexport function isUuidValue(value: string): boolean {\n return UUID_RE.test(value);\n}\n\n// ============================================================================\n// File value — the canonical struct a `file`-typed field holds at rest.\n// ONE owner for the shape; mirrors `file_value_fields()` in orbital-core\n// (ir/render.rs) and the codegen zod emitter.\n// ============================================================================\n\n/** The value a `file`-typed entity field holds: an uploaded artifact.\n * `url` is a `data:` URI in mock/playground mode (size-ceilinged by the\n * mock adapter) or an object-storage URL in production. */\nexport type FileValue = {\n name: string;\n url: string;\n mimeType: string;\n sizeBytes: number;\n};\n\n/** Zod schema for {@link FileValue}. */\nexport const FileValueSchema = z.object({\n name: z.string(),\n url: z.string(),\n mimeType: z.string(),\n sizeBytes: z.number(),\n});\n\n/** Is `value` a well-formed {@link FileValue}? The `file` twin of\n * `isSemanticStringValue` — the seeder's output must satisfy this. */\nexport function isFileValue(value: unknown): value is FileValue {\n return FileValueSchema.safeParse(value).success;\n}\n\n/** Does `value` satisfy the declared semantic domain? `image` is a URL. */\nexport function isSemanticStringValue(type: SemanticStringType, value: string): boolean {\n switch (type) {\n case 'email':\n return isEmailValue(value);\n case 'url':\n case 'image':\n return isUrlValue(value);\n case 'phone':\n return isPhoneValue(value);\n case 'uuid':\n return isUuidValue(value);\n }\n}\n\n// ============================================================================\n// Entity Field — discriminated union by `type`\n// ============================================================================\n\n/**\n * Field-type tags that don't carry a type-dependent payload. The base\n * `EntityField` shape applies as-is.\n */\ntype ScalarFieldType =\n | 'string'\n | 'number'\n | 'boolean'\n | 'date'\n | 'timestamp'\n | 'datetime'\n | 'email'\n | 'url'\n | 'phone'\n | 'uuid'\n | 'image'\n | 'money'\n | 'file'\n | 'trait'\n | 'slot'\n | 'pattern'\n | 'node'\n | 'event'\n // Closed scalar transport union (`ControlValue`) — a real .lolo/.orb type\n // the compiler accepts in payloads and map values; the TS mirror must carry\n // it or generated factories fail DTS (docs/Almadar_LOLO_Gaps.md L-6).\n | 'scalar';\n\n/** Fields shared across every variant. */\ntype EntityFieldBase = {\n /**\n * Field name (camelCase). Optional for nested item/property descriptors\n * where the name is implied by the parent (`items`, `properties[k]`).\n * Mirrors Rust's `FieldDefinition.name: Option<String>`.\n */\n name?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Primary-key marker. Mirrors Rust's `FieldDefinition.primary_key`\n * (serde `primaryKey`). */\n primaryKey?: boolean;\n /** Default value — parsed from `.orb`, always JSON-shaped. */\n default?: JsonValue;\n /** Minimum value (for number) or length (for string) */\n min?: number;\n /** Maximum value or length */\n max?: number;\n /** Object property schemas keyed by property name (for object type).\n * Mirrors Rust's `FieldDefinition.properties: Option<HashMap<String,\n * FieldDefinition>>`. Populated by the lolo lowerer when a field /\n * config slot's type expression resolves to a struct shape\n * (`TypeExpr::Object`), including named-type aliases like `[MetricSpec]`. */\n properties?: Record<string, EntityField>;\n /** Runtime-managed widget state (authored `@intrinsic` in `.lolo`). Exempt\n * from the explicit-binding rule and never a domain-data bind target. */\n intrinsic?: boolean;\n /** Human/semantic description (authored `@description \"...\"` in `.lolo`).\n * Authoring/build-time metadata — factory-signature catalog, embeddings,\n * curation field-matching; the runtime ignores it. */\n description?: string;\n /** User-vocabulary synonyms (authored `@synonyms \"...\"` in `.lolo`).\n * Free text feeding catalog search / curation field-matching. */\n synonyms?: string;\n /** Declared mock value(s) (authored `@mock \"...\"` in `.lolo`), used\n * LITERALLY by the seeder (`sampleValue.ts`, `seed.rs`) — never mapped\n * through a domain-name lookup table. Comma-separated is an explicit\n * candidate list rotated by row index (`@mock \"Acme Corp, Globex Inc\"`);\n * no comma is a single literal value, index-suffixed per row\n * (`@mock \"person-name\"` -> \"person-name-1\", \"person-name-2\", ...). */\n mock?: string;\n /**\n * The imported entity this field was merged from on a rebind (sibling\n * pull / entity contract). Absent on author-declared fields — a merged\n * field's `required` is the ATOM's own write contract, never the host\n * writer's.\n */\n mergedFrom?: string;\n};\n\n/**\n * Scalar / structural fields — no type-dependent payload required.\n * `values?` is permitted as an OPTIONAL UI/validation hint (e.g. lolo's\n * `'a' | 'b' | 'c'` string-union sugar lowers to `type: 'string', values:\n * [...]`). Only `EnumEntityField` MANDATES values.\n */\nexport type ScalarEntityField = EntityFieldBase & {\n type: ScalarFieldType;\n /** Optional vocabulary hint for scalar fields (e.g. string unions\n * authored as `'a'|'b'|'c'` in lolo). Not required at this variant. */\n values?: string[];\n};\n\n/** `type: 'enum'` REQUIRES the closed vocabulary in `values`. */\nexport type EnumEntityField = EntityFieldBase & {\n type: 'enum';\n /** Closed string vocabulary the field accepts. */\n values: string[];\n};\n\n/** `type: 'relation'` REQUIRES the relation target binding. */\nexport type RelationEntityField = EntityFieldBase & {\n type: 'relation';\n /** Relation target binding (entity + cardinality). */\n relation: RelationConfig;\n};\n\n/**\n * `type: 'union'` — a TAGGED union of struct variants (`.lolo`\n * `type DrawItem = DrawShape | DrawText`). `values` carries the variant NAMES\n * in declaration order; `properties` (from the base shape) carries each\n * variant's shape keyed by that name. The discriminator is the variant's own\n * literal-typed tag field, so selection is data-driven. Recursion is carried\n * BY NAME: a variant referring back to the union gets `values` with no\n * `properties` (mirrors `FieldType::Union` in orbital-core).\n */\nexport type UnionEntityField = EntityFieldBase & {\n type: 'union';\n /** Variant type names in declaration order. */\n values: string[];\n};\n\n/** `type: 'array'` — element schema in `items` strongly preferred but\n * optional for legacy compatibility with codegen-emitted scalar-array\n * fields (e.g. `{type: 'array', default: []}`). The lolo lowerer + Rust\n * validator catch typed-element-required cases downstream. */\nexport type ArrayEntityField = EntityFieldBase & {\n type: 'array';\n /** Element schema for the array. */\n items?: EntityField;\n};\n\n/**\n * `type: 'object'` — a fixed-key struct (fields in `properties`) OR a\n * dynamic-key map (`Map K V` in `.lolo`; the uniform value schema lives in\n * `items`, mirroring an array's element schema). A distinct variant so `items`\n * is statically allowed only on object/array fields, never on scalars.\n */\nexport type ObjectEntityField = EntityFieldBase & {\n type: 'object';\n /** Uniform value schema for a dynamic-key map (`Map K V`). */\n items?: EntityField;\n};\n\n/**\n * Entity field definition — discriminated union by `type`. Each variant\n * statically enforces its dependent payload (`values` for enum,\n * `relation` for relation, `items` for array) so TS / Zod / JSON Schema\n * consumers all agree on the dependency, not just the Rust validator.\n *\n * @example\n * { name: 'status', type: 'enum', values: ['draft', 'published'] }\n * { name: 'authorId', type: 'relation', relation: { entity: 'User', cardinality: 'one' } }\n * { name: 'tags', type: 'array', items: { type: 'string' } }\n */\nexport type EntityField =\n | ScalarEntityField\n | EnumEntityField\n | RelationEntityField\n | UnionEntityField\n | ArrayEntityField\n | ObjectEntityField;\n\n/**\n * Alias map for legacy/loose field-type spellings. Preprocessed into the\n * canonical `FieldType` enum before zod validates. Without this, agent-produced\n * schemas using `text`/`int`/`float`/`ts` were rejected at parse time — this\n * normalizes them so the rest of the pipeline sees only canonical types.\n */\nconst FIELD_TYPE_ALIASES: Record<string, FieldType> = {\n text: 'string',\n int: 'number',\n float: 'number',\n ts: 'timestamp',\n};\n\n/**\n * Zod schema for `EntityField`. Preprocess normalizes:\n * - legacy `type` aliases (text → string, int → number, etc.)\n * - legacy `enum: string[]` alias → `values: string[]`\n *\n * Branches on `type` so TS narrows the parsed output to the matching\n * discriminated-union variant.\n */\n// The third type param stays `unknown`: zod v3 bakes `unknown` into\n// `z.preprocess`'s input type, and the recursion needs the explicit annotation.\nexport const EntityFieldSchema: z.ZodType<EntityField, z.ZodTypeDef, unknown> = z.lazy(() => {\n const baseFieldShape = {\n name: z.string().min(1, 'Field name is required').optional(),\n required: z.boolean().optional(),\n primaryKey: z.boolean().optional(),\n default: JsonValueSchema.optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n properties: z.record(EntityFieldSchema).optional(),\n intrinsic: z.boolean().optional(),\n description: z.string().optional(),\n synonyms: z.string().optional(),\n mock: z.string().optional(),\n mergedFrom: z.string().optional(),\n };\n\n /** Build a scalar variant schema. `values?` is permitted as a hint;\n * only the enum variant mandates a non-empty values array. */\n function scalarVariant<T extends ScalarFieldType>(t: T) {\n return z.object({\n ...baseFieldShape,\n type: z.literal(t),\n values: z.array(z.string()).optional(),\n });\n }\n\n return z.preprocess(\n (input) => {\n if (\n input === null ||\n typeof input !== 'object' ||\n !('type' in input) ||\n typeof (input as { type?: RuntimeValue }).type !== 'string'\n ) {\n return input;\n }\n const obj = input as { type: string; enum?: RuntimeValue; values?: RuntimeValue };\n const next: { type: string; enum?: RuntimeValue; values?: RuntimeValue } = { ...obj };\n const aliased = FIELD_TYPE_ALIASES[obj.type];\n if (aliased !== undefined) next.type = aliased;\n // Fold legacy `enum: string[]` into `values: string[]`.\n if (next.enum !== undefined && next.values === undefined) {\n next.values = next.enum;\n }\n delete next.enum;\n return next;\n },\n z.discriminatedUnion('type', [\n scalarVariant('string'),\n scalarVariant('number'),\n scalarVariant('boolean'),\n scalarVariant('date'),\n scalarVariant('timestamp'),\n scalarVariant('datetime'),\n scalarVariant('email'),\n scalarVariant('url'),\n scalarVariant('phone'),\n scalarVariant('uuid'),\n scalarVariant('image'),\n scalarVariant('trait'),\n scalarVariant('slot'),\n scalarVariant('pattern'),\n scalarVariant('node'),\n scalarVariant('event'),\n scalarVariant('money'),\n scalarVariant('file'),\n scalarVariant('scalar'),\n // Enum variant — REQUIRES non-empty values.\n z.object({\n ...baseFieldShape,\n type: z.literal('enum'),\n values: z.array(z.string()).min(1, 'Enum field requires a non-empty `values` array'),\n }),\n // Union variant — tagged struct union; values = variant names,\n // per-variant shapes in `properties` (absent on named recursion).\n z.object({\n ...baseFieldShape,\n type: z.literal('union'),\n values: z.array(z.string()).min(1, 'Union field requires a non-empty `values` array'),\n }),\n // Relation variant — REQUIRES relation config.\n z.object({\n ...baseFieldShape,\n type: z.literal('relation'),\n relation: RelationConfigSchema,\n }),\n // Array variant — items optional to match relaxed TS shape.\n z.object({\n ...baseFieldShape,\n type: z.literal('array'),\n items: EntityFieldSchema.optional(),\n }),\n // Object variant — fixed-key struct (`properties`) or dynamic-key\n // map (`Map K V`, uniform value schema in `items`).\n z.object({\n ...baseFieldShape,\n type: z.literal('object'),\n items: EntityFieldSchema.optional(),\n values: z.array(z.string()).optional(),\n }),\n ]),\n );\n});\n\nexport type EntityFieldInput = z.input<typeof EntityFieldSchema>;\n\n// ============================================================================\n// Type Aliases (for cleaner imports)\n// ============================================================================\n\n/** Alias for EntityField - preferred name */\nexport type Field = EntityField;\n\n/** Alias for EntityFieldSchema - preferred name */\nexport const FieldSchema = EntityFieldSchema;\n","/**\n * Asset Types for Semantic Asset References\n *\n * Defines types for abstracting asset paths into semantic references.\n * Assets are resolved from SemanticAssetRef to actual paths at compile time.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Entity Roles\n// ============================================================================\n\n/**\n * Entity roles in game contexts\n */\nexport const ENTITY_ROLES = [\n 'player',\n 'enemy',\n 'npc',\n 'item',\n 'tile',\n 'projectile',\n 'effect',\n 'ui',\n 'decoration',\n 'vehicle',\n] as const;\n\nexport type EntityRole = (typeof ENTITY_ROLES)[number];\n\nexport const EntityRoleSchema = z.enum(ENTITY_ROLES);\n\n// ============================================================================\n// Visual Styles\n// ============================================================================\n\n/**\n * Visual art styles for games\n */\nexport const VISUAL_STYLES = ['pixel', 'vector', 'hd', '1-bit', 'isometric'] as const;\n\nexport type VisualStyle = (typeof VISUAL_STYLES)[number];\n\nexport const VisualStyleSchema = z.enum(VISUAL_STYLES);\n\n// ============================================================================\n// Asset Dimension + Aspect (render metadata carried with the asset / the need)\n// ============================================================================\n\n/**\n * Whether the asset is a 2D sprite/image or a 3D model. Set by the consuming\n * canvas: the same entity role is a 2D sprite-sheet on a tile board and a 3D\n * rigged model on a 3D board.\n */\nexport const ASSET_DIMENSIONS = ['2d', '3d'] as const;\n\nexport type AssetDimension = (typeof ASSET_DIMENSIONS)[number];\n\nexport const AssetDimensionSchema = z.enum(ASSET_DIMENSIONS);\n\n/**\n * Rendering aspect ratio of an asset: square (tiles/sprites/portraits/icons),\n * 16:9 (scene backdrops), 5:7 (cards), 8:1 (effect frame strips),\n * 4:1 (wide paddles/bars), 5:3 (wide scenes), 1:2 (tall banners).\n */\nexport const ASSET_ASPECTS = ['1:1', '16:9', '5:7', '8:1', '4:1', '5:3', '1:2'] as const;\n\nexport type AssetAspect = (typeof ASSET_ASPECTS)[number];\n\nexport const AssetAspectSchema = z.enum(ASSET_ASPECTS);\n\n// ============================================================================\n// Animation Name + Sheet Direction\n// ============================================================================\n\n/**\n * Animation names matching a sprite sheet's row layout. Canonical home for\n * this vocabulary — `@almadar/ui`'s `spriteAnimationTypes.ts` re-exports it\n * rather than redeclaring, so board `.lolo` config and the render library\n * agree on one enum.\n */\nexport const ANIMATION_NAMES = ['idle', 'walk', 'skate', 'jump', 'fall', 'attack', 'hit', 'death'] as const;\n\nexport type AnimationName = (typeof ANIMATION_NAMES)[number];\n\nexport const AnimationNameSchema = z.enum(ANIMATION_NAMES);\n\n/**\n * Sheet file directions (physical PNG files a sprite sheet ships as).\n * Legacy hand-drawn packs ship only se/sw and mirror-flip for ne/nw (a cheat\n * that shows the face while walking away); 3D-baked sheets ship all four real\n * directions — the renderer prefers a real sheet and keeps the flip only as\n * the legacy fallback.\n */\nexport const SPRITE_DIRECTIONS = ['se', 'sw', 'ne', 'nw'] as const;\n\nexport type SpriteDirection = (typeof SPRITE_DIRECTIONS)[number];\n\nexport const SpriteDirectionSchema = z.enum(SPRITE_DIRECTIONS);\n\n/**\n * Camera projections a baked sprite sheet can ship. `iso` is directional\n * (se/sw physical sheets, ne/nw by mirror); `front`/`top`/`perspective` are\n * single fixed-camera sheets (the mesh reference-sheet camera vocabulary).\n */\nexport const SHEET_PROJECTIONS = ['iso', 'front', 'back', 'top', 'perspective'] as const;\n\nexport type SheetProjection = (typeof SHEET_PROJECTIONS)[number];\n\nexport const SheetProjectionSchema = z.enum(SHEET_PROJECTIONS);\n\n// ============================================================================\n// Animation Definition\n// ============================================================================\n\n/**\n * Definition for a single named animation within a sprite sheet: which row\n * it occupies, how many frames it has, and its playback rate. This is the\n * shape actually consumed by `@almadar/ui`'s sprite-sheet renderer\n * (`spriteAnimation.ts`'s `frameRect`/`getCurrentFrameFromDef`) — moved here\n * verbatim rather than reconciled with a differently-shaped guess, since\n * `@almadar/ui`'s version is the one with real production consumers.\n */\nexport interface AnimationDef {\n /** Row index in the sprite sheet (0-based; each animation occupies one row). */\n row: number;\n /** Number of frames in this animation. */\n frames: number;\n /** Frames per second. */\n frameRate: number;\n /** Whether the animation loops. */\n loop: boolean;\n}\n\nexport const AnimationDefSchema = z.object({\n row: z.number().int().nonnegative(),\n frames: z.number().int().positive(),\n frameRate: z.number().positive(),\n loop: z.boolean(),\n});\n\n// ============================================================================\n// Sprite Sheet Atlas\n// ============================================================================\n\n/**\n * Parsed sprite-sheet atlas JSON — the contract a `spriteSheet`-role `Asset.url`\n * resolves to when fetched (see `Asset.url` usage in `@almadar/ui`'s\n * `useUnitSpriteAtlas`). A unit's `sprite?: Asset` stays the static single-pose\n * image; `spriteSheet?: Asset` is a SEPARATE reference whose URL points at a\n * `SpriteSheetAtlas`-shaped JSON manifest (e.g. `.../guardian-sprite-sheet.json`),\n * not a PNG. Frame-cutting geometry lives here, not inlined onto `Asset` — an\n * `Asset` traveling through `render-ui` every tick stays small.\n */\nexport interface SpriteSheetAtlas {\n /** Unit archetype key. */\n unit?: string;\n /** Visual type key. */\n type?: string;\n /** Width of a single frame in pixels. */\n frameWidth: number;\n /** Height of a single frame in pixels. */\n frameHeight: number;\n /** Number of columns (frames per row). */\n columns: number;\n /** Number of rows (animations). */\n rows: number;\n /** Directions present as physical PNG files. */\n directions: SpriteDirection[];\n /** Relative PNG sheet paths per direction. */\n sheets: Partial<Record<SpriteDirection, string>>;\n /** Animation row layout keyed by animation name. Unit sheets use the canonical `AnimationName` rows; one-shot fx sheets declare their own names (e.g. `burst`) — the manifest is authoritative for its rows. */\n animations: Partial<Record<string, AnimationDef>>;\n /**\n * Per-projection sheet PNGs (additive; absent on legacy atlases). `iso`\n * mirrors `sheets` (directional se/sw); the fixed cameras carry one sheet\n * each. `sheets` remains the iso back-compat alias — writers emit both.\n */\n projections?: {\n iso?: Partial<Record<SpriteDirection, string>>;\n front?: string;\n back?: string;\n top?: string;\n perspective?: string;\n };\n}\n\nexport const SpriteSheetAtlasSchema = z.object({\n unit: z.string().optional(),\n type: z.string().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n directions: z.array(SpriteDirectionSchema),\n sheets: z.record(SpriteDirectionSchema, z.string()),\n animations: z.record(z.string(), AnimationDefSchema),\n projections: z\n .object({\n iso: z.record(SpriteDirectionSchema, z.string()).optional(),\n front: z.string().optional(),\n back: z.string().optional(),\n top: z.string().optional(),\n perspective: z.string().optional(),\n })\n .optional(),\n});\n\n// ============================================================================\n// Texture Atlas — named-subrect packed sheet (the industry standard)\n// ============================================================================\n\n/**\n * One named sub-rectangle inside a packed sheet. Mirrors the ShoeBox /\n * TexturePacker `<SubTexture>` element every Kenney `Spritesheet/*.xml` ships\n * (`x`/`y`/`width`/`height` = the rect in the sheet PNG; `frameX`/`frameY`/\n * `frameWidth`/`frameHeight` = the trim/pad offsets for sprites packed with\n * transparent edges removed — optional, present only on trimmed atlases).\n */\nexport interface SubTexture {\n x: number;\n y: number;\n width: number;\n height: number;\n frameX?: number;\n frameY?: number;\n frameWidth?: number;\n frameHeight?: number;\n}\n\nexport const SubTextureSchema = z.object({\n x: z.number().nonnegative(),\n y: z.number().nonnegative(),\n width: z.number().positive(),\n height: z.number().positive(),\n frameX: z.number().optional(),\n frameY: z.number().optional(),\n frameWidth: z.number().positive().optional(),\n frameHeight: z.number().positive().optional(),\n});\n\n/**\n * A packed sheet + its named sub-rectangles — the canonical parse target for a\n * Kenney `Spritesheet/*.xml` atlas. A STATIC tile/prop/UI Asset references one\n * of these: `{ url: <sheet.png>, atlas: <this.json>, sprite: \"grass.png\" }` →\n * the renderer fetches the sheet + atlas ONCE and blits the named sub-rect,\n * instead of loading N individual PNGs. (Animated actors use `SpriteSheetAtlas`\n * instead; a uniform-grid tile page uses `Tilesheet`.)\n */\nexport interface TextureAtlas {\n /** Relative path to the sheet PNG the sub-rects index into (the atlas's own `imagePath`). */\n imagePath: string;\n /** Sub-rectangles keyed by their atlas name (e.g. `\"grass.png\"`). */\n subTextures: Record<string, SubTexture>;\n}\n\nexport const TextureAtlasSchema = z.object({\n imagePath: z.string(),\n subTextures: z.record(z.string(), SubTextureSchema),\n});\n\n// ============================================================================\n// Tilesheet — uniform-grid packed page (cut by index)\n// ============================================================================\n\n/**\n * A uniform-grid tile page — the shape a Kenney `Tilesheet/` sheet takes (e.g.\n * Pirate Pack: \"each tile is 64×64, no margin\"). Tiles are cut by `(col,row)`\n * index rather than by named rect. `names` is present only when a sibling\n * `.xml`/`.txt` supplies an index→name list; otherwise a tile is addressed by\n * its `\"col,row\"` (or flat index) via `Asset.sprite`.\n */\nexport interface Tilesheet {\n /** Relative path to the tile sheet PNG. */\n imagePath: string;\n /** Width of one tile cell in pixels. */\n tileWidth: number;\n /** Height of one tile cell in pixels. */\n tileHeight: number;\n /** Number of columns in the grid. */\n columns: number;\n /** Number of rows in the grid. */\n rows: number;\n /** Outer margin before the first tile, in pixels (default 0). */\n margin?: number;\n /** Gap between adjacent tiles, in pixels (default 0). */\n spacing?: number;\n /** Optional index→name labels when a descriptor supplies them. */\n names?: string[];\n}\n\nexport const TilesheetSchema = z.object({\n imagePath: z.string(),\n tileWidth: z.number().positive(),\n tileHeight: z.number().positive(),\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n margin: z.number().nonnegative().optional(),\n spacing: z.number().nonnegative().optional(),\n names: z.array(z.string()).optional(),\n});\n\n// ============================================================================\n// Semantic Asset Reference\n// ============================================================================\n\n/**\n * Semantic reference to an asset (not a hardcoded path).\n * Resolved to actual paths at compile time via asset maps.\n */\nexport type SemanticAssetRef = {\n /**\n * Entity role — a free string. Core no longer constrains the vocabulary to\n * `EntityRole` (that enum stays an exported shared reference for the asset\n * tool + renderer); genre boards may use their own roles (`boss`, `tower`, …).\n */\n role: string;\n /** Sub-category within role (hero, slime, coin, etc.) */\n category: string;\n /** Required animations for this entity */\n animations?: string[];\n /** Visual style preference */\n style?: VisualStyle;\n /** Variant identifier (for multiple versions) */\n variant?: string;\n /** 2D sprite vs 3D model — the rendering dimension the consuming canvas needs. */\n dimension?: AssetDimension;\n /** Rendering aspect ratio (square sprite/portrait/tile, 16:9 backdrop, 5:7 card, 8:1 fx-strip). */\n aspect?: AssetAspect;\n};\n\nexport const SemanticAssetRefSchema = z.object({\n role: z.string().min(1),\n category: z.string().min(1),\n animations: z.array(z.string()).optional(),\n style: VisualStyleSchema.optional(),\n variant: z.string().optional(),\n dimension: AssetDimensionSchema.optional(),\n aspect: AssetAspectSchema.optional(),\n});\n\n// ============================================================================\n// Asset — the UNIFIED asset type\n// ============================================================================\n\n/**\n * The single asset type: a `SemanticAssetRef` (role/dimension/animations/aspect/style)\n * WITH its resolved URL folded in. Used everywhere an asset is referenced — a lolo\n * board `assetManifest` (`Map string Asset`), every `@almadar/ui` game prop, the\n * asset-workflow's resolved/pool assets, and the inspector picker. Replaces the bare\n * `AssetUrl`-string asset field so the render metadata travels WITH the asset (no\n * pixel-dimension or filename heuristics needed to know sheet-vs-frame / 2d-vs-3d).\n */\nexport interface Asset extends SemanticAssetRef {\n /** The resolved asset URL. When `atlas`/`sprite` are set this is the SHEET png; otherwise a standalone image. */\n url: AssetUrl;\n /**\n * Optional atlas JSON (a `TextureAtlas` or `Tilesheet`) that slices `url`.\n * When present with `sprite`, the renderer fetches sheet + atlas once and\n * blits one sub-rect instead of loading a standalone PNG. Absent → `url` is\n * a plain whole-image asset (the existing, non-atlas path).\n */\n atlas?: AssetUrl;\n /**\n * The sub-texture selector within `atlas`: a `SubTexture` name for a\n * `TextureAtlas` (e.g. `\"grass.png\"`), or a `\"col,row\"`/flat index for a\n * `Tilesheet`. Only meaningful alongside `atlas`.\n */\n sprite?: string;\n /** Optional display name (inspector picker). */\n name?: string;\n /** Optional thumbnail URL (inspector picker grid). */\n thumbnailUrl?: string;\n /** Authored generation subject (visualDNA) for asset-workflow regeneration. */\n prompt?: string;\n /** Authored per-animation frame choreography — the exact pose per frame, the only pose source for animated slots. */\n choreography?: Record<string, string[]>;\n}\n\nexport const AssetSchema = SemanticAssetRefSchema.extend({\n url: z.string(),\n atlas: z.string().optional(),\n sprite: z.string().optional(),\n name: z.string().optional(),\n thumbnailUrl: z.string().optional(),\n prompt: z.string().optional(),\n choreography: z.record(z.string(), z.array(z.string())).optional(),\n});\n\n// ============================================================================\n// Asset Catalog\n// ============================================================================\n\n/**\n * Single browsable asset in the inspector picker catalog.\n * Backs the asset/icon pickers — a flat list the inspector renders for\n * the user to choose from when a config field's type is `'asset'`.\n */\nexport interface AssetCatalogEntry {\n /** Resolvable URL to the asset. */\n url: string;\n /** Display name for the asset. */\n name: string;\n /** Grouping category within the catalog. */\n category: string;\n /** Asset kind the picker dispatches on. */\n kind: 'image' | 'spritesheet' | 'audio' | 'scene' | 'portrait' | 'model' | 'other';\n /** Optional thumbnail URL for grid previews. */\n thumbnailUrl?: string;\n /** 2D sprite vs 3D model — the asset's actual rendering dimension. */\n dimension?: AssetDimension;\n /** The asset's actual rendering aspect ratio. */\n aspect?: AssetAspect;\n}\n\nexport const AssetCatalogEntrySchema = z.object({\n url: z.string(),\n name: z.string(),\n category: z.string(),\n kind: z.enum(['image', 'spritesheet', 'audio', 'scene', 'portrait', 'model', 'other']),\n thumbnailUrl: z.string().optional(),\n dimension: AssetDimensionSchema.optional(),\n aspect: AssetAspectSchema.optional(),\n});\n\n/**\n * Flat list of browsable assets surfaced by the inspector pickers.\n */\nexport type AssetCatalog = AssetCatalogEntry[];\n\nexport const AssetCatalogSchema = z.array(AssetCatalogEntrySchema);\n\n/**\n * Asset-reference URL marker. A plain alias over `string` — the value is a\n * resolvable asset URL — but the named type lets the pattern-sync tool\n * (`tools/almadar-pattern-sync/parser.ts`) detect a component prop as an asset\n * field (tagged `asset`) the same way `EventKey`/`LucideIcon` are detected by\n * type identity. Components annotate image/url props as `AssetUrl` (`src`,\n * `backgroundImage`, `avatar`, …); the generator emits a `string` config knob\n * declared as the `asset` config type, which the property inspector dispatches\n * an AssetPicker on. Not branded — asset urls originate from user data, so cast\n * friction would buy nothing; the value is the marker the tool finds.\n */\nexport type AssetUrl = string;\n\n// ============================================================================\n// ScenePos — neutral scene coordinate\n// ============================================================================\n\n/**\n * A neutral position in scene space: 2D (`x`,`y`) or optionally 3D (`x`,`y`,`z`).\n * The single coordinate type shared by every drawable descriptor and camera pose\n * across the 2D and 3D canvas hosts, so a scene composes from the same `{x,y,z?}`\n * regardless of projection or painter. Logical, not pixel — the host's projector\n * maps a `ScenePos` to screen space.\n */\nexport interface ScenePos {\n x: number;\n y: number;\n z?: number;\n}\n\nexport const ScenePosSchema = z.object({\n x: z.number(),\n y: z.number(),\n z: z.number().optional(),\n});\n\n// ============================================================================\n// Camera — neutral camera pose shared by the 2D and 3D canvas hosts\n// ============================================================================\n\n/**\n * Camera behaviors, unifying the former per-host vocab (2D `camera` string +\n * 3D `cameraMode`). `isometric`/`top-down`/`front` are fixed framings (`front` =\n * the straight-on flat elevation — side-scroller / reference-sheet view);\n * `follow`/`chase` track a target; `perspective` is the 3D dramatic framing.\n */\nexport const CAMERA_MODES = ['isometric', 'perspective', 'top-down', 'front', 'follow', 'chase'] as const;\n\nexport type CameraMode = (typeof CAMERA_MODES)[number];\n\nexport const CameraModeSchema = z.enum(CAMERA_MODES);\n\n/**\n * A neutral camera pose shared by the 2D and 3D canvas hosts, so `type: canvas`\n * carries one camera object regardless of painter. `pos`/`target` are `ScenePos`\n * (logical scene space, not pixels); `zoom` scales the view (the former `scale`);\n * `fov` is the 3D field of view; `mode` selects the framing/tracking behavior.\n * Every field is optional — an omitted camera means the host's default framing.\n */\nexport interface Camera {\n pos?: ScenePos;\n target?: ScenePos;\n zoom?: number;\n fov?: number;\n mode?: CameraMode;\n /** Orbit the mode's framing position around the vertical axis through the target, in radians (3D hosts only). */\n azimuth?: number;\n /** Orbit height angle above the ground plane, in radians (3D hosts only). */\n elevation?: number;\n}\n\nexport const CameraSchema = z.object({\n pos: ScenePosSchema.optional(),\n target: ScenePosSchema.optional(),\n zoom: z.number().optional(),\n fov: z.number().optional(),\n mode: CameraModeSchema.optional(),\n azimuth: z.number().optional(),\n elevation: z.number().optional(),\n});\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type SemanticAssetRefInput = z.input<typeof SemanticAssetRefSchema>;\nexport type AnimationDefInput = z.input<typeof AnimationDefSchema>;\nexport type AssetCatalogEntryInput = z.input<typeof AssetCatalogEntrySchema>;\nexport type SpriteSheetAtlasInput = z.input<typeof SpriteSheetAtlasSchema>;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Creates a semantic asset key from role and category.\n * \n * Generates a unique asset identifier by combining role and category\n * with a colon separator. Used for asset management and lookup.\n * \n * @param {EntityRole} role - Entity role (e.g., 'player', 'enemy')\n * @param {string} category - Asset category (e.g., 'sprite', 'animation')\n * @returns {string} Asset key in format 'role:category'\n * \n * @example\n * createAssetKey('player', 'sprite'); // returns 'player:sprite'\n * createAssetKey('enemy', 'animation'); // returns 'enemy:animation'\n */\nexport function createAssetKey(role: EntityRole, category: string): string {\n return `${role}:${category}`;\n}\n\n/**\n * Parses an asset key into role and category components.\n * \n * Deconstructs an asset key string (format 'role:category') into its\n * constituent parts. Returns null if the key format is invalid.\n * \n * @param {string} key - Asset key in format 'role:category'\n * @returns {{ role: string; category: string } | null} Parsed components or null\n * \n * @example\n * parseAssetKey('player:sprite'); // returns { role: 'player', category: 'sprite' }\n * parseAssetKey('enemy:animation'); // returns { role: 'enemy', category: 'animation' }\n * parseAssetKey('invalid'); // returns null\n */\nexport function parseAssetKey(key: string): { role: string; category: string } | null {\n const parts = key.split(':');\n if (parts.length !== 2) return null;\n return { role: parts[0], category: parts[1] };\n}\n\n/**\n * Gets common animations for an entity role.\n * \n * Returns an array of default animation names appropriate for the\n * specified entity role. Used for asset configuration and validation.\n * \n * @param {EntityRole} role - Entity role\n * @returns {string[]} Array of default animation names\n * \n * @example\n * getDefaultAnimationsForRole('player'); // returns ['idle', 'run', 'jump', 'fall', 'attack', 'hurt', 'die']\n * getDefaultAnimationsForRole('enemy'); // returns ['idle', 'walk', 'attack', 'hurt', 'die']\n */\nexport function getDefaultAnimationsForRole(role: EntityRole): string[] {\n switch (role) {\n case 'player':\n return ['idle', 'run', 'jump', 'fall', 'attack', 'hurt', 'die'];\n case 'enemy':\n return ['idle', 'walk', 'attack', 'hurt', 'die'];\n case 'npc':\n return ['idle', 'walk', 'talk'];\n case 'item':\n return ['idle', 'collected'];\n case 'tile':\n return ['static'];\n case 'projectile':\n return ['fly', 'hit', 'expire'];\n case 'effect':\n return ['play'];\n case 'ui':\n return ['normal', 'hover', 'pressed', 'disabled'];\n case 'decoration':\n return ['idle'];\n case 'vehicle':\n return ['idle', 'move', 'brake'];\n default:\n return ['idle'];\n }\n}\n\n/**\n * Validates that an asset reference has required animations.\n * \n * Checks if an asset reference contains all required animations.\n * Returns an error message if validation fails, or null if valid.\n * \n * @param {SemanticAssetRef} assetRef - Asset reference to validate\n * @param {string[]} requiredAnimations - Required animation names\n * @returns {string | null} Error message or null if valid\n * \n * @example\n * validateAssetAnimations(assetRef, ['idle', 'run']); // returns null if valid\n * validateAssetAnimations(assetRef, ['missing-animation']); // returns error message\n */\nexport function validateAssetAnimations(\n assetRef: SemanticAssetRef,\n requiredAnimations: string[]\n): { valid: boolean; missing: string[] } {\n const provided = assetRef.animations || [];\n const missing = requiredAnimations.filter((anim) => !provided.includes(anim));\n return { valid: missing.length === 0, missing };\n}\n\n// ============================================================================\n// Sprite Sheet Layout — the canonical unit sheet convention (owner-approved\n// \"Sheet convergence\": 8 cols x 5 rows @ 256px, dark charcoal background).\n// `tools/asset-workflow`'s `spritesheet-bake.ts` (SPRITE_LAYOUT) and\n// `prompt-composer.ts` derive from this; this is the single source.\n// ============================================================================\n\nexport const SPRITE_SHEET_LAYOUT = {\n frameWidth: 256,\n frameHeight: 256,\n columns: 8,\n rows: 5,\n background: '#20202E',\n} as const;\n\nexport type SpriteSheetLayout = typeof SPRITE_SHEET_LAYOUT;\n\n/**\n * The canonical unit animation row table (idle/walk/attack/hit/death), one\n * row per `AnimationName`, in sheet-row order. Mirrors\n * `tools/asset-workflow/src/spritesheet-bake.ts`'s `SPRITE_LAYOUT`.\n */\nexport const DEFAULT_UNIT_ANIMATION_ROWS: ReadonlyArray<{ name: AnimationName } & AnimationDef> = [\n { name: 'idle', row: 0, frames: 4, loop: true, frameRate: 6 },\n { name: 'walk', row: 1, frames: 8, loop: true, frameRate: 10 },\n { name: 'attack', row: 2, frames: 6, loop: false, frameRate: 12 },\n { name: 'hit', row: 3, frames: 3, loop: false, frameRate: 8 },\n { name: 'death', row: 4, frames: 6, loop: false, frameRate: 8 },\n] as const;\n\n/**\n * Builds the canonical unit `SpriteSheetAtlas` from `SPRITE_SHEET_LAYOUT` +\n * `DEFAULT_UNIT_ANIMATION_ROWS` for a given set of direction sheets. Directions\n * default to whichever keys `sheets` actually carries (legacy se/sw-only packs\n * included), or the caller can force a specific set via `opts.directions`.\n */\nexport function defaultUnitAtlas(\n sheets: SpriteSheetAtlas['sheets'],\n opts?: { directions?: SpriteDirection[] }\n): SpriteSheetAtlas {\n const directions = opts?.directions ?? SPRITE_DIRECTIONS.filter((direction) => sheets[direction] !== undefined);\n const animations: Partial<Record<string, AnimationDef>> = {};\n for (const { name, ...def } of DEFAULT_UNIT_ANIMATION_ROWS) {\n animations[name] = def;\n }\n return {\n frameWidth: SPRITE_SHEET_LAYOUT.frameWidth,\n frameHeight: SPRITE_SHEET_LAYOUT.frameHeight,\n columns: SPRITE_SHEET_LAYOUT.columns,\n rows: SPRITE_SHEET_LAYOUT.rows,\n directions,\n sheets,\n animations,\n };\n}\n\n// ============================================================================\n// Manifest Entry — the kflow-assets `manifest.json` row shape. Core is the\n// owner; `tools/asset-workflow`'s `ExtendedManifestEntry` converges onto this\n// (mirrors `tools/asset-workflow/src/asset-schema.ts`'s `CanvasAffinity`,\n// `FrameSpec`, `AssetLicense`, `SourceCatalog` literal unions).\n// ============================================================================\n\nexport const MANIFEST_ENTRY_KINDS = ['model', 'image', 'spritesheet', 'audio', 'json'] as const;\n\nexport type ManifestEntryKind = (typeof MANIFEST_ENTRY_KINDS)[number];\n\nexport const ManifestEntryKindSchema = z.enum(MANIFEST_ENTRY_KINDS);\n\n// ============================================================================\n// Game audio\n// ============================================================================\n\n/**\n * One entry of a game's sound manifest, keyed by logical cue name. Core owns\n * the shape so both the render substrate (`useGameAudio` / the `game-audio-cue`\n * pattern) and the generated `.lolo` factories resolve the SAME declaration —\n * a hook-local interface is invisible to the pattern extractor and lowers to a\n * shapeless `object`, which the `.lolo` type system rejects outright.\n */\nexport interface SoundEntry {\n /** Single path, or several to pick from at random on each play. */\n path: string | string[];\n /** Volume 0-1, multiplied by the master volume. */\n volume?: number;\n /** Whether this sound loops (background music). */\n loop?: boolean;\n /** Concurrent Audio instances kept in the pool. */\n poolSize?: number;\n /** Start automatically on the first user interaction. */\n autostart?: boolean;\n /** Use crossfade transitions when played as music. */\n crossfade?: boolean;\n /** Crossfade duration in milliseconds. */\n crossfadeDurationMs?: number;\n}\n\nexport const SoundEntrySchema = z.object({\n path: z.union([z.string(), z.array(z.string())]),\n volume: z.number().optional(),\n loop: z.boolean().optional(),\n poolSize: z.number().optional(),\n autostart: z.boolean().optional(),\n crossfade: z.boolean().optional(),\n crossfadeDurationMs: z.number().optional(),\n});\n\n/** A game's sound manifest: logical cue name → its definition. */\nexport type AudioManifest = Record<string, SoundEntry>;\n\nexport const AudioManifestSchema = z.record(z.string(), SoundEntrySchema);\n\nexport const MANIFEST_CANVAS_AFFINITIES = ['isometric', 'hex', 'flat', 'side', '3d', 'none'] as const;\n\nexport type ManifestCanvasAffinity = (typeof MANIFEST_CANVAS_AFFINITIES)[number];\n\nexport const ManifestCanvasAffinitySchema = z.enum(MANIFEST_CANVAS_AFFINITIES);\n\nexport const MANIFEST_SOURCE_CATALOGS = ['kenny', 'kekec-assets', 'iram-assets', 'trait-wars-assets', 'kflow-assets'] as const;\n\nexport type ManifestSourceCatalog = (typeof MANIFEST_SOURCE_CATALOGS)[number];\n\nexport const ManifestSourceCatalogSchema = z.enum(MANIFEST_SOURCE_CATALOGS);\n\nexport const MANIFEST_ASSET_LICENSES = ['CC0', 'proprietary'] as const;\n\nexport type ManifestAssetLicense = (typeof MANIFEST_ASSET_LICENSES)[number];\n\nexport const ManifestAssetLicenseSchema = z.enum(MANIFEST_ASSET_LICENSES);\n\n/**\n * Path of the sheet's `atlas.json` relative to the pack's `shared/` root\n * (`riya-platformer/units/riya/atlas.json`) — the executable frame truth for\n * unit sheets whose rows are not uniform.\n */\nexport type ManifestAtlasRef = string;\n\n/** Tile/sprite-sheet frame layout for a manifest row, an atlas reference, else `null`. */\nexport type ManifestFrameSpec =\n | { kind: 'iso-tile'; w: number; h: number }\n | { kind: 'sprite-sheet'; frame: number; cols: number; rows: number }\n | ManifestAtlasRef\n | null;\n\nexport const ManifestFrameSpecSchema = z.union([\n z.object({ kind: z.literal('iso-tile'), w: z.number(), h: z.number() }),\n z.object({ kind: z.literal('sprite-sheet'), frame: z.number(), cols: z.number(), rows: z.number() }),\n z.string().min(1),\n z.null(),\n]);\n\n/**\n * One row of `almadar-assets/kflow-assets/manifest.json`. Core owns this\n * shape; `tools/asset-workflow`'s `ExtendedManifestEntry` converges onto it.\n */\nexport interface ManifestEntry {\n url: string;\n name: string;\n category: string;\n kind: ManifestEntryKind;\n width: number;\n height: number;\n canvasAffinity: ManifestCanvasAffinity;\n genreAffinity: string[];\n swapClass: string;\n sourceCatalog: ManifestSourceCatalog;\n frameSpec: ManifestFrameSpec;\n /** Provenance-extended field: present on the promote/register path only. */\n license?: ManifestAssetLicense;\n}\n\nexport const ManifestEntrySchema = z.object({\n url: z.string(),\n name: z.string(),\n category: z.string(),\n kind: ManifestEntryKindSchema,\n width: z.number(),\n height: z.number(),\n canvasAffinity: ManifestCanvasAffinitySchema,\n genreAffinity: z.array(z.string()),\n swapClass: z.string(),\n sourceCatalog: ManifestSourceCatalogSchema,\n frameSpec: ManifestFrameSpecSchema,\n license: ManifestAssetLicenseSchema.optional(),\n});\n\nexport type ManifestEntryInput = z.input<typeof ManifestEntrySchema>;\n\n// ============================================================================\n// Manifest -> Asset Catalog adapter\n// ============================================================================\n\nconst ASSET_CATALOG_ENTRY_KINDS: readonly AssetCatalogEntry['kind'][] = [\n 'image',\n 'spritesheet',\n 'audio',\n 'scene',\n 'portrait',\n 'model',\n 'other',\n];\n\nconst MODEL_URL_EXTENSIONS = ['.glb', '.gltf'];\nconst AUDIO_URL_EXTENSIONS = ['.mp3', '.ogg', '.wav'];\n\nfunction urlEndsWithAny(url: string, extensions: readonly string[]): boolean {\n const lower = url.toLowerCase();\n return extensions.some((extension) => lower.endsWith(extension));\n}\n\n/**\n * Declared, order-sensitive rule for deriving the catalog `kind` from a\n * manifest row: `frameSpec`/`kind==='spritesheet'` beats extension, which\n * beats the manifest's own `kind`. No filename-keyword guessing.\n */\nfunction deriveManifestAssetKind(entry: ManifestEntry): AssetCatalogEntry['kind'] {\n if (typeof entry.frameSpec === 'string' || entry.frameSpec?.kind === 'sprite-sheet' || entry.kind === 'spritesheet') return 'spritesheet';\n if (entry.kind === 'model' || urlEndsWithAny(entry.url, MODEL_URL_EXTENSIONS)) return 'model';\n if (entry.kind === 'audio' || urlEndsWithAny(entry.url, AUDIO_URL_EXTENSIONS)) return 'audio';\n if (entry.kind === 'image') return 'image';\n return 'other';\n}\n\nfunction parseAssetAspectRatio(aspect: AssetAspect): number {\n const [w, h] = aspect.split(':').map(Number);\n return w / h;\n}\n\nconst ASSET_ASPECT_RATIO_TOLERANCE = 0.01;\n\n/**\n * The asset's aspect only when width/height are both known (> 0) and their\n * ratio matches exactly one `ASSET_ASPECTS` entry within 1%; otherwise\n * omitted (never guessed).\n */\nfunction deriveManifestAssetAspect(width: number, height: number): AssetAspect | undefined {\n if (width <= 0 || height <= 0) return undefined;\n const ratio = width / height;\n for (const aspect of ASSET_ASPECTS) {\n const expected = parseAssetAspectRatio(aspect);\n if (Math.abs(ratio / expected - 1) <= ASSET_ASPECT_RATIO_TOLERANCE) return aspect;\n }\n return undefined;\n}\n\nconst ABSOLUTE_URL_PATTERN = /^[a-z][a-z0-9+.-]*:\\/\\//i;\n\n/** Prefixes a relative manifest url with `cdnPrefix`; leaves an absolute url untouched. */\nfunction resolveManifestUrl(url: string, cdnPrefix?: string): string {\n if (!cdnPrefix || ABSOLUTE_URL_PATTERN.test(url)) return url;\n const prefix = cdnPrefix.endsWith('/') ? cdnPrefix : `${cdnPrefix}/`;\n const rest = url.startsWith('/') ? url.slice(1) : url;\n return `${prefix}${rest}`;\n}\n\n/**\n * Adapts kflow-assets manifest rows into the inspector picker's\n * `AssetCatalog`. The ONE deterministic derivation the Kura assets server\n * route (`GET /api/assets/catalog`) and any other manifest consumer share.\n */\nexport function manifestToAssetCatalog(entries: ReadonlyArray<ManifestEntry>, opts?: { cdnPrefix?: string }): AssetCatalog {\n return entries.map((entry) => {\n const kind = deriveManifestAssetKind(entry);\n const dimension: AssetDimension = entry.canvasAffinity === '3d' ? '3d' : '2d';\n const aspect = deriveManifestAssetAspect(entry.width, entry.height);\n const url = resolveManifestUrl(entry.url, opts?.cdnPrefix);\n const catalogEntry: AssetCatalogEntry = {\n url,\n name: entry.name,\n category: entry.category,\n kind,\n dimension,\n };\n if (aspect !== undefined) catalogEntry.aspect = aspect;\n if (kind === 'image' || kind === 'spritesheet') catalogEntry.thumbnailUrl = url;\n return catalogEntry;\n });\n}\n\n// ============================================================================\n// Asset query grammar — Unity-style `t:<kind>` / `l:<label>` + free text.\n// The ONE grammar `parseAssetQuery`/`matchAssetQuery` implement; every\n// consumer (the Kura assets server route, the client's `asset-query.ts`)\n// imports these instead of re-parsing.\n// ============================================================================\n\nconst ASSET_QUERY_TYPE_PREFIX = 't:';\nconst ASSET_QUERY_LABEL_PREFIX = 'l:';\n\nfunction isAssetCatalogEntryKind(value: string): value is AssetCatalogEntry['kind'] {\n return ASSET_CATALOG_ENTRY_KINDS.some((kind) => kind === value);\n}\n\ninterface ParsedAssetQuery {\n text: string;\n kind?: AssetCatalogEntry['kind'];\n labels: string[];\n /** A `t:` token whose value is not a known `AssetCatalogEntry['kind']` — the query matches nothing. */\n unknownKind: boolean;\n}\n\nfunction parseAssetQueryTokens(q: string): ParsedAssetQuery {\n const tokens = q.trim().length > 0 ? q.trim().split(/\\s+/) : [];\n const textParts: string[] = [];\n const labels: string[] = [];\n let kind: AssetCatalogEntry['kind'] | undefined;\n let unknownKind = false;\n for (const token of tokens) {\n if (token.startsWith(ASSET_QUERY_TYPE_PREFIX)) {\n const value = token.slice(ASSET_QUERY_TYPE_PREFIX.length);\n if (isAssetCatalogEntryKind(value)) kind = value;\n else unknownKind = true;\n } else if (token.startsWith(ASSET_QUERY_LABEL_PREFIX)) {\n const value = token.slice(ASSET_QUERY_LABEL_PREFIX.length);\n if (value.length > 0) labels.push(value);\n } else {\n textParts.push(token);\n }\n }\n return { text: textParts.join(' '), kind, labels, unknownKind };\n}\n\n/**\n * Parses a `t:<kind>` / `l:<label>` / free-text asset search query. An\n * unrecognized `t:` value is dropped from the returned `kind` (there is no\n * value of `AssetCatalogEntry['kind']` to report) — `matchAssetQuery`, which\n * shares this same tokenizer internally, is the authority that turns it into\n * \"matches nothing\".\n */\nexport function parseAssetQuery(q: string): { text: string; kind?: AssetCatalogEntry['kind']; labels: string[] } {\n const parsed = parseAssetQueryTokens(q);\n return parsed.kind === undefined ? { text: parsed.text, labels: parsed.labels } : { text: parsed.text, kind: parsed.kind, labels: parsed.labels };\n}\n\n/**\n * Matches one catalog entry against a `t:`/`l:`/free-text query. `l:` labels\n * are ANDed against `entry.category` (exact, case-insensitive); free text is\n * an ANDed case-insensitive substring over `name`+`category`. An unrecognized\n * `t:` kind matches nothing.\n */\nexport function matchAssetQuery(entry: AssetCatalogEntry, q: string): boolean {\n const parsed = parseAssetQueryTokens(q);\n if (parsed.unknownKind) return false;\n if (parsed.kind !== undefined && entry.kind !== parsed.kind) return false;\n for (const label of parsed.labels) {\n if (entry.category.toLowerCase() !== label.toLowerCase()) return false;\n }\n if (parsed.text.length > 0) {\n const haystack = `${entry.name} ${entry.category}`.toLowerCase();\n if (!haystack.includes(parsed.text.toLowerCase())) return false;\n }\n return true;\n}\n","/**\n * Entity Types for Orbital Units\n *\n * Defines the OrbitalEntity type - the nucleus of an Orbital Unit.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { EntityIdSchema } from './identity.js';\nimport type { EntityId } from './identity.js';\nimport { EntityFieldSchema, type EntityField, type FileValue } from './field.js';\nimport { SemanticAssetRefSchema, type SemanticAssetRef } from './asset.js';\nimport { JsonValueSchema, type RuntimeValue } from './json.js';\nimport { SExprSchema, type SExpr } from './expression.js';\n\n// ============================================================================\n// Entity Persistence\n// ============================================================================\n\n/**\n * Entity persistence types.\n *\n * - persistent: Stored in database (has collection)\n * - runtime: Exists only at runtime (not persisted)\n */\nexport type EntityPersistence = 'persistent' | 'runtime';\n\nexport const EntityPersistenceSchema = z.enum([\n 'persistent',\n 'runtime',\n]);\n\n// ============================================================================\n// Orbital Entity\n// ============================================================================\n\n/**\n * OrbitalEntity - the nucleus of an Orbital Unit.\n *\n * This is a simplified entity definition optimized for orbital composition.\n * Collection names are derived automatically from persistence type if not provided.\n */\nexport type OrbitalEntity = {\n /** V4 dual-carry id sibling of `name` — optional until the Phase-7 flip. */\n id?: EntityId;\n\n /** Entity name (PascalCase, e.g., \"Task\", \"User\") */\n name: string;\n\n /** Entity persistence type (defaults to 'persistent' if not specified) */\n persistence?: EntityPersistence;\n\n /** Whether this entity's state is shared across all bound traits (vs per-trait copy). Orthogonal to persistence. */\n shared?: boolean;\n\n /**\n * Whether this entity types the ambient `@user` viewer. Orthogonal to both\n * `persistence` and `shared`: `[persistent: people, identity]` is an\n * app-owned user directory, `[runtime, identity]` the provider-supplied\n * current viewer. At most one per composed program.\n */\n identity?: boolean;\n\n /**\n * `@read` — a per-row predicate (`@entity` = candidate row, `@user` =\n * viewer) ANDed with any call-site `filter:`. The un-bypassable twin of\n * `filter:`, enforced once for every trait that fetches this entity.\n */\n read_policy?: SExpr;\n\n /** `@create` — `@entity` binds the incoming data about to become a row. */\n create_policy?: SExpr;\n\n /** `@update` — `@entity` binds the existing row before mutation. */\n update_policy?: SExpr;\n\n /** `@delete` — same binding shape as `@update`. */\n delete_policy?: SExpr;\n\n /**\n * `@<op> none \"<reason>\"` — a directive's omission, DECLARED.\n *\n * Runtime behaviour is identical to leaving the directive out (an absent\n * policy is allow-all). It records that the author concluded no per-row\n * predicate can express the rule — usually because visibility depends on a\n * DIFFERENT entity, which a per-row predicate cannot join across. Without\n * it a lint must flag considered and forgotten omissions alike, and a lint\n * that flags correct code is one people learn to ignore.\n */\n access_waivers?: {\n read?: string;\n create?: string;\n update?: string;\n delete?: string;\n };\n\n /** Collection name (auto-derived if not provided for persistent entities) */\n collection?: string;\n\n /** Entity fields */\n fields: EntityField[];\n\n /** Pre-authored instances (seed data or static reference data) */\n instances?: EntityRow[];\n\n /** Auto-add createdAt/updatedAt timestamps */\n timestamps?: boolean;\n\n /** Soft delete support */\n softDelete?: boolean;\n\n /** Human-readable description */\n description?: string;\n\n /** Visual prompt for AI generation */\n visual_prompt?: string;\n\n /** Semantic asset reference for visual representation (games) */\n assetRef?: SemanticAssetRef;\n};\n\nexport const OrbitalEntitySchema = z.object({\n name: z.string().min(1, 'Entity name is required'),\n // V4 arena id (`EntityDefinition.id`); declared so the strip-mode zod gate\n // carries an imported entity's id through instead of erasing it.\n id: EntityIdSchema.optional(),\n persistence: EntityPersistenceSchema.default('persistent'),\n shared: z.boolean().optional(),\n // Must stay in step with the Rust serde field (`EntityDefinition.identity`,\n // orbital-core/src/schema/types.rs). `z.object()` STRIPS unknown keys rather\n // than rejecting them, so a Rust-only field works on the compiled path and\n // silently vanishes on the interpreter path.\n identity: z.boolean().optional(),\n // Same \"must stay in step with Rust serde\" hazard as `identity` above —\n // these four mirror `EntityDefinition.{read,create,update,delete}_policy`.\n // Rust has no `rename_all` on this struct, so the wire key IS snake_case\n // (unlike this file's other camelCase fields, which are Rust-side-absent\n // and so never hit this cross-language constraint — see `visual_prompt`\n // just below for the existing precedent).\n read_policy: SExprSchema.optional(),\n create_policy: SExprSchema.optional(),\n update_policy: SExprSchema.optional(),\n delete_policy: SExprSchema.optional(),\n // Snake_case for the same cross-language reason as the four policies above.\n access_waivers: z\n .object({\n read: z.string().optional(),\n create: z.string().optional(),\n update: z.string().optional(),\n delete: z.string().optional(),\n })\n .optional(),\n collection: z.string().optional(),\n fields: z.array(EntityFieldSchema).min(1, 'At least one field is required'),\n instances: z.array(z.record(JsonValueSchema)).optional(),\n timestamps: z.boolean().optional(),\n softDelete: z.boolean().optional(),\n description: z.string().optional(),\n visual_prompt: z.string().optional(),\n assetRef: SemanticAssetRefSchema.optional(),\n});\n\nexport type OrbitalEntityInput = z.input<typeof OrbitalEntitySchema>;\n\n// ============================================================================\n// Type Aliases (for cleaner imports)\n// ============================================================================\n\n/** Alias for OrbitalEntity - preferred name */\nexport type Entity = OrbitalEntity;\n\n/** Alias for OrbitalEntitySchema - preferred name */\nexport const EntitySchema = OrbitalEntitySchema;\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Derives the collection name for a persistent entity.\n * \n * Generates the database collection name by converting the entity name\n * to lowercase and adding an 's' suffix (simple pluralization).\n * Returns undefined for non-persistent (runtime) entities.\n * \n * @param {OrbitalEntity} entity - Entity to derive collection name for\n * @returns {string | undefined} Collection name or undefined for non-persistent entities\n * \n * @example\n * deriveCollection({ name: 'User', persistence: 'persistent' }); // returns 'users'\n * deriveCollection({ name: 'Task', persistence: 'runtime' }); // returns undefined\n */\nexport function deriveCollection(entity: OrbitalEntity): string | undefined {\n if (entity.persistence !== 'persistent') {\n return undefined;\n }\n // Lowercase + 's' suffix (simple pluralization)\n return entity.name.toLowerCase() + 's';\n}\n\n/**\n * Checks if an entity is runtime-only (not persisted).\n * \n * Type guard to determine if an entity exists only at runtime\n * and is not stored in the database.\n * \n * @param {OrbitalEntity} entity - Entity to check\n * @returns {boolean} True if entity is runtime-only, false otherwise\n * \n * @example\n * isRuntimeEntity({ persistence: 'runtime' }); // returns true\n * isRuntimeEntity({ persistence: 'persistent' }); // returns false\n */\nexport function isRuntimeEntity(entity: OrbitalEntity): boolean {\n return entity.persistence === 'runtime';\n}\n\n/**\n * Checks whether an entity's persistence mode allows `persistence` /\n * `collection` overrides at the factory call site.\n *\n * Only `persistent` entities (explicit or default) support these overrides.\n * Runtime entities are fixed; callers must not expose `persistence` or\n * `collection` params for them.\n *\n * @param persistence - The entity persistence mode (undefined = default persistent)\n * @returns True when overrides are allowed, false otherwise\n *\n * @example\n * persistenceModeAllowsOverrides('persistent'); // returns true\n * persistenceModeAllowsOverrides('runtime'); // returns false\n * persistenceModeAllowsOverrides(undefined); // returns true (default persistent)\n */\nexport function persistenceModeAllowsOverrides(\n persistence: EntityPersistence | undefined,\n): boolean {\n return persistence === 'persistent' || persistence === undefined;\n}\n\n// ============================================================================\n// Entity Instance Data (Runtime)\n// ============================================================================\n\n/**\n * A single field value at runtime.\n * Union of all possible types from FieldType: string, number, boolean, date, array, nested.\n * The nested-record branch's index signature tolerates `undefined` so that\n * TypeScript optional properties (`x?: string`, carrying `string | undefined`)\n * on EntityRow extenders typecheck without ceremony. At JSON serialization\n * time `undefined` is equivalent to \"key absent\" and never appears on the\n * wire; the inclusion here is a pure type-surface accommodation.\n */\nexport type FieldValue = string | number | boolean | Date | null | string[] | FieldValue[] | { [key: string]: FieldValue | undefined };\n\n/** Zod twin of `FieldValue` — the one runtime validator for a stored field slot. */\nexport const FieldValueSchema: z.ZodType<FieldValue> = z.lazy(() =>\n z.union([z.string(), z.number(), z.boolean(), z.date(), z.null(), z.array(FieldValueSchema), z.record(FieldValueSchema.optional())]),\n);\n\n/**\n * What a FORM CONTROL puts on the event bus — the closed set of shapes an\n * Input / Select / Checkbox / Date / multi-select / file field actually\n * produces.\n *\n * A TRANSPORT type, deliberately distinct from `FieldValue`, and the separation\n * is the point. `FieldValue` conflated two jobs: what a control emits, and what\n * an entity field holds. The second never needed it — an entity field always\n * has one declared type (`email : email!`, `age : number`) — so the openness\n * only travelled outward, degrading every generated `.lolo` payload to a\n * shapeless `object`.\n *\n * NOT recursive, and the variants are enumerated from what is actually emitted\n * rather than guessed. `FileValue` is here because the compiler put it here: a\n * scalar-only draft failed against the file field, which hands\n * `Form.handleChange` a `{ name, url, mimeType, sizeBytes }` record.\n *\n * The rule is Aeson's — enumerate the shapes that occur, keep the open type at\n * the boundary, convert on the way in. In `.lolo` that boundary is the\n * `(set @entity.X ?value)` of the receiving transition, where the entity\n * field's own declared type does the checking.\n */\nexport type ControlValue = string | number | boolean | null | string[] | FileValue;\n\n/**\n * Runtime guard for `FieldValue` — narrows interpreter-produced `unknown`\n * values at typed substrate boundaries (e.g. `IntegrationContext.http` body).\n */\nexport function isFieldValue(value: RuntimeValue): value is FieldValue {\n if (value === null) return true;\n const kind = typeof value;\n if (kind === 'string' || kind === 'number' || kind === 'boolean') return true;\n if (value instanceof Date) return true;\n if (Array.isArray(value)) return value.every((item: RuntimeValue) => isFieldValue(item));\n if (kind === 'object' && value !== null && typeof value === 'object') {\n return Object.values(value).every((item: RuntimeValue) => item === undefined || isFieldValue(item));\n }\n return false;\n}\n\n/**\n * One instance of an entity with actual field values.\n * The shape is determined by the Entity definition at schema time.\n *\n * @example\n * // Entity defines: Patient { fullName: string, age: number, active: boolean }\n * // EntityRow is: { id: \"p1\", fullName: \"Sarah\", age: 34, active: true }\n */\nexport type EntityRow = { id?: string } & Record<string, FieldValue | undefined>;\n\n/** Zod twin of `EntityRow` — the one runtime validator for an `@entity` wire row. */\nexport const EntityRowSchema: z.ZodType<EntityRow> = z\n .object({ id: z.string().optional() })\n .catchall(FieldValueSchema.optional());\n\n/**\n * A field-TYPED `EntityRow` — the SINGLE entity type, refined with a concrete\n * field SHAPE `S`. Non-optional members of `S` are REQUIRED, each with its real\n * type; the result stays `& EntityRow`, so the index signature is intact and\n * every other field is still field-open — any domain entity that provides those\n * fields satisfies it.\n *\n * One declaration, two jobs: (1) TypeScript enforces the bound entity has the\n * fields WITH their types (a behavior binding a thinner/mistyped entity fails to\n * typecheck); and (2) pattern-sync reads the same type and writes the entity\n * prop's field shape (`properties` + `requiredFields`) onto the registry, so\n * lolo-ui emits a COMPLETE `entity { … }` (every field, typed + demo-seeded) and\n * the `ORB_X_ENTITY_PROP_CONTRACT` validator rejects an incompatible bind at\n * `orbital validate`. (A raw `EntityRow & { rating: number }` intersection is\n * equivalent for one-off shapes.)\n *\n * @example\n * // HeroOrganism renders entity.title / entity.subtitle:\n * entity?: EntityWith<{ title: string; subtitle?: string }>;\n * // entity.title → string (required)\n * // entity.subtitle → string | undefined (optional)\n * // entity.other → FieldValue | undefined (still field-open)\n */\n// `S extends object` (not `Record<string, FieldValue>`) so a plain `interface`\n// row shape satisfies it — interfaces lack the implicit index signature `Record`\n// requires. FieldValue-compatibility is still enforced structurally: `& EntityRow`\n// intersects every field with the `FieldValue | undefined` index signature, so a\n// non-FieldValue field (e.g. a React `LucideIcon`) collapses to `never` at use.\nexport type EntityWith<S extends object> = EntityRow & S;\n\n/**\n * Collection of entity instances keyed by entity name.\n * Used by OrbPreview mockData, OrbitalServerRuntime state, data grids, etc.\n *\n * @example\n * const data: EntityData = {\n * Patient: [{ id: \"1\", fullName: \"Sarah\", age: 34 }],\n * QueueEntry: [{ id: \"1\", patientName: \"Sarah\", waitMinutes: 12 }],\n * };\n */\nexport type EntityData = Record<string, EntityRow[]>;\n","/**\n * Effect Types (Self-Contained)\n *\n * Defines effect types for trait transitions and ticks.\n * Effects are S-expressions (arrays) that describe actions to perform.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { type SExpr, type Expression, type EventPayload, SExprDataSchema } from './expression.js';\nimport type { RuntimeValue, JsonValue } from './json.js';\nimport { type ServiceParams } from './service.js';\nimport { type EntityRow, type FieldValue } from './entity.js';\n\n// ============================================================================\n// UI Slots\n// ============================================================================\n\n/**\n * Known UI slots where content can be rendered\n */\nexport const UI_SLOTS = [\n // App slots\n 'main',\n 'sidebar',\n 'modal',\n 'drawer',\n 'overlay',\n 'center',\n 'toast',\n 'floating',\n 'system', // For invisible system components (InputListener, CollisionDetector)\n 'content',\n 'screen',\n // Game HUD slots\n 'hud',\n 'hud-top',\n 'hud-bottom',\n 'hud.health',\n 'hud.score',\n 'hud.inventory',\n 'hud.stamina',\n // Game overlay slots\n 'overlay.inventory',\n 'overlay.dialogue',\n 'overlay.menu',\n 'overlay.pause',\n] as const;\n\nexport type UISlot = (typeof UI_SLOTS)[number];\n\nexport const UISlotSchema = z.enum(UI_SLOTS);\n\n// ============================================================================\n// Pattern Config (for render-ui effects)\n// ============================================================================\n\n// Import pattern types for local use and re-export for consumers\nimport type {\n PatternType,\n PatternConfig,\n PatternProps,\n PatternPropsMap,\n AnyPatternConfig,\n} from '../patterns/index.js';\n\n/**\n * Type-safe pattern configuration for render-ui effects.\n *\n * Re-exported from @almadar/patterns. Generated from patterns-registry.json.\n *\n * @example\n * // Type-safe with specific pattern type\n * const config: PatternConfig<'entity-table'> = {\n * patternType: 'entity-table',\n * columns: ['name', 'email'], // ✅ Required prop\n * entity: 'User',\n * };\n *\n * // Error: Property 'columns' is missing (required prop)\n * const bad: PatternConfig<'entity-table'> = { patternType: 'entity-table' };\n *\n * // Error: 'fake-pattern' is not assignable to PatternType\n * const invalid: PatternConfig = { patternType: 'fake-pattern' };\n */\nexport type {\n PatternType,\n PatternConfig,\n PatternProps,\n PatternPropsMap,\n AnyPatternConfig,\n};\n\n// ============================================================================\n// Service Config (for call-service effects)\n// ============================================================================\n\n/**\n * Configuration extracted from call-service effects\n */\nexport type CallServiceConfig = {\n service: string;\n action: string;\n endpoint?: string;\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n params?: ServiceParams;\n onSuccess?: string;\n onError?: string;\n};\n\n// ============================================================================\n// Typed Effect Tuples\n// ============================================================================\n\n/**\n * A binding reference to a render tree stored elsewhere — a trait `config`\n * knob or a payload field — e.g. `\"@config.bodyContent\"`. Resolved to a pattern\n * node at render time. This is how an atom renders a tree that contains data\n * bindings (`entity: \"@payload.data\"`, `fields: \"@config.fields\"`): the tree is\n * a permissive `TraitConfigValue` stored in `config` (a binding string is not a\n * valid `AnyPatternConfig` prop value), and the render-ui effect points at it.\n * Worked example: `std-browse`'s loaded transition is `['render-ui', 'main',\n * '@config.bodyContent']`. The Rust validator accepts this form; this variant\n * lets the TS effect type express it.\n */\nexport type RenderBinding = `@${string}`;\n\n/**\n * A binding reference resolving to a {@link UISlot} at inline time — a trait\n * `config` knob holding the slot name, e.g. `\"@config.reviewSlot\"`. Mirrors\n * {@link RenderBinding} for the SLOT position: the compiler's inline phase\n * substitutes the config value before anything renders, and the Rust\n * validator accepts the pre-substitution form (worked example:\n * `std-approval-gate`'s review queue renders into `@config.reviewSlot`).\n * This variant lets the TS effect type express the template-layer form.\n */\nexport type SlotBinding = `@config.${string}`;\n\n/**\n * Template-layer pattern node: a render tree whose discriminant and/or props\n * are still bindings (`type: '@config.viewPattern'`, `title: '@config.title'`)\n * or loose nested descriptors the compiler's inline phase resolves. The\n * resolved layer is {@link AnyPatternConfig}; this variant lets generated\n * behavior descriptors (std-ts) carry the pre-substitution form the Rust\n * validator accepts (worked example: `std-graphs` renders\n * `{ type: '@config.viewPattern', chartType: '@config.chartType', … }`).\n */\nexport type TemplatePatternConfig = { type: PatternType | RenderBinding } & Record<string, JsonValue>;\n\n/**\n * Render UI effect - displays a pattern in a UI slot.\n * @example ['render-ui', 'main', { patternType: 'entity-table', columns: ['name'] }]\n * @example ['render-ui', 'main', '@config.bodyContent'] // a {@link RenderBinding} target\n * @example ['render-ui', '@config.reviewSlot', { patternType: 'entity-table' }] // a {@link SlotBinding} slot\n */\nexport type RenderUIEffect =\n | ['render-ui', UISlot | SlotBinding, AnyPatternConfig]\n | ['render-ui', UISlot | SlotBinding, AnyPatternConfig, ResolvedPatternProps]\n | ['render-ui', UISlot | SlotBinding, TemplatePatternConfig]\n | ['render-ui', UISlot | SlotBinding, RenderBinding]\n | ['render-ui', UISlot | SlotBinding, null];\n\n/**\n * Lambda expression for per-item rendering in data-grid/data-list.\n * The compiler generates: {(paramName: Record<string, unknown>) => (<>JSX</>)}\n * where @{paramName}.field bindings reference the current iteration item.\n *\n * @example [\"fn\", \"item\", { \"type\": \"stack\", \"children\": [{ \"type\": \"typography\", \"content\": \"@item.title\" }] }]\n */\nexport type RenderItemLambda = ['fn', string, AnyPatternConfig];\n\n/**\n * Dynamic-collection children entry: renders one child per item of a collection\n * expression, authored inline in a `children:` position and kept verbatim as IR\n * (no new node kind). The collection expression is an {@link SExpr} evaluated at\n * render time; the {@link RenderItemLambda} body is instantiated per item with\n * the lambda param bound as an `@item`-scope binding. Both execution paths lower\n * onto the one lambda + `@item` + splice machinery.\n *\n * @example [\"array/map\", \"@entity.tasks\", [\"fn\", \"item\", { \"type\": \"typography\", \"content\": \"@item.title\" }]]\n */\nexport type RenderChildrenMap = ['array/map', SExpr, RenderItemLambda];\n\n/**\n * Trailing options object on navigate effects. `crumb` labels the navigation\n * stack entry the client pushes for the target page (e.g. the record title a\n * list router has in `?row` at push time); without it the entry falls back to\n * the target page's declared/derived label.\n */\nexport type NavigateOptions = { crumb?: string | SExpr };\n\n/**\n * Navigate effect - navigates to an internal page path or an external URL.\n * @example ['navigate', '/tasks'] or ['navigate', '/tasks/:id', { id: '123' }]\n * @example ['navigate', 'https://example.com']\n * @example ['navigate', '/contracts/42', { id: '42' }, { crumb: '@payload.row.title' }]\n */\nexport type NavigateEffect =\n | ['navigate', string | SExpr]\n | ['navigate', string | SExpr, Record<string, string | SExpr>]\n | ['navigate', string | SExpr, Record<string, string | SExpr>, NavigateOptions];\n\n/**\n * Navigate-back effect - pops the current entry off the orbital-scoped\n * navigation stack and navigates to the previous one. The stack is\n * client-session state (cold loads are seeded from declared page-path\n * prefixes), so an ancestor always exists on nested paths; the validator\n * rejects `navigate-back` reachable only from pages with no path ancestor.\n * @example ['navigate-back']\n */\nexport type NavigateBackEffect = ['navigate-back'];\n\n/**\n * Emit effect - emits an event, optionally with payload.\n * @example ['emit', 'SAVE'] or ['emit', 'PLAYER_DIED', { playerId: '@entity.id' }]\n * @example ['emit', 'FILTER_CHANGED', '@entity.filters']\n */\nexport type EmitEffect = ['emit', string] | ['emit', string, EventPayload | string];\n\n/**\n * `emit:` config block attached to async / reactive data operators.\n *\n * Each key names an event the runtime should fire on the bus when the\n * effect reaches the corresponding lifecycle point. The set of keys an\n * operator actually supports is enforced by the compiler validator:\n *\n * | Operator | Supported keys |\n * |------------------|---------------------------|\n * | `fetch` | `success`, `failure` |\n * | `persist` | `success`, `failure` |\n * | `call-service` | `success`, `failure` |\n * | `set` | `success` |\n * | `ref` | `on_change`, `failure` |\n * | `os/watch-*` | `on_message`, `failure` |\n *\n * Payload convention:\n * - `success` / `on_change` → the effect's result (fetched entity, new value)\n * - `failure` → `{ error: string, code?: string }`\n * - `on_message` → the incoming message (os/watch-* streams)\n *\n * See `docs/Almadar_Std_Gaps.md` §3.1 for the close-the-circuit design.\n */\nexport interface EmitConfig {\n /** Fires after a one-shot async effect resolves successfully. */\n success?: string;\n /** Fires when the effect throws; payload is `{ error: string }`. */\n failure?: string;\n /** Reactive-subscription event (per update for `ref`). */\n on_change?: string;\n /** Per-event fire for `os/watch-*` streams. */\n on_message?: string;\n}\n\n/**\n * Set effect - sets a binding to a value.\n *\n * Two forms are supported to match the runtime's `set` handler signature\n * `(targetId, field, value)`:\n *\n * - 3-element binding form (legacy / std behaviors): ['set', '@entity.field', value]\n * - 4-element target form (canonical runtime): ['set', entityId, fieldName, value]\n *\n * The 4-element form is what `OrbitalServerRuntime`'s set handler\n * dispatches directly (`update(entityType, targetId, { field: value })`).\n * Prefer the 4-element form when authoring schemas in TypeScript that\n * load directly into the runtime.\n *\n * @example ['set', '@entity.health', 100] // 3-element\n * @example ['set', '@entity.id', 'health', 100] // 4-element\n * @example ['set', '@entity.id', 'count', ['+', '@entity.count', 1]]\n */\nexport type SetEffect =\n | ['set', string, SExpr]\n | ['set', string, string, SExpr];\n\n/**\n * Trailing config object on persist effects. When present, it carries the\n * `emit` map specifying which events to fire on persist success/failure.\n * Mirrors what the runtime's `EffectExecutor` reads at the 5th tuple\n * position. See `(persist create Entity @payload.data { emit: { success:\n * \"Saved\", failure: \"SaveFailed\" } })` in `.lolo` source.\n */\nexport type PersistEmitConfig = {\n emit?: { success?: string; failure?: string };\n};\n\n/**\n * Persist effect data argument: an entity row literal (field map), a\n * binding string referencing a row in scope (e.g. `@payload.data`,\n * `@entity`), or an expression form that evaluates to a row (e.g.\n * `[\"object/merge\", \"@payload.data\", { sender: \"@user.id\" }]`). At\n * runtime, binding strings and expressions resolve to `EntityRow` values\n * before the persist op runs — both paths evaluate the expression first.\n */\nexport type PersistRowInput = { id?: string | SExpr } & Record<string, FieldValue | SExpr | undefined>;\n\nexport type PersistData = EntityRow | PersistRowInput | string | SExpr[];\n\n/**\n * One EVALUATED operation of the runtime path's `[\"persist\", \"batch\", [...ops]]`\n * form, as `EffectExecutor` hands it to `handlers.persist('batch', '', { operations })`\n * and both server persist handlers execute it. The row is optional on\n * create/update (an absent row persists `{}`), exactly as the handlers always\n * tolerated. The compiled path has no batch persist — ledger §169.\n */\nexport type PersistBatchOperation =\n | ['create', string, EntityRow?]\n | ['update', string, string, EntityRow?]\n | ['delete', string, string];\n\nfunction isRowObject(value: RuntimeValue): value is EntityRow {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date);\n}\n\n/** The ONE structural check for a batch operation — every consumer narrows through it. */\nexport function isPersistBatchOperation(value: RuntimeValue): value is PersistBatchOperation {\n if (!Array.isArray(value) || typeof value[1] !== 'string') return false;\n switch (value[0]) {\n case 'create':\n return value.length === 2 || (value.length === 3 && isRowObject(value[2]));\n case 'update':\n return typeof value[2] === 'string' && (value.length === 3 || (value.length === 4 && isRowObject(value[3])));\n case 'delete':\n return value.length === 3 && typeof value[2] === 'string';\n default:\n return false;\n }\n}\n\n/**\n * Persist effect - creates, updates, deletes, or clears entities.\n *\n * Each operation accepts an optional trailing `PersistEmitConfig` so the\n * runtime can fire success / failure events when the operation completes.\n *\n * @example ['persist', 'create', 'Task', { title: '@payload.title' }]\n * @example ['persist', 'update', '@entity.entityType', '@payload.data']\n * @example ['persist', 'create', 'Task', '@payload.data', { emit: { success: 'TaskCreated' } }]\n */\nexport type PersistEffect =\n | ['persist', 'create', string, PersistData]\n | ['persist', 'create', string, PersistData, PersistEmitConfig]\n | ['persist', 'update', string, PersistData]\n | ['persist', 'update', string, PersistData, PersistEmitConfig]\n | ['persist', 'delete', string]\n | ['persist', 'delete', string, PersistData]\n | ['persist', 'delete', string, PersistData, PersistEmitConfig]\n | ['persist', 'clear', string]\n | ['persist', 'clear', string, PersistData]\n | ['persist', 'clear', string, PersistData, PersistEmitConfig];\n\n/**\n * Call service effect - invokes an external service.\n *\n * Two shapes are accepted:\n *\n * 1. Flat form (what the runtime reads and every .orb file uses):\n * `['call-service', serviceName, action, params?]` — args[0]=service,\n * args[1]=action, args[2]=params. This is the canonical form; the\n * runtime's EffectExecutor decodes exactly these positions.\n *\n * 2. Legacy config-object form (kept for the `callService()` helper):\n * `['call-service', serviceName, CallServiceConfig]` — retained so\n * older call sites using the builder helper continue to typecheck.\n *\n * @example ['call-service', 'llm', 'generate', { userPrompt: '@entity.inputText' }]\n * @example ['call-service', 'llm', 'generate', { userPrompt: '...' }, { emit: { success: 'OK', failure: 'ERR' } }]\n * @example ['call-service', 'WeatherAPI', { service: 'weather', action: 'get', onSuccess: 'OK' }]\n */\nexport type CallServiceEffect =\n | ['call-service', string, string]\n | ['call-service', string, string, ServiceParams]\n | ['call-service', string, string, ServiceParams, PersistEmitConfig]\n | ['call-service', string, CallServiceConfig];\n\n/**\n * Spawn effect - creates a new entity instance (games).\n * @example ['spawn', 'Bullet', { x: '@entity.x', y: '@entity.y' }]\n */\nexport type SpawnEffect = ['spawn', string] | ['spawn', string, EntityRow];\n\n/**\n * Despawn effect - removes an entity instance (games).\n * @example ['despawn', '@entity.id']\n */\nexport type DespawnEffect = ['despawn', string];\n\n/**\n * Do effect - executes multiple effects in sequence.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['do', ['set', '@entity.x', 0], ['set', '@entity.y', 0]]\n */\nexport type DoEffect = ['do', ...SExpr[]];\n\n/**\n * Options accepted by `fetch` / `ref` / `deref` effects. Mirrors what\n * `OrbitalServerRuntime`'s fetch handler reads at runtime: `id`, `filter`,\n * `limit`, `offset`, `include`, plus the trailing `emit:` map for\n * success/failure event names.\n */\nexport type FetchOptions = {\n /** Fetch a single entity by ID */\n id?: string;\n /** Filter expression (S-expression) */\n filter?: SExpr;\n /** Maximum number of entities to return. The template layer may carry a\n * binding (`'@config.pageSize'`) or a computed S-expression — the\n * compiler's inline phase resolves it to a number. */\n limit?: number | RenderBinding | SExpr[];\n /** Number of entities to skip — same template-layer forms as `limit`. */\n offset?: number | RenderBinding | SExpr[];\n /** Relations to populate (entity field names). The template layer may\n * carry a binding (`'@config.include'`) — same as `limit`/`offset`, the\n * compiler's inline phase resolves it to the concrete list. */\n include?: string[] | RenderBinding;\n /** Lifecycle events to emit on resolve / reject */\n emit?: { success?: string; failure?: string };\n};\n\n/**\n * Fetch effect - retrieves entity data (server-side).\n * @example ['fetch', 'User'] or ['fetch', 'User', { id: '@payload.userId' }]\n */\nexport type FetchEffect = ['fetch', string] | ['fetch', string, FetchOptions];\n\n/** Options for `fetch-stream` — mirror of the compiler's `OirEffect::FetchStream`\n * (`orbital-core/src/ir/effects.rs`) and the runtime's `fetchStream` handler. */\nexport type FetchStreamOptions = {\n id?: string | SExpr;\n filter?: SExpr;\n /** `on_message` fires per chunk; `success` on completion. */\n emit?: { on_message?: string; success?: string; failure?: string };\n};\n\n/**\n * Fetch-stream effect - streams entity rows (server-side), one `on_message`\n * emit per chunk. The compiled path (`OirEffect::FetchStream`) and the\n * runtime (`EffectExecutor` `'fetch-stream'`) both execute it.\n * @example ['fetch-stream', 'Message', { filter: ['=', '@entity.roomId', '@payload.roomId'], emit: { on_message: 'CHUNK' } }]\n */\nexport type FetchStreamEffect = ['fetch-stream', string] | ['fetch-stream', string, FetchStreamOptions];\n\n/**\n * Result returned by a fetch / ref / deref handler.\n *\n * `rows` carries the entity (or entities) that survived `filter` AND\n * pagination (`offset`/`limit`). `total` is the count of rows that\n * matched the filter BEFORE pagination, so paginating consumers can\n * compute `totalPages = ceil(total / pageSize)` without a second\n * round-trip. Single-entity fetches by id return `total: 1` (or `0`\n * if not found, in which case the handler returns `null` instead).\n */\nexport interface FetchResult {\n rows: EntityRow | EntityRow[];\n total: number;\n}\n\n/**\n * If effect - conditional effect execution.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['if', ['>', '@entity.health', 0], ['emit', 'ALIVE'], ['emit', 'DEAD']]\n */\nexport type IfEffect = ['if', Expression, SExpr] | ['if', Expression, SExpr, SExpr];\n\n/**\n * When effect - conditional effect similar to if but without else.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['when', ['>', '@entity.health', 0], ['emit', 'ALIVE']]\n */\nexport type WhenEffect = ['when', Expression, SExpr];\n\n/**\n * Let effect - creates local bindings for effects.\n * Uses SExpr to allow deeply nested conditionals.\n * @example ['let', ['temp', ['get', '@payload.value']], ['set', '@entity.value', 'temp']]\n */\nexport type LetEffect = ['let', [string, SExpr][], ...SExpr[]];\n\n/**\n * Log effect - logs a message for debugging.\n * @example ['log', 'User created:', '@entity.name']\n */\nexport type LogEffect = ['log', ...SExpr[]];\n\n/**\n * Wait effect - delays execution.\n * @example ['wait', 1000] - wait 1 second\n */\nexport type WaitEffect = ['wait', number];\n\n// ============================================================================\n// Resource Effects (reactive entity subscriptions and atomic operations)\n// ============================================================================\n\n/**\n * Ref effect - creates a reactive entity subscription.\n * Returns a reactive reference that auto-updates when the entity changes.\n * @example ['ref', '@entity.health'] - reactive subscription to health\n * @example ['ref', 'User', { id: '@payload.userId' }] - reactive ref to specific user\n */\nexport type RefEffect =\n | ['ref', string]\n | ['ref', string, FetchOptions];\n\n/**\n * Deref effect - snapshot read of an entity value.\n * Returns the current value without subscribing to changes.\n * @example ['deref', '@entity.health'] - read current health value\n * @example ['deref', 'User', { id: '@payload.userId' }] - read specific user snapshot\n */\nexport type DerefEffect =\n | ['deref', string]\n | ['deref', string, FetchOptions];\n\n/**\n * Swap! effect - atomic compare-and-swap on an entity field.\n * Only updates if the current value matches the expected value.\n * @example ['swap!', '@entity.health', ['fn', ['old'], ['-', 'old', '@payload.damage']]]\n * @example ['swap!', '@entity.counter', ['+', '@entity.counter', 1]]\n */\nexport type SwapEffect = ['swap!', string, SExpr];\n\n/**\n * Options accepted by `watch` effects. Mirrors what the runtime reads when\n * registering the change callback: `debounce` and the trailing `emit:` map.\n */\nexport type WatchOptions = {\n /** Debounce duration in milliseconds */\n debounce?: number;\n /** Lifecycle events to emit on update / failure */\n emit?: { on_message?: string; failure?: string };\n};\n\n/**\n * Watch effect - registers a callback for entity changes.\n * Emits an event whenever the watched binding changes.\n * @example ['watch', '@entity.health', 'HEALTH_CHANGED']\n * @example ['watch', '@entity.status', 'STATUS_UPDATED', { debounce: 100 }]\n */\nexport type WatchEffect =\n | ['watch', string, string]\n | ['watch', string, string, WatchOptions];\n\n/**\n * Atomic effect - groups multiple effects into an atomic transaction.\n * All effects either succeed together or are rolled back.\n * @example ['atomic', ['set', '@entity.x', 10], ['set', '@entity.y', 20]]\n * @example ['atomic', ['persist', 'update', 'User', { balance: 100 }], ['emit', 'BALANCE_UPDATED']]\n */\nexport type AtomicEffect = ['atomic', ...SExpr[]];\n\n// ============================================================================\n// ML Effects (from almadar-std/modules/nn, tensor, train)\n// ============================================================================\n\n/**\n * One layer in an NN architecture description. The set of valid layer kinds\n * lives in `almadar-std/modules/nn`; here we keep the wire shape generic\n * enough for the cross-package runtime + Python bridge to round-trip.\n */\nexport type NnLayer = {\n type: string;\n [key: string]: string | number | boolean | number[] | string[] | undefined;\n};\n\n/**\n * Hyperparameters for `train` and `evaluate`. Recursive to allow nested\n * optimizer / scheduler config blocks without falling back to `unknown`.\n */\nexport type NnConfig = {\n [key: string]: string | number | boolean | string[] | number[] | NnConfig | undefined;\n};\n\n/**\n * Forward-pass config: `input` is a binding string (`@payload.input`), and\n * `on-complete` names the event to fire when the prediction lands.\n */\nexport type ForwardConfig = {\n architecture: NnLayer[];\n input: string;\n 'on-complete'?: string;\n config?: NnConfig;\n};\n\n/**\n * Training-loop config. `dataset` is a binding string referencing the rows\n * to train on. Optimizer / loss / scheduler land inside `config`.\n */\nexport type TrainConfig = {\n architecture: NnLayer[];\n dataset: string;\n config?: NnConfig;\n 'on-complete'?: string;\n};\n\n/**\n * Evaluation config. `metrics` lists named metrics the Python backend\n * computes (`accuracy`, `precision`, ...).\n */\nexport type EvaluateConfig = {\n architecture: NnLayer[];\n dataset: string;\n metrics: string[];\n config?: NnConfig;\n 'on-complete'?: string;\n};\n\n/**\n * Forward effect - runs a neural network forward pass (Python backend).\n * @example ['forward', 'primary', { architecture: [...], input: '@payload.input', 'on-complete': 'PREDICTION_READY' }]\n */\nexport type ForwardEffect = ['forward', string, ForwardConfig];\n\n/**\n * Train effect - runs a training loop (Python backend).\n * @example ['train', { architecture: [...], dataset: '@entity.data', config: { epochs: 10 }, 'on-complete': 'TRAINING_DONE' }]\n */\nexport type TrainEffect = ['train', TrainConfig];\n\n/**\n * Evaluate effect - runs model evaluation (Python backend).\n * @example ['evaluate', { architecture: [...], dataset: '@entity.testData', metrics: ['accuracy'], 'on-complete': 'EVAL_DONE' }]\n */\nexport type EvaluateEffect = ['evaluate', EvaluateConfig];\n\n/**\n * Checkpoint save effect - saves model weights.\n * @example ['checkpoint/save', '/path/to/model.pt', '@entity.weights']\n */\nexport type CheckpointSaveEffect = ['checkpoint/save', string, SExpr];\n\n/**\n * Checkpoint load effect - loads model weights.\n * @example ['checkpoint/load', '/path/to/model.pt']\n */\nexport type CheckpointLoadEffect = ['checkpoint/load', string];\n\n// ============================================================================\n// Agent Effects (from agent/* operator namespace)\n// ============================================================================\n\n/**\n * Agent effect - invokes an agent/* operator.\n * Covers all 22 operators in the std-agent category.\n * @example ['agent/memorize', 'use data-grid for tables', 'preference']\n * @example ['agent/recall', 'user preferences']\n * @example ['agent/generate', 'Summarize this schema']\n */\nexport type AgentEffect = [`agent/${string}`, ...SExpr[]];\n\n/**\n * OS effect - invokes an os/* operator.\n *\n * Covers reactive subscriptions to OS / network resources:\n * - `os/watch-http`, `os/watch-ws`, `os/watch-sse` — long-lived streams\n * that fire `on_message` / `failure` events through a trailing\n * `EmitConfig` block (see `EmitConfig` for the supported keys).\n * - `os/read-file`, `os/exec`, etc. — one-shot OS operations.\n *\n * @example ['os/watch-http', 'wss://push.example.com', { emit: { on_message: 'PUSH_RECEIVED', failure: 'PUSH_DISCONNECTED' } }]\n * @example ['os/read-file', '/etc/hosts']\n */\nexport type OsEffect = [`os/${string}`, ...SExpr[]];\n\n/**\n * Browser effect - invokes a browser/* device operator (client host path).\n * User-initiated, async, resolves via the standard trailing emit envelope.\n * Concrete operators (browser/open-file-picker, browser/clipboard-read,\n * browser/clipboard-write, browser/geolocation-current) and their arity /\n * payload shapes live in @almadar/std BROWSER_OPERATORS.\n * @example ['browser/open-file-picker', { multiple: false }, { emit: { success: 'FILES_PICKED', failure: 'PICK_CANCELLED' } }]\n */\nexport type BrowserEffect = [`browser/${string}`, ...SExpr[]];\n\n/**\n * LLM effect - invokes an llm/* operator (agent path).\n * @example ['llm/generate', '@entity.request', { emit: { success: 'PLANNED', failure: 'PLAN_FAILED' } }]\n */\nexport type LlmEffect = [`llm/${string}`, ...SExpr[]];\n\n/**\n * Behavior effect - invokes a behavior/* operator (agent path).\n * @example ['behavior/instantiate', '@entity.plan', { emit: { failure: 'BUILD_FAILED' } }]\n */\nexport type BehaviorEffect = [`behavior/${string}`, ...SExpr[]];\n\n/**\n * Validate effect - invokes a validate/* operator (agent path).\n * @example ['validate/validate', '@entity.schema', { emit: { failure: 'INVALID' } }]\n */\nexport type ValidateEffect = [`validate/${string}`, ...SExpr[]];\n\n/**\n * Remaining agent-path operator effects: session/* (workspace session ops),\n * compose/* (schema composition), trace/* (trace emission), memory/*\n * (agent memory), application/* (app lifecycle). Expression-only namespaces\n * (array/, math/, object/, str/, …) are deliberately NOT effect heads.\n * @example ['session/write-spec', '@entity.spec']\n * @example ['compose/compose-all', { emit: { failure: 'COMPOSE_FAILED' } }]\n */\nexport type SessionEffect = [`session/${string}`, ...SExpr[]];\nexport type ComposeEffect = [`compose/${string}`, ...SExpr[]];\nexport type TraceEffect = [`trace/${string}`, ...SExpr[]];\nexport type MemoryEffect = [`memory/${string}`, ...SExpr[]];\nexport type ApplicationEffect = [`application/${string}`, ...SExpr[]];\n\n// ============================================================================\n// Async Effects (from almadar-std/modules/async)\n// ============================================================================\n\n/**\n * Async delay effect - wait then execute effects.\n * @example ['async/delay', 2000, ['emit', 'TIMEOUT']]\n */\nexport type AsyncDelayEffect = ['async/delay', number | string, ...Effect[]];\n\n/**\n * Async debounce effect - debounce then execute effect.\n * @example ['async/debounce', 300, ['emit', 'SEARCH_COMPLETE']]\n * @example ['async/debounce', '@entity.debounceMs', ['emit', 'SEARCH_COMPLETE']]\n */\nexport type AsyncDebounceEffect = ['async/debounce', number | string, SExpr];\n\n/**\n * Async throttle effect - throttle then execute effect.\n * @example ['async/throttle', 100, ['emit', 'SCROLL_HANDLED']]\n * @example ['async/throttle', '@entity.throttleMs', ['emit', 'SCROLL_HANDLED']]\n */\nexport type AsyncThrottleEffect = ['async/throttle', number | string, SExpr];\n\n/**\n * Async interval effect - execute effect at intervals.\n * @example ['async/interval', 1000, ['emit', 'TICK']]\n * @example ['async/interval', '@entity.intervalMs', ['emit', 'POLL_TICK']]\n */\nexport type AsyncIntervalEffect = ['async/interval', number | string, SExpr];\n\n/**\n * Async race effect - first effect to complete wins.\n * @example ['async/race', ['call', 'api1'], ['call', 'api2']]\n */\nexport type AsyncRaceEffect = ['async/race', ...Effect[]];\n\n/**\n * Async all effect - wait for all effects to complete.\n * @example ['async/all', ['call', 'api1'], ['call', 'api2']]\n */\nexport type AsyncAllEffect = ['async/all', ...Effect[]];\n\n/**\n * Async sequence effect - execute effects in sequence.\n * @example ['async/sequence', ['call', 'validate'], ['call', 'save']]\n */\nexport type AsyncSequenceEffect = ['async/sequence', ...Effect[]];\n\n/**\n * Union of all typed effects.\n * Provides compile-time validation for common effect types.\n */\nexport type TypedEffect =\n | RenderUIEffect\n | NavigateEffect\n | NavigateBackEffect\n | EmitEffect\n | SetEffect\n | PersistEffect\n | CallServiceEffect\n | SpawnEffect\n | DespawnEffect\n | DoEffect\n | FetchEffect\n | FetchStreamEffect\n | IfEffect\n | WhenEffect\n | LetEffect\n | LogEffect\n | WaitEffect\n | RefEffect\n | DerefEffect\n | SwapEffect\n | WatchEffect\n | AtomicEffect\n | AsyncDelayEffect\n | AsyncDebounceEffect\n | AsyncThrottleEffect\n | AsyncIntervalEffect\n | AsyncRaceEffect\n | AsyncAllEffect\n | AsyncSequenceEffect\n | ForwardEffect\n | TrainEffect\n | EvaluateEffect\n | CheckpointSaveEffect\n | CheckpointLoadEffect\n | AgentEffect\n | OsEffect\n | BrowserEffect\n | LlmEffect\n | BehaviorEffect\n | ValidateEffect\n | SessionEffect\n | ComposeEffect\n | TraceEffect\n | MemoryEffect\n | ApplicationEffect;\n\n// ============================================================================\n// Effect Type (Strictly Typed)\n// ============================================================================\n\n/**\n * Effect type - typed S-expression format.\n *\n * Effects are strongly typed tuples that enforce:\n * - Valid effect operators (render-ui, emit, set, persist, navigate, call-service)\n * - Valid UISlots for render-ui\n * - Valid PatternTypes and props for render-ui\n * - Correct argument types for each effect\n *\n * Available typed effects:\n * - RenderUIEffect: ['render-ui', UISlot, PatternConfig]\n * - NavigateEffect: ['navigate', path] or ['navigate', path, params]\n * - EmitEffect: ['emit', eventName] or ['emit', eventName, payload]\n * - SetEffect: ['set', binding, value]\n * - PersistEffect: ['persist', operation, entity, data?]\n * - CallServiceEffect: ['call-service', serviceName, config]\n *\n * @example\n * [\"set\", \"@entity.health\", 100]\n * [\"emit\", \"PLAYER_DIED\", { \"playerId\": \"@entity.id\" }]\n * [\"render-ui\", \"main\", { \"patternType\": \"entity-table\", \"columns\": [\"name\"] }]\n * [\"call-service\", \"WeatherAPI\", { \"action\": \"getWeather\", \"onSuccess\": \"OK\" }]\n * [\"navigate\", \"/tasks\"]\n * [\"persist\", \"create\", \"Task\", { \"title\": \"@payload.title\" }]\n */\nexport type Effect = TypedEffect;\n\n/**\n * The effects a server reports an outcome for on\n * `OrbitalEventResponse.effectResults` (`ServerEffectResult.effect`). Every\n * member is checked against the effect heads above at compile time, so a\n * name that is not an effect cannot be listed and a new server-reported\n * effect is added HERE only — the wire type, its zod twin and the\n * `events-wire` fixture case all derive from this array.\n */\nexport const SERVER_REPORTED_EFFECTS = [\n 'set',\n 'persist',\n 'call-service',\n 'fetch',\n 'fetch-stream',\n 'ref',\n 'deref',\n 'swap!',\n 'atomic',\n 'emit',\n] as const satisfies readonly Effect[0][];\n\nexport type ServerReportedEffect = (typeof SERVER_REPORTED_EFFECTS)[number];\n\n/** A namespaced effect head (`trace/emit`, `memory/store`, `llm/…`) — what a\n * `substrate` result's `name` carries. Derived from the union, never listed. */\nexport type NamespacedEffectName = Extract<Effect[0], `${string}/${string}`>;\n\n/**\n * Schema for Effect - validates S-expression format. Arguments validate as\n * s-expr-shaped DATA (`SExprDataSchema`) — literal data arrays (empty or\n * non-operator-headed) are valid argument values; the operator-head refine\n * applies to the effect itself, not to every argument.\n */\nexport const EffectSchema = z.array(SExprDataSchema).min(1).refine(\n (arr) => typeof arr[0] === 'string',\n { message: 'Effect must be an S-expression with a string operator as first element' }\n);\n\nexport type EffectInput = z.input<typeof EffectSchema>;\n\n/**\n * Type guard to check if a value is a valid Effect (S-expression).\n * \n * Validates that a value conforms to the Effect structure. Effects are\n * represented as arrays where the first element is a string (effect type)\n * and subsequent elements are parameters. Used for runtime validation\n * of effect structures.\n * \n * @param {RuntimeValue} value - Value to check\n * @returns {boolean} True if value is a valid Effect, false otherwise\n *\n * @example\n * isEffect(['set', '@entity.health', 100]); // returns true\n * isEffect('not-an-effect'); // returns false\n * isEffect([]); // returns false\n */\nexport function isEffect(value: RuntimeValue): value is Effect {\n return Array.isArray(value) && value.length > 0 && typeof value[0] === 'string';\n}\n\n/**\n * Alias for isEffect (for clarity when working with S-expressions)\n */\nexport const isSExprEffect = isEffect;\n\n// ============================================================================\n// Effect Builder Helpers\n// ============================================================================\n\n/**\n * Creates a set effect for state updates.\n * \n * Generates an effect that sets a binding to a value. Used in state\n * machine transitions to update entity fields, UI state, or other\n * mutable data.\n * \n * @param {string} binding - Target binding (e.g., '@entity.health')\n * @param {SExpr} value - Value to set (can be literal or expression)\n * @returns {Effect} Set effect array\n * \n * @example\n * set('@entity.health', 100); // returns [\"set\", \"@entity.health\", 100]\n * set('@state.loading', false); // returns [\"set\", \"@state.loading\", false]\n */\nexport function set(binding: string, value: SExpr): Effect {\n return ['set', binding, value];\n}\n\n/**\n * Creates an emit effect for event dispatching.\n * \n * Generates an effect that emits an event with optional payload.\n * Used in state machine transitions to trigger events that can be\n * handled by other traits, services, or external systems.\n * \n * @param {string} event - Event name to emit\n * @param {EventPayload} [payload] - Optional event payload\n * @returns {Effect} Emit effect array\n * \n * @example\n * emit('PLAYER_DIED', { playerId: '@entity.id' }); // returns [\"emit\", \"PLAYER_DIED\", { playerId: \"@entity.id\" }]\n * emit('GAME_STARTED'); // returns [\"emit\", \"GAME_STARTED\"]\n */\nexport function emit(event: string, payload?: EventPayload): Effect {\n return payload ? ['emit', event, payload] : ['emit', event];\n}\n\n/**\n * Creates a navigation effect for page routing.\n * \n * Generates an effect that navigates to a specified path with optional\n * parameters. Used in state machine transitions to change pages or\n * update URL parameters.\n * \n * @param {string} path - Target path (e.g., '/tasks')\n * @param {Record<string, string>} [params] - Optional URL parameters\n * @returns {NavigateEffect} Navigation effect array\n * \n * @example\n * navigate('/tasks'); // returns [\"navigate\", \"/tasks\"]\n * navigate('/user', { id: '123' }); // returns [\"navigate\", \"/user\", { id: \"123\" }]\n */\nexport function navigate(path: string): NavigateEffect;\nexport function navigate(path: string, params: Record<string, string>): NavigateEffect;\nexport function navigate(path: string, params: Record<string, string>, options: NavigateOptions): NavigateEffect;\nexport function navigate(path: string, params?: Record<string, string>, options?: NavigateOptions): NavigateEffect {\n if (params && options) return ['navigate', path, params, options];\n return params ? ['navigate', path, params] : ['navigate', path];\n}\n\n/**\n * Creates a navigate-back effect: pop the orbital's navigation stack and\n * navigate to the previous entry.\n *\n * @example\n * navigateBack(); // returns [\"navigate-back\"]\n */\nexport function navigateBack(): NavigateBackEffect {\n return ['navigate-back'];\n}\n\n/**\n * Create a render-ui effect\n * @example [\"render-ui\", \"main\", { \"patternType\": \"entity-table\", \"columns\": [\"name\"] }]\n */\nexport function renderUI(\n target: UISlot,\n pattern: AnyPatternConfig\n): RenderUIEffect;\nexport function renderUI(\n target: UISlot,\n pattern: AnyPatternConfig,\n props: ResolvedPatternProps\n): RenderUIEffect;\nexport function renderUI(\n target: UISlot,\n pattern: AnyPatternConfig,\n props?: ResolvedPatternProps\n): RenderUIEffect {\n return props\n ? ['render-ui', target, pattern, props]\n : ['render-ui', target, pattern];\n}\n\n/**\n * Create a persist effect\n * @example [\"persist\", \"create\", \"Task\", { \"title\": \"@payload.title\" }]\n */\nexport function persist(\n action: 'create' | 'update',\n entity: string,\n data: PersistData\n): PersistEffect;\nexport function persist(\n action: 'delete' | 'clear',\n entity: string,\n data?: PersistData\n): PersistEffect;\nexport function persist(\n action: 'create' | 'update' | 'delete' | 'clear',\n entity: string,\n data?: PersistData\n): PersistEffect {\n if (action === 'create' || action === 'update') {\n return ['persist', action, entity, data!] as PersistEffect;\n }\n return data\n ? ['persist', action, entity, data] as PersistEffect\n : ['persist', action, entity] as PersistEffect;\n}\n\n/**\n * Create a call-service effect\n * @example [\"call-service\", \"stripe\", { \"service\": \"stripe\", \"action\": \"charge\", \"onSuccess\": \"OK\", \"onError\": \"ERR\" }]\n */\nexport function callService(\n serviceName: string,\n config: CallServiceConfig\n): CallServiceEffect {\n return ['call-service', serviceName, config];\n}\n\n/**\n * Create a spawn effect (games)\n * @example [\"spawn\", \"Bullet\", { \"x\": \"@entity.x\", \"y\": \"@entity.y\" }]\n */\nexport function spawn(entity: string): SpawnEffect;\nexport function spawn(entity: string, initialState: EntityRow): SpawnEffect;\nexport function spawn(entity: string, initialState?: EntityRow): SpawnEffect {\n return initialState ? ['spawn', entity, initialState] : ['spawn', entity];\n}\n\n/**\n * Create a despawn effect (games)\n * @example [\"despawn\", \"@entity.id\"]\n */\nexport function despawn(entityId: string): DespawnEffect {\n return ['despawn', entityId];\n}\n\n/**\n * Create a do effect (multiple effects)\n * @example [\"do\", [\"set\", \"@entity.x\", 0], [\"set\", \"@entity.y\", 0]]\n */\nexport function doEffects(...effects: SExpr[]): DoEffect {\n return ['do', ...effects];\n}\n\n/**\n * Create a fetch effect (server-side data retrieval)\n * @example [\"fetch\", \"User\"] - fetch all users\n * @example [\"fetch\", \"User\", { \"id\": \"@payload.userId\" }] - fetch by ID\n * @example [\"fetch\", \"User\", { \"filter\": [\"=\", \"@entity.status\", \"active\"], \"limit\": 10 }]\n */\nexport function fetch(entity: string): FetchEffect;\nexport function fetch(entity: string, options: FetchOptions): FetchEffect;\nexport function fetch(entity: string, options?: FetchOptions): FetchEffect {\n return options ? ['fetch', entity, options] : ['fetch', entity];\n}\n\n// ============================================================================\n// Resource Effect Builder Helpers\n// ============================================================================\n\n/**\n * Create a ref effect (reactive entity subscription).\n *\n * @param {string} binding - Binding or entity name to subscribe to\n * @param {FetchOptions} [selector] - Optional selector for specific entity\n * @returns {RefEffect} Ref effect array\n *\n * @example\n * ref('@entity.health'); // returns [\"ref\", \"@entity.health\"]\n * ref('User', { id: '@payload.userId' }); // returns [\"ref\", \"User\", { id: \"@payload.userId\" }]\n */\nexport function ref(binding: string): RefEffect;\nexport function ref(binding: string, selector: FetchOptions): RefEffect;\nexport function ref(binding: string, selector?: FetchOptions): RefEffect {\n return selector ? ['ref', binding, selector] : ['ref', binding];\n}\n\n/**\n * Create a deref effect (snapshot read).\n *\n * @param {string} binding - Binding or entity name to read\n * @param {FetchOptions} [selector] - Optional selector for specific entity\n * @returns {DerefEffect} Deref effect array\n *\n * @example\n * deref('@entity.health'); // returns [\"deref\", \"@entity.health\"]\n * deref('User', { id: '@payload.userId' }); // returns [\"deref\", \"User\", { id: \"@payload.userId\" }]\n */\nexport function deref(binding: string): DerefEffect;\nexport function deref(binding: string, selector: FetchOptions): DerefEffect;\nexport function deref(binding: string, selector?: FetchOptions): DerefEffect {\n return selector ? ['deref', binding, selector] : ['deref', binding];\n}\n\n/**\n * Create a swap! effect (atomic compare-and-swap).\n *\n * @param {string} binding - Binding to atomically update\n * @param {SExpr} transform - Transformation expression applied to the current value\n * @returns {SwapEffect} Swap effect array\n *\n * @example\n * swap('@entity.counter', ['+', '@entity.counter', 1]);\n * // returns [\"swap!\", \"@entity.counter\", [\"+\", \"@entity.counter\", 1]]\n */\nexport function swap(binding: string, transform: SExpr): SwapEffect {\n return ['swap!', binding, transform];\n}\n\n/**\n * Create a watch effect (entity change callback).\n *\n * @example\n * watch('@entity.health', 'HEALTH_CHANGED');\n * watch('@entity.status', 'STATUS_UPDATED', { debounce: 100 });\n */\nexport function watch(binding: string, event: string): WatchEffect;\nexport function watch(binding: string, event: string, options: WatchOptions): WatchEffect;\nexport function watch(binding: string, event: string, options?: WatchOptions): WatchEffect {\n return options\n ? ['watch', binding, event, options]\n : ['watch', binding, event];\n}\n\n/**\n * Create an atomic effect (transaction group).\n *\n * @param {...SExpr[]} effects - Effects to execute atomically\n * @returns {AtomicEffect} Atomic effect array\n *\n * @example\n * atomic(['set', '@entity.x', 10], ['set', '@entity.y', 20]);\n * // returns [\"atomic\", [\"set\", \"@entity.x\", 10], [\"set\", \"@entity.y\", 20]]\n */\nexport function atomic(...effects: SExpr[]): AtomicEffect {\n return ['atomic', ...effects];\n}\n\n// ============================================================================\n// Runtime Pattern Types\n// ============================================================================\n\n/** Resolved pattern props for render-ui effects at runtime. Recursive for nested pattern configs. */\nexport type ResolvedPatternProps = {\n [prop: string]:\n | string\n | number\n | boolean\n | null\n | undefined\n | ResolvedPatternProps\n | RenderChildrenMap\n | Array<ResolvedPatternProps | RenderChildrenMap>;\n};\n\n/**\n * Zod twin of `PatternConfig`/`AnyPatternConfig` — validates the WIRE SHAPE\n * (a plain object, or `null` for an unset render-ui target) only. Per-pattern\n * prop shape (the hundreds of generated `PatternPropsMap` variants) is\n * enforced by the patterns registry at `orb validate` / lolo parse time, not\n * re-validated here — a second, drifting copy of that registry is exactly\n * the duplicate this schema must not become.\n */\nexport const PatternConfigSchema: z.ZodType<AnyPatternConfig | null> = z.custom<AnyPatternConfig | null>(\n (value) => value === null || (typeof value === 'object' && value !== null && !Array.isArray(value)),\n { message: 'Expected a pattern config object or null' },\n);\n\n/** Zod twin of `ResolvedPatternProps` — validates the wire shape (a plain object) only, see {@link PatternConfigSchema}. */\nexport const ResolvedPatternPropsSchema: z.ZodType<ResolvedPatternProps> = z.custom<ResolvedPatternProps>(\n (value) => typeof value === 'object' && value !== null && !Array.isArray(value),\n { message: 'Expected a resolved pattern props object' },\n);\n\n/** A node in a render-ui effect tree. */\nexport interface RenderUINode {\n type: string;\n props?: ResolvedPatternProps;\n /** Static child nodes and/or dynamic-collection map entries. A\n * {@link RenderChildrenMap} entry expands at render time into resolved\n * `RenderUINode`s, so components always receive a flat, fully-resolved list. */\n children?: Array<RenderUINode | RenderChildrenMap>;\n content?: string;\n entity?: string;\n renderItem?: RenderUINode;\n}\n\n","/**\n * Authenticated user context — what `@user.x` resolves against.\n *\n * The canonical shape for the `user` binding root, shared by both execution\n * paths: the JS interpreter resolves `@user.id` through\n * `EvaluationContext.user`, and the compiled shell emits `user?.id` against the\n * `UserContext` its `@app/shared` re-exports from here.\n *\n * `id` is the field the behavior library reads for ownership scoping and `role`\n * the field it reads for capability gating. Auth providers that name the subject\n * `uid` must normalize at their boundary — {@link normalizeUserContext} does that.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { FieldValueSchema, type FieldValue } from './entity.js';\n\n/** Authenticated user / agent identity behind `@user.x` bindings. */\nexport interface UserContext {\n /** Stable subject identifier. `@user.id` — the ownership key. */\n id: string;\n /** `@user.email` */\n email?: string;\n /** `@user.name` — display name. */\n name?: string;\n /** `@user.role` — single role string, compared against a policy's allowed list. */\n role?: string;\n /** `@user.permissions` — fine-grained capability strings. */\n permissions?: string[];\n /** Additional provider claims, readable as `@user.<claim>`. */\n [key: string]: FieldValue | undefined;\n}\n\n/**\n * The identity of an unauthenticated viewer. A resolvable object rather than\n * `undefined` so a role predicate evaluates to a definite `false` instead of\n * comparing against nothing.\n */\nexport const ANONYMOUS_USER: UserContext = {\n id: 'anonymous',\n role: 'anonymous',\n permissions: [],\n};\n\n/** Provider-shaped identity claims, before normalization. */\nexport interface RawUserClaims {\n id?: string;\n uid?: string;\n email?: string | null;\n name?: string;\n displayName?: string | null;\n role?: string;\n permissions?: string[];\n [key: string]: FieldValue | undefined;\n}\n\n/** Zod twin of `RawUserClaims` — the wire shape of `OrbitalEventRequest.user`. */\nexport const RawUserClaimsSchema: z.ZodType<RawUserClaims> = z\n .object({\n id: z.string().optional(),\n uid: z.string().optional(),\n email: z.string().nullable().optional(),\n name: z.string().optional(),\n displayName: z.string().nullable().optional(),\n role: z.string().optional(),\n permissions: z.array(z.string()).optional(),\n })\n .catchall(FieldValueSchema.optional());\n\n/** Claim keys {@link normalizeUserContext} derives rather than copies verbatim. */\nconst DERIVED_CLAIM_KEYS: readonly string[] = ['id', 'name', 'displayName', 'email'];\n\n/**\n * Normalize provider claims into a {@link UserContext}.\n *\n * Firebase (and most OIDC providers) name the subject `uid` and the display name\n * `displayName`, while every `.lolo` behavior reads `@user.id` / `@user.name`.\n * Without this normalization `@user.id` is `undefined` against a fully\n * authenticated request and every ownership filter silently matches no rows.\n * `uid` is preserved so `@user.uid` keeps working.\n *\n * Returns `undefined` for absent or subject-less claims so callers can\n * distinguish \"no auth ran\" from \"anonymous\"; use {@link ANONYMOUS_USER} where a\n * definite identity is required.\n */\nexport function normalizeUserContext(\n claims: RawUserClaims | null | undefined,\n): UserContext | undefined {\n if (!claims) return undefined;\n const id = claims.id ?? claims.uid;\n if (typeof id !== 'string' || id.length === 0) return undefined;\n\n const user: UserContext = { id };\n for (const [key, value] of Object.entries(claims)) {\n if (value === undefined || DERIVED_CLAIM_KEYS.includes(key)) continue;\n user[key] = value;\n }\n\n const name = claims.name ?? claims.displayName;\n if (typeof name === 'string' && name.length > 0) user.name = name;\n if (typeof claims.email === 'string' && claims.email.length > 0) user.email = claims.email;\n\n return user;\n}\n\n/**\n * Turn a row of an app's `[identity]` entity into a viewer.\n *\n * There is no separate persona shape: an identity row IS the persona\n * (`Almadar_LOLO_Identity.md` §4.3), so this only guards the one field the\n * behavior library requires — a non-empty string `id` — and passes every other\n * declared field through as a `@user.<field>` claim. Rows without a usable id\n * yield `undefined` rather than a persona nobody can own rows as.\n */\nexport function personaFromIdentityRow(\n row: Record<string, FieldValue | undefined>,\n): UserContext | undefined {\n const id = row['id'];\n if (typeof id !== 'string' || id.length === 0) return undefined;\n const persona: UserContext = { id };\n for (const [key, value] of Object.entries(row)) {\n if (key === 'id' || value === undefined) continue;\n persona[key] = value;\n }\n return persona;\n}\n\n/**\n * The viewer a host presents when nothing named one.\n *\n * Without this, `@user` is `Null` in headless verify and preview, so every\n * `viewerName: @user.name` binding renders blank and the account menu never\n * appears — an app that cannot say who you are. Worse, an ownership filter that\n * works and one that is broken both render an empty table.\n *\n * `role` is deliberately EMPTY, not a guess. A default of `admin` would silently\n * flip which branch renders at the 38 `@user.role` comparisons in the corpus;\n * an empty role matches no literal, exactly as `Null` did, so this fixes\n * \"undefined at runtime\" without changing a single guard outcome.\n */\nexport const DEFAULT_VIEWER: UserContext = {\n id: 'viewer-1',\n name: 'Dev Viewer',\n email: 'viewer@example.com',\n role: '',\n};\n\n/**\n * The viewer to present an app as when nothing named one.\n *\n * `DEFAULT_VIEWER` is synthetic — `viewer-1` is in no app's roster — so under it\n * every ownership predicate (`@entity.<owner> == @user.id`) matches zero rows and\n * a correctly-scoped app renders empty tables everywhere. That is indistinguishable\n * on screen from a broken filter, which is exactly the failure DEFAULT_VIEWER's own\n * comment warns about.\n *\n * So when the app declares an `[identity]` roster, the default viewer is a REAL\n * member of it. `DEFAULT_VIEWER` remains the fallback for apps that declare no\n * identity entity, where there is nobody to be.\n *\n * Both execution paths share this rule; the Rust twin is\n * `orbital-core::runtime::persona::resolve_default_viewer`.\n */\nexport function resolveDefaultViewer(roster: readonly UserContext[]): UserContext {\n return roster.length > 0 ? (roster[0] as UserContext) : DEFAULT_VIEWER;\n}\n\n/** Look a persona up in a roster by id, or by role when no id matches. */\nexport function findPersonaInRoster(\n roster: readonly UserContext[],\n idOrRole: string,\n): UserContext | undefined {\n return (\n roster.find((p) => p.id === idOrRole) ??\n roster.find((p) => p.role === idOrRole)\n );\n}\n\n/**\n * Resolve a persona spec — a bare id/role (`Person Id 3`, `moderator`) or a full\n * JSON `UserContext` — into a viewer. This is the `ALMADAR_PERSONA` contract,\n * shared by every host that presents an app as somebody.\n *\n * The roster is the app's OWN declared personas — the seeded rows of its\n * `[identity]` entity (`Almadar_LOLO_Identity.md` §4.3) — supplied by the host\n * that has them in hand (the runtime's live store on the interpreter path, the\n * schema-derived seed rows on the compiled path). There is no global roster:\n * an app without an `[identity]` entity resolves only JSON-form specs.\n *\n * Throws on anything unresolvable rather than returning `undefined`: \"no persona\"\n * and \"persona silently ignored\" look identical on screen, so a bad spec must\n * fail at boot instead of rendering as nobody.\n */\nexport function resolvePersonaSpec(spec: string, roster: readonly UserContext[]): UserContext {\n const raw = spec.trim();\n if (!raw.startsWith('{')) {\n const declared = findPersonaInRoster(roster, raw);\n if (!declared) {\n const known = roster.map((p) => `${p.id}/${p.role ?? '-'}`).join(', ');\n throw new Error(\n `Persona \"${raw}\" is not a declared persona id or role. ` +\n (roster.length > 0\n ? `Known: ${known}`\n : 'This app declares no [identity] entity, so only the JSON persona form is accepted.'),\n );\n }\n return declared;\n }\n let claims: RawUserClaims;\n try {\n claims = JSON.parse(raw);\n } catch {\n throw new Error(`Persona is not valid JSON: ${raw}`);\n }\n const user = normalizeUserContext(claims);\n if (!user) {\n throw new Error(`Persona needs an \"id\" (or \"uid\"): ${raw}`);\n }\n return user;\n}\n\n// ============================================================================\n// Dev identity token\n// ============================================================================\n\n/**\n * Marks a bearer token as a mocked dev identity rather than a real ID token.\n * The prefix is deliberately unmistakable: a server accepts these ONLY behind an\n * explicit dev opt-in, so a production deployment rejects them like any other\n * malformed token.\n */\nexport const DEV_TOKEN_PREFIX = 'almadar-dev.';\n\n/**\n * Encode a viewer as a dev bearer token.\n *\n * Carries the WHOLE identity, not just the subject: real Firebase claims have no\n * `role`, so a server that only reads `uid` leaves every `@user.role` gate inert\n * even for a signed-in user. URI-encoded JSON keeps the token header-safe (no\n * spaces or delimiters) and works unchanged in Node and the browser.\n */\nexport function encodeDevIdentityToken(user: UserContext): string {\n return DEV_TOKEN_PREFIX + encodeURIComponent(JSON.stringify(user));\n}\n\n/**\n * Decode a dev bearer token back into a viewer, or `undefined` if it is not one\n * / is malformed — callers fail closed rather than inventing an identity.\n */\nexport function decodeDevIdentityToken(token: string): UserContext | undefined {\n if (!token.startsWith(DEV_TOKEN_PREFIX)) return undefined;\n try {\n const claims: RawUserClaims = JSON.parse(\n decodeURIComponent(token.slice(DEV_TOKEN_PREFIX.length)),\n );\n return normalizeUserContext(claims);\n } catch {\n return undefined;\n }\n}\n","/**\n * Server-side effect result — the wire shape a server-executed effect\n * (`SERVER_REPORTED_EFFECTS` in `effect.ts`) reports back to the client,\n * closing the circuit on `OrbitalEventResponse.effectResults`.\n *\n * Promoted from `@almadar/runtime`'s `ServerEffectHandlers.ts` (the JS\n * interpreter's own definition, canonical per `CLAUDE.md`'s \"converge on\n * the TypeScript implementation\" ruling) so `@almadar/core` owns the one\n * shape both execution paths report against.\n *\n * @packageDocumentation\n */\n\nimport { z } from 'zod';\nimport { EntityRowSchema, type EntityRow } from './entity.js';\nimport { SERVER_REPORTED_EFFECTS, type ServerReportedEffect, type NamespacedEffectName } from './effect.js';\nimport { EventPayloadValueSchema, type EventPayloadValue } from './expression.js';\n\n/**\n * Result entry recorded for each effect invocation. Mirrors the server\n * runtime's `EffectResult`. Callers who want telemetry pass an array that\n * the factory appends to; otherwise it's unused.\n */\nexport interface ServerBatchSummary {\n operations: EntityRow[];\n completedCount: number;\n totalCount: number;\n}\n\n/** Zod twin of `ServerBatchSummary`. */\nexport const ServerBatchSummarySchema: z.ZodType<ServerBatchSummary> = z.object({\n operations: z.array(EntityRowSchema),\n completedCount: z.number(),\n totalCount: z.number(),\n});\n\nexport interface ServerEffectResult {\n /**\n * The reported effect's head (`SERVER_REPORTED_EFFECTS`, derived from the\n * effect union in `effect.ts`), or `\"substrate\"` — the one wire grouping\n * for the namespaced operators (`trace/*`, `memory/*`, `session/*`,\n * `behavior/*`, `compose/*`), whose head rides `name`.\n */\n effect: ServerReportedEffect | \"substrate\";\n action?: string;\n entityType?: string;\n /** The invoked namespaced operator (e.g. `\"memory/store\"`), set only on `effect: \"substrate\"`. */\n name?: NamespacedEffectName;\n /** Entity row for CRUD/set/swap, the batch summary for `persist batch`, the raw service/substrate result. */\n data?: EntityRow | ServerBatchSummary | EventPayloadValue;\n success: boolean;\n /**\n * Set when a persist failed because an access policy rejected it or the\n * write resolved no row key — mirrors `OrbitalServerRuntime.EffectResult`\n * so the offline-preview and real-server persist paths report the same\n * denial discriminator to the verification trace.\n */\n denied?: true;\n error?: string;\n /** Coded failure reason for a persist that resolved no target row. */\n code?: \"not-found\" | \"no-row-key\";\n}\n\n/** Zod twin of `ServerEffectResult`. */\nexport const ServerEffectResultSchema: z.ZodType<ServerEffectResult> = z.object({\n effect: z.union([z.enum(SERVER_REPORTED_EFFECTS), z.literal(\"substrate\")]),\n action: z.string().optional(),\n entityType: z.string().optional(),\n name: z.custom<NamespacedEffectName>((v) => typeof v === \"string\" && /^[^/]+\\/.+$/.test(v)).optional(),\n data: z.union([EntityRowSchema, ServerBatchSummarySchema, EventPayloadValueSchema]).optional(),\n success: z.boolean(),\n denied: z.literal(true).optional(),\n error: z.string().optional(),\n code: z.enum([\"not-found\", \"no-row-key\"]).optional(),\n});\n","/**\n * Bus Event Types (framework concept)\n *\n * Canonical event shape for Almadar's cross-package event bus. Hoisted into\n * `@almadar/core` so `@almadar/ui`, `@almadar/runtime`, and generated code\n * all agree on the same structure. Replaces the previously divergent\n * `KFlowEvent` (ui) and `RuntimeEvent` (runtime) definitions.\n *\n * @packageDocumentation\n */\n\nimport { z } from \"zod\";\nimport { EventPayloadSchema, type EventPayload } from \"./expression.js\";\nimport { OrbitalIdSchema, TraitIdSchema, EventIdSchema, type OrbitalId, type TraitId, type EventId } from \"./identity.js\";\nimport { EntityRowSchema, type EntityRow } from \"./entity.js\";\nimport { PatternConfigSchema, ResolvedPatternPropsSchema, type PatternConfig, type ResolvedPatternProps } from \"./effect.js\";\nimport { RawUserClaimsSchema, type RawUserClaims } from \"./user.js\";\nimport { ServerEffectResultSchema, type ServerEffectResult } from \"./effect-result.js\";\n\n/**\n * Declared event key. A trait's event names (INIT, SAVE, CLOSE,\n * CONFIRM_REMOVE, ...) flow through the orbital schema and the UI as\n * strings; this alias marks \"this string is a declared event key, not\n * arbitrary text.\"\n *\n * Component props typed as `EventKey` are detected by the pattern-sync\n * tool (`tools/almadar-pattern-sync/parser.ts`) via a TS-type lookup and\n * marked as `kind: \"event\"` in the patterns registry\n * (`@almadar/patterns`). Consumers of the registry — the Rust compiler's\n * inline phase and the `@almadar/runtime` preprocess — read that marker\n * to apply call-site `events: { OLD: NEW }` renames to render-ui trees\n * without name-matching heuristics.\n *\n * Plain alias over `string`. Not branded because event keys originate\n * from user data at runtime (orb schema literals, bus emits), so cast\n * friction would buy nothing. The value of the alias is at the type\n * surface — it's a marker the pattern-sync tool can find via\n * `getSymbolAtLocation`.\n */\nexport type EventKey = string;\n\n/**\n * Phantom-typed brand for declarative bus-emit props on UI components.\n *\n * Used by component authors to BOTH mark a prop as a bus-event reference\n * AND document the payload shape that the component will fire onto the\n * bus when that prop is bound. Authors write:\n *\n * // Tabs.tsx\n * export interface TabsProps {\n * tabChangeEvent?: EventEmit<{ tabId: string }>;\n * }\n *\n * Consumers see only the structural `string` (no UX impact: passing a\n * literal `\"TAB_CHANGED\"` keeps working). The phantom `P` parameter\n * carries the bus-payload schema at the type level for pattern-sync to\n * extract.\n *\n * Pattern-sync (`tools/almadar-pattern-sync/parser.ts`) detects this\n * brand via TS type-lookup (mirrors how it detects `EventKey`) and\n * writes two registry fields per prop:\n * - `kind: \"event-ref\"` — the discriminant rules read in lolo / orb\n * validator to know \"this prop's string value is a bus event name.\"\n * - `emitPayloadSchema` — the structural shape of `P`, serialized as\n * the same JSON-Schema-shaped record Almadar uses for trait\n * `payloadSchema`. Validator rules cross-check this against the\n * trait's declared `emits { EVENT { ... } }` payload to catch mismatches\n * at parse / validate time instead of runtime.\n *\n * Example payload bus emission inside the component (no wrapper —\n * `EventEmit<P>` erases to `string`):\n *\n * if (tabChangeEvent) eventBus.emit(`UI:${tabChangeEvent}`, { tabId });\n *\n * The brand is structurally an unused optional readonly property; TS\n * never asks for it at construction, so authors and consumers never\n * see it.\n */\nexport type EventEmit<P> = string & { readonly __emitPayload?: P };\n\n/**\n * Phantom-typed brand for declarative bus-listen props on UI components.\n *\n * Mirror of `EventEmit<P>`. Used by future patterns where a UI component\n * subscribes to a bus event and forwards its payload upward via prop\n * (e.g. an editor pattern that listens for `EXTERNAL_RESET` and exposes\n * the consumed payload to the parent). Pattern-sync detects this brand\n * the same way as `EventEmit<P>` and writes:\n * - `kind: \"event-listen\"` (or a sub-discriminant of `event-ref`)\n * - `listenPayloadSchema` with the structural shape of `P`\n *\n * Validator rules use this to verify the trait the prop is bound to\n * actually emits a payload of the expected shape.\n *\n * Reserved for symmetry; no @almadar/ui component uses it as of this\n * commit. Add usages incrementally as patterns require them.\n */\nexport type EventListen<P> = string & { readonly __listenPayload?: P };\n\n// NOTE: The phantom entity-inlet brands `EntityInlet`/`EntityRecord`/\n// `EntityCollection` were removed in the entity-row clean slate. There is now\n// ONE entity type — `EntityRow` (`./entity`), used directly: a single record is\n// `EntityRow`, a collection is `readonly EntityRow[]`. pattern-sync detects an\n// entity prop by the `EntityRow` type identity and derives record-vs-collection\n// from array-vs-not, so no brand is needed.\n\n/**\n * Identifies the origin of a bus event. Used by cross-trait listeners to\n * filter emits from specific orbitals, traits, transitions, or ticks.\n *\n * `transition` and `tick` are optional runtime-internal details; most\n * consumers only care about `orbital` and `trait`.\n */\nexport interface BusEventSource {\n orbital?: string;\n /** V4 dual-carry id sibling of `orbital` — stable across an orbital rename. */\n orbitalId?: OrbitalId;\n trait?: string;\n /** V4 dual-carry id sibling of `trait` — stable across a trait rename. */\n traitId?: TraitId;\n /** V4 dual-carry id of the emitted event — stable across an event rename. */\n eventId?: EventId;\n transition?: string;\n tick?: string;\n /**\n * True when the orbital bridge re-broadcasts an event onto the bus\n * (any source — both echoes of the dispatched event and server-side\n * cascade emits via `(emit X)` / `fetch.emit.success`). Cross-trait\n * listeners filter on this flag so the click-time qualified emit\n * (which has no `fromBridge`) doesn't double-fire alongside the\n * post-server bridge confirmation. See `dispatched` for the narrower\n * \"echo of the just-dispatched event\" signal.\n */\n fromBridge?: boolean;\n /**\n * True ONLY for bridge echoes the receiving tab already processed, so\n * the originating trait's self-subscription skips them instead of\n * re-dispatching its own echo (infinite loop / double execution).\n * Set by path 1 of useOrbitalBridge (compiled shell — echo of the\n * just-dispatched event; server-side cascade emits there carry\n * `fromBridge: true` but NOT `dispatched`, so they still reach the\n * source trait's transition handler, e.g. `loading -> browsing` on a\n * fetch's `emit.success`) and by ServerBridge (runtime path — stamped\n * on exactly one response-cascade echo per event the dispatch delivered\n * locally on the bare key, `stampLocallyDeliveredEchoes`; server-only\n * results stay unstamped). Cross-trait `listens` never filter on this\n * flag, so their delivery is unaffected. Push-leg events from OTHER\n * tabs (multiplayer) are never stamped.\n */\n dispatched?: boolean;\n /**\n * The client that originated the dispatch whose effects emitted this\n * event (from `OrbitalEventRequest.clientId`); absent for headless\n * dispatches (ticks, circuit-router probes, walkers). The server-side\n * listens fan-out skips client-originated cascade emits — under dual\n * execution the originating client relays every cascade hop through the\n * bridge itself, so the server dispatching the same hop double-ran it\n * (one Send persisted two rows). Headless topology keeps the fan-out:\n * there is no client to drive the circuit.\n */\n originClientId?: string;\n}\n\n// The third type param is `object` on schemas nesting a branded-id\n// `.refine(<type predicate>)` field: the refine's parsed INPUT is a plain\n// `string`, not the branded output type, so the input/output-equal default\n// `z.ZodType<T>` mis-typechecks. `object` is what the wire actually carries\n// (a JSON body) — never `unknown`.\n\n/** Zod twin of `BusEventSource`. */\nexport const BusEventSourceSchema: z.ZodType<BusEventSource, z.ZodTypeDef, object> = z.object({\n orbital: z.string().optional(),\n orbitalId: OrbitalIdSchema.optional(),\n trait: z.string().optional(),\n traitId: TraitIdSchema.optional(),\n eventId: EventIdSchema.optional(),\n transition: z.string().optional(),\n tick: z.string().optional(),\n fromBridge: z.boolean().optional(),\n dispatched: z.boolean().optional(),\n originClientId: z.string().optional(),\n});\n\n/**\n * An event flowing on the bus.\n *\n * The `source` field is structured so cross-trait listeners can match\n * `event.source?.orbital === 'X' && event.source?.trait === 'Y'` without\n * parsing a delimiter.\n */\nexport interface BusEvent {\n /** Event type identifier (e.g., 'CartItemLoaded', 'TASK_COMPLETED') */\n type: EventKey;\n /** Optional structured payload */\n payload?: EventPayload;\n /** Timestamp when the event was emitted */\n timestamp: number;\n /** Optional origin info for filtering */\n source?: BusEventSource;\n}\n\n/** Bus event listener callback. */\nexport type BusEventListener = (event: BusEvent) => void;\n\n/** Returned by `on()` / `once()` to detach a listener. */\nexport type Unsubscribe = () => void;\n\n/**\n * One event a transition's effects emitted, carried back to the client to\n * re-dispatch (in order) so the state machine advances through the\n * cascade without server-side recursion. Named/shaped to match the\n * generated compiled-path `EmittedEvent` (orbital-shell-typescript's\n * `shared/types.ts`) so the two execution paths agree on one shape.\n */\nexport interface EmittedEvent {\n event: string;\n payload?: EventPayload;\n source?: BusEventSource;\n}\n\n/** Zod twin of `EmittedEvent`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const EmittedEventSchema: z.ZodType<EmittedEvent, z.ZodTypeDef, object> = z.object({\n event: z.string(),\n payload: EventPayloadSchema.optional(),\n source: BusEventSourceSchema.optional(),\n});\n\n// ============================================================================\n// Client-effect wire grammar\n// ============================================================================\n\n/**\n * Client-side effect tuple shipped in `OrbitalEventResponse.clientEffects`.\n * Restricted to the effect kinds the client knows how to apply to the\n * UI: render-ui (slot mutation, including the `toast` slot that carries\n * what used to be the separate notify effect) and navigate (route change).\n * Server-only effects (persist, set, fetch, ...) execute on the server and\n * surface their results via `effectResults` and `emittedEvents`, not here.\n *\n * Shape note: the wire form is broader than `RenderUIEffect` /\n * `NavigateEffect` from `@almadar/core/types/effect.ts` in two places — the\n * runtime appends an interpolated `props` object plus an optional `priority`\n * slot to render-ui (slot 4 + 5), and `navigate`'s optional argument may\n * surface as `undefined` rather than absent. The local union spells those\n * variants out explicitly so consumers (ServerBridge.tsx parser, debugger\n * inspector) get accurate completions instead of `unknown[]`.\n *\n * `slot` is a plain `string` in this wire shape (not `UISlot`'s literal\n * union) because the runtime forwards the raw string from the trait's\n * `(render-ui slot ...)` SExpr without re-validating against the registry —\n * registry validation lives in `orbital validate` / `lolo` parse, not here.\n */\nexport type ClientRenderUITuple =\n | ['render-ui', string, PatternConfig | null]\n | ['render-ui', string, PatternConfig | null, ResolvedPatternProps]\n | ['render-ui', string, PatternConfig | null, ResolvedPatternProps | undefined, number | undefined];\n\nexport type ClientNavigateTuple =\n | ['navigate', string]\n | ['navigate', string, Record<string, string> | undefined]\n | ['navigate', string, Record<string, string> | undefined, { crumb?: string }];\n\nexport type ClientNavigateBackTuple = ['navigate-back'];\n\nexport type ClientEffectTuple =\n | ClientRenderUITuple\n | ClientNavigateTuple\n | ClientNavigateBackTuple;\n\n/** Zod twin of `ClientRenderUITuple` — one variant per fixed arity (3/4/5), unioned. */\nexport const ClientRenderUITupleSchema = z.union([\n z.tuple([z.literal('render-ui'), z.string(), PatternConfigSchema]),\n z.tuple([z.literal('render-ui'), z.string(), PatternConfigSchema, ResolvedPatternPropsSchema]),\n z.tuple([\n z.literal('render-ui'),\n z.string(),\n PatternConfigSchema,\n ResolvedPatternPropsSchema.optional(),\n z.number().optional(),\n ]),\n]);\n\n/** Zod twin of `ClientNavigateTuple` — one variant per fixed arity (2/3/4), unioned. */\nexport const ClientNavigateTupleSchema = z.union([\n z.tuple([z.literal('navigate'), z.string()]),\n z.tuple([z.literal('navigate'), z.string(), z.record(z.string()).optional()]),\n z.tuple([\n z.literal('navigate'),\n z.string(),\n z.record(z.string()).optional(),\n z.object({ crumb: z.string().optional() }),\n ]),\n]);\n\n/** Zod twin of `ClientNavigateBackTuple`. */\nexport const ClientNavigateBackTupleSchema = z.tuple([z.literal('navigate-back')]);\n\n/** Zod twin of `ClientEffectTuple`. */\nexport const ClientEffectTupleSchema: z.ZodType<ClientEffectTuple> = z.union([\n ClientRenderUITupleSchema,\n ClientNavigateTupleSchema,\n ClientNavigateBackTupleSchema,\n]);\n\n// ============================================================================\n// Event dispatch wire (single owner — canonical = the TS runtime)\n// ============================================================================\n\n/**\n * Client → server event dispatch request. The single upstream owner of\n * this shape — both the JS interpreter (`@almadar/runtime`'s\n * `OrbitalEventRequest`) and the compiled path's generated `EventRequest`\n * (orbital-shell-typescript's `shared/types.ts`, mirrored 1:1 in\n * `orbital-core`) carry the same fields, so the two execution paths cannot\n * drift.\n */\nexport interface OrbitalEventRequest {\n event: string;\n /**\n * V4 dual-carry id sibling of `event` — the fired event's id, when known\n * (e.g. threaded from a `listens[].triggersId`). Optional; absent means\n * the state machine dispatches by name only (legacy).\n */\n eventId?: EventId;\n payload?: EventPayload;\n entityId?: string;\n /**\n * Scoped-listen delivery: dispatch to THIS trait only. A listens-matched\n * trigger is addressed to the listening trait; without this, a trigger\n * renamed to INIT broadcast orbital-wide and re-ran every trait's\n * initializer (R-SCOPED-LISTEN-INIT-RENAME-FREEZE re-fire cascade).\n */\n targetTrait?: string;\n /** Provider claims for `@user` bindings, normalized by `normalizeUserContext`. */\n user?: RawUserClaims;\n /** Per-tab client identity (UUID) — excludes this request's origin from live-broadcast delivery. */\n clientId?: string;\n /**\n * Broadcast-class marker (T6, docs/Almadar_Tick_Loop.md §3a): the name of\n * the tick that emitted this event. Tick-stamped dispatches are\n * latest-state broadcasts — the client fires them without awaiting the\n * response, and the server relays them to OTHER tabs coalesced\n * (newest-per-key) at a snapshot rate instead of 1:1.\n */\n tick?: string;\n /** Emitting trait for a tick-stamped dispatch — builds the relay's BusEventSource (sourceless emits are dropped client-side). */\n sourceTrait?: string;\n /**\n * Stateless addressing: the traits this dispatch runs against, each with\n * the scope it dispatches `from` (a single-element array is the common\n * case; a listens fan-out that crosses traits carries more than one). The\n * compiled server is stateless-per-trait too (`handlers.rs:510-532` seeds\n * state from `currentState`) — this generalizes that mechanism instead of\n * the retired single `currentState`/`fields` pair.\n */\n traits?: Array<{ trait: string; from: string }>;\n /**\n * The dispatching traits' current `@entity` frames (declared defaults <\n * fetched row < `[shared]` frame), keyed by trait name. The server layers\n * each row over the one it resolves via `resolveEntityView` so guards and\n * effects read the same values the client does.\n */\n entityByTrait?: Record<string, EntityRow>;\n /** The orbital/behavior name this dispatch targets, for stateless multi-orbital addressing. */\n behavior?: string;\n}\n\n/** Structured reason one trait (or the whole dispatch) did not transition. */\nexport type TransitionRejectionCode =\n | 'no-matching-transition'\n | 'guard-rejected'\n | 'no-dispatchable-traits';\n\n/**\n * Why a dispatched trait (or the whole request) did not transition —\n * G-RUNTIME-023. `statesDeclaringEvent` lists the states whose transition\n * table DOES declare the event, which makes a stale client-supplied `from`\n * self-explanatory in a stateless response.\n */\nexport interface TransitionRejection {\n code: TransitionRejectionCode;\n trait?: string;\n from?: string;\n event?: string;\n statesDeclaringEvent?: string[];\n transition?: string;\n guard?: unknown;\n}\n\n/**\n * Server → client event dispatch response. Mirrors the compiled path's\n * generated `EventResponse` (orbital-shell-typescript's `shared/types.ts`,\n * mirrored 1:1 in `orbital-core`'s `effects/response.rs`) — canonical = the\n * TS runtime's `OrbitalEventResponse` (`@almadar/runtime`'s\n * `OrbitalServerRuntime.ts`).\n */\nexport interface OrbitalEventResponse {\n success: boolean;\n transitioned: boolean;\n /** Whole-orbital state snapshot, keyed by trait name. */\n states: Record<string, string>;\n /**\n * Events emitted during processing, in declaration order. ALWAYS present\n * (`[]` when none) — the compiled Hono path used to omit this field on a\n * no-cascade response, which forced every consumer to optional-chain a\n * field that is really always there.\n *\n * Each entry carries a `source: BusEventSource` so the client-side\n * ServerBridge can re-broadcast on the qualified `UI:Orbital.Trait.EVENT`\n * bus key. Without source the re-broadcast skips the entry and downstream\n * listeners (e.g. ContactBrowse waiting for ContactLoaded after a fetch)\n * never fire — the dashboard-layout that ContactLoaded renders disappears.\n */\n emittedEvents: EmittedEvent[];\n /** Fetched/queried entity collections this response carries, keyed by entity name. */\n data?: Record<string, EntityRow[]>;\n /**\n * `@entity` fields this transition's server-side `set` effects wrote,\n * post-effect, keyed by trait name — the response-side twin of the\n * request's `entityByTrait`. The client merges them over its own effect\n * results (server wins).\n */\n entityByTrait?: Record<string, EntityRow>;\n /** Client-side effects to execute (render-ui, navigate). */\n clientEffects?: ClientEffectTuple[];\n /**\n * Same effects as `clientEffects`, paired with the producing trait name.\n * Consumers that need per-trait attribution (e.g. `<TraitFrame>` resolving\n * `@trait.X` bindings) read from this field; legacy consumers ignore it\n * and continue with the flat `clientEffects` array unchanged.\n *\n * Same length and ordering as `clientEffects`; entries are 1:1 by index.\n */\n clientEffectsByTrait?: Array<{ traitName: string; effect: ClientEffectTuple }>;\n /** Results from server-side effects (persist, call-service, set). */\n effectResults?: ServerEffectResult[];\n /** Guard that failed, addressed as `\"<Trait>.<event>\"`, for debugging. */\n guardFailed?: string;\n /**\n * Structured per-trait / per-request rejection reasons (G-RUNTIME-023) —\n * present only when nothing transitioned. Supersedes the `guardFailed`\n * string (kept for backcompat) with a machine-readable shape.\n */\n rejections?: TransitionRejection[];\n /**\n * Names of traits DROPPED from a stateless cascade because the cross-trait\n * worklist hit its safety-valve cap (G-RUNTIME-027) — the response's\n * states/effects/entity rows are INCOMPLETE for these traits. Absent when\n * the whole worklist ran. Surfaced so the truncation is observable\n * (previously the tail of any page over ~20 traits silently never\n * executed).\n */\n cascadeTruncated?: string[];\n error?: string;\n}\n\n/** Zod twin of `OrbitalEventRequest`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const OrbitalEventRequestSchema: z.ZodType<OrbitalEventRequest, z.ZodTypeDef, object> = z.object({\n event: z.string(),\n eventId: EventIdSchema.optional(),\n payload: EventPayloadSchema.optional(),\n entityId: z.string().optional(),\n targetTrait: z.string().optional(),\n user: RawUserClaimsSchema.optional(),\n clientId: z.string().optional(),\n tick: z.string().optional(),\n sourceTrait: z.string().optional(),\n traits: z.array(z.object({ trait: z.string(), from: z.string() })).optional(),\n entityByTrait: z.record(EntityRowSchema).optional(),\n behavior: z.string().optional(),\n});\n\n/** Zod twin of `OrbitalEventResponse`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const OrbitalEventResponseSchema: z.ZodType<OrbitalEventResponse, z.ZodTypeDef, object> = z.object({\n success: z.boolean(),\n transitioned: z.boolean(),\n states: z.record(z.string()),\n emittedEvents: z.array(EmittedEventSchema),\n data: z.record(z.array(EntityRowSchema)).optional(),\n entityByTrait: z.record(EntityRowSchema).optional(),\n clientEffects: z.array(ClientEffectTupleSchema).optional(),\n clientEffectsByTrait: z\n .array(z.object({ traitName: z.string(), effect: ClientEffectTupleSchema }))\n .optional(),\n effectResults: z.array(ServerEffectResultSchema).optional(),\n guardFailed: z.string().optional(),\n rejections: z\n .array(\n z.object({\n code: z.enum(['no-matching-transition', 'guard-rejected', 'no-dispatchable-traits']),\n trait: z.string().optional(),\n from: z.string().optional(),\n event: z.string().optional(),\n statesDeclaringEvent: z.array(z.string()).optional(),\n transition: z.string().optional(),\n guard: z.unknown().optional(),\n }),\n )\n .optional(),\n cascadeTruncated: z.array(z.string()).optional(),\n error: z.string().optional(),\n});\n\n// ============================================================================\n// Register wire (client → server schema registration)\n// ============================================================================\n\n/**\n * Where circuit state lives between events (`docs/Almadar_Runtime_Stateless_Stateful_PLAN.md` §1a):\n * `'stateless'` = the client carries it on every request, `'stateful'` = the server holds it.\n */\nexport type ServerTopology = 'stateless' | 'stateful';\n\nexport const ServerTopologySchema = z.enum(['stateless', 'stateful']);\n\n/** `POST /register` response. `topology` absent = a server that predates the declaration. */\nexport interface OrbitalRegisterResponse {\n success: boolean;\n topology?: ServerTopology;\n message?: string;\n orbitals?: string[];\n error?: string;\n}\n\nexport const OrbitalRegisterResponseSchema: z.ZodType<OrbitalRegisterResponse, z.ZodTypeDef, object> = z.object({\n success: z.boolean(),\n topology: ServerTopologySchema.optional(),\n message: z.string().optional(),\n orbitals: z.array(z.string()).optional(),\n error: z.string().optional(),\n});\n\n// ============================================================================\n// Live broadcast wire (server → other connected clients)\n// ============================================================================\n\n/**\n * One persist-envelope success emit, handed to the live-broadcast sink\n * (`OrbitalServerRuntime.setLiveBroadcastSink`) and relayed to every OTHER\n * connected client. Fired only from the `persist` effect's `emit:{success}`\n * envelope (batch and single-op) — never from the generic emit funnel — so\n * transport layers can fan it out without matching on event names. Promoted\n * from `@almadar/runtime`'s own `LiveBroadcastItem` (canonical per Program\n * A's \"converge on the TS runtime\" ruling) so `orbital-server`'s `GET\n * /api/events` broadcast mirrors the same shape.\n */\nexport interface LiveBroadcastItem {\n event: string;\n payload?: EventPayload;\n source: BusEventSource;\n /** `clientId` of the request that produced this emit; excluded from delivery by the transport. */\n originClientId?: string;\n}\n\n/** Zod twin of `LiveBroadcastItem`. Third type param `object`, see `BusEventSourceSchema`. */\nexport const LiveBroadcastItemSchema: z.ZodType<LiveBroadcastItem, z.ZodTypeDef, object> = z.object({\n event: z.string(),\n payload: EventPayloadSchema.optional(),\n source: BusEventSourceSchema,\n originClientId: z.string().optional(),\n});\n\n/** @deprecated use {@link OrbitalEventRequest}. Kept until every referrer migrates (Program A wave A8). */\nexport type EventDispatchRequest = OrbitalEventRequest;\n\n/** @deprecated use {@link OrbitalEventRequestSchema}. */\nexport const EventDispatchRequestSchema = OrbitalEventRequestSchema;\n\n/** @deprecated use {@link OrbitalEventResponse}. Kept until every referrer migrates (Program A wave A8). */\nexport type EventDispatchResponse = OrbitalEventResponse;\n\n/** @deprecated use {@link OrbitalEventResponseSchema}. */\nexport const EventDispatchResponseSchema = OrbitalEventResponseSchema;\n","/**\n * Event-wire fixtures (Program A, §156, wave A2) — the ONE recorded fixture\n * set every server and client test loads: vitest in `@almadar/runtime` /\n * `@almadar/ui` / `almadar-playground-runtime`, `cargo test` in\n * `orbital-core` / `orbital-server` / `orbital-client` and the native\n * (Android/iOS) shell decoders, the Hono codegen contract test, and `orb\n * verify --server`. Generated by `scripts/generate-event-wire-fixtures.ts`\n * (`pnpm run build:fixtures`, wired into `build`) into\n * `fixtures/events-wire/<case>/{request,response}.json` (+ `stream.json` for\n * `sse-stream`, `live-push.json` for `live-push`), each already validated\n * against the zod schemas at generation time.\n *\n * Node-only (reads from disk with `node:fs`) — this module is exported ONLY\n * from the `@almadar/core/fixtures` subpath, never the main entry, so\n * browser bundles (`@almadar/ui`, the playground client, both of which the\n * root workspace Vite pre-bundles `@almadar/core` through) never pull in\n * `node:fs`. Mirrors the `@almadar/core/mock` subpath precedent for\n * Node/build-only surface area.\n *\n * @packageDocumentation\n */\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { z } from 'zod';\n\nimport {\n type OrbitalEventRequest,\n type OrbitalEventResponse,\n type ClientEffectTuple,\n type EmittedEvent,\n type LiveBroadcastItem,\n OrbitalEventRequestSchema,\n OrbitalEventResponseSchema,\n ClientEffectTupleSchema,\n EmittedEventSchema,\n LiveBroadcastItemSchema,\n} from './types/bus.js';\nimport type { JsonValue } from './types/json.js';\n\n/**\n * One SSE stream item, as written by the `POST .../events?stream=true`\n * endpoint's `onPush` calls plus its final write — see `stream.json`'s\n * generator comment (`scripts/generate-event-wire-fixtures.ts`) for the\n * exact source lines. Not part of `types/bus.ts`: the enclosing envelope is\n * `@almadar/server`'s `SSEEvent<T>` transport shape, downstream of core.\n */\nexport interface SSEStreamItem {\n type: 'event' | 'effect' | 'complete' | 'error';\n data: EmittedEvent | ClientEffectTuple | OrbitalEventResponse | { message: string };\n timestamp: number;\n}\n\n/** Zod twin of `SSEStreamItem` — validates at generation AND on load. Input\n * slot is `object` for the reason given at `BusEventSourceSchema`. */\nexport const SSEStreamItemSchema: z.ZodType<SSEStreamItem, z.ZodTypeDef, object> = z.union([\n z.object({ type: z.literal('event'), data: EmittedEventSchema, timestamp: z.number() }),\n z.object({ type: z.literal('effect'), data: ClientEffectTupleSchema, timestamp: z.number() }),\n z.object({ type: z.literal('complete'), data: OrbitalEventResponseSchema, timestamp: z.number() }),\n z.object({ type: z.literal('error'), data: z.object({ message: z.string() }), timestamp: z.number() }),\n]);\n\n/** One loaded fixture case — the files actually present under `<case>/`. */\nexport interface EventWireFixture {\n request?: OrbitalEventRequest;\n response?: OrbitalEventResponse;\n stream?: SSEStreamItem[];\n livePush?: LiveBroadcastItem;\n}\n\n/**\n * Case names under `fixtures/events-wire/`, in sync with\n * `scripts/generate-event-wire-fixtures.ts` (a generator-time assertion\n * fails the build if the two lists diverge).\n */\nexport const EVENT_WIRE_FIXTURE_CASES: readonly string[] = [\n 'cascade-emitted-events',\n 'client-effects-by-trait',\n 'effect-results',\n 'effect-results-every-kind',\n 'guard-rejected',\n 'live-push',\n 'navigate-1',\n 'navigate-2',\n 'navigate-3',\n 'navigate-back',\n 'render-ui-3',\n 'render-ui-4',\n 'render-ui-5',\n 'render-ui-clear',\n 'sse-stream',\n 'stateless-traits',\n];\n\n// `src/fixtures.ts` and its built output `dist/fixtures.js` are both exactly\n// one path segment below the package root, so a single `..` resolves\n// correctly whether this module runs from source (tests, via tsx/vitest) or\n// from the published `dist/`.\nconst PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');\n\nfunction readJsonIfExists(path: string): JsonValue | undefined {\n try {\n const json: JsonValue = JSON.parse(readFileSync(path, 'utf8'));\n return json;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined;\n throw error;\n }\n}\n\n/** Reads `<caseDir>/<file>` and validates it through its schema — the load is\n * typed by the parse, never by a cast. */\nfunction loadValidated<T>(caseDir: string, file: string, schema: z.ZodType<T, z.ZodTypeDef, object>): T | undefined {\n const json = readJsonIfExists(join(caseDir, file));\n return json === undefined ? undefined : schema.parse(json);\n}\n\n/**\n * Loads one case of the recorded event-wire fixture set from disk, relative\n * to the package root (works both from `packages/almadar-core` source and\n * from an installed `node_modules/@almadar/core`, since `fixtures/` ships\n * alongside `dist/` — see `package.json` `files`).\n */\nexport function loadEventWireFixture(caseName: string): EventWireFixture {\n if (!EVENT_WIRE_FIXTURE_CASES.includes(caseName)) {\n throw new Error(`Unknown event-wire fixture case: \"${caseName}\". Known cases: ${EVENT_WIRE_FIXTURE_CASES.join(', ')}`);\n }\n const caseDir = join(PACKAGE_ROOT, 'fixtures', 'events-wire', caseName);\n return {\n request: loadValidated(caseDir, 'request.json', OrbitalEventRequestSchema),\n response: loadValidated(caseDir, 'response.json', OrbitalEventResponseSchema),\n stream: loadValidated(caseDir, 'stream.json', z.array(SSEStreamItemSchema)),\n livePush: loadValidated(caseDir, 'live-push.json', LiveBroadcastItemSchema),\n };\n}\n"]}