@mooloo-ai/eutaxy 0.0.0-stage → 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.mjs","names":["isD1"],"sources":["../../cloudflare/src/check.ts","../../cloudflare/src/json.ts","../../cloudflare/src/d1.ts","../../cloudflare/src/platform.ts","../../cloudflare/src/differential.ts","../../cloudflare/src/scenario.ts"],"sourcesContent":["import {\n describeVerdict,\n type Platform,\n type ScenarioSpec,\n type ScenarioVerdict,\n} from \"@eutaxy/core\";\nimport { type ExploreOptions, explore } from \"@eutaxy/engine\";\n\n/** Explore a scenario on a platform and return its verdict. */\nexport function check(\n spec: ScenarioSpec,\n platform: Platform,\n options: ExploreOptions = { seed: spec.name },\n): Promise<ScenarioVerdict> {\n return explore(spec, platform, options);\n}\n\n/** For use from a test: passes only when the scenario is BOUNDED. */\nexport async function expectHolds(\n spec: ScenarioSpec,\n platform: Platform,\n options?: ExploreOptions,\n): Promise<void> {\n const verdict = await check(spec, platform, options);\n if (verdict.kind !== \"BOUNDED\") throw new Error(describeVerdict(verdict));\n}\n","import type { JsonValue } from \"@eutaxy/core\";\n\n/** Reduce any runtime value to JSON data for the effect log; never throws. */\nexport function toJson(value: unknown, depth = 0): JsonValue {\n if (value === null || value === undefined) return null;\n switch (typeof value) {\n case \"boolean\":\n case \"string\":\n return value;\n case \"number\":\n return Number.isFinite(value) ? value : String(value);\n case \"bigint\":\n return value.toString();\n case \"object\": {\n if (depth > 8) return \"<nested>\";\n if (Array.isArray(value)) return value.map((v) => toJson(v, depth + 1));\n if (value instanceof ArrayBuffer) return `<bytes ${value.byteLength}>`;\n if (ArrayBuffer.isView(value)) return `<bytes ${value.byteLength}>`;\n if (value instanceof Date) return value.toISOString();\n const out: Record<string, JsonValue> = {};\n for (const k of Object.keys(value).sort()) {\n out[k] = toJson((value as Record<string, unknown>)[k], depth + 1);\n }\n return out;\n }\n default:\n return `<${typeof value}>`;\n }\n}\n","/**\n * The D1 binding proxy. Every statement execution is an effect point: the\n * engine decides the fault, the real Miniflare-backed D1 performs the query,\n * and the log records call, result and fault in the documented shape.\n */\n\nimport {\n canonicalJson,\n type EffectPoint,\n type FaultKind,\n type JsonValue,\n type RunHooks,\n} from \"@eutaxy/core\";\nimport { toJson } from \"./json.ts\";\n\nconst WRITE: readonly FaultKind[] = [\"crash_before\", \"crash_after\", \"ambiguous\", \"error\"];\nconst READ: readonly FaultKind[] = [\"crash_before\", \"crash_after\", \"error\"];\n\nexport interface ProxyContext {\n readonly hooks: RunHooks;\n /** The invocation currently running; one at a time for now. */\n readonly currentInvocation: () => string;\n}\n\nfunction point(\n ctx: ProxyContext,\n target: string,\n op: string,\n args: JsonValue,\n allowed: readonly FaultKind[],\n): EffectPoint {\n return { invocation: ctx.currentInvocation(), target, op, args, allowed };\n}\n\nfunction metaOf(result: D1Result<unknown>): JsonValue {\n return { changes: result.meta.changes ?? 0, lastRowId: result.meta.last_row_id ?? null };\n}\n\nclass StatementProxy {\n private readonly real: D1PreparedStatement;\n private readonly target: string;\n private readonly ctx: ProxyContext;\n readonly sql: string;\n readonly params: readonly unknown[];\n\n constructor(\n real: D1PreparedStatement,\n target: string,\n ctx: ProxyContext,\n sql: string,\n params: readonly unknown[],\n ) {\n this.real = real;\n this.target = target;\n this.ctx = ctx;\n this.sql = sql;\n this.params = params;\n }\n\n /** The real statement, for `batch()`. */\n get statement(): D1PreparedStatement {\n return this.real;\n }\n\n private args(): JsonValue {\n return { sql: this.sql, params: toJson(this.params) };\n }\n\n bind(...values: unknown[]): StatementProxy {\n return new StatementProxy(this.real.bind(...values), this.target, this.ctx, this.sql, values);\n }\n\n run<T = Record<string, unknown>>(): Promise<D1Result<T>> {\n return this.ctx.hooks.effect(\n point(this.ctx, this.target, \"run\", this.args(), WRITE),\n () => this.real.run<T>(),\n (r) => metaOf(r),\n );\n }\n\n all<T = Record<string, unknown>>(): Promise<D1Result<T>> {\n return this.ctx.hooks.effect(\n point(this.ctx, this.target, \"all\", this.args(), READ),\n () => this.real.all<T>(),\n (r) => ({ rows: r.results.length, changes: r.meta.changes ?? 0 }),\n );\n }\n\n first<T = unknown>(colName?: string): Promise<T | null> {\n return this.ctx.hooks.effect(\n point(\n this.ctx,\n this.target,\n \"first\",\n { ...(this.args() as object), column: colName ?? null } as JsonValue,\n READ,\n ),\n () => (colName === undefined ? this.real.first<T>() : this.real.first<T>(colName)),\n (r) => ({ row: toJson(r) }),\n );\n }\n\n raw<T = unknown[]>(options?: { columnNames?: boolean }): Promise<T[]> {\n return this.ctx.hooks.effect(\n point(this.ctx, this.target, \"raw\", this.args(), READ),\n () =>\n (options\n ? this.real.raw<T>(options as { columnNames: true })\n : this.real.raw<T>()) as Promise<T[]>,\n (r) => ({ rows: r.length }),\n );\n }\n}\n\n/** Wrap a D1 binding. Methods not modelled fall through to the real binding and mark the run unsupported. */\nexport function proxyD1(real: D1Database, binding: string, ctx: ProxyContext): D1Database {\n const target = `D1:${binding}`;\n const modelled = {\n prepare(sql: string): StatementProxy {\n return new StatementProxy(real.prepare(sql), target, ctx, sql, []);\n },\n batch<T = Record<string, unknown>>(\n statements: readonly (StatementProxy | D1PreparedStatement)[],\n ): Promise<D1Result<T>[]> {\n const unwrapped = statements.map((s) => (s instanceof StatementProxy ? s.statement : s));\n const args = {\n statements: statements.map((s) =>\n s instanceof StatementProxy\n ? { sql: s.sql, params: toJson(s.params) }\n : \"<unproxied statement>\",\n ),\n };\n return ctx.hooks.effect(\n point(ctx, target, \"batch\", args, WRITE),\n () => real.batch<T>(unwrapped as D1PreparedStatement[]),\n (rs) => ({\n changes: rs.reduce((n, r) => n + (r.meta.changes ?? 0), 0),\n statements: rs.length,\n }),\n );\n },\n exec(sql: string): Promise<D1ExecResult> {\n return ctx.hooks.effect(\n point(ctx, target, \"exec\", { sql }, WRITE),\n () => real.exec(sql),\n (r) => ({ count: r.count, duration: 0 }),\n );\n },\n };\n return new Proxy(real, {\n get(obj, prop, receiver) {\n if (prop in modelled) return modelled[prop as keyof typeof modelled];\n const value = Reflect.get(obj, prop, receiver) as unknown;\n if (typeof value === \"function\") {\n ctx.hooks.unsupported(`D1 ${binding}.${String(prop)} is not modelled`);\n return (value as (...a: unknown[]) => unknown).bind(obj);\n }\n return value;\n },\n }) as D1Database;\n}\n\n/**\n * Statements in a schema file. Splits on semicolons outside string literals,\n * quoted identifiers and comments, and keeps CREATE TRIGGER bodies (and CASE\n * expressions) whole by tracking BEGIN/CASE ... END nesting.\n */\nexport function splitSql(sql: string): readonly string[] {\n const out: string[] = [];\n let cur = \"\";\n let depth = 0;\n let i = 0;\n const isWordChar = (c: string | undefined): boolean => c !== undefined && /[A-Za-z0-9_]/.test(c);\n while (i < sql.length) {\n const c = sql[i] as string;\n const next = sql[i + 1];\n if (c === \"-\" && next === \"-\") {\n while (i < sql.length && sql[i] !== \"\\n\") i++;\n continue;\n }\n if (c === \"/\" && next === \"*\") {\n const end = sql.indexOf(\"*/\", i + 2);\n i = end === -1 ? sql.length : end + 2;\n continue;\n }\n if (c === \"'\" || c === '\"' || c === \"`\" || c === \"[\") {\n const close = c === \"[\" ? \"]\" : c;\n let j = i + 1;\n for (;;) {\n const k = sql.indexOf(close, j);\n if (k === -1) {\n j = sql.length;\n break;\n }\n if (close !== \"]\" && sql[k + 1] === close) {\n j = k + 2; // a doubled quote inside the literal\n continue;\n }\n j = k + 1;\n break;\n }\n cur += sql.slice(i, j);\n i = j;\n continue;\n }\n if (isWordChar(c) && !isWordChar(sql[i - 1])) {\n let j = i;\n while (isWordChar(sql[j])) j++;\n const word = sql.slice(i, j);\n const upper = word.toUpperCase();\n if (upper === \"BEGIN\" || upper === \"CASE\") depth++;\n else if (upper === \"END\" && depth > 0) depth--;\n cur += word;\n i = j;\n continue;\n }\n if (c === \";\" && depth === 0) {\n const statement = cur.trim();\n if (statement.length > 0) out.push(statement);\n cur = \"\";\n i++;\n continue;\n }\n cur += c;\n i++;\n }\n const last = cur.trim();\n if (last.length > 0) out.push(last);\n return out;\n}\n\n/** Drop every user table and re-apply the schema, using the real binding (not an effect). */\nexport async function resetD1(real: D1Database, schema: string): Promise<void> {\n const tables = await real\n .prepare(\n \"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '\\\\_cf\\\\_%' ESCAPE '\\\\'\",\n )\n .all<{ name: string }>();\n for (const { name } of tables.results) {\n await real.prepare(`DROP TABLE IF EXISTS \"${name.replace(/\"/g, '\"\"')}\"`).run();\n }\n for (const statement of splitSql(schema)) {\n await real.prepare(statement).run();\n }\n}\n\n/** Every user table's rows, sorted canonically, read through the real binding (not an effect). */\nexport async function snapshotD1(\n real: D1Database,\n): Promise<{ readonly [table: string]: readonly JsonValue[] }> {\n const tables = await real\n .prepare(\n \"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '\\\\_cf\\\\_%' ESCAPE '\\\\' ORDER BY name\",\n )\n .all<{ name: string }>();\n const out: Record<string, JsonValue[]> = {};\n for (const { name } of tables.results) {\n const rows = await real\n .prepare(`SELECT * FROM \"${name.replace(/\"/g, '\"\"')}\"`)\n .all<Record<string, unknown>>();\n out[name] = rows.results\n .map((r) => toJson(r))\n .map((j) => [canonicalJson(j), j] as const)\n .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))\n .map(([, j]) => j);\n }\n return out;\n}\n","/**\n * The Cloudflare platform: delivers queue messages to the Worker's `queue()`\n * handler with proxied bindings and proxied messages, and applies Queues'\n * at-least-once semantics (explicit and implicit ack, retry, redelivery up\n * to max_retries, dead-lettering) as documented by Cloudflare.\n */\n\nimport type {\n DeliveryResult,\n EventRef,\n FaultKind,\n JsonValue,\n Platform,\n RunHooks,\n ScenarioSpec,\n} from \"@eutaxy/core\";\nimport { CrashSignal } from \"@eutaxy/engine\";\nimport { type ProxyContext, proxyD1, resetD1, snapshotD1 } from \"./d1.ts\";\nimport type { QueueDrive } from \"./scenario.ts\";\n\nconst ACK: readonly FaultKind[] = [\"crash_before\", \"crash_after\"];\nconst CUT_OFF: readonly FaultKind[] = [\"cut_off\"];\n\nexport interface QueueHandler {\n queue?(batch: MessageBatch<unknown>, env: unknown, ctx: ExecutionContext): void | Promise<void>;\n}\n\nexport interface CloudflarePlatformOptions {\n /** The bindings from `cloudflare:workers`. */\n readonly env: object;\n /** The Worker's default export. */\n readonly handler: QueueHandler;\n /** Schema SQL per D1 binding named in the scenario's setup. */\n readonly schemas: Readonly<Record<string, string>>;\n /** Cloudflare's default when the consumer does not set max_retries. */\n readonly maxRetries?: number;\n}\n\nfunction isD1(value: unknown): value is D1Database {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { prepare?: unknown }).prepare === \"function\" &&\n typeof (value as { batch?: unknown }).batch === \"function\"\n );\n}\n\nfunction isBindingLike(value: unknown): boolean {\n if (typeof value === \"function\") return true;\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as object | null;\n const names = [...Object.getOwnPropertyNames(value), ...Object.getOwnPropertyNames(proto ?? {})];\n return names.some(\n (k) => k !== \"constructor\" && typeof (value as Record<string, unknown>)[k] === \"function\",\n );\n}\n\n/** Deep-copy JSON data so a handler that mutates its message cannot leak into other runs. */\nfunction cloneJson(value: JsonValue): JsonValue {\n return JSON.parse(JSON.stringify(value)) as JsonValue;\n}\n\nconst assumptions: readonly string[] = [\n \"platform model: Cloudflare Queues at-least-once delivery; the first ack or retry decision per message wins; unacked messages are redelivered up to max_retries then dead-lettered\",\n \"D1 statements run against Miniflare's SQLite; each run/first/all/raw/batch/exec is one effect\",\n \"message.timestamp is the virtual clock's time at delivery\",\n \"only D1 bindings are proxied; touching any other binding makes the run UNSUPPORTED\",\n \"state invariants read a snapshot of every D1 binding named in setup, taken after the last event\",\n \"work passed to ctx.waitUntil runs after the handler returns and never affects acknowledgement; a cut_off fault at that point loses work not yet started, and an effect in flight commits without its continuation\",\n];\n\nexport function createCloudflarePlatform(options: CloudflarePlatformOptions): Platform {\n const env = options.env as Record<string, unknown>;\n const maxRetries = options.maxRetries ?? 3;\n let currentInvocation = \"\";\n let hooksRef: RunHooks | null = null;\n\n const ctx: ProxyContext = {\n get hooks() {\n if (!hooksRef) throw new Error(\"no run in progress\");\n return hooksRef;\n },\n currentInvocation: () => currentInvocation,\n };\n\n const d1Proxies = new Map<string, D1Database>();\n const proxiedEnv = new Proxy(env, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver) as unknown;\n if (typeof prop !== \"string\") return value;\n if (isD1(value)) {\n let p = d1Proxies.get(prop);\n if (!p) {\n p = proxyD1(value, prop, ctx);\n d1Proxies.set(prop, p);\n }\n return p;\n }\n if (isBindingLike(value)) ctx.hooks.unsupported(`binding ${prop} is not proxied`);\n return value;\n },\n });\n\n /** Platform-level actions (dead-lettering) are recorded under an invocation no fault can crash. */\n const platformInvocations = new WeakMap<RunHooks, string>();\n function platformInvocation(hooks: RunHooks): string {\n let id = platformInvocations.get(hooks);\n if (id === undefined) {\n id = \"platform\";\n hooks.startInvocation(id);\n platformInvocations.set(hooks, id);\n }\n return id;\n }\n\n return {\n name: \"cloudflare\",\n assumptions,\n\n async reset(spec: ScenarioSpec): Promise<void> {\n for (const step of spec.setup) {\n if (step.kind !== \"d1\") continue;\n const binding = String(step[\"binding\"]);\n const schema = options.schemas[binding];\n if (schema === undefined) throw new Error(`no schema provided for D1 binding ${binding}`);\n const real = env[binding];\n if (!isD1(real)) throw new Error(`env.${binding} is not a D1 binding`);\n await resetD1(real, schema);\n }\n },\n\n restrictEvents(spec: ScenarioSpec, keepIds: readonly string[]): ScenarioSpec {\n const drive = spec.drive as QueueDrive;\n return {\n ...spec,\n drive: { ...drive, messages: drive.messages.filter((m) => keepIds.includes(m.id)) },\n };\n },\n\n async finish(spec: ScenarioSpec, hooks: RunHooks): Promise<void> {\n for (const step of spec.setup) {\n if (step.kind !== \"d1\") continue;\n const binding = String(step[\"binding\"]);\n const real = env[binding];\n if (!isD1(real)) continue;\n const tables = await snapshotD1(real);\n hooks.snapshot(platformInvocation(hooks), `D1:${binding}`, { tables });\n }\n },\n\n initialEvents(spec: ScenarioSpec): readonly EventRef[] {\n const drive = spec.drive as QueueDrive;\n if (drive.kind !== \"queue\") {\n throw new Error(`drive ${drive.kind} is not supported by the Cloudflare platform yet`);\n }\n return drive.messages.map((m) => ({ id: m.id, attempt: 1, data: m.body }));\n },\n\n async deliver(event: EventRef, hooks: RunHooks, spec: ScenarioSpec): Promise<DeliveryResult> {\n const drive = spec.drive as QueueDrive;\n const queueTarget = `Queue:${drive.queue}`;\n const invocation = `${event.id}#${event.attempt}`;\n hooksRef = hooks;\n currentInvocation = invocation;\n const inv = hooks.startInvocation(invocation);\n /** Cloudflare honours the first ack or retry decision per message; later ones are ignored. */\n const state: { decision: \"ack\" | \"retry\" | null } = { decision: null };\n const background: Promise<unknown>[] = [];\n\n /** Records the call; the result says whether it took effect (the first decision wins). */\n const decide = (op: \"ack\" | \"retry\", args: JsonValue): void => {\n hooks.effectSync(\n { invocation, target: queueTarget, op, args, allowed: ACK },\n () => {\n if (state.decision !== null) return false;\n state.decision = op;\n return true;\n },\n (effective) => ({ effective }),\n );\n };\n const message: Message<unknown> = {\n id: event.id,\n timestamp: new Date(),\n body: cloneJson(event.data),\n attempts: event.attempt,\n ack: () => decide(\"ack\", { messageId: event.id, implicit: false, body: event.data }),\n retry: () => decide(\"retry\", { messageId: event.id, body: event.data }),\n };\n const batch: MessageBatch<unknown> = {\n queue: drive.queue,\n messages: [message],\n metadata: { metrics: { backlogCount: 0, backlogBytes: 0 } },\n ackAll: () => message.ack(),\n retryAll: () => message.retry(),\n };\n const execution: ExecutionContext = {\n waitUntil: (promise: Promise<unknown>) => {\n background.push(\n promise.then(\n () => undefined,\n () => undefined,\n ),\n );\n },\n passThroughOnException: () => {},\n props: {},\n } as unknown as ExecutionContext;\n\n const handler = options.handler.queue;\n if (!handler) throw new Error(\"the Worker has no queue() handler\");\n const outcome = Promise.resolve()\n .then(() => handler.call(options.handler, batch, proxiedEnv, execution))\n .then(\n () => \"completed\" as const,\n (err: unknown) =>\n err instanceof CrashSignal ? (\"crashed\" as const) : (\"errored\" as const),\n );\n let status = await Promise.race([\n hooks.settle(outcome, invocation),\n inv.crashed.then(() => \"crashed\" as const),\n ]);\n\n if (status === \"completed\" && state.decision === null) {\n try {\n decide(\"ack\", { messageId: event.id, implicit: true, body: event.data });\n } catch (err) {\n if (err instanceof CrashSignal) status = \"crashed\";\n else throw err;\n }\n }\n\n // Background work extends the invocation but never changes the acknowledgement.\n // A cut-off here is the isolate dying after the acknowledgement: work not yet started is lost.\n if (background.length > 0 && !inv.isCrashed()) {\n try {\n hooks.effectSync(\n {\n invocation,\n target: queueTarget,\n op: \"background\",\n args: { pending: background.length },\n allowed: CUT_OFF,\n },\n () => null,\n () => null,\n );\n await Promise.race([hooks.settle(Promise.all(background), invocation), inv.crashed]);\n } catch (err) {\n if (!(err instanceof CrashSignal)) throw err;\n status = \"crashed\";\n }\n }\n\n const followUps: EventRef[] = [];\n if (state.decision !== \"ack\") {\n const redeliveries = event.attempt - 1;\n if (event.attempt <= maxRetries && redeliveries < spec.bounds.maxRedeliveries) {\n followUps.push({ ...event, attempt: event.attempt + 1 });\n } else {\n hooks.effectSync(\n {\n invocation: platformInvocation(hooks),\n target: queueTarget,\n op: \"dead_letter\",\n args: { messageId: event.id, attempts: event.attempt },\n allowed: [],\n },\n () => null,\n () => null,\n );\n }\n }\n currentInvocation = \"\";\n return { status, followUps };\n },\n };\n}\n","/**\n * Differential check: the same fault-free scenario run once through Eutaxy's\n * proxies and once against the raw bindings, with the queue model applied by\n * hand on the raw side. Any difference in the per-attempt decisions or in\n * the final D1 state is a bug in the proxies or the platform model, not in\n * the Worker. The raw side shares Eutaxy's *reading* of Cloudflare's queue\n * semantics; what it does not share is any proxy code.\n */\n\nimport {\n canonicalJson,\n type EventRef,\n getPath,\n type JsonValue,\n type ScenarioSpec,\n} from \"@eutaxy/core\";\nimport {\n CrashSignal,\n effectLatencyMs,\n patchGlobals,\n Run,\n settleOn,\n type VirtualClock,\n} from \"@eutaxy/engine\";\nimport { resetD1, snapshotD1 } from \"./d1.ts\";\nimport { type CloudflarePlatformOptions, createCloudflarePlatform } from \"./platform.ts\";\nimport type { QueueDrive } from \"./scenario.ts\";\n\nexport interface AttemptRecord {\n readonly event: string;\n readonly attempt: number;\n readonly status: \"completed\" | \"errored\";\n readonly decision: \"ack\" | \"retry\" | null;\n}\n\nexport interface Side {\n readonly attempts: readonly AttemptRecord[];\n readonly state: {\n readonly [binding: string]: { readonly [table: string]: readonly JsonValue[] };\n };\n}\n\nexport interface DifferentialResult {\n /** True only when both sides agree and the proxied run touched nothing unmodelled. */\n readonly equal: boolean;\n readonly eutaxy: Side;\n readonly raw: Side;\n readonly differences: readonly string[];\n /** What the proxied run could not control; non-empty means the comparison proves nothing. */\n readonly unsupported: readonly string[];\n}\n\n/** The raw side cannot abandon an invocation the way the engine does; a stuck handler ends the comparison. */\nclass StuckError extends Error {\n override readonly name = \"StuckError\";\n constructor() {\n super(\n \"the handler is waiting on something outside the run (no timer due, no effect in flight)\",\n );\n }\n}\n\n/**\n * The raw side's only wrapper: counts D1 calls in flight (so the settle loop\n * knows real I/O is pending) and advances the clock as the proxies do. It\n * records nothing and injects nothing.\n */\nfunction countingD1(real: D1Database, io: { n: number }, clock: VirtualClock): D1Database {\n const realOf = new WeakMap<object, D1PreparedStatement>();\n const track = async <T>(p: Promise<T>): Promise<T> => {\n io.n++;\n try {\n return await p;\n } finally {\n io.n--;\n clock.advance(effectLatencyMs);\n }\n };\n const wrapStatement = (s: D1PreparedStatement): D1PreparedStatement => {\n const proxy = new Proxy(s, {\n get(t, prop, r) {\n const v = Reflect.get(t, prop, r) as unknown;\n if (prop === \"bind\") return (...a: unknown[]) => wrapStatement(t.bind(...a));\n if (prop === \"run\" || prop === \"all\" || prop === \"first\" || prop === \"raw\") {\n return (...a: unknown[]) =>\n track((v as (...x: unknown[]) => Promise<unknown>).apply(t, a));\n }\n return typeof v === \"function\" ? (v as (...x: unknown[]) => unknown).bind(t) : v;\n },\n });\n realOf.set(proxy, s);\n return proxy;\n };\n return new Proxy(real, {\n get(t, prop, r) {\n const v = Reflect.get(t, prop, r) as unknown;\n if (prop === \"prepare\") return (sql: string) => wrapStatement(t.prepare(sql));\n if (prop === \"batch\") {\n return (stmts: D1PreparedStatement[]) =>\n track(t.batch(stmts.map((s) => realOf.get(s) ?? s)));\n }\n if (prop === \"exec\") return (sql: string) => track(t.exec(sql));\n return typeof v === \"function\" ? (v as (...x: unknown[]) => unknown).bind(t) : v;\n },\n });\n}\n\nfunction isD1(value: unknown): value is D1Database {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { prepare?: unknown }).prepare === \"function\"\n );\n}\n\nasync function snapshotAll(\n spec: ScenarioSpec,\n options: CloudflarePlatformOptions,\n): Promise<Side[\"state\"]> {\n const env = options.env as Record<string, unknown>;\n const out: Record<string, { readonly [table: string]: readonly JsonValue[] }> = {};\n for (const step of spec.setup) {\n if (step.kind !== \"d1\") continue;\n const binding = String(step[\"binding\"]);\n const real = env[binding];\n if (isD1(real)) out[binding] = await snapshotD1(real);\n }\n return out;\n}\n\n/** The Eutaxy side: one run with no faults, driven like `runOnce` but keeping each delivery's status. */\nasync function eutaxySide(\n spec: ScenarioSpec,\n options: CloudflarePlatformOptions,\n): Promise<Side & { readonly unsupported: readonly string[] }> {\n const platform = createCloudflarePlatform(options);\n const run = new Run({\n mode: \"replay\",\n schedule: { seed: 0, faults: [] },\n bounds: spec.bounds,\n faultProbability: 0,\n });\n const attempts: AttemptRecord[] = [];\n run.install();\n try {\n await platform.reset(spec);\n const pending: EventRef[] = [...platform.initialEvents(spec)];\n while (pending.length > 0) {\n const event = pending.shift() as EventRef;\n const invocation = `${event.id}#${event.attempt}`;\n const before = run.log.entries.length;\n const result = await platform.deliver(event, run, spec);\n const decision = run.log.entries\n .slice(before)\n .find(\n (e) =>\n e.invocation === invocation &&\n e.kind === \"result\" &&\n (e.op === \"ack\" || e.op === \"retry\") &&\n getPath(e.payload, \"result.effective\") === true,\n )?.op as \"ack\" | \"retry\" | undefined;\n attempts.push({\n event: event.id,\n attempt: event.attempt,\n status: result.status === \"completed\" ? \"completed\" : \"errored\",\n decision: decision ?? null,\n });\n pending.push(...result.followUps);\n }\n await platform.finish?.(spec, run);\n } finally {\n run.uninstall();\n }\n return { attempts, state: await snapshotAll(spec, options), unsupported: run.unsupportedReasons };\n}\n\n/** The raw side: the handler called directly with the real bindings and plain message objects. */\nasync function rawSide(spec: ScenarioSpec, options: CloudflarePlatformOptions): Promise<Side> {\n const env = options.env as Record<string, unknown>;\n const drive = spec.drive as QueueDrive;\n const maxRetries = options.maxRetries ?? 3;\n for (const step of spec.setup) {\n if (step.kind !== \"d1\") continue;\n const binding = String(step[\"binding\"]);\n const schema = options.schemas[binding];\n const real = env[binding];\n if (schema !== undefined && isD1(real)) await resetD1(real, schema);\n }\n const handler = options.handler.queue;\n if (!handler) throw new Error(\"the Worker has no queue() handler\");\n const attempts: AttemptRecord[] = [];\n const pending: EventRef[] = drive.messages.map((m) => ({ id: m.id, attempt: 1, data: m.body }));\n // The same virtual globals as the proxied side, from the same seed, so Date.now and randomness agree.\n const patched = patchGlobals(0);\n const io = { n: 0 };\n const counting = new Map<string, D1Database>();\n const countedEnv = new Proxy(env, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver) as unknown;\n if (typeof prop !== \"string\" || !isD1(value)) return value;\n let c = counting.get(prop);\n if (!c) {\n c = countingD1(value, io, patched.clock);\n counting.set(prop, c);\n }\n return c;\n },\n });\n const settle = <T>(p: Promise<T>): Promise<T> =>\n settleOn(p, {\n clock: patched.clock,\n inFlight: () => io.n,\n crashed: () => false,\n stuck: () => {\n throw new StuckError();\n },\n });\n try {\n while (pending.length > 0) {\n const event = pending.shift() as EventRef;\n let decision: \"ack\" | \"retry\" | null = null;\n const background: Promise<unknown>[] = [];\n const message: Message<unknown> = {\n id: event.id,\n timestamp: new Date(),\n body: JSON.parse(JSON.stringify(event.data)) as JsonValue,\n attempts: event.attempt,\n ack: () => {\n decision ??= \"ack\";\n },\n retry: () => {\n decision ??= \"retry\";\n },\n };\n const batch: MessageBatch<unknown> = {\n queue: drive.queue,\n messages: [message],\n metadata: { metrics: { backlogCount: 0, backlogBytes: 0 } },\n ackAll: () => message.ack(),\n retryAll: () => message.retry(),\n };\n const ctx = {\n waitUntil: (p: Promise<unknown>) => {\n background.push(\n p.then(\n () => undefined,\n () => undefined,\n ),\n );\n },\n passThroughOnException: () => {},\n props: {},\n } as unknown as ExecutionContext;\n let status: \"completed\" | \"errored\";\n try {\n await settle(\n Promise.resolve().then(() => handler.call(options.handler, batch, countedEnv, ctx)),\n );\n status = \"completed\";\n } catch (err) {\n if (err instanceof CrashSignal || err instanceof StuckError) throw err;\n status = \"errored\";\n }\n if (status === \"completed\") decision ??= \"ack\";\n await settle(Promise.all(background));\n attempts.push({ event: event.id, attempt: event.attempt, status, decision });\n if (\n decision !== \"ack\" &&\n event.attempt <= maxRetries &&\n event.attempt - 1 < spec.bounds.maxRedeliveries\n ) {\n pending.push({ ...event, attempt: event.attempt + 1 });\n }\n }\n } finally {\n patched.restore();\n }\n return { attempts, state: await snapshotAll(spec, options) };\n}\n\n/** Run both sides and compare. The Eutaxy side runs first; both start from the schema. */\nexport async function runDifferential(\n spec: ScenarioSpec,\n options: CloudflarePlatformOptions,\n): Promise<DifferentialResult> {\n const { unsupported, ...eutaxy } = await eutaxySide(spec, options);\n const raw = await rawSide(spec, options);\n const differences: string[] = [];\n if (unsupported.length > 0) {\n differences.push(`the proxied run touched unsupported APIs: ${unsupported.join(\"; \")}`);\n }\n const a = canonicalJson(eutaxy.attempts as unknown as JsonValue);\n const b = canonicalJson(raw.attempts as unknown as JsonValue);\n if (a !== b) differences.push(`attempts differ:\\n eutaxy ${a}\\n raw ${b}`);\n const bindings = new Set([...Object.keys(eutaxy.state), ...Object.keys(raw.state)]);\n for (const binding of [...bindings].sort()) {\n const tables = new Set([\n ...Object.keys(eutaxy.state[binding] ?? {}),\n ...Object.keys(raw.state[binding] ?? {}),\n ]);\n for (const table of [...tables].sort()) {\n const x = canonicalJson((eutaxy.state[binding]?.[table] ?? []) as unknown as JsonValue);\n const y = canonicalJson((raw.state[binding]?.[table] ?? []) as unknown as JsonValue);\n if (x !== y) differences.push(`${binding}.${table} differs:\\n eutaxy ${x}\\n raw ${y}`);\n }\n }\n return { equal: differences.length === 0, eutaxy, raw, differences, unsupported };\n}\n","/**\n * Typed construction of scenario specs for Cloudflare Workers. Everything here\n * produces the plain-data `ScenarioSpec` from core; this module only knows the\n * Cloudflare shapes (queues, D1 bindings) and the effect conventions the\n * proxies follow.\n */\n\nimport {\n type AtLeastOnce,\n type AtMostOncePerKey,\n type Bounds,\n defaultBounds,\n type EffectSelector,\n type EveryRow,\n type ExternalDecl,\n getPath,\n type Implies,\n type Invariant,\n type JsonValue,\n type PlatformData,\n type RowCondition,\n type ScenarioSpec,\n type StateQuery,\n validateScenario,\n type WorkerRef,\n} from \"@eutaxy/core\";\n\n/** One queue message to deliver; `id` defaults to its position. */\nexport interface QueueMessage {\n readonly id?: string;\n readonly body: JsonValue;\n}\n\n/** Drive the Worker's `queue()` handler with these messages. */\nexport interface QueueDrive extends PlatformData {\n readonly kind: \"queue\";\n readonly queue: string;\n readonly messages: readonly { readonly id: string; readonly body: JsonValue }[];\n}\n\n/** Apply a SQL file to a D1 binding before each run. */\nexport interface D1Setup extends PlatformData {\n readonly kind: \"d1\";\n readonly binding: string;\n readonly schemaFile: string;\n}\n\nexport interface CloudflareScenarioInput {\n readonly name: string;\n readonly worker: WorkerRef;\n readonly drive:\n | QueueDrive\n | {\n readonly kind: \"queue\";\n readonly queue: string;\n readonly messages: readonly QueueMessage[];\n };\n readonly setup?: readonly D1Setup[];\n readonly externals?: readonly ExternalDecl[];\n readonly invariants: readonly Invariant[];\n readonly bounds?: Partial<Bounds>;\n}\n\nexport function queue(name: string, messages: readonly QueueMessage[]): QueueDrive {\n return {\n kind: \"queue\",\n queue: name,\n messages: messages.map((m, i) => ({ id: m.id ?? `msg-${i + 1}`, body: m.body })),\n };\n}\n\nexport function d1Schema(binding: string, schemaFile: string): D1Setup {\n return { kind: \"d1\", binding, schemaFile };\n}\n\n/**\n * Effect conventions for D1 (what the proxies record):\n * call payload { args: { sql, params } }\n * result payload { args: { sql, params }, result: { changes, lastRowId } }\n * A committed write is a `result` whose `result.changes` is at least 1.\n */\nexport function d1Write(binding: string, op: \"run\" | \"batch\" = \"run\"): EffectSelector {\n return { target: `D1:${binding}`, op, kind: \"result\", atLeast: { \"result.changes\": 1 } };\n}\n\n/** Dot path to the Nth bound parameter of a D1 statement, in an effect payload. */\nexport function d1Param(index: number): string {\n return `args.params.${index}`;\n}\n\nexport function atMostOncePerKey(\n name: string,\n effect: EffectSelector,\n key: string,\n): AtMostOncePerKey {\n return { kind: \"atMostOncePerKey\", name, effect, key };\n}\n\nexport function atLeastOnce(\n name: string,\n effect: EffectSelector,\n key: string,\n expected: readonly JsonValue[],\n): AtLeastOnce {\n return { kind: \"atLeastOnce\", name, effect, key, expected };\n}\n\n/**\n * Every message's `bodyKey` value must appear at least once as `key` in a\n * selected effect: nothing the queue delivered may be lost.\n */\nexport function atLeastOncePerMessage(\n name: string,\n drive: QueueDrive,\n effect: EffectSelector,\n key: string,\n bodyKey: string,\n): AtLeastOnce {\n const expected: JsonValue[] = [];\n for (const m of drive.messages) {\n const v = getPath(m.body, bodyKey);\n if (v === undefined) {\n throw new Error(`message ${m.id} has no ${JSON.stringify(bodyKey)} in its body`);\n }\n expected.push(v);\n }\n return { ...atLeastOnce(name, effect, key, expected), perMessage: { bodyKey } };\n}\n\n/** Rows of a D1 table in the end-of-run snapshot, optionally filtered. */\nexport function d1Rows(\n binding: string,\n table: string,\n where?: readonly RowCondition[],\n): StateQuery {\n return where ? { target: `D1:${binding}`, table, where } : { target: `D1:${binding}`, table };\n}\n\n/** Every row the query selects satisfies all conditions. */\nexport function everyRow(\n name: string,\n query: StateQuery,\n holds: readonly RowCondition[],\n): EveryRow {\n return { kind: \"everyRow\", name, query, holds };\n}\n\n/** Every selected effect has a row whose column equals the effect's key. */\nexport function implies(\n name: string,\n when: EffectSelector,\n key: string,\n state: StateQuery,\n column: string,\n): Implies {\n return { kind: \"implies\", name, when, key, state, column };\n}\n\n/** Selects the acknowledgement that took effect for each message (explicit or implicit; not one ignored after a retry). */\nexport function queueAck(queueName: string): EffectSelector {\n return {\n target: `Queue:${queueName}`,\n op: \"ack\",\n kind: \"result\",\n where: { \"result.effective\": true },\n };\n}\n\n/** Build and validate a scenario spec; throws with every problem listed. */\nexport function defineScenario(input: CloudflareScenarioInput): ScenarioSpec {\n const drive: QueueDrive =\n \"messages\" in input.drive &&\n input.drive.messages.every((m) => \"id\" in m && typeof m.id === \"string\")\n ? (input.drive as QueueDrive)\n : queue(input.drive.queue, input.drive.messages);\n const spec: ScenarioSpec = {\n version: 1,\n name: input.name,\n worker: input.worker,\n drive,\n setup: input.setup ?? [],\n externals: input.externals ?? [],\n invariants: input.invariants,\n bounds: { ...defaultBounds, ...input.bounds },\n };\n const errors = validateScenario(spec);\n if (errors.length > 0) {\n throw new Error(`invalid scenario ${JSON.stringify(input.name)}:\\n- ${errors.join(\"\\n- \")}`);\n }\n return spec;\n}\n"],"mappings":";;;;;AASA,SAAgB,MACd,MACA,UACA,UAA0B,EAAE,MAAM,KAAK,KAAK,GAClB;CAC1B,OAAO,QAAQ,MAAM,UAAU,OAAO;AACxC;;AAGA,eAAsB,YACpB,MACA,UACA,SACe;CACf,MAAM,UAAU,MAAM,MAAM,MAAM,UAAU,OAAO;CACnD,IAAI,QAAQ,SAAS,WAAW,MAAM,IAAI,MAAM,gBAAgB,OAAO,CAAC;AAC1E;;;ACtBA,SAAgB,OAAO,OAAgB,QAAQ,GAAc;CAC3D,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;CAClD,QAAQ,OAAO,OAAf;EACE,KAAK;EACL,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK;EACtD,KAAK,UACH,OAAO,MAAM,SAAS;EACxB,KAAK,UAAU;GACb,IAAI,QAAQ,GAAG,OAAO;GACtB,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,KAAK,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC;GACtE,IAAI,iBAAiB,aAAa,OAAO,UAAU,MAAM,WAAW;GACpE,IAAI,YAAY,OAAO,KAAK,GAAG,OAAO,UAAU,MAAM,WAAW;GACjE,IAAI,iBAAiB,MAAM,OAAO,MAAM,YAAY;GACpD,MAAM,MAAiC,CAAC;GACxC,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK,GACtC,IAAI,KAAK,OAAQ,MAAkC,IAAI,QAAQ,CAAC;GAElE,OAAO;EACT;EACA,SACE,OAAO,IAAI,OAAO,MAAM;CAC5B;AACF;;;;;;;ACbA,MAAM,QAA8B;CAAC;CAAgB;CAAe;CAAa;AAAO;AACxF,MAAM,OAA6B;CAAC;CAAgB;CAAe;AAAO;AAQ1E,SAAS,MACP,KACA,QACA,IACA,MACA,SACa;CACb,OAAO;EAAE,YAAY,IAAI,kBAAkB;EAAG;EAAQ;EAAI;EAAM;CAAQ;AAC1E;AAEA,SAAS,OAAO,QAAsC;CACpD,OAAO;EAAE,SAAS,OAAO,KAAK,WAAW;EAAG,WAAW,OAAO,KAAK,eAAe;CAAK;AACzF;AAEA,IAAM,iBAAN,MAAM,eAAe;CACnB;CACA;CACA;CACA;CACA;CAEA,YACE,MACA,QACA,KACA,KACA,QACA;EACA,KAAK,OAAO;EACZ,KAAK,SAAS;EACd,KAAK,MAAM;EACX,KAAK,MAAM;EACX,KAAK,SAAS;CAChB;;CAGA,IAAI,YAAiC;EACnC,OAAO,KAAK;CACd;CAEA,OAA0B;EACxB,OAAO;GAAE,KAAK,KAAK;GAAK,QAAQ,OAAO,KAAK,MAAM;EAAE;CACtD;CAEA,KAAK,GAAG,QAAmC;EACzC,OAAO,IAAI,eAAe,KAAK,KAAK,KAAK,GAAG,MAAM,GAAG,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM;CAC9F;CAEA,MAAyD;EACvD,OAAO,KAAK,IAAI,MAAM,OACpB,MAAM,KAAK,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,GAAG,KAAK,SAChD,KAAK,KAAK,IAAO,IACtB,MAAM,OAAO,CAAC,CACjB;CACF;CAEA,MAAyD;EACvD,OAAO,KAAK,IAAI,MAAM,OACpB,MAAM,KAAK,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,GAAG,IAAI,SAC/C,KAAK,KAAK,IAAO,IACtB,OAAO;GAAE,MAAM,EAAE,QAAQ;GAAQ,SAAS,EAAE,KAAK,WAAW;EAAE,EACjE;CACF;CAEA,MAAmB,SAAqC;EACtD,OAAO,KAAK,IAAI,MAAM,OACpB,MACE,KAAK,KACL,KAAK,QACL,SACA;GAAE,GAAI,KAAK,KAAK;GAAc,QAAQ,WAAW;EAAK,GACtD,IACF,SACO,YAAY,KAAA,IAAY,KAAK,KAAK,MAAS,IAAI,KAAK,KAAK,MAAS,OAAO,IAC/E,OAAO,EAAE,KAAK,OAAO,CAAC,EAAE,EAC3B;CACF;CAEA,IAAmB,SAAmD;EACpE,OAAO,KAAK,IAAI,MAAM,OACpB,MAAM,KAAK,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,GAAG,IAAI,SAElD,UACG,KAAK,KAAK,IAAO,OAAgC,IACjD,KAAK,KAAK,IAAO,IACtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAC3B;CACF;AACF;;AAGA,SAAgB,QAAQ,MAAkB,SAAiB,KAA+B;CACxF,MAAM,SAAS,MAAM;CACrB,MAAM,WAAW;EACf,QAAQ,KAA6B;GACnC,OAAO,IAAI,eAAe,KAAK,QAAQ,GAAG,GAAG,QAAQ,KAAK,KAAK,CAAC,CAAC;EACnE;EACA,MACE,YACwB;GACxB,MAAM,YAAY,WAAW,KAAK,MAAO,aAAa,iBAAiB,EAAE,YAAY,CAAE;GACvF,MAAM,OAAO,EACX,YAAY,WAAW,KAAK,MAC1B,aAAa,iBACT;IAAE,KAAK,EAAE;IAAK,QAAQ,OAAO,EAAE,MAAM;GAAE,IACvC,uBACN,EACF;GACA,OAAO,IAAI,MAAM,OACf,MAAM,KAAK,QAAQ,SAAS,MAAM,KAAK,SACjC,KAAK,MAAS,SAAkC,IACrD,QAAQ;IACP,SAAS,GAAG,QAAQ,GAAG,MAAM,KAAK,EAAE,KAAK,WAAW,IAAI,CAAC;IACzD,YAAY,GAAG;GACjB,EACF;EACF;EACA,KAAK,KAAoC;GACvC,OAAO,IAAI,MAAM,OACf,MAAM,KAAK,QAAQ,QAAQ,EAAE,IAAI,GAAG,KAAK,SACnC,KAAK,KAAK,GAAG,IAClB,OAAO;IAAE,OAAO,EAAE;IAAO,UAAU;GAAE,EACxC;EACF;CACF;CACA,OAAO,IAAI,MAAM,MAAM,EACrB,IAAI,KAAK,MAAM,UAAU;EACvB,IAAI,QAAQ,UAAU,OAAO,SAAS;EACtC,MAAM,QAAQ,QAAQ,IAAI,KAAK,MAAM,QAAQ;EAC7C,IAAI,OAAO,UAAU,YAAY;GAC/B,IAAI,MAAM,YAAY,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,iBAAiB;GACrE,OAAQ,MAAuC,KAAK,GAAG;EACzD;EACA,OAAO;CACT,EACF,CAAC;AACH;;;;;;AAOA,SAAgB,SAAS,KAAgC;CACvD,MAAM,MAAgB,CAAC;CACvB,IAAI,MAAM;CACV,IAAI,QAAQ;CACZ,IAAI,IAAI;CACR,MAAM,cAAc,MAAmC,MAAM,KAAA,KAAa,eAAe,KAAK,CAAC;CAC/F,OAAO,IAAI,IAAI,QAAQ;EACrB,MAAM,IAAI,IAAI;EACd,MAAM,OAAO,IAAI,IAAI;EACrB,IAAI,MAAM,OAAO,SAAS,KAAK;GAC7B,OAAO,IAAI,IAAI,UAAU,IAAI,OAAO,MAAM;GAC1C;EACF;EACA,IAAI,MAAM,OAAO,SAAS,KAAK;GAC7B,MAAM,MAAM,IAAI,QAAQ,MAAM,IAAI,CAAC;GACnC,IAAI,QAAQ,KAAK,IAAI,SAAS,MAAM;GACpC;EACF;EACA,IAAI,MAAM,OAAO,MAAM,QAAO,MAAM,OAAO,MAAM,KAAK;GACpD,MAAM,QAAQ,MAAM,MAAM,MAAM;GAChC,IAAI,IAAI,IAAI;GACZ,SAAS;IACP,MAAM,IAAI,IAAI,QAAQ,OAAO,CAAC;IAC9B,IAAI,MAAM,IAAI;KACZ,IAAI,IAAI;KACR;IACF;IACA,IAAI,UAAU,OAAO,IAAI,IAAI,OAAO,OAAO;KACzC,IAAI,IAAI;KACR;IACF;IACA,IAAI,IAAI;IACR;GACF;GACA,OAAO,IAAI,MAAM,GAAG,CAAC;GACrB,IAAI;GACJ;EACF;EACA,IAAI,WAAW,CAAC,KAAK,CAAC,WAAW,IAAI,IAAI,EAAE,GAAG;GAC5C,IAAI,IAAI;GACR,OAAO,WAAW,IAAI,EAAE,GAAG;GAC3B,MAAM,OAAO,IAAI,MAAM,GAAG,CAAC;GAC3B,MAAM,QAAQ,KAAK,YAAY;GAC/B,IAAI,UAAU,WAAW,UAAU,QAAQ;QACtC,IAAI,UAAU,SAAS,QAAQ,GAAG;GACvC,OAAO;GACP,IAAI;GACJ;EACF;EACA,IAAI,MAAM,OAAO,UAAU,GAAG;GAC5B,MAAM,YAAY,IAAI,KAAK;GAC3B,IAAI,UAAU,SAAS,GAAG,IAAI,KAAK,SAAS;GAC5C,MAAM;GACN;GACA;EACF;EACA,OAAO;EACP;CACF;CACA,MAAM,OAAO,IAAI,KAAK;CACtB,IAAI,KAAK,SAAS,GAAG,IAAI,KAAK,IAAI;CAClC,OAAO;AACT;;AAGA,eAAsB,QAAQ,MAAkB,QAA+B;CAC7E,MAAM,SAAS,MAAM,KAClB,QACC,4HACF,CAAC,CACA,IAAsB;CACzB,KAAK,MAAM,EAAE,UAAU,OAAO,SAC5B,MAAM,KAAK,QAAQ,yBAAyB,KAAK,QAAQ,MAAM,MAAI,EAAE,EAAE,CAAC,CAAC,IAAI;CAE/E,KAAK,MAAM,aAAa,SAAS,MAAM,GACrC,MAAM,KAAK,QAAQ,SAAS,CAAC,CAAC,IAAI;AAEtC;;AAGA,eAAsB,WACpB,MAC6D;CAC7D,MAAM,SAAS,MAAM,KAClB,QACC,0IACF,CAAC,CACA,IAAsB;CACzB,MAAM,MAAmC,CAAC;CAC1C,KAAK,MAAM,EAAE,UAAU,OAAO,SAI5B,IAAI,SAAQ,MAHO,KAChB,QAAQ,kBAAkB,KAAK,QAAQ,MAAM,MAAI,EAAE,EAAE,CAAC,CACtD,IAA6B,EAAA,CACf,QACd,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,CACrB,KAAK,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAU,CAAC,CAC1C,MAAM,GAAG,MAAO,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAE,CAAC,CACxD,KAAK,GAAG,OAAO,CAAC;CAErB,OAAO;AACT;;ACvPA,MAAM,MAA4B,CAAC,gBAAgB,aAAa;AAChE,MAAM,UAAgC,CAAC,SAAS;AAiBhD,SAASA,OAAK,OAAqC;CACjD,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAgC,YAAY,cACpD,OAAQ,MAA8B,UAAU;AAEpD;AAEA,SAAS,cAAc,OAAyB;CAC9C,IAAI,OAAO,UAAU,YAAY,OAAO;CACxC,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,QAAQ,OAAO,eAAe,KAAK;CAEzC,OAAO,CADQ,GAAG,OAAO,oBAAoB,KAAK,GAAG,GAAG,OAAO,oBAAoB,SAAS,CAAC,CAAC,CACnF,CAAC,CAAC,MACV,MAAM,MAAM,iBAAiB,OAAQ,MAAkC,OAAO,UACjF;AACF;;AAGA,SAAS,UAAU,OAA6B;CAC9C,OAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACzC;AAEA,MAAM,cAAiC;CACrC;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,yBAAyB,SAA8C;CACrF,MAAM,MAAM,QAAQ;CACpB,MAAM,aAAa,QAAQ,cAAc;CACzC,IAAI,oBAAoB;CACxB,IAAI,WAA4B;CAEhC,MAAM,MAAoB;EACxB,IAAI,QAAQ;GACV,IAAI,CAAC,UAAU,MAAM,IAAI,MAAM,oBAAoB;GACnD,OAAO;EACT;EACA,yBAAyB;CAC3B;CAEA,MAAM,4BAAY,IAAI,IAAwB;CAC9C,MAAM,aAAa,IAAI,MAAM,KAAK,EAChC,IAAI,QAAQ,MAAM,UAAU;EAC1B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;EAChD,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,IAAIA,OAAK,KAAK,GAAG;GACf,IAAI,IAAI,UAAU,IAAI,IAAI;GAC1B,IAAI,CAAC,GAAG;IACN,IAAI,QAAQ,OAAO,MAAM,GAAG;IAC5B,UAAU,IAAI,MAAM,CAAC;GACvB;GACA,OAAO;EACT;EACA,IAAI,cAAc,KAAK,GAAG,IAAI,MAAM,YAAY,WAAW,KAAK,gBAAgB;EAChF,OAAO;CACT,EACF,CAAC;;CAGD,MAAM,sCAAsB,IAAI,QAA0B;CAC1D,SAAS,mBAAmB,OAAyB;EACnD,IAAI,KAAK,oBAAoB,IAAI,KAAK;EACtC,IAAI,OAAO,KAAA,GAAW;GACpB,KAAK;GACL,MAAM,gBAAgB,EAAE;GACxB,oBAAoB,IAAI,OAAO,EAAE;EACnC;EACA,OAAO;CACT;CAEA,OAAO;EACL,MAAM;EACN;EAEA,MAAM,MAAM,MAAmC;GAC7C,KAAK,MAAM,QAAQ,KAAK,OAAO;IAC7B,IAAI,KAAK,SAAS,MAAM;IACxB,MAAM,UAAU,OAAO,KAAK,UAAU;IACtC,MAAM,SAAS,QAAQ,QAAQ;IAC/B,IAAI,WAAW,KAAA,GAAW,MAAM,IAAI,MAAM,qCAAqC,SAAS;IACxF,MAAM,OAAO,IAAI;IACjB,IAAI,CAACA,OAAK,IAAI,GAAG,MAAM,IAAI,MAAM,OAAO,QAAQ,qBAAqB;IACrE,MAAM,QAAQ,MAAM,MAAM;GAC5B;EACF;EAEA,eAAe,MAAoB,SAA0C;GAC3E,MAAM,QAAQ,KAAK;GACnB,OAAO;IACL,GAAG;IACH,OAAO;KAAE,GAAG;KAAO,UAAU,MAAM,SAAS,QAAQ,MAAM,QAAQ,SAAS,EAAE,EAAE,CAAC;IAAE;GACpF;EACF;EAEA,MAAM,OAAO,MAAoB,OAAgC;GAC/D,KAAK,MAAM,QAAQ,KAAK,OAAO;IAC7B,IAAI,KAAK,SAAS,MAAM;IACxB,MAAM,UAAU,OAAO,KAAK,UAAU;IACtC,MAAM,OAAO,IAAI;IACjB,IAAI,CAACA,OAAK,IAAI,GAAG;IACjB,MAAM,SAAS,MAAM,WAAW,IAAI;IACpC,MAAM,SAAS,mBAAmB,KAAK,GAAG,MAAM,WAAW,EAAE,OAAO,CAAC;GACvE;EACF;EAEA,cAAc,MAAyC;GACrD,MAAM,QAAQ,KAAK;GACnB,IAAI,MAAM,SAAS,SACjB,MAAM,IAAI,MAAM,SAAS,MAAM,KAAK,iDAAiD;GAEvF,OAAO,MAAM,SAAS,KAAK,OAAO;IAAE,IAAI,EAAE;IAAI,SAAS;IAAG,MAAM,EAAE;GAAK,EAAE;EAC3E;EAEA,MAAM,QAAQ,OAAiB,OAAiB,MAA6C;GAC3F,MAAM,QAAQ,KAAK;GACnB,MAAM,cAAc,SAAS,MAAM;GACnC,MAAM,aAAa,GAAG,MAAM,GAAG,GAAG,MAAM;GACxC,WAAW;GACX,oBAAoB;GACpB,MAAM,MAAM,MAAM,gBAAgB,UAAU;;GAE5C,MAAM,QAA8C,EAAE,UAAU,KAAK;GACrE,MAAM,aAAiC,CAAC;;GAGxC,MAAM,UAAU,IAAqB,SAA0B;IAC7D,MAAM,WACJ;KAAE;KAAY,QAAQ;KAAa;KAAI;KAAM,SAAS;IAAI,SACpD;KACJ,IAAI,MAAM,aAAa,MAAM,OAAO;KACpC,MAAM,WAAW;KACjB,OAAO;IACT,IACC,eAAe,EAAE,UAAU,EAC9B;GACF;GACA,MAAM,UAA4B;IAChC,IAAI,MAAM;IACV,2BAAW,IAAI,KAAK;IACpB,MAAM,UAAU,MAAM,IAAI;IAC1B,UAAU,MAAM;IAChB,WAAW,OAAO,OAAO;KAAE,WAAW,MAAM;KAAI,UAAU;KAAO,MAAM,MAAM;IAAK,CAAC;IACnF,aAAa,OAAO,SAAS;KAAE,WAAW,MAAM;KAAI,MAAM,MAAM;IAAK,CAAC;GACxE;GACA,MAAM,QAA+B;IACnC,OAAO,MAAM;IACb,UAAU,CAAC,OAAO;IAClB,UAAU,EAAE,SAAS;KAAE,cAAc;KAAG,cAAc;IAAE,EAAE;IAC1D,cAAc,QAAQ,IAAI;IAC1B,gBAAgB,QAAQ,MAAM;GAChC;GACA,MAAM,YAA8B;IAClC,YAAY,YAA8B;KACxC,WAAW,KACT,QAAQ,WACA,KAAA,SACA,KAAA,CACR,CACF;IACF;IACA,8BAA8B,CAAC;IAC/B,OAAO,CAAC;GACV;GAEA,MAAM,UAAU,QAAQ,QAAQ;GAChC,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,mCAAmC;GACjE,MAAM,UAAU,QAAQ,QAAQ,CAAC,CAC9B,WAAW,QAAQ,KAAK,QAAQ,SAAS,OAAO,YAAY,SAAS,CAAC,CAAC,CACvE,WACO,cACL,QACC,eAAe,cAAe,YAAuB,SACzD;GACF,IAAI,SAAS,MAAM,QAAQ,KAAK,CAC9B,MAAM,OAAO,SAAS,UAAU,GAChC,IAAI,QAAQ,WAAW,SAAkB,CAC3C,CAAC;GAED,IAAI,WAAW,eAAe,MAAM,aAAa,MAC/C,IAAI;IACF,OAAO,OAAO;KAAE,WAAW,MAAM;KAAI,UAAU;KAAM,MAAM,MAAM;IAAK,CAAC;GACzE,SAAS,KAAK;IACZ,IAAI,eAAe,aAAa,SAAS;SACpC,MAAM;GACb;GAKF,IAAI,WAAW,SAAS,KAAK,CAAC,IAAI,UAAU,GAC1C,IAAI;IACF,MAAM,WACJ;KACE;KACA,QAAQ;KACR,IAAI;KACJ,MAAM,EAAE,SAAS,WAAW,OAAO;KACnC,SAAS;IACX,SACM,YACA,IACR;IACA,MAAM,QAAQ,KAAK,CAAC,MAAM,OAAO,QAAQ,IAAI,UAAU,GAAG,UAAU,GAAG,IAAI,OAAO,CAAC;GACrF,SAAS,KAAK;IACZ,IAAI,EAAE,eAAe,cAAc,MAAM;IACzC,SAAS;GACX;GAGF,MAAM,YAAwB,CAAC;GAC/B,IAAI,MAAM,aAAa,OAAO;IAC5B,MAAM,eAAe,MAAM,UAAU;IACrC,IAAI,MAAM,WAAW,cAAc,eAAe,KAAK,OAAO,iBAC5D,UAAU,KAAK;KAAE,GAAG;KAAO,SAAS,MAAM,UAAU;IAAE,CAAC;SAEvD,MAAM,WACJ;KACE,YAAY,mBAAmB,KAAK;KACpC,QAAQ;KACR,IAAI;KACJ,MAAM;MAAE,WAAW,MAAM;MAAI,UAAU,MAAM;KAAQ;KACrD,SAAS,CAAC;IACZ,SACM,YACA,IACR;GAEJ;GACA,oBAAoB;GACpB,OAAO;IAAE;IAAQ;GAAU;EAC7B;CACF;AACF;;;;;;;;;;;AChOA,IAAM,aAAN,cAAyB,MAAM;CAC7B,OAAyB;CACzB,cAAc;EACZ,MACE,yFACF;CACF;AACF;;;;;;AAOA,SAAS,WAAW,MAAkB,IAAmB,OAAiC;CACxF,MAAM,yBAAS,IAAI,QAAqC;CACxD,MAAM,QAAQ,OAAU,MAA8B;EACpD,GAAG;EACH,IAAI;GACF,OAAO,MAAM;EACf,UAAU;GACR,GAAG;GACH,MAAM,QAAA,CAAuB;EAC/B;CACF;CACA,MAAM,iBAAiB,MAAgD;EACrE,MAAM,QAAQ,IAAI,MAAM,GAAG,EACzB,IAAI,GAAG,MAAM,GAAG;GACd,MAAM,IAAI,QAAQ,IAAI,GAAG,MAAM,CAAC;GAChC,IAAI,SAAS,QAAQ,QAAQ,GAAG,MAAiB,cAAc,EAAE,KAAK,GAAG,CAAC,CAAC;GAC3E,IAAI,SAAS,SAAS,SAAS,SAAS,SAAS,WAAW,SAAS,OACnE,QAAQ,GAAG,MACT,MAAO,EAA4C,MAAM,GAAG,CAAC,CAAC;GAElE,OAAO,OAAO,MAAM,aAAc,EAAmC,KAAK,CAAC,IAAI;EACjF,EACF,CAAC;EACD,OAAO,IAAI,OAAO,CAAC;EACnB,OAAO;CACT;CACA,OAAO,IAAI,MAAM,MAAM,EACrB,IAAI,GAAG,MAAM,GAAG;EACd,MAAM,IAAI,QAAQ,IAAI,GAAG,MAAM,CAAC;EAChC,IAAI,SAAS,WAAW,QAAQ,QAAgB,cAAc,EAAE,QAAQ,GAAG,CAAC;EAC5E,IAAI,SAAS,SACX,QAAQ,UACN,MAAM,EAAE,MAAM,MAAM,KAAK,MAAM,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;EAEvD,IAAI,SAAS,QAAQ,QAAQ,QAAgB,MAAM,EAAE,KAAK,GAAG,CAAC;EAC9D,OAAO,OAAO,MAAM,aAAc,EAAmC,KAAK,CAAC,IAAI;CACjF,EACF,CAAC;AACH;AAEA,SAAS,KAAK,OAAqC;CACjD,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAgC,YAAY;AAExD;AAEA,eAAe,YACb,MACA,SACwB;CACxB,MAAM,MAAM,QAAQ;CACpB,MAAM,MAA0E,CAAC;CACjF,KAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,IAAI,KAAK,SAAS,MAAM;EACxB,MAAM,UAAU,OAAO,KAAK,UAAU;EACtC,MAAM,OAAO,IAAI;EACjB,IAAI,KAAK,IAAI,GAAG,IAAI,WAAW,MAAM,WAAW,IAAI;CACtD;CACA,OAAO;AACT;;AAGA,eAAe,WACb,MACA,SAC6D;CAC7D,MAAM,WAAW,yBAAyB,OAAO;CACjD,MAAM,MAAM,IAAI,IAAI;EAClB,MAAM;EACN,UAAU;GAAE,MAAM;GAAG,QAAQ,CAAC;EAAE;EAChC,QAAQ,KAAK;EACb,kBAAkB;CACpB,CAAC;CACD,MAAM,WAA4B,CAAC;CACnC,IAAI,QAAQ;CACZ,IAAI;EACF,MAAM,SAAS,MAAM,IAAI;EACzB,MAAM,UAAsB,CAAC,GAAG,SAAS,cAAc,IAAI,CAAC;EAC5D,OAAO,QAAQ,SAAS,GAAG;GACzB,MAAM,QAAQ,QAAQ,MAAM;GAC5B,MAAM,aAAa,GAAG,MAAM,GAAG,GAAG,MAAM;GACxC,MAAM,SAAS,IAAI,IAAI,QAAQ;GAC/B,MAAM,SAAS,MAAM,SAAS,QAAQ,OAAO,KAAK,IAAI;GACtD,MAAM,WAAW,IAAI,IAAI,QACtB,MAAM,MAAM,CAAC,CACb,MACE,MACC,EAAE,eAAe,cACjB,EAAE,SAAS,aACV,EAAE,OAAO,SAAS,EAAE,OAAO,YAC5B,QAAQ,EAAE,SAAS,kBAAkB,MAAM,IAC/C,CAAC,EAAE;GACL,SAAS,KAAK;IACZ,OAAO,MAAM;IACb,SAAS,MAAM;IACf,QAAQ,OAAO,WAAW,cAAc,cAAc;IACtD,UAAU,YAAY;GACxB,CAAC;GACD,QAAQ,KAAK,GAAG,OAAO,SAAS;EAClC;EACA,MAAM,SAAS,SAAS,MAAM,GAAG;CACnC,UAAU;EACR,IAAI,UAAU;CAChB;CACA,OAAO;EAAE;EAAU,OAAO,MAAM,YAAY,MAAM,OAAO;EAAG,aAAa,IAAI;CAAmB;AAClG;;AAGA,eAAe,QAAQ,MAAoB,SAAmD;CAC5F,MAAM,MAAM,QAAQ;CACpB,MAAM,QAAQ,KAAK;CACnB,MAAM,aAAa,QAAQ,cAAc;CACzC,KAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,IAAI,KAAK,SAAS,MAAM;EACxB,MAAM,UAAU,OAAO,KAAK,UAAU;EACtC,MAAM,SAAS,QAAQ,QAAQ;EAC/B,MAAM,OAAO,IAAI;EACjB,IAAI,WAAW,KAAA,KAAa,KAAK,IAAI,GAAG,MAAM,QAAQ,MAAM,MAAM;CACpE;CACA,MAAM,UAAU,QAAQ,QAAQ;CAChC,IAAI,CAAC,SAAS,MAAM,IAAI,MAAM,mCAAmC;CACjE,MAAM,WAA4B,CAAC;CACnC,MAAM,UAAsB,MAAM,SAAS,KAAK,OAAO;EAAE,IAAI,EAAE;EAAI,SAAS;EAAG,MAAM,EAAE;CAAK,EAAE;CAE9F,MAAM,UAAU,aAAa,CAAC;CAC9B,MAAM,KAAK,EAAE,GAAG,EAAE;CAClB,MAAM,2BAAW,IAAI,IAAwB;CAC7C,MAAM,aAAa,IAAI,MAAM,KAAK,EAChC,IAAI,QAAQ,MAAM,UAAU;EAC1B,MAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;EAChD,IAAI,OAAO,SAAS,YAAY,CAAC,KAAK,KAAK,GAAG,OAAO;EACrD,IAAI,IAAI,SAAS,IAAI,IAAI;EACzB,IAAI,CAAC,GAAG;GACN,IAAI,WAAW,OAAO,IAAI,QAAQ,KAAK;GACvC,SAAS,IAAI,MAAM,CAAC;EACtB;EACA,OAAO;CACT,EACF,CAAC;CACD,MAAM,UAAa,MACjB,SAAS,GAAG;EACV,OAAO,QAAQ;EACf,gBAAgB,GAAG;EACnB,eAAe;EACf,aAAa;GACX,MAAM,IAAI,WAAW;EACvB;CACF,CAAC;CACH,IAAI;EACF,OAAO,QAAQ,SAAS,GAAG;GACzB,MAAM,QAAQ,QAAQ,MAAM;GAC5B,IAAI,WAAmC;GACvC,MAAM,aAAiC,CAAC;GACxC,MAAM,UAA4B;IAChC,IAAI,MAAM;IACV,2BAAW,IAAI,KAAK;IACpB,MAAM,KAAK,MAAM,KAAK,UAAU,MAAM,IAAI,CAAC;IAC3C,UAAU,MAAM;IAChB,WAAW;KACT,aAAa;IACf;IACA,aAAa;KACX,aAAa;IACf;GACF;GACA,MAAM,QAA+B;IACnC,OAAO,MAAM;IACb,UAAU,CAAC,OAAO;IAClB,UAAU,EAAE,SAAS;KAAE,cAAc;KAAG,cAAc;IAAE,EAAE;IAC1D,cAAc,QAAQ,IAAI;IAC1B,gBAAgB,QAAQ,MAAM;GAChC;GACA,MAAM,MAAM;IACV,YAAY,MAAwB;KAClC,WAAW,KACT,EAAE,WACM,KAAA,SACA,KAAA,CACR,CACF;IACF;IACA,8BAA8B,CAAC;IAC/B,OAAO,CAAC;GACV;GACA,IAAI;GACJ,IAAI;IACF,MAAM,OACJ,QAAQ,QAAQ,CAAC,CAAC,WAAW,QAAQ,KAAK,QAAQ,SAAS,OAAO,YAAY,GAAG,CAAC,CACpF;IACA,SAAS;GACX,SAAS,KAAK;IACZ,IAAI,eAAe,eAAe,eAAe,YAAY,MAAM;IACnE,SAAS;GACX;GACA,IAAI,WAAW,aAAa,aAAa;GACzC,MAAM,OAAO,QAAQ,IAAI,UAAU,CAAC;GACpC,SAAS,KAAK;IAAE,OAAO,MAAM;IAAI,SAAS,MAAM;IAAS;IAAQ;GAAS,CAAC;GAC3E,IACE,aAAa,SACb,MAAM,WAAW,cACjB,MAAM,UAAU,IAAI,KAAK,OAAO,iBAEhC,QAAQ,KAAK;IAAE,GAAG;IAAO,SAAS,MAAM,UAAU;GAAE,CAAC;EAEzD;CACF,UAAU;EACR,QAAQ,QAAQ;CAClB;CACA,OAAO;EAAE;EAAU,OAAO,MAAM,YAAY,MAAM,OAAO;CAAE;AAC7D;;AAGA,eAAsB,gBACpB,MACA,SAC6B;CAC7B,MAAM,EAAE,aAAa,GAAG,WAAW,MAAM,WAAW,MAAM,OAAO;CACjE,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO;CACvC,MAAM,cAAwB,CAAC;CAC/B,IAAI,YAAY,SAAS,GACvB,YAAY,KAAK,6CAA6C,YAAY,KAAK,IAAI,GAAG;CAExF,MAAM,IAAI,cAAc,OAAO,QAAgC;CAC/D,MAAM,IAAI,cAAc,IAAI,QAAgC;CAC5D,IAAI,MAAM,GAAG,YAAY,KAAK,8BAA8B,EAAE,aAAa,GAAG;CAC9E,MAAM,2BAAW,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,OAAO,KAAK,GAAG,GAAG,OAAO,KAAK,IAAI,KAAK,CAAC,CAAC;CAClF,KAAK,MAAM,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,KAAK,GAAG;EAC1C,MAAM,yBAAS,IAAI,IAAI,CACrB,GAAG,OAAO,KAAK,OAAO,MAAM,YAAY,CAAC,CAAC,GAC1C,GAAG,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC,CAAC,CACzC,CAAC;EACD,KAAK,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,GAAG;GACtC,MAAM,IAAI,cAAe,OAAO,MAAM,QAAQ,GAAG,UAAU,CAAC,CAA0B;GACtF,MAAM,IAAI,cAAe,IAAI,MAAM,QAAQ,GAAG,UAAU,CAAC,CAA0B;GACnF,IAAI,MAAM,GAAG,YAAY,KAAK,GAAG,QAAQ,GAAG,MAAM,sBAAsB,EAAE,aAAa,GAAG;EAC5F;CACF;CACA,OAAO;EAAE,OAAO,YAAY,WAAW;EAAG;EAAQ;EAAK;EAAa;CAAY;AAClF;;;;;;;;ACpPA,SAAgB,MAAM,MAAc,UAA+C;CACjF,OAAO;EACL,MAAM;EACN,OAAO;EACP,UAAU,SAAS,KAAK,GAAG,OAAO;GAAE,IAAI,EAAE,MAAM,OAAO,IAAI;GAAK,MAAM,EAAE;EAAK,EAAE;CACjF;AACF;AAEA,SAAgB,SAAS,SAAiB,YAA6B;CACrE,OAAO;EAAE,MAAM;EAAM;EAAS;CAAW;AAC3C;;;;;;;AAQA,SAAgB,QAAQ,SAAiB,KAAsB,OAAuB;CACpF,OAAO;EAAE,QAAQ,MAAM;EAAW;EAAI,MAAM;EAAU,SAAS,EAAE,kBAAkB,EAAE;CAAE;AACzF;;AAGA,SAAgB,QAAQ,OAAuB;CAC7C,OAAO,eAAe;AACxB;AAEA,SAAgB,iBACd,MACA,QACA,KACkB;CAClB,OAAO;EAAE,MAAM;EAAoB;EAAM;EAAQ;CAAI;AACvD;AAEA,SAAgB,YACd,MACA,QACA,KACA,UACa;CACb,OAAO;EAAE,MAAM;EAAe;EAAM;EAAQ;EAAK;CAAS;AAC5D;;;;;AAMA,SAAgB,sBACd,MACA,OACA,QACA,KACA,SACa;CACb,MAAM,WAAwB,CAAC;CAC/B,KAAK,MAAM,KAAK,MAAM,UAAU;EAC9B,MAAM,IAAI,QAAQ,EAAE,MAAM,OAAO;EACjC,IAAI,MAAM,KAAA,GACR,MAAM,IAAI,MAAM,WAAW,EAAE,GAAG,UAAU,KAAK,UAAU,OAAO,EAAE,aAAa;EAEjF,SAAS,KAAK,CAAC;CACjB;CACA,OAAO;EAAE,GAAG,YAAY,MAAM,QAAQ,KAAK,QAAQ;EAAG,YAAY,EAAE,QAAQ;CAAE;AAChF;;AAGA,SAAgB,OACd,SACA,OACA,OACY;CACZ,OAAO,QAAQ;EAAE,QAAQ,MAAM;EAAW;EAAO;CAAM,IAAI;EAAE,QAAQ,MAAM;EAAW;CAAM;AAC9F;;AAGA,SAAgB,SACd,MACA,OACA,OACU;CACV,OAAO;EAAE,MAAM;EAAY;EAAM;EAAO;CAAM;AAChD;;AAGA,SAAgB,QACd,MACA,MACA,KACA,OACA,QACS;CACT,OAAO;EAAE,MAAM;EAAW;EAAM;EAAM;EAAK;EAAO;CAAO;AAC3D;;AAGA,SAAgB,SAAS,WAAmC;CAC1D,OAAO;EACL,QAAQ,SAAS;EACjB,IAAI;EACJ,MAAM;EACN,OAAO,EAAE,oBAAoB,KAAK;CACpC;AACF;;AAGA,SAAgB,eAAe,OAA8C;CAC3E,MAAM,QACJ,cAAc,MAAM,SACpB,MAAM,MAAM,SAAS,OAAO,MAAM,QAAQ,KAAK,OAAO,EAAE,OAAO,QAAQ,IAClE,MAAM,QACP,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,QAAQ;CACnD,MAAM,OAAqB;EACzB,SAAS;EACT,MAAM,MAAM;EACZ,QAAQ,MAAM;EACd;EACA,OAAO,MAAM,SAAS,CAAC;EACvB,WAAW,MAAM,aAAa,CAAC;EAC/B,YAAY,MAAM;EAClB,QAAQ;GAAE,GAAG;GAAe,GAAG,MAAM;EAAO;CAC9C;CACA,MAAM,SAAS,iBAAiB,IAAI;CACpC,IAAI,OAAO,SAAS,GAClB,MAAM,IAAI,MAAM,oBAAoB,KAAK,UAAU,MAAM,IAAI,EAAE,OAAO,OAAO,KAAK,MAAM,GAAG;CAE7F,OAAO;AACT"}
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Canonical JSON: the one serialisation of a value, so that equal data always
3
+ * produces equal bytes. Object keys are sorted; numbers must be finite; there
4
+ * is no whitespace. Anything that is not plain JSON data is rejected.
5
+ */
6
+ type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
7
+ readonly [key: string]: JsonValue;
8
+ };
9
+ /** `snapshot` records platform state (e.g. D1 tables) captured at the end of a run; it is not an effect point. */
10
+ type EffectKind = "call" | "result" | "fault" | "snapshot";
11
+ interface EffectRecord {
12
+ /** Position in the log, dense from 0. */
13
+ readonly seq: number;
14
+ readonly kind: EffectKind;
15
+ /** The invocation (request, message, alarm) this effect belongs to. */
16
+ readonly invocation: string;
17
+ /** The binding or global the effect went through, e.g. "D1:DB". */
18
+ readonly target: string;
19
+ /** The operation, e.g. "run", "batch", "send". */
20
+ readonly op: string;
21
+ /** Operation-specific data: arguments, results, or the injected fault. */
22
+ readonly payload: JsonValue;
23
+ }
24
+ interface EffectLog {
25
+ readonly entries: readonly EffectRecord[];
26
+ }
27
+ /**
28
+ * `cut_off` is a crash that happens after a response or acknowledgement was
29
+ * already sent, so only background work (ctx.waitUntil) is lost; platforms
30
+ * offer it at the point where that work would start.
31
+ */
32
+ type FaultKind = "crash_before" | "crash_after" | "ambiguous" | "error" | "cut_off";
33
+ interface FaultDecision {
34
+ /** The invocation the effect belongs to, e.g. "msg-1#2". */
35
+ readonly invocation: string;
36
+ /** Position of the effect within that invocation, from 0. Stable when other invocations are removed. */
37
+ readonly ordinal: number;
38
+ readonly fault: FaultKind;
39
+ /** What the effect was, for people reading the schedule. */
40
+ readonly target: string;
41
+ readonly op: string;
42
+ }
43
+ interface Schedule {
44
+ /** The per-run seed the decisions were drawn from. */
45
+ readonly seed: number;
46
+ readonly faults: readonly FaultDecision[];
47
+ }
48
+ /** Picks effect records by target, op, kind and payload fields. */
49
+ interface EffectSelector {
50
+ readonly target: string;
51
+ readonly op?: string;
52
+ readonly kind?: EffectKind;
53
+ /** Dot paths into the payload that must equal the given values. */
54
+ readonly where?: {
55
+ readonly [path: string]: JsonValue;
56
+ };
57
+ /** Dot paths into the payload whose numeric value must be at least the given bound. */
58
+ readonly atLeast?: {
59
+ readonly [path: string]: number;
60
+ };
61
+ }
62
+ /** No two selected effects share the same key. Catches duplicate writes. */
63
+ interface AtMostOncePerKey {
64
+ readonly kind: "atMostOncePerKey";
65
+ readonly name: string;
66
+ readonly effect: EffectSelector;
67
+ /** Dot path into the payload that identifies the key. */
68
+ readonly key: string;
69
+ }
70
+ /** Every expected key appears in at least one selected effect. Catches lost work. */
71
+ interface AtLeastOnce {
72
+ readonly kind: "atLeastOnce";
73
+ readonly name: string;
74
+ readonly effect: EffectSelector;
75
+ readonly key: string;
76
+ readonly expected: readonly JsonValue[];
77
+ /** Set when `expected` was derived from the drive's message bodies, so it can be re-derived when messages are removed. */
78
+ readonly perMessage?: {
79
+ readonly bodyKey: string;
80
+ };
81
+ }
82
+ /** A condition on one column of a row. */
83
+ type RowCondition = {
84
+ readonly column: string;
85
+ readonly op: "eq" | "neq";
86
+ readonly value: JsonValue;
87
+ } | {
88
+ readonly column: string;
89
+ readonly op: "gt" | "gte" | "lt" | "lte";
90
+ readonly value: number;
91
+ } | {
92
+ readonly column: string;
93
+ readonly op: "in";
94
+ readonly value: readonly JsonValue[];
95
+ } | {
96
+ readonly column: string;
97
+ readonly op: "notNull";
98
+ };
99
+ /** Rows of a table in the last snapshot of a target, optionally filtered. */
100
+ interface StateQuery {
101
+ /** The snapshot target, e.g. "D1:DB". */
102
+ readonly target: string;
103
+ readonly table: string;
104
+ readonly where?: readonly RowCondition[];
105
+ }
106
+ /** Every row the query returns satisfies all of `holds`. */
107
+ interface EveryRow {
108
+ readonly kind: "everyRow";
109
+ readonly name: string;
110
+ readonly query: StateQuery;
111
+ readonly holds: readonly RowCondition[];
112
+ }
113
+ /**
114
+ * For every selected effect, a row exists whose `column` equals the effect's
115
+ * key. Ties what the shell did to what the state says, e.g. "every acked
116
+ * message has its payment row".
117
+ */
118
+ interface Implies {
119
+ readonly kind: "implies";
120
+ readonly name: string;
121
+ readonly when: EffectSelector;
122
+ /** Dot path into the effect payload that yields the key. */
123
+ readonly key: string;
124
+ readonly state: StateQuery;
125
+ readonly column: string;
126
+ }
127
+ type Invariant = AtMostOncePerKey | AtLeastOnce | EveryRow | Implies;
128
+ interface Violation {
129
+ readonly invariant: string;
130
+ readonly message: string;
131
+ /** The keys involved, in canonical JSON, so two violations can be compared across runs. */
132
+ readonly keys: readonly string[];
133
+ /** Sequence numbers of the effects that witness the violation. */
134
+ readonly evidence: readonly number[];
135
+ }
136
+ declare function checkInvariant(log: EffectLog, inv: Invariant): Violation | null;
137
+ declare function checkInvariants(log: EffectLog, invariants: readonly Invariant[]): readonly Violation[];
138
+ /** Opaque, JSON-shaped data owned by a platform package. `kind` names its shape. */
139
+ interface PlatformData {
140
+ readonly kind: string;
141
+ readonly [key: string]: JsonValue;
142
+ }
143
+ /** Where the Worker under test lives, relative to the scenario file. */
144
+ interface WorkerRef {
145
+ readonly entry: string;
146
+ readonly config: string;
147
+ }
148
+ /** An external service the Worker talks to, and what it promises. */
149
+ interface ExternalDecl {
150
+ readonly name: string;
151
+ /** Host pattern for outbound requests, e.g. "api.stripe.com". */
152
+ readonly host: string;
153
+ readonly guarantees: {
154
+ /** Header whose value makes repeated requests idempotent, if any. */
155
+ readonly dedupeBy?: string;
156
+ };
157
+ }
158
+ /** Exploration bounds. Every verdict reports the bounds actually reached. */
159
+ interface Bounds {
160
+ readonly maxFaultsPerRun: number;
161
+ readonly maxRedeliveries: number;
162
+ readonly maxConcurrentInvocations: number;
163
+ readonly budgetMs: number;
164
+ }
165
+ interface ScenarioSpec {
166
+ readonly version: 1;
167
+ readonly name: string;
168
+ readonly worker: WorkerRef;
169
+ /** How the scenario drives the Worker (which events, with what payloads). */
170
+ readonly drive: PlatformData;
171
+ /** State to establish before each run, in order. */
172
+ readonly setup: readonly PlatformData[];
173
+ readonly externals: readonly ExternalDecl[];
174
+ readonly invariants: readonly Invariant[];
175
+ readonly bounds: Bounds;
176
+ }
177
+ /** Every reason a spec is not usable; empty when it is. */
178
+ declare function validateScenario(spec: ScenarioSpec): readonly string[];
179
+ /** One deliverable event, e.g. one attempt to deliver one queue message. */
180
+ interface EventRef {
181
+ readonly id: string;
182
+ /** 1 for the first delivery, 2 for the first redelivery, and so on. */
183
+ readonly attempt: number;
184
+ readonly data: JsonValue;
185
+ }
186
+ /** What a proxy tells the engine about an effect it is about to perform. */
187
+ interface EffectPoint {
188
+ readonly invocation: string;
189
+ readonly target: string;
190
+ readonly op: string;
191
+ readonly args: JsonValue;
192
+ /** Which faults make sense here; the engine only injects from this list. */
193
+ readonly allowed: readonly FaultKind[];
194
+ }
195
+ /** One invocation of the Worker, as the engine tracks it. */
196
+ interface Invocation {
197
+ readonly id: string;
198
+ /** Resolves when the invocation is crashed by an injected fault. */
199
+ readonly crashed: Promise<void>;
200
+ isCrashed(): boolean;
201
+ }
202
+ /** What the engine offers a platform during one run. */
203
+ interface RunHooks {
204
+ startInvocation(id: string): Invocation;
205
+ /** Perform an asynchronous effect under fault injection and record it. */
206
+ effect<T>(point: EffectPoint, perform: () => Promise<T>, summarize: (value: T) => JsonValue): Promise<T>;
207
+ /** Perform a synchronous effect under fault injection and record it. */
208
+ effectSync<T>(point: EffectPoint, perform: () => T, summarize: (value: T) => JsonValue): T;
209
+ /** Declare that the run touched something Eutaxy cannot control. */
210
+ unsupported(reason: string): void;
211
+ /** Record a state snapshot (not an effect point; never faulted). */
212
+ snapshot(invocation: string, target: string, payload: JsonValue): void;
213
+ /**
214
+ * Wait for user code under the engine's virtual clock: real I/O completes,
215
+ * timers fire while the invocation is idle, and a crashed invocation's
216
+ * promise is abandoned. Platforms await handler and background promises
217
+ * through this, never directly.
218
+ */
219
+ settle<T>(promise: Promise<T>, invocation: string): Promise<T>;
220
+ }
221
+ interface DeliveryResult {
222
+ readonly status: "completed" | "errored" | "crashed";
223
+ /** Events the platform's semantics require next, e.g. redeliveries. */
224
+ readonly followUps: readonly EventRef[];
225
+ }
226
+ interface Platform {
227
+ readonly name: string;
228
+ /** What a verdict rests on that this platform decides, one line each. */
229
+ readonly assumptions: readonly string[];
230
+ /** Establish the scenario's initial state. Called before every run. */
231
+ reset(spec: ScenarioSpec): Promise<void>;
232
+ /** The events the scenario's drive produces, in order. */
233
+ initialEvents(spec: ScenarioSpec): readonly EventRef[];
234
+ /** Deliver one event to the Worker under the run's fault injection. */
235
+ deliver(event: EventRef, hooks: RunHooks, spec: ScenarioSpec): Promise<DeliveryResult>;
236
+ /** The same scenario driven only by the events with these ids (for shrinking and regression tests). */
237
+ restrictEvents(spec: ScenarioSpec, keepIds: readonly string[]): ScenarioSpec;
238
+ /** Called once all events are delivered; the place to record end-of-run state snapshots. */
239
+ finish?(spec: ScenarioSpec, hooks: RunHooks): Promise<void>;
240
+ }
241
+ interface BoundsReached {
242
+ readonly runs: number;
243
+ readonly effectPoints: number;
244
+ readonly faultsInjected: number;
245
+ readonly elapsedMs: number;
246
+ }
247
+ interface VerdictBase {
248
+ readonly scenario: string;
249
+ readonly seed: number | string;
250
+ readonly reached: BoundsReached;
251
+ readonly assumptions: readonly string[];
252
+ }
253
+ interface Shrunk {
254
+ readonly faultsRemoved: number;
255
+ readonly eventsRemoved: number;
256
+ readonly runs: number;
257
+ }
258
+ interface Violated extends VerdictBase {
259
+ readonly kind: "VIOLATED";
260
+ readonly violation: Violation;
261
+ /** The replayed, shrunk trace that breaks the invariant. */
262
+ readonly trace: EffectLog;
263
+ readonly schedule: Schedule;
264
+ /** Ids of the drive's events that remain after shrinking. */
265
+ readonly keptEvents: readonly string[];
266
+ readonly shrunk: Shrunk;
267
+ }
268
+ interface Bounded extends VerdictBase {
269
+ readonly kind: "BOUNDED";
270
+ readonly bounds: Bounds;
271
+ }
272
+ type UnsupportedCause = "unsupported_api" | "not_replayable" | "module_state_leak" | "unsupported_bounds";
273
+ interface Unsupported extends VerdictBase {
274
+ readonly kind: "UNSUPPORTED";
275
+ readonly cause: UnsupportedCause;
276
+ readonly reason: string;
277
+ }
278
+ type ScenarioVerdict = Violated | Bounded | Unsupported;
279
+ /** One line per verdict, for error messages; full rendering lives in `report`. */
280
+ declare function describeVerdict(v: ScenarioVerdict): string;
281
+ interface ExploreOptions {
282
+ readonly seed: number | string;
283
+ /** Hard cap on runs, in addition to the scenario's time budget. */
284
+ readonly maxRuns?: number;
285
+ /** Probability of injecting at an eligible effect point. */
286
+ readonly faultProbability?: number;
287
+ /** Clock for the time budget; injectable for tests. */
288
+ readonly now?: () => number;
289
+ /** Hard cap on replay runs spent shrinking a violation. */
290
+ readonly maxShrinkRuns?: number;
291
+ /**
292
+ * How many of the first exploration runs to replay in reverse order
293
+ * before reporting BOUNDED, to detect module-level state leaking between
294
+ * runs. 0 disables the pass.
295
+ */
296
+ readonly leakCheckRuns?: number;
297
+ }
298
+ /** Re-run a recorded schedule exactly. */
299
+ declare function replay(spec: ScenarioSpec, platform: Platform, schedule: Schedule): Promise<EffectLog>;
300
+ declare function explore(spec: ScenarioSpec, platform: Platform, options: ExploreOptions): Promise<ScenarioVerdict>;
301
+ export { FaultKind as A, Invariant as C, checkInvariant as D, Violation as E, EffectLog as M, EffectRecord as N, checkInvariants as O, JsonValue as P, Implies as S, StateQuery as T, validateScenario as _, BoundsReached as a, EffectSelector as b, Violated as c, Platform as d, Bounds as f, WorkerRef as g, ScenarioSpec as h, Bounded as i, Schedule as j, FaultDecision as k, describeVerdict as l, PlatformData as m, explore as n, ScenarioVerdict as o, ExternalDecl as p, replay as r, Unsupported as s, ExploreOptions as t, EventRef as u, AtLeastOnce as v, RowCondition as w, EveryRow as x, AtMostOncePerKey as y };
302
+ //# sourceMappingURL=explore-BB77_V0x.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore-BB77_V0x.d.mts","names":[],"sources":["../../core/src/canonical-json.ts","../../core/src/effect-log.ts","../../core/src/faults.ts","../../core/src/invariants.ts","../../core/src/scenario.ts","../../core/src/platform.d.ts","../../core/src/verdict.ts","../../engine/src/explore.ts"],"mappings":";;;;;KAMY,wDAKC;YACG,cAAc;;;KCDlB;UAEK;;WAEN;WACA,MAAM;;WAEN;;WAEA;;WAEA;;WAEA,SAAS;;UAGH;WACN,kBAAkB;;;;;;;KChBjB;UAUK;;WAEN;;WAEA;WACA,OAAO;;WAEP;WACA;;UAGM;;WAEN;WACA,iBAAiB;;;UC1BX;WACN;WACA;WACA,OAAO;;WAEP;cAAoB,eAAe;;;WAEnC;cAAsB;;;;UAIhB;WACN;WACA;WACA,QAAQ;;WAER;;;UAIM;WACN;WACA;WACA,QAAQ;WACR;WACA,mBAAmB;;WAEnB;aAAwB;;;;KAqBvB;WACG;WAAyB;WAA2B,OAAO;;WAC3D;WAAyB;WAA0C;;WACnE;WAAyB;WAAmB,gBAAgB;;WAC5D;WAAyB;;;UAGvB;;WAEN;WACA;WACA,iBAAiB;;;UAIX;WACN;WACA;WACA,OAAO;WACP,gBAAgB;;;;;;;UAQV;WACN;WACA;WACA,MAAM;;WAEN;WACA,OAAO;WACP;;KAGC,YAAY,mBAAmB,cAAc,WAAW;UA2DnD;WACN;WACA;;WAEA;;WAEA;;iBA4EK,eAAe,KAAK,WAAW,KAAK,YAAY;iBAiGhD,gBACd,KAAK,WACL,qBAAqB,uBACX;;UCrUK;WACN;YACC,cAAc;;;UAIT;WACN;WACA;;;UAIM;WACN;;WAEA;WACA;;aAEE;;;;UAKI;WACN;WACA;WACA;WACA;;UAGM;WACN;WACA;WACA,QAAQ;;WAER,OAAO;;WAEP,gBAAgB;WAChB,oBAAoB;WACpB,qBAAqB;WACrB,QAAQ;;;iBAeH,iBAAiB,MAAM;;UCxDtB;WACN;;WAEA;WACA,MAAM;;;UAGA;WACN;WACA;WACA;WACA,MAAM;;WAEN,kBAAkB;;;UAGZ;WACN;;WAEA,SAAS;EAClB;;;UAGe;EACf,gBAAgB,aAAa;;EAE7B,OAAO,GACL,OAAO,aACP,eAAe,QAAQ,IACvB,YAAY,OAAO,MAAM,YACxB,QAAQ;;EAEX,WAAW,GAAG,OAAO,aAAa,eAAe,GAAG,YAAY,OAAO,MAAM,YAAY;;EAEzF,YAAY;;EAEZ,SAAS,oBAAoB,gBAAgB,SAAS;;;;;;;EAOtD,OAAO,GAAG,SAAS,QAAQ,IAAI,qBAAqB,QAAQ;;UAE7C;WACN;;WAEA,oBAAoB;;UAEd;WACN;;WAEA;;EAET,MAAM,MAAM,eAAe;;EAE3B,cAAc,MAAM,wBAAwB;;EAE5C,QAAQ,OAAO,UAAU,OAAO,UAAU,MAAM,eAAe,QAAQ;;EAEvE,eAAe,MAAM,cAAc,6BAA6B;;EAEhE,QAAQ,MAAM,cAAc,OAAO,WAAW;;UClE/B;WACN;WACA;WACA;WACA;;UAGD;WACC;WACA;WACA,SAAS;WACT;;UAGM;WACN;WACA;WACA;;UAGM,iBAAiB;WACvB;WACA,WAAW;;WAEX,OAAO;WACP,UAAU;;WAEV;WACA,QAAQ;;UAGF,gBAAgB;WACtB;WACA,QAAQ;;KAGP;UAMK,oBAAoB;WAC1B;WACA,OAAO;WACP;;KAGC,kBAAkB,WAAW,UAAU;;iBAGnC,gBAAgB,GAAG;UCnClB;WACN;;WAEA;;WAEA;;WAEA;;WAEA;;;;;;WAMA;;;iBA8CW,OACpB,MAAM,cACN,UAAU,UACV,UAAU,WACT,QAAQ;iBAIW,QACpB,MAAM,cACN,UAAU,UACV,SAAS,iBACR,QAAQ"}
@@ -0,0 +1,23 @@
1
+ import { A as FaultKind, C as Invariant, D as checkInvariant, E as Violation, M as EffectLog, N as EffectRecord, O as checkInvariants, S as Implies, T as StateQuery, _ as validateScenario, a as BoundsReached, b as EffectSelector, c as Violated, d as Platform, f as Bounds, h as ScenarioSpec, i as Bounded, j as Schedule, k as FaultDecision, l as describeVerdict, n as explore, o as ScenarioVerdict, r as replay, s as Unsupported, t as ExploreOptions, u as EventRef, v as AtLeastOnce, w as RowCondition, x as EveryRow, y as AtMostOncePerKey } from "./explore-BB77_V0x.mjs";
2
+ /** The scenario restricted to the kept events, with per-message invariants re-derived. */
3
+ export declare function restrictSpec(platform: Platform, spec: ScenarioSpec, keepIds: readonly string[]): ScenarioSpec;
4
+ interface RegressionTestOptions {
5
+ /** Import lines for the scenario, the platform's dependencies, and anything the platform expression needs. */
6
+ readonly imports: readonly string[];
7
+ /** An expression evaluating to the `Platform` (may reference the imports). */
8
+ readonly platform: string;
9
+ /** An expression evaluating to the `ScenarioSpec`. */
10
+ readonly scenario: string;
11
+ /** Module that exports `replay`, `restrictSpec` and `checkInvariants`; the public facade by default. */
12
+ readonly engineModule?: string;
13
+ readonly expect?: "holds" | "violates";
14
+ }
15
+ export declare function emitRegressionTest(verdict: Violated, options: RegressionTestOptions): string;
16
+ /** The JSON report: one object, canonical, with a schema version at the top. */
17
+ export declare function renderJson(verdict: ScenarioVerdict): string;
18
+ /** The trace as a fixed-width table; evidence rows are marked with `*`. */
19
+ export declare function renderTrace(log: EffectLog, evidence?: readonly number[]): string;
20
+ /** A readable report: verdict, what it rests on, and for a violation the schedule and trace. */
21
+ export declare function renderText(verdict: ScenarioVerdict): string;
22
+ export { type AtLeastOnce, type AtMostOncePerKey, type Bounded, type Bounds, type BoundsReached, type EffectLog, type EffectRecord, type EffectSelector, type EventRef, type EveryRow, type ExploreOptions, type FaultDecision, type FaultKind, type Implies, type Invariant, type Platform, type RegressionTestOptions, type RowCondition, type ScenarioSpec, type ScenarioVerdict, type Schedule, type StateQuery, type Unsupported, type Violated, type Violation, checkInvariant, checkInvariants, describeVerdict, explore, replay, validateScenario };
23
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../engine/src/shrink.ts","../../report/src/regression.ts","../../report/src/render.ts"],"mappings":";;wBAsCgB,aACd,UAAU,UACV,MAAM,cACN,6BACC;UC7Bc;;WAEN;;WAEA;;WAEA;;WAEA;WACA;;wBAGK,mBAAmB,SAAS,UAAU,SAAS;;wBCf/C,WAAW,SAAS;;wBAiBpB,YAAY,KAAK,WAAW;;wBAuB5B,WAAW,SAAS"}
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import { i as emitRegressionTest, n as renderText, r as renderTrace, t as renderJson } from "./src-Bef00JwK.mjs";
2
+ import { c as describeVerdict, d as checkInvariant, f as checkInvariants, n as replay, r as restrictSpec, t as explore, u as validateScenario } from "./src-Dn3Lm5Us.mjs";
3
+ export { checkInvariant, checkInvariants, describeVerdict, emitRegressionTest, explore, renderJson, renderText, renderTrace, replay, restrictSpec, validateScenario };