@aaac/observability 0.1.10 → 0.1.12
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.
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/generated/program.ts","../../src/generated/contract.ts","../../src/cli/record.ts","../../src/cli/record-hook.ts","../../src/cli/query.ts","../../src/cli/handlers.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * aaac-observ CLI entry point.\n *\n * Reads the version from package.json, creates the generated Commander\n * program with hand-written handlers, and executes it.\n */\nimport { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createProgram } from \"../generated/program.js\";\nimport { handlers } from \"./handlers.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n readFileSync(resolve(__dirname, \"../../package.json\"), \"utf8\"),\n) as { version: string };\n\nconst program = createProgram(handlers, pkg.version);\nawait program.parseAsync();\n","// Auto-generated by cli-contracts. Do not edit.\nimport { Command } from \"commander\";\nimport { CONTRACT_YAML, CONTRACT_JSON_STR } from \"./contract.js\";\n\nexport interface CommandHandlers {\n record: (options: { eventType?: string; lifecycle?: string; spanId?: string; parentSpanId?: string; sessionId?: string; traceId?: string; source?: string; attr?: string; link?: string; db?: string }, parentOpts: Record<string, unknown>) => Promise<void>;\n recordHook: (hookName: string | undefined, options: { mappingConfig?: string; db?: string }, parentOpts: Record<string, unknown>) => Promise<void>;\n query: (options: { kind?: string; traceId?: string; spanId?: string; eventType?: string; taskId?: string; from?: string; to?: string; direction?: string; db?: string }, parentOpts: Record<string, unknown>) => Promise<void>;\n}\n\nexport function createProgram(\n handlers: CommandHandlers,\n version: string,\n): Command {\n const program = new Command();\n program\n .name(\"aaac-observ\")\n .version(version, \"-V, --version\")\n .description(\"aaac-observ — register external events and query the observability store\");\n\n\n program\n .command(\"record\")\n .description(\"Register an external event into the observability pipeline (thin entrypoint for EventCollector.registerExternalEvent)\")\n .option(\"-t, --event-type <value>\", \"Event type (e.g. promotion.commit, process.edit, agent.session)\")\n .option(\"-l, --lifecycle <value>\", \"Event lifecycle phase: open | close | event | instant\")\n .option(\"-s, --span-id <value>\", \"Span ID (auto-generated if omitted)\")\n .option(\"--parent-span-id <value>\", \"Parent span ID for hierarchy\")\n .option(\"--session-id <value>\", \"Session ID to associate with the event\")\n .option(\"--trace-id <value>\", \"Trace ID for distributed tracing\")\n .option(\"--source <value>\", \"Event source identifier (default: external)\")\n .option(\"--attr <value>\", \"Attribute as key=value (repeatable, e.g. --attr git.commit=abc123)\")\n .option(\"--link <value>\", \"Cross-axis link as targetSpanId:linkType[:targetTraceId] (repeatable)\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .action(async (opts, cmd) => {\n await handlers.record(opts, cmd.optsWithGlobals());\n });\n\n program\n .command(\"record-hook\")\n .description(\"Record a Cursor/git hook event — parses stdin JSON, resolves event_mapping into 3-axis spans/links, injects session_id, and emits human-events (fail-open)\")\n .argument(\"<hook-name>\", \"Cursor/git hook name (e.g. afterFileEdit, subagentStart, beforeShellExecution)\")\n .option(\"--mapping-config <value>\", \"Path to event-mapping.json (default: .agent-logs/config/event-mapping.json)\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .action(async (hookName, opts, cmd) => {\n await handlers.recordHook(hookName, opts, cmd.optsWithGlobals());\n });\n\n program\n .command(\"query\")\n .description(\"Query the observability store via QueryAdapter\")\n .option(\"-k, --kind <value>\", \"Query kind: trace | span | search | links\")\n .option(\"--trace-id <value>\", \"Trace ID for trace queries (--kind trace)\")\n .option(\"-s, --span-id <value>\", \"Span ID for span/links queries (--kind span or --kind links)\")\n .option(\"--event-type <value>\", \"Event type filter for search queries (--kind search)\")\n .option(\"--task-id <value>\", \"Task ID filter for search queries (--kind search)\")\n .option(\"--from <value>\", \"Start time in ISO 8601 format for search queries (--kind search)\")\n .option(\"--to <value>\", \"End time in ISO 8601 format for search queries (--kind search)\")\n .option(\"-d, --direction <value>\", \"Link traversal direction for links queries (default: both)\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .action(async (opts, cmd) => {\n await handlers.query(opts, cmd.optsWithGlobals());\n });\n\n\n // Built-in extract command (auto-injected by cli-contracts)\n program\n .command(\"extract\")\n .description(\"Extract contract specification for this CLI tool.\")\n .argument(\"[commands...]\", \"Command IDs to extract. Use dot notation.\")\n .option(\"-a, --all\", \"Extract all commands.\", false)\n .option(\"--include-meta\", \"Include extraction metadata.\", true)\n .option(\"-F, --format <format>\", \"Output format (yaml or json).\", \"yaml\")\n .action(async (commands: string[], opts: { all?: boolean; includeMeta?: boolean; format?: string }, cmd: Command) => {\n if (commands.length === 0 && !opts.all) {\n process.stderr.write(JSON.stringify({ code: \"INVALID_ARGS\", message: \"Specify command IDs or use --all\" }) + \"\\n\");\n process.exit(2);\n }\n\n const format = opts.format || \"yaml\";\n const doc = JSON.parse(CONTRACT_JSON_STR);\n const cmdIds = opts.all ? [] : commands;\n\n if (cmdIds.length === 0) {\n // --all: output full contract\n if (format === \"json\") {\n const out: Record<string, unknown> = {};\n if (opts.includeMeta) {\n out._meta = {\n source: \"embedded\",\n type: \"cli-contracts/extract\",\n extractedAt: new Date().toISOString(),\n specVersion: doc.cli_contracts ?? \"0.1.0\",\n commands: [\"aaac-observ.record\",\"aaac-observ.record-hook\",\"aaac-observ.query\"],\n };\n }\n Object.assign(out, doc);\n process.stdout.write(JSON.stringify(out, null, 2) + \"\\n\");\n } else {\n // YAML output\n const yamlLines: string[] = [];\n yamlLines.push(\"# aaac-observ extract\");\n yamlLines.push(\"# source: embedded\");\n yamlLines.push(\"# type: cli-contracts/command-extract\");\n if (opts.includeMeta) {\n yamlLines.push(\"---\");\n yamlLines.push(\"source: embedded\");\n yamlLines.push(\"type: cli-contracts/command-extract\");\n yamlLines.push(\"extractedAt: \" + new Date().toISOString());\n yamlLines.push(\"spec_version: \" + (doc.cli_contracts ?? \"0.1.0\"));\n yamlLines.push(\"commands:\");\n for (const id of [\"aaac-observ.record\",\"aaac-observ.record-hook\",\"aaac-observ.query\"]) {\n yamlLines.push(\" - \" + id);\n }\n }\n yamlLines.push(\"---\");\n yamlLines.push(CONTRACT_YAML);\n process.stdout.write(yamlLines.join(\"\\n\") + \"\\n\");\n }\n } else {\n // Filter specific commands\n const filtered: Record<string, unknown> = {\n cli_contracts: doc.cli_contracts,\n info: doc.info,\n command_sets: {},\n };\n const fcs = filtered.command_sets as Record<string, Record<string, unknown>>;\n for (const [setId, cs] of Object.entries(doc.command_sets ?? {})) {\n const cmds = (cs as Record<string, unknown>).commands as Record<string, unknown> | undefined;\n if (!cmds) continue;\n const matched: Record<string, unknown> = {};\n for (const [cmdId, cmdDef] of Object.entries(cmds)) {\n const fullId = setId + \".\" + cmdId;\n if (cmdIds.some((id) => id === cmdId || id === fullId || cmdId.startsWith(id + \".\"))) {\n matched[cmdId] = cmdDef;\n }\n }\n if (Object.keys(matched).length > 0) {\n const setCopy = { ...(cs as Record<string, unknown>) };\n setCopy.commands = matched;\n fcs[setId] = setCopy;\n }\n }\n if (doc.components) filtered.components = doc.components;\n process.stdout.write(JSON.stringify(filtered, null, 2) + \"\\n\");\n }\n process.exit(0);\n });\n return program;\n}\n","// Auto-generated by cli-contracts. Do not edit.\n// Embedded contract for the extract subcommand.\n\nexport const CONTRACT_YAML: string = \"# yaml-language-server: $schema=./node_modules/cli-contracts/schemas/cli-contract.schema.json\\ncli_contracts: 0.1.0\\n\\ninfo:\\n title: AaaC Observability CLI\\n version: 0.1.0\\n description: aaac-observ — external event registration and query for @aaac/observability\\n\\ncommand_sets:\\n aaac-observ:\\n summary: aaac-observ — register external events and query the observability store\\n executable: aaac-observ\\n commands:\\n record:\\n summary: Register an external event into the observability pipeline (thin entrypoint for EventCollector.registerExternalEvent)\\n options:\\n - name: event-type\\n aliases: [t]\\n schema: { type: string }\\n description: \\\"Event type (e.g. promotion.commit, process.edit, agent.session)\\\"\\n - name: lifecycle\\n aliases: [l]\\n schema:\\n type: string\\n enum: [open, close, event, instant]\\n description: \\\"Event lifecycle phase: open | close | event | instant\\\"\\n - name: span-id\\n aliases: [s]\\n schema: { type: string }\\n description: Span ID (auto-generated if omitted)\\n - name: parent-span-id\\n schema: { type: string }\\n description: Parent span ID for hierarchy\\n - name: session-id\\n schema: { type: string }\\n description: Session ID to associate with the event\\n - name: trace-id\\n schema: { type: string }\\n description: Trace ID for distributed tracing\\n - name: source\\n schema: { type: string }\\n description: \\\"Event source identifier (default: external)\\\"\\n - name: attr\\n schema:\\n type: array\\n items: { type: string }\\n description: \\\"Attribute as key=value (repeatable, e.g. --attr git.commit=abc123)\\\"\\n - name: link\\n schema:\\n type: array\\n items: { type: string }\\n description: \\\"Cross-axis link as targetSpanId:linkType[:targetTraceId] (repeatable)\\\"\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n exits:\\n '0':\\n description: Event registered successfully\\n stdout:\\n format: json\\n schema:\\n type: object\\n properties:\\n eventId:\\n type: string\\n spanId:\\n type: string\\n '1':\\n description: Registration failed (validation error or write error)\\n stderr:\\n format: text\\n\\n record-hook:\\n summary: Record a Cursor/git hook event — parses stdin JSON, resolves event_mapping into 3-axis spans/links, injects session_id, and emits human-events (fail-open)\\n arguments:\\n - name: hook-name\\n index: 0\\n required: true\\n schema: { type: string }\\n description: \\\"Cursor/git hook name (e.g. afterFileEdit, subagentStart, beforeShellExecution)\\\"\\n options:\\n - name: mapping-config\\n schema: { type: string }\\n description: \\\"Path to event-mapping.json (default: .agent-logs/config/event-mapping.json)\\\"\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n exits:\\n '0':\\n description: Hook recorded (or no-op when stdin/mapping unavailable) — always fail-open\\n stdout:\\n format: json\\n schema:\\n type: object\\n properties:\\n recorded:\\n type: integer\\n fallback:\\n type: boolean\\n\\n query:\\n summary: Query the observability store via QueryAdapter\\n options:\\n - name: kind\\n aliases: [k]\\n schema:\\n type: string\\n enum: [trace, span, search, links]\\n description: \\\"Query kind: trace | span | search | links\\\"\\n - name: trace-id\\n schema: { type: string }\\n description: Trace ID for trace queries (--kind trace)\\n - name: span-id\\n aliases: [s]\\n schema: { type: string }\\n description: Span ID for span/links queries (--kind span or --kind links)\\n - name: event-type\\n schema: { type: string }\\n description: Event type filter for search queries (--kind search)\\n - name: task-id\\n schema: { type: string }\\n description: Task ID filter for search queries (--kind search)\\n - name: from\\n schema: { type: string }\\n description: Start time in ISO 8601 format for search queries (--kind search)\\n - name: to\\n schema: { type: string }\\n description: End time in ISO 8601 format for search queries (--kind search)\\n - name: direction\\n aliases: [d]\\n schema:\\n type: string\\n enum: [forward, reverse, both]\\n description: \\\"Link traversal direction for links queries (default: both)\\\"\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n exits:\\n '0':\\n description: Query succeeded — results as JSON array\\n stdout:\\n format: json\\n schema:\\n type: object\\n '1':\\n description: Query failed\\n stderr:\\n format: text\\n\";\n\nexport const CONTRACT_JSON_STR: string = \"{\\n \\\"cli_contracts\\\": \\\"0.1.0\\\",\\n \\\"info\\\": {\\n \\\"title\\\": \\\"AaaC Observability CLI\\\",\\n \\\"version\\\": \\\"0.1.0\\\",\\n \\\"description\\\": \\\"aaac-observ — external event registration and query for @aaac/observability\\\"\\n },\\n \\\"command_sets\\\": {\\n \\\"aaac-observ\\\": {\\n \\\"summary\\\": \\\"aaac-observ — register external events and query the observability store\\\",\\n \\\"executable\\\": \\\"aaac-observ\\\",\\n \\\"commands\\\": {\\n \\\"record\\\": {\\n \\\"summary\\\": \\\"Register an external event into the observability pipeline (thin entrypoint for EventCollector.registerExternalEvent)\\\",\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"event-type\\\",\\n \\\"aliases\\\": [\\n \\\"t\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Event type (e.g. promotion.commit, process.edit, agent.session)\\\"\\n },\\n {\\n \\\"name\\\": \\\"lifecycle\\\",\\n \\\"aliases\\\": [\\n \\\"l\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\",\\n \\\"enum\\\": [\\n \\\"open\\\",\\n \\\"close\\\",\\n \\\"event\\\",\\n \\\"instant\\\"\\n ]\\n },\\n \\\"description\\\": \\\"Event lifecycle phase: open | close | event | instant\\\"\\n },\\n {\\n \\\"name\\\": \\\"span-id\\\",\\n \\\"aliases\\\": [\\n \\\"s\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Span ID (auto-generated if omitted)\\\"\\n },\\n {\\n \\\"name\\\": \\\"parent-span-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Parent span ID for hierarchy\\\"\\n },\\n {\\n \\\"name\\\": \\\"session-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Session ID to associate with the event\\\"\\n },\\n {\\n \\\"name\\\": \\\"trace-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Trace ID for distributed tracing\\\"\\n },\\n {\\n \\\"name\\\": \\\"source\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Event source identifier (default: external)\\\"\\n },\\n {\\n \\\"name\\\": \\\"attr\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"array\\\",\\n \\\"items\\\": {\\n \\\"type\\\": \\\"string\\\"\\n }\\n },\\n \\\"description\\\": \\\"Attribute as key=value (repeatable, e.g. --attr git.commit=abc123)\\\"\\n },\\n {\\n \\\"name\\\": \\\"link\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"array\\\",\\n \\\"items\\\": {\\n \\\"type\\\": \\\"string\\\"\\n }\\n },\\n \\\"description\\\": \\\"Cross-axis link as targetSpanId:linkType[:targetTraceId] (repeatable)\\\"\\n },\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Event registered successfully\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\",\\n \\\"properties\\\": {\\n \\\"eventId\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"spanId\\\": {\\n \\\"type\\\": \\\"string\\\"\\n }\\n }\\n }\\n }\\n },\\n \\\"1\\\": {\\n \\\"description\\\": \\\"Registration failed (validation error or write error)\\\",\\n \\\"stderr\\\": {\\n \\\"format\\\": \\\"text\\\"\\n }\\n }\\n }\\n },\\n \\\"record-hook\\\": {\\n \\\"summary\\\": \\\"Record a Cursor/git hook event — parses stdin JSON, resolves event_mapping into 3-axis spans/links, injects session_id, and emits human-events (fail-open)\\\",\\n \\\"arguments\\\": [\\n {\\n \\\"name\\\": \\\"hook-name\\\",\\n \\\"index\\\": 0,\\n \\\"required\\\": true,\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Cursor/git hook name (e.g. afterFileEdit, subagentStart, beforeShellExecution)\\\"\\n }\\n ],\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"mapping-config\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to event-mapping.json (default: .agent-logs/config/event-mapping.json)\\\"\\n },\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Hook recorded (or no-op when stdin/mapping unavailable) — always fail-open\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\",\\n \\\"properties\\\": {\\n \\\"recorded\\\": {\\n \\\"type\\\": \\\"integer\\\"\\n },\\n \\\"fallback\\\": {\\n \\\"type\\\": \\\"boolean\\\"\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"query\\\": {\\n \\\"summary\\\": \\\"Query the observability store via QueryAdapter\\\",\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"kind\\\",\\n \\\"aliases\\\": [\\n \\\"k\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\",\\n \\\"enum\\\": [\\n \\\"trace\\\",\\n \\\"span\\\",\\n \\\"search\\\",\\n \\\"links\\\"\\n ]\\n },\\n \\\"description\\\": \\\"Query kind: trace | span | search | links\\\"\\n },\\n {\\n \\\"name\\\": \\\"trace-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Trace ID for trace queries (--kind trace)\\\"\\n },\\n {\\n \\\"name\\\": \\\"span-id\\\",\\n \\\"aliases\\\": [\\n \\\"s\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Span ID for span/links queries (--kind span or --kind links)\\\"\\n },\\n {\\n \\\"name\\\": \\\"event-type\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Event type filter for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"task-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Task ID filter for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"from\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Start time in ISO 8601 format for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"to\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"End time in ISO 8601 format for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"direction\\\",\\n \\\"aliases\\\": [\\n \\\"d\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\",\\n \\\"enum\\\": [\\n \\\"forward\\\",\\n \\\"reverse\\\",\\n \\\"both\\\"\\n ]\\n },\\n \\\"description\\\": \\\"Link traversal direction for links queries (default: both)\\\"\\n },\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Query succeeded — results as JSON array\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\"\\n }\\n }\\n },\\n \\\"1\\\": {\\n \\\"description\\\": \\\"Query failed\\\",\\n \\\"stderr\\\": {\\n \\\"format\\\": \\\"text\\\"\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n}\";\n","/**\n * record handler — thin entrypoint for EventCollector.registerExternalEvent.\n *\n * Wires the CLI options to the write pipeline:\n * options → EventCollector.registerExternalEvent\n * → Normalizer → Correlator → Enricher → SqliteSink + OtelEmitter\n *\n * architecture.md §9 / OBSERVABILITY_TASKS.md Phase 3-2\n * shift-left-event-mapping.md: aaac-observ record is the thin entrypoint\n */\nimport { createPipeline, generateId, DEFAULT_DB_PATH } from \"../index.js\";\nimport type { CanonicalLink, AttrValue, Lifecycle } from \"../types/canonical-event.js\";\n\n// ── Parsers ──────────────────────────────────────────────────────────────────\n\n/**\n * Parse comma-separated key=value attribute string into a Record.\n * Also accepts a JSON object string.\n *\n * Examples:\n * \"git.commit=abc123,git.branch=main\"\n * '{\"git.commit\":\"abc123\",\"git.branch\":\"main\"}'\n */\nexport function parseAttr(attrStr: string | undefined): Record<string, AttrValue> {\n if (!attrStr) return {};\n const trimmed = attrStr.trim();\n if (trimmed.startsWith(\"{\")) {\n try {\n return JSON.parse(trimmed) as Record<string, AttrValue>;\n } catch {\n // fall through to key=value parsing\n }\n }\n const result: Record<string, AttrValue> = {};\n for (const pair of trimmed.split(\",\")) {\n const eqIdx = pair.indexOf(\"=\");\n if (eqIdx > 0) {\n const key = pair.slice(0, eqIdx).trim();\n const val = pair.slice(eqIdx + 1).trim();\n result[key] = val;\n }\n }\n return result;\n}\n\n/**\n * Parse comma-separated link string into a CanonicalLink array.\n * Format per item: targetSpanId:linkType[:targetTraceId]\n *\n * Example: \"spanId123:materializes_as_commit,spanId456:contains_change:traceId789\"\n */\nexport function parseLinks(linkStr: string | undefined): CanonicalLink[] {\n if (!linkStr) return [];\n const links: CanonicalLink[] = [];\n for (const item of linkStr.split(\",\")) {\n const parts = item.trim().split(\":\");\n if (parts.length >= 2) {\n const targetSpanId = parts[0].trim();\n const linkType = parts[1].trim();\n const targetTraceId = parts[2]?.trim() || undefined;\n if (targetSpanId && linkType) {\n links.push({ targetSpanId, linkType, targetTraceId });\n }\n }\n }\n return links;\n}\n\n// ── Handler ──────────────────────────────────────────────────────────────────\n\n/**\n * Options as parsed from the generated CommandHandlers interface.\n * NOTE: attr and link are strings (last value from --option) not arrays,\n * because the generated Commander program does not use a collector.\n * Comma-separate multiple values: --attr \"key1=val1,key2=val2\"\n */\nexport interface RecordHandlerOptions {\n eventType?: string;\n lifecycle?: string;\n spanId?: string;\n parentSpanId?: string;\n sessionId?: string;\n traceId?: string;\n source?: string;\n attr?: string;\n link?: string;\n db?: string;\n}\n\n/**\n * Handle `aaac-observ record`.\n *\n * Required options: --event-type, --lifecycle\n * On success: writes the event through the full pipeline and prints\n * { eventId, spanId } to stdout.\n * On error: writes to stderr and exits with code 1.\n */\nexport async function handleRecord(\n options: RecordHandlerOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n // ── Validate required options ──────────────────────────────────────────────\n if (!options.eventType) {\n process.stderr.write(\"Error: --event-type (-t) is required\\n\");\n process.exit(1);\n }\n const validLifecycles: readonly string[] = [\"open\", \"close\", \"event\", \"instant\"];\n if (!options.lifecycle) {\n process.stderr.write(\n `Error: --lifecycle (-l) is required (${validLifecycles.join(\"|\")})\\n`,\n );\n process.exit(1);\n }\n if (!validLifecycles.includes(options.lifecycle)) {\n process.stderr.write(\n `Error: --lifecycle must be one of: ${validLifecycles.join(\"|\")}\\n`,\n );\n process.exit(1);\n }\n\n // ── Build event payload ────────────────────────────────────────────────────\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const spanId = options.spanId ?? generateId();\n const attributes = parseAttr(options.attr);\n const links = parseLinks(options.link);\n\n // Inject well-known scalars into attributes so the Normalizer picks them up\n if (options.sessionId) {\n attributes[\"session_id\"] = options.sessionId;\n }\n // trace_id stored as attribute for user reference; canonical traceId is\n // managed by Normalizer/Correlator (propagated via parentSpanId chain)\n if (options.traceId) {\n attributes[\"trace_id\"] = options.traceId;\n }\n\n // ── Build & execute pipeline ───────────────────────────────────────────────\n let capturedEventId: string | undefined;\n\n const { collector, sink } = createPipeline({\n dbPath,\n // Use afterCorrelate to capture the event id before it is written\n afterCorrelate: (event) => {\n capturedEventId = event.id;\n return event;\n },\n // Enable the default enrichment rules (R1–R5). This is the path the git\n // post-commit hook uses to record promotion.commit (close) with\n // committed_files; R5 (cross-axis) must run here to add the\n // materializes_as_commit link to task spans whose modified files intersect\n // the commit. R3/R4 accumulation persists in the SQLite-backed cache of the\n // same db file, so R5 sees it across the process boundary (#143 / #140).\n // Enricher is fail-open, so a rule error never blocks recording.\n });\n\n try {\n collector.registerExternalEvent({\n source: options.source ?? \"external\",\n eventType: options.eventType,\n lifecycle: options.lifecycle as Lifecycle,\n spanId,\n parentSpanId: options.parentSpanId,\n attributes,\n links,\n });\n } catch (err) {\n process.stderr.write(\n `Error: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n sink.close();\n process.exit(1);\n }\n\n sink.close();\n\n const result = { eventId: capturedEventId, spanId };\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n}\n","/**\n * record-hook handler — stdin-aware Cursor/git hook recorder.\n *\n * This is the runtime entrypoint for `.cursor/hooks/observ-record.sh`. Unlike the\n * thin `record` command (scalar flags only), `record-hook`:\n *\n * 1. parses the hook JSON payload from stdin (conversation_id + hook-specific fields)\n * 2. loads `.agent-logs/config/event-mapping.json` and resolves the matching\n * mapping rule into 3-axis spans + cross-axis links (evaluateMapping)\n * 3. injects session_id = conversation_id on every emitted event (correlation key\n * with @aaac/runtime in-process events)\n * 4. emits human-interaction events (human.instruction / quality_gate.result /\n * promotion.pr) for the relevant hooks\n * 5. manages the short-lived git context file `.agent-logs/.observ-context.json`\n * (write on beforeShellExecution for git commit/push/merge, delete on\n * afterShellExecution) so git hooks can correlate (read side: #115)\n *\n * It is strictly fail-open: any parse/IO/config error degrades to the generic\n * fallback recording (or a no-op) and never throws — recording must NEVER block\n * the underlying hook operation.\n *\n * Issue #114 / shift-left-event-mapping.md §6 (option B).\n */\nimport { mkdir, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport {\n createPipeline,\n generateId,\n DEFAULT_DB_PATH,\n loadEventMappingConfig,\n evaluateMapping,\n emitHumanInstruction,\n emitQualityGateResult,\n emitPromotionPr,\n} from \"../index.js\";\nimport type { EventCollector } from \"../collector/event-collector.js\";\nimport type { AttrValue, CanonicalLink } from \"../types/canonical-event.js\";\nimport type { EventMappingConfig, EventMappingRule } from \"../event-mapping/types.js\";\n\n// ── Constants ──────────────────────────────────────────────────────────────────\n\n/** git subcommands that warrant propagating session context to git hooks. */\nconst GIT_CONTEXT_COMMAND_RE = /\\bgit\\s+(?:commit|push|merge)\\b/;\n\n/** Hook names that map to git.* event types in the generic fallback. */\nconst GIT_HOOK_NAMES = new Set([\n \"pre-commit\",\n \"post-commit\",\n \"pre-push\",\n \"post-merge\",\n \"post-checkout\",\n]);\n\n// ── Options ──────────────────────────────────────────────────────────────────\n\nexport interface RecordHookOptions {\n mappingConfig?: string;\n db?: string;\n}\n\n/** Parsed result of running the hook recorder (also written to stdout as JSON). */\nexport interface RecordHookResult {\n /** Number of events emitted into the pipeline. */\n recorded: number;\n /** True when no mapping rule matched and the generic fallback was used. */\n fallback: boolean;\n}\n\n// ── Path helpers ───────────────────────────────────────────────────────────────\n\n/** Default event-mapping config path, derived from the db directory. */\nexport function defaultMappingConfigPath(dbPath: string): string {\n return join(dirname(dbPath), \"config\", \"event-mapping.json\");\n}\n\n/** Short-lived git context file path, derived from the db directory. */\nexport function contextFilePath(dbPath: string): string {\n return join(dirname(dbPath), \".observ-context.json\");\n}\n\n// ── stdin parsing ────────────────────────────────────────────────────────────\n\n/**\n * Read the entire stdin stream as a string.\n * Resolves \"\" when stdin is a TTY (no payload) or on any error — the git-hook\n * path frequently provides no stdin, which must be handled gracefully (AC-1).\n */\nexport async function readStdin(): Promise<string> {\n if (process.stdin.isTTY) return \"\";\n return new Promise<string>((resolve) => {\n let data = \"\";\n let settled = false;\n const finish = (): void => {\n if (settled) return;\n settled = true;\n resolve(data);\n };\n try {\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", finish);\n process.stdin.on(\"error\", finish);\n process.stdin.on(\"close\", finish);\n // Safety net: never hang the hook if stdin is left open.\n const t = setTimeout(finish, 1000);\n if (typeof t.unref === \"function\") t.unref();\n } catch {\n finish();\n }\n });\n}\n\n/** Parse a stdin payload into an object; returns {} for empty/invalid JSON. */\nexport function parseHookInput(raw: string): Record<string, unknown> {\n const trimmed = raw.trim();\n if (!trimmed) return {};\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n return parsed !== null && typeof parsed === \"object\"\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\n// ── Field coercion ───────────────────────────────────────────────────────────\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\n// ── Emission ─────────────────────────────────────────────────────────────────\n\n/**\n * Emit the 3-axis spans + cross-axis links resolved from a mapping rule.\n * session_id (and parent_conversation_id on subagentStart) are injected on every\n * span so all hook-derived events share the correlation key.\n */\nfunction emitMappedSpans(\n collector: EventCollector,\n hook: string,\n rule: EventMappingRule,\n hookInput: Record<string, unknown>,\n sessionId: string,\n): number {\n const { spans, links } = evaluateMapping(rule, hookInput);\n\n // Group resolved links by their source spanId so they can be attached to the\n // emitting (source) event as CanonicalLink entries.\n const linksBySpan = new Map<string, CanonicalLink[]>();\n for (const link of links) {\n const arr = linksBySpan.get(link.fromSpanId) ?? [];\n arr.push({ targetSpanId: link.toSpanId, linkType: link.linkType });\n linksBySpan.set(link.fromSpanId, arr);\n }\n\n const parentConversationId =\n hook === \"subagentStart\" ? asString(hookInput.parent_conversation_id) : undefined;\n\n for (const span of spans) {\n const attributes: Record<string, AttrValue> = { ...span.attributes };\n if (sessionId) attributes[\"session_id\"] = sessionId;\n if (parentConversationId) {\n attributes[\"parent_conversation_id\"] = parentConversationId;\n }\n collector.emit({\n source: \"cursor-hook\",\n eventType: span.eventType,\n lifecycle: span.lifecycle,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId,\n attributes,\n links: linksBySpan.get(span.spanId) ?? [],\n });\n }\n\n return spans.length;\n}\n\n/**\n * Emit a single generic instant event (current pre-#114 behaviour) when no\n * mapping rule matches — preserves fail-open recording (AC-3).\n */\nfunction emitGenericFallback(\n collector: EventCollector,\n hook: string,\n sessionId: string,\n): number {\n const eventType = (GIT_HOOK_NAMES.has(hook) ? \"git.\" : \"cursor.\") + hook;\n const attributes: Record<string, AttrValue> = { \"hook.name\": hook };\n if (sessionId) attributes[\"session_id\"] = sessionId;\n collector.emit({\n source: \"cursor-hook\",\n eventType,\n lifecycle: \"instant\",\n attributes,\n });\n return 1;\n}\n\n/** Emit human-interaction events for the relevant hooks (AC-5). */\nfunction emitHumanEvents(\n collector: EventCollector,\n hook: string,\n hookInput: Record<string, unknown>,\n sessionId: string,\n): number {\n let count = 0;\n\n if (hook === \"beforeSubmitPrompt\") {\n const prompt = asString(hookInput.prompt);\n if (prompt !== undefined) {\n const attachments = Array.isArray(hookInput.attachments)\n ? (hookInput.attachments as unknown[])\n : [];\n emitHumanInstruction(collector, { sessionId, prompt, attachments });\n count += 1;\n }\n } else if (hook === \"afterShellExecution\") {\n const command = asString(hookInput.command);\n if (command !== undefined) {\n const exitCode = asNumber(hookInput.exit_code) ?? asNumber(hookInput.exitCode) ?? 0;\n const durationMs = asNumber(hookInput.duration);\n if (emitQualityGateResult(collector, { sessionId, command, exitCode, durationMs })) {\n count += 1;\n }\n const output = asString(hookInput.output) ?? \"\";\n if (emitPromotionPr(collector, { sessionId, command, output })) {\n count += 1;\n }\n }\n }\n\n return count;\n}\n\n// ── Context file lifecycle ──────────────────────────────────────────────────\n\n/**\n * Manage the short-lived git context file (AC-4).\n *\n * beforeShellExecution + git commit/push/merge → atomic write\n * afterShellExecution + git commit/push/merge → delete (fail-open)\n *\n * Atomic write uses write-to-temp + rename so a git hook never observes a\n * partially written file. Non-git commands never write the file.\n */\nasync function manageContextFile(\n hook: string,\n hookInput: Record<string, unknown>,\n sessionId: string,\n dbPath: string,\n): Promise<void> {\n const command = asString(hookInput.command) ?? \"\";\n const isGitContextCommand = GIT_CONTEXT_COMMAND_RE.test(command);\n const file = contextFilePath(dbPath);\n\n if (hook === \"beforeShellExecution\" && isGitContextCommand) {\n await mkdir(dirname(file), { recursive: true });\n const payload =\n JSON.stringify({\n session_id: sessionId || null,\n nonce: generateId(),\n created_at_ms: Date.now(),\n }) + \"\\n\";\n const tmp = `${file}.${process.pid}.${generateId()}.tmp`;\n await writeFile(tmp, payload, \"utf8\");\n await rename(tmp, file);\n } else if (hook === \"afterShellExecution\" && isGitContextCommand) {\n await unlink(file).catch(() => {\n // rm -f semantics: missing file is not an error.\n });\n }\n}\n\n// ── Core (testable) ────────────────────────────────────────────────────────────\n\n/**\n * Run the hook recorder against an already-parsed hook input.\n *\n * Separated from {@link handleRecordHook} (which reads stdin) so it can be unit\n * tested without mocking process.stdin.\n */\nexport async function runRecordHook(args: {\n hook: string;\n hookInput: Record<string, unknown>;\n dbPath: string;\n mappingConfigPath: string;\n}): Promise<RecordHookResult> {\n const { hook, hookInput, dbPath, mappingConfigPath } = args;\n const sessionId = asString(hookInput.conversation_id) ?? \"\";\n\n // Context-file lifecycle is independent of recording and must not block it.\n await manageContextFile(hook, hookInput, sessionId, dbPath).catch(() => {\n // fail-open\n });\n\n // Load mapping config; absence/parse-error → generic fallback (AC-3).\n let config: EventMappingConfig | undefined;\n try {\n config = await loadEventMappingConfig(mappingConfigPath);\n } catch {\n config = undefined;\n }\n const rule = config?.mappings?.[hook];\n\n let recorded = 0;\n let fallback = false;\n\n // Enable the default enrichment rules (R1–R5) so hook-derived spans/links are\n // enriched on the same SQLite-backed cache the runtime populates, allowing\n // cross-axis (R5) linking across the process boundary (#143 / #140). The\n // Enricher is fail-open, so a rule error never blocks the underlying hook.\n const { collector, sink } = createPipeline({ dbPath });\n try {\n if (rule) {\n recorded += emitMappedSpans(collector, hook, rule, hookInput, sessionId);\n } else {\n recorded += emitGenericFallback(collector, hook, sessionId);\n fallback = true;\n }\n recorded += emitHumanEvents(collector, hook, hookInput, sessionId);\n } finally {\n sink.close();\n }\n\n return { recorded, fallback };\n}\n\n// ── Handler ─────────────────────────────────────────────────────────────────\n\n/**\n * Handle `aaac-observ record-hook <hook-name>`.\n *\n * Reads the hook JSON from stdin, records the resolved events, and prints\n * `{ recorded, fallback }` to stdout. Strictly fail-open: never throws and\n * always returns; the calling shell wrapper additionally guarantees exit 0.\n */\nexport async function handleRecordHook(\n hookName: string | undefined,\n options: RecordHookOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n const hook = hookName ?? \"unknown\";\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const mappingConfigPath = options.mappingConfig ?? defaultMappingConfigPath(dbPath);\n\n let result: RecordHookResult = { recorded: 0, fallback: false };\n try {\n const hookInput = parseHookInput(await readStdin());\n result = await runRecordHook({ hook, hookInput, dbPath, mappingConfigPath });\n } catch (err) {\n // Recorder is fail-open: report to stderr but never block the operation.\n process.stderr.write(\n `record-hook: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n}\n","/**\n * query handler — read path via QueryAdapter.\n *\n * Routes --kind to the appropriate SqliteQueryAdapter method and emits\n * results as JSON to stdout.\n *\n * Supported kinds:\n * trace → QueryAdapter.getTrace(--trace-id)\n * span → QueryAdapter.getSpan(--span-id) [+ QueryAdapter.getSpanEvents]\n * search → QueryAdapter.querySpans({ eventType, taskId, from, to })\n * links → QueryAdapter.getLinks(--span-id, --direction)\n *\n * architecture.md §12 / OBSERVABILITY_TASKS.md Phase 3-2 (record CLI + query)\n */\nimport { SqliteQueryAdapter, DEFAULT_DB_PATH } from \"../index.js\";\nimport { isoToUnixNano } from \"../types/ids.js\";\nimport type { LinkDirection } from \"../query/models.js\";\n\n// ── Handler ───────────────────────────────────────────────────────────────────\n\n/**\n * Options as parsed from the generated CommandHandlers interface.\n */\nexport interface QueryHandlerOptions {\n kind?: string;\n traceId?: string;\n spanId?: string;\n eventType?: string;\n taskId?: string;\n from?: string;\n to?: string;\n direction?: string;\n db?: string;\n}\n\n/** JSON replacer that serialises BigInt as a string. */\nfunction bigIntReplacer(_key: string, value: unknown): unknown {\n return typeof value === \"bigint\" ? value.toString() : value;\n}\n\n/**\n * Handle `aaac-observ query`.\n *\n * Required option: --kind (trace|span|search|links)\n * On success: writes a JSON array/object to stdout.\n * On error: writes to stderr and exits with code 1.\n *\n * DESIGN NOTE: all required-arg validation happens BEFORE the adapter is\n * created, so that when process.exit is mocked to throw in tests there is no\n * risk of a double-close on the database connection.\n */\nexport async function handleQuery(\n options: QueryHandlerOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n const validKinds = [\"trace\", \"span\", \"search\", \"links\"] as const;\n type QueryKind = (typeof validKinds)[number];\n\n // ── Validate options (before opening the adapter) ─────────────────────────\n if (!options.kind) {\n process.stderr.write(\n `Error: --kind (-k) is required (${validKinds.join(\"|\")})\\n`,\n );\n process.exit(1);\n }\n if (!validKinds.includes(options.kind as QueryKind)) {\n process.stderr.write(\n `Error: --kind must be one of: ${validKinds.join(\"|\")}\\n`,\n );\n process.exit(1);\n }\n\n const kind = options.kind as QueryKind;\n\n // Validate sub-command required args (before adapter creation)\n if (kind === \"trace\" && !options.traceId) {\n process.stderr.write(\"Error: --trace-id is required for --kind trace\\n\");\n process.exit(1);\n }\n if (kind === \"span\" && !options.spanId) {\n process.stderr.write(\"Error: --span-id is required for --kind span\\n\");\n process.exit(1);\n }\n if (kind === \"links\" && !options.spanId) {\n process.stderr.write(\"Error: --span-id is required for --kind links\\n\");\n process.exit(1);\n }\n\n // ── Open adapter ──────────────────────────────────────────────────────────\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const adapter = new SqliteQueryAdapter(dbPath);\n\n try {\n let result: unknown;\n\n switch (kind) {\n // ── trace: all spans in a trace ─────────────────────────────────────\n case \"trace\": {\n // options.traceId is guaranteed by pre-validation above\n result = adapter.getTrace(options.traceId!);\n break;\n }\n\n // ── span: single span + its events ──────────────────────────────────\n case \"span\": {\n // options.spanId is guaranteed by pre-validation above\n const span = adapter.getSpan(options.spanId!);\n const events = adapter.getSpanEvents(options.spanId!);\n result = span !== undefined ? { span, events } : null;\n break;\n }\n\n // ── search: spans matching event-type / task-id / time range ─────────\n case \"search\": {\n const filter: Parameters<typeof adapter.querySpans>[0] = {};\n if (options.eventType) filter.eventType = options.eventType;\n if (options.taskId) filter.taskId = options.taskId;\n if (options.from) filter.fromTimeUnixNano = isoToUnixNano(options.from);\n if (options.to) filter.toTimeUnixNano = isoToUnixNano(options.to);\n result = adapter.querySpans(filter);\n break;\n }\n\n // ── links: link traversal ─────────────────────────────────────────────\n case \"links\": {\n const validDirections = [\"forward\", \"reverse\", \"both\"] as const;\n type Dir = (typeof validDirections)[number];\n const dir: Dir =\n options.direction !== undefined &&\n validDirections.includes(options.direction as Dir)\n ? (options.direction as Dir)\n : \"both\";\n result = adapter.getLinks(options.spanId!, dir as LinkDirection);\n break;\n }\n }\n\n process.stdout.write(JSON.stringify(result, bigIntReplacer) + \"\\n\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n\n // Graceful handling: an un-initialised (fresh empty) database has no\n // tables yet. Return an empty / null result rather than an error so that\n // `aaac-observ query` on a machine with no recorded events behaves\n // predictably.\n if (msg.includes(\"no such table\") || msg.includes(\"no such column\")) {\n const emptyResult = kind === \"span\" ? null : [];\n process.stdout.write(JSON.stringify(emptyResult, bigIntReplacer) + \"\\n\");\n adapter.close();\n return;\n }\n\n process.stderr.write(`Error: ${msg}\\n`);\n adapter.close();\n process.exit(1);\n }\n\n adapter.close();\n}\n","/**\n * CLI command handlers for aaac-observ.\n *\n * Implements the CommandHandlers interface generated by cli-contracts and\n * delegates to the domain-specific handler modules.\n *\n * Usage (in index.ts):\n * import { handlers } from './handlers.js';\n * import { createProgram } from '../generated/program.js';\n * const program = createProgram(handlers, version);\n * await program.parseAsync();\n */\nimport type { CommandHandlers } from \"../generated/program.js\";\nimport { handleRecord } from \"./record.js\";\nimport { handleRecordHook } from \"./record-hook.js\";\nimport { handleQuery } from \"./query.js\";\n\nexport const handlers: CommandHandlers = {\n record: handleRecord,\n recordHook: handleRecordHook,\n query: handleQuery,\n};\n"],"mappings":";;;;;;;;;;;;;;;AAOA,SAAS,oBAAoB;AAC7B,SAAS,WAAAA,UAAS,eAAe;AACjC,SAAS,qBAAqB;;;ACR9B,SAAS,eAAe;;;ACEjB,IAAM,gBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAE9B,IAAM,oBAA4B;;;ADKlC,SAAS,cACdC,WACA,SACS;AACT,QAAMC,WAAU,IAAI,QAAQ;AAC5B,EAAAA,SACG,KAAK,aAAa,EAClB,QAAQ,SAAS,eAAe,EAChC,YAAY,+EAA0E;AAGzF,EAAAA,SACG,QAAQ,QAAQ,EAChB,YAAY,uHAAuH,EACnI,OAAO,4BAA4B,iEAAiE,EACpG,OAAO,2BAA2B,uDAAuD,EACzF,OAAO,yBAAyB,qCAAqC,EACrE,OAAO,4BAA4B,8BAA8B,EACjE,OAAO,wBAAwB,wCAAwC,EACvE,OAAO,sBAAsB,kCAAkC,EAC/D,OAAO,oBAAoB,6CAA6C,EACxE,OAAO,kBAAkB,oEAAoE,EAC7F,OAAO,kBAAkB,uEAAuE,EAChG,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,OAAO,MAAM,QAAQ;AAC3B,UAAMD,UAAS,OAAO,MAAM,IAAI,gBAAgB,CAAC;AAAA,EACnD,CAAC;AAEH,EAAAC,SACG,QAAQ,aAAa,EACrB,YAAY,iKAA4J,EACxK,SAAS,eAAe,gFAAgF,EACxG,OAAO,4BAA4B,6EAA6E,EAChH,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,OAAO,UAAU,MAAM,QAAQ;AACrC,UAAMD,UAAS,WAAW,UAAU,MAAM,IAAI,gBAAgB,CAAC;AAAA,EACjE,CAAC;AAEH,EAAAC,SACG,QAAQ,OAAO,EACf,YAAY,gDAAgD,EAC5D,OAAO,sBAAsB,2CAA2C,EACxE,OAAO,sBAAsB,2CAA2C,EACxE,OAAO,yBAAyB,8DAA8D,EAC9F,OAAO,wBAAwB,sDAAsD,EACrF,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,kBAAkB,kEAAkE,EAC3F,OAAO,gBAAgB,gEAAgE,EACvF,OAAO,2BAA2B,4DAA4D,EAC9F,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,OAAO,MAAM,QAAQ;AAC3B,UAAMD,UAAS,MAAM,MAAM,IAAI,gBAAgB,CAAC;AAAA,EAClD,CAAC;AAIH,EAAAC,SACG,QAAQ,SAAS,EACjB,YAAY,mDAAmD,EAC/D,SAAS,iBAAiB,2CAA2C,EACrE,OAAO,aAAa,yBAAyB,KAAK,EAClD,OAAO,kBAAkB,gCAAgC,IAAI,EAC7D,OAAO,yBAAyB,iCAAiC,MAAM,EACvE,OAAO,OAAO,UAAoB,MAAiE,QAAiB;AACnH,QAAI,SAAS,WAAW,KAAK,CAAC,KAAK,KAAK;AACtC,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,MAAM,gBAAgB,SAAS,mCAAmC,CAAC,IAAI,IAAI;AACjH,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,MAAM,KAAK,MAAM,iBAAiB;AACxC,UAAM,SAAS,KAAK,MAAM,CAAC,IAAI;AAE/B,QAAI,OAAO,WAAW,GAAG;AAEvB,UAAI,WAAW,QAAQ;AACrB,cAAM,MAA+B,CAAC;AACtC,YAAI,KAAK,aAAa;AACpB,cAAI,QAAQ;AAAA,YACV,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,YACpC,aAAa,IAAI,iBAAiB;AAAA,YAClC,UAAU,CAAC,sBAAqB,2BAA0B,mBAAmB;AAAA,UAC/E;AAAA,QACF;AACA,eAAO,OAAO,KAAK,GAAG;AACtB,gBAAQ,OAAO,MAAM,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAAA,MAC1D,OAAO;AAEL,cAAM,YAAsB,CAAC;AAC7B,kBAAU,KAAK,uBAAuB;AACtC,kBAAU,KAAK,oBAAoB;AACnC,kBAAU,KAAK,uCAAuC;AACtD,YAAI,KAAK,aAAa;AACpB,oBAAU,KAAK,KAAK;AACpB,oBAAU,KAAK,kBAAkB;AACjC,oBAAU,KAAK,qCAAqC;AACpD,oBAAU,KAAK,mBAAkB,oBAAI,KAAK,GAAE,YAAY,CAAC;AACzD,oBAAU,KAAK,oBAAoB,IAAI,iBAAiB,QAAQ;AAChE,oBAAU,KAAK,WAAW;AAC1B,qBAAW,MAAM,CAAC,sBAAqB,2BAA0B,mBAAmB,GAAG;AACrF,sBAAU,KAAK,SAAS,EAAE;AAAA,UAC5B;AAAA,QACF;AACA,kBAAU,KAAK,KAAK;AACpB,kBAAU,KAAK,aAAa;AAC5B,gBAAQ,OAAO,MAAM,UAAU,KAAK,IAAI,IAAI,IAAI;AAAA,MAClD;AAAA,IACF,OAAO;AAEL,YAAM,WAAoC;AAAA,QACxC,eAAe,IAAI;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,cAAc,CAAC;AAAA,MACjB;AACA,YAAM,MAAM,SAAS;AACrB,iBAAW,CAAC,OAAO,EAAE,KAAK,OAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,GAAG;AAChE,cAAM,OAAQ,GAA+B;AAC7C,YAAI,CAAC,KAAM;AACX,cAAM,UAAmC,CAAC;AAC1C,mBAAW,CAAC,OAAO,MAAM,KAAK,OAAO,QAAQ,IAAI,GAAG;AAClD,gBAAM,SAAS,QAAQ,MAAM;AAC7B,cAAI,OAAO,KAAK,CAAC,OAAO,OAAO,SAAS,OAAO,UAAU,MAAM,WAAW,KAAK,GAAG,CAAC,GAAG;AACpF,oBAAQ,KAAK,IAAI;AAAA,UACnB;AAAA,QACF;AACA,YAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACnC,gBAAM,UAAU,EAAE,GAAI,GAA+B;AACrD,kBAAQ,WAAW;AACnB,cAAI,KAAK,IAAI;AAAA,QACf;AAAA,MACF;AACA,UAAI,IAAI,WAAY,UAAS,aAAa,IAAI;AAC9C,cAAQ,OAAO,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,IAC/D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH,SAAOA;AACT;;;AE9HO,SAAS,UAAU,SAAwD;AAChF,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,SAAoC,CAAC;AAC3C,aAAW,QAAQ,QAAQ,MAAM,GAAG,GAAG;AACrC,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,QAAI,QAAQ,GAAG;AACb,YAAM,MAAM,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK;AACtC,YAAM,MAAM,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK;AACvC,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,WAAW,SAA8C;AACvE,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,QAAyB,CAAC;AAChC,aAAW,QAAQ,QAAQ,MAAM,GAAG,GAAG;AACrC,UAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,GAAG;AACnC,QAAI,MAAM,UAAU,GAAG;AACrB,YAAM,eAAe,MAAM,CAAC,EAAE,KAAK;AACnC,YAAM,WAAW,MAAM,CAAC,EAAE,KAAK;AAC/B,YAAM,gBAAgB,MAAM,CAAC,GAAG,KAAK,KAAK;AAC1C,UAAI,gBAAgB,UAAU;AAC5B,cAAM,KAAK,EAAE,cAAc,UAAU,cAAc,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AA+BA,eAAsB,aACpB,SACA,aACe;AAEf,MAAI,CAAC,QAAQ,WAAW;AACtB,YAAQ,OAAO,MAAM,wCAAwC;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,kBAAqC,CAAC,QAAQ,SAAS,SAAS,SAAS;AAC/E,MAAI,CAAC,QAAQ,WAAW;AACtB,YAAQ,OAAO;AAAA,MACb,wCAAwC,gBAAgB,KAAK,GAAG,CAAC;AAAA;AAAA,IACnE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,gBAAgB,SAAS,QAAQ,SAAS,GAAG;AAChD,YAAQ,OAAO;AAAA,MACb,sCAAsC,gBAAgB,KAAK,GAAG,CAAC;AAAA;AAAA,IACjE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,SAAS,QAAQ,UAAU,WAAW;AAC5C,QAAM,aAAa,UAAU,QAAQ,IAAI;AACzC,QAAM,QAAQ,WAAW,QAAQ,IAAI;AAGrC,MAAI,QAAQ,WAAW;AACrB,eAAW,YAAY,IAAI,QAAQ;AAAA,EACrC;AAGA,MAAI,QAAQ,SAAS;AACnB,eAAW,UAAU,IAAI,QAAQ;AAAA,EACnC;AAGA,MAAI;AAEJ,QAAM,EAAE,WAAW,KAAK,IAAI,eAAe;AAAA,IACzC;AAAA;AAAA,IAEA,gBAAgB,CAAC,UAAU;AACzB,wBAAkB,MAAM;AACxB,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,CAAC;AAED,MAAI;AACF,cAAU,sBAAsB;AAAA,MAC9B,QAAQ,QAAQ,UAAU;AAAA,MAC1B,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,OAAO;AAAA,MACb,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA;AAAA,IAC5D;AACA,SAAK,MAAM;AACX,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,OAAK,MAAM;AAEX,QAAM,SAAS,EAAE,SAAS,iBAAiB,OAAO;AAClD,UAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,IAAI,IAAI;AACpD;;;AC1JA,SAAS,OAAO,QAAQ,QAAQ,iBAAiB;AACjD,SAAS,SAAS,YAAY;AAkB9B,IAAM,yBAAyB;AAG/B,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAoBM,SAAS,yBAAyB,QAAwB;AAC/D,SAAO,KAAK,QAAQ,MAAM,GAAG,UAAU,oBAAoB;AAC7D;AAGO,SAAS,gBAAgB,QAAwB;AACtD,SAAO,KAAK,QAAQ,MAAM,GAAG,sBAAsB;AACrD;AASA,eAAsB,YAA6B;AACjD,MAAI,QAAQ,MAAM,MAAO,QAAO;AAChC,SAAO,IAAI,QAAgB,CAACC,aAAY;AACtC,QAAI,OAAO;AACX,QAAI,UAAU;AACd,UAAM,SAAS,MAAY;AACzB,UAAI,QAAS;AACb,gBAAU;AACV,MAAAA,SAAQ,IAAI;AAAA,IACd;AACA,QAAI;AACF,cAAQ,MAAM,YAAY,MAAM;AAChC,cAAQ,MAAM,GAAG,QAAQ,CAAC,UAAU;AAClC,gBAAQ;AAAA,MACV,CAAC;AACD,cAAQ,MAAM,GAAG,OAAO,MAAM;AAC9B,cAAQ,MAAM,GAAG,SAAS,MAAM;AAChC,cAAQ,MAAM,GAAG,SAAS,MAAM;AAEhC,YAAM,IAAI,WAAW,QAAQ,GAAI;AACjC,UAAI,OAAO,EAAE,UAAU,WAAY,GAAE,MAAM;AAAA,IAC7C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAGO,SAAS,eAAe,KAAsC;AACnE,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,WAAO,WAAW,QAAQ,OAAO,WAAW,WACvC,SACD,CAAC;AAAA,EACP,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAIA,SAAS,SAAS,OAAoC;AACpD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,SAAS,OAAoC;AACpD,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAI;AACpD,UAAM,IAAI,OAAO,KAAK;AACtB,QAAI,OAAO,SAAS,CAAC,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AASA,SAAS,gBACP,WACA,MACA,MACA,WACA,WACQ;AACR,QAAM,EAAE,OAAO,MAAM,IAAI,gBAAgB,MAAM,SAAS;AAIxD,QAAM,cAAc,oBAAI,IAA6B;AACrD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,YAAY,IAAI,KAAK,UAAU,KAAK,CAAC;AACjD,QAAI,KAAK,EAAE,cAAc,KAAK,UAAU,UAAU,KAAK,SAAS,CAAC;AACjE,gBAAY,IAAI,KAAK,YAAY,GAAG;AAAA,EACtC;AAEA,QAAM,uBACJ,SAAS,kBAAkB,SAAS,UAAU,sBAAsB,IAAI;AAE1E,aAAW,QAAQ,OAAO;AACxB,UAAM,aAAwC,EAAE,GAAG,KAAK,WAAW;AACnE,QAAI,UAAW,YAAW,YAAY,IAAI;AAC1C,QAAI,sBAAsB;AACxB,iBAAW,wBAAwB,IAAI;AAAA,IACzC;AACA,cAAU,KAAK;AAAA,MACb,QAAQ;AAAA,MACR,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK;AAAA,MACnB;AAAA,MACA,OAAO,YAAY,IAAI,KAAK,MAAM,KAAK,CAAC;AAAA,IAC1C,CAAC;AAAA,EACH;AAEA,SAAO,MAAM;AACf;AAMA,SAAS,oBACP,WACA,MACA,WACQ;AACR,QAAM,aAAa,eAAe,IAAI,IAAI,IAAI,SAAS,aAAa;AACpE,QAAM,aAAwC,EAAE,aAAa,KAAK;AAClE,MAAI,UAAW,YAAW,YAAY,IAAI;AAC1C,YAAU,KAAK;AAAA,IACb,QAAQ;AAAA,IACR;AAAA,IACA,WAAW;AAAA,IACX;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGA,SAAS,gBACP,WACA,MACA,WACA,WACQ;AACR,MAAI,QAAQ;AAEZ,MAAI,SAAS,sBAAsB;AACjC,UAAM,SAAS,SAAS,UAAU,MAAM;AACxC,QAAI,WAAW,QAAW;AACxB,YAAM,cAAc,MAAM,QAAQ,UAAU,WAAW,IAClD,UAAU,cACX,CAAC;AACL,2BAAqB,WAAW,EAAE,WAAW,QAAQ,YAAY,CAAC;AAClE,eAAS;AAAA,IACX;AAAA,EACF,WAAW,SAAS,uBAAuB;AACzC,UAAM,UAAU,SAAS,UAAU,OAAO;AAC1C,QAAI,YAAY,QAAW;AACzB,YAAM,WAAW,SAAS,UAAU,SAAS,KAAK,SAAS,UAAU,QAAQ,KAAK;AAClF,YAAM,aAAa,SAAS,UAAU,QAAQ;AAC9C,UAAI,sBAAsB,WAAW,EAAE,WAAW,SAAS,UAAU,WAAW,CAAC,GAAG;AAClF,iBAAS;AAAA,MACX;AACA,YAAM,SAAS,SAAS,UAAU,MAAM,KAAK;AAC7C,UAAI,gBAAgB,WAAW,EAAE,WAAW,SAAS,OAAO,CAAC,GAAG;AAC9D,iBAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAaA,eAAe,kBACb,MACA,WACA,WACA,QACe;AACf,QAAM,UAAU,SAAS,UAAU,OAAO,KAAK;AAC/C,QAAM,sBAAsB,uBAAuB,KAAK,OAAO;AAC/D,QAAM,OAAO,gBAAgB,MAAM;AAEnC,MAAI,SAAS,0BAA0B,qBAAqB;AAC1D,UAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,UAAM,UACJ,KAAK,UAAU;AAAA,MACb,YAAY,aAAa;AAAA,MACzB,OAAO,WAAW;AAAA,MAClB,eAAe,KAAK,IAAI;AAAA,IAC1B,CAAC,IAAI;AACP,UAAM,MAAM,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,WAAW,CAAC;AAClD,UAAM,UAAU,KAAK,SAAS,MAAM;AACpC,UAAM,OAAO,KAAK,IAAI;AAAA,EACxB,WAAW,SAAS,yBAAyB,qBAAqB;AAChE,UAAM,OAAO,IAAI,EAAE,MAAM,MAAM;AAAA,IAE/B,CAAC;AAAA,EACH;AACF;AAUA,eAAsB,cAAc,MAKN;AAC5B,QAAM,EAAE,MAAM,WAAW,QAAQ,kBAAkB,IAAI;AACvD,QAAM,YAAY,SAAS,UAAU,eAAe,KAAK;AAGzD,QAAM,kBAAkB,MAAM,WAAW,WAAW,MAAM,EAAE,MAAM,MAAM;AAAA,EAExE,CAAC;AAGD,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,uBAAuB,iBAAiB;AAAA,EACzD,QAAQ;AACN,aAAS;AAAA,EACX;AACA,QAAM,OAAO,QAAQ,WAAW,IAAI;AAEpC,MAAI,WAAW;AACf,MAAI,WAAW;AAMf,QAAM,EAAE,WAAW,KAAK,IAAI,eAAe,EAAE,OAAO,CAAC;AACrD,MAAI;AACF,QAAI,MAAM;AACR,kBAAY,gBAAgB,WAAW,MAAM,MAAM,WAAW,SAAS;AAAA,IACzE,OAAO;AACL,kBAAY,oBAAoB,WAAW,MAAM,SAAS;AAC1D,iBAAW;AAAA,IACb;AACA,gBAAY,gBAAgB,WAAW,MAAM,WAAW,SAAS;AAAA,EACnE,UAAE;AACA,SAAK,MAAM;AAAA,EACb;AAEA,SAAO,EAAE,UAAU,SAAS;AAC9B;AAWA,eAAsB,iBACpB,UACA,SACA,aACe;AACf,QAAM,OAAO,YAAY;AACzB,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,oBAAoB,QAAQ,iBAAiB,yBAAyB,MAAM;AAElF,MAAI,SAA2B,EAAE,UAAU,GAAG,UAAU,MAAM;AAC9D,MAAI;AACF,UAAM,YAAY,eAAe,MAAM,UAAU,CAAC;AAClD,aAAS,MAAM,cAAc,EAAE,MAAM,WAAW,QAAQ,kBAAkB,CAAC;AAAA,EAC7E,SAAS,KAAK;AAEZ,YAAQ,OAAO;AAAA,MACb,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA;AAAA,IAClE;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,IAAI,IAAI;AACpD;;;AC/UA,SAAS,eAAe,MAAc,OAAyB;AAC7D,SAAO,OAAO,UAAU,WAAW,MAAM,SAAS,IAAI;AACxD;AAaA,eAAsB,YACpB,SACA,aACe;AACf,QAAM,aAAa,CAAC,SAAS,QAAQ,UAAU,OAAO;AAItD,MAAI,CAAC,QAAQ,MAAM;AACjB,YAAQ,OAAO;AAAA,MACb,mCAAmC,WAAW,KAAK,GAAG,CAAC;AAAA;AAAA,IACzD;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,WAAW,SAAS,QAAQ,IAAiB,GAAG;AACnD,YAAQ,OAAO;AAAA,MACb,iCAAiC,WAAW,KAAK,GAAG,CAAC;AAAA;AAAA,IACvD;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,QAAQ;AAGrB,MAAI,SAAS,WAAW,CAAC,QAAQ,SAAS;AACxC,YAAQ,OAAO,MAAM,kDAAkD;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,SAAS,UAAU,CAAC,QAAQ,QAAQ;AACtC,YAAQ,OAAO,MAAM,gDAAgD;AACrE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,SAAS,WAAW,CAAC,QAAQ,QAAQ;AACvC,YAAQ,OAAO,MAAM,iDAAiD;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,UAAU,IAAI,mBAAmB,MAAM;AAE7C,MAAI;AACF,QAAI;AAEJ,YAAQ,MAAM;AAAA;AAAA,MAEZ,KAAK,SAAS;AAEZ,iBAAS,QAAQ,SAAS,QAAQ,OAAQ;AAC1C;AAAA,MACF;AAAA;AAAA,MAGA,KAAK,QAAQ;AAEX,cAAM,OAAO,QAAQ,QAAQ,QAAQ,MAAO;AAC5C,cAAM,SAAS,QAAQ,cAAc,QAAQ,MAAO;AACpD,iBAAS,SAAS,SAAY,EAAE,MAAM,OAAO,IAAI;AACjD;AAAA,MACF;AAAA;AAAA,MAGA,KAAK,UAAU;AACb,cAAM,SAAmD,CAAC;AAC1D,YAAI,QAAQ,UAAW,QAAO,YAAY,QAAQ;AAClD,YAAI,QAAQ,OAAQ,QAAO,SAAS,QAAQ;AAC5C,YAAI,QAAQ,KAAM,QAAO,mBAAmB,cAAc,QAAQ,IAAI;AACtE,YAAI,QAAQ,GAAI,QAAO,iBAAiB,cAAc,QAAQ,EAAE;AAChE,iBAAS,QAAQ,WAAW,MAAM;AAClC;AAAA,MACF;AAAA;AAAA,MAGA,KAAK,SAAS;AACZ,cAAM,kBAAkB,CAAC,WAAW,WAAW,MAAM;AAErD,cAAM,MACJ,QAAQ,cAAc,UACtB,gBAAgB,SAAS,QAAQ,SAAgB,IAC5C,QAAQ,YACT;AACN,iBAAS,QAAQ,SAAS,QAAQ,QAAS,GAAoB;AAC/D;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM,KAAK,UAAU,QAAQ,cAAc,IAAI,IAAI;AAAA,EACpE,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAM3D,QAAI,IAAI,SAAS,eAAe,KAAK,IAAI,SAAS,gBAAgB,GAAG;AACnE,YAAM,cAAc,SAAS,SAAS,OAAO,CAAC;AAC9C,cAAQ,OAAO,MAAM,KAAK,UAAU,aAAa,cAAc,IAAI,IAAI;AACvE,cAAQ,MAAM;AACd;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM,UAAU,GAAG;AAAA,CAAI;AACtC,YAAQ,MAAM;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,MAAM;AAChB;;;AC7IO,IAAM,WAA4B;AAAA,EACvC,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AACT;;;ANRA,IAAM,YAAYC,SAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,IAAM,MAAM,KAAK;AAAA,EACf,aAAa,QAAQ,WAAW,oBAAoB,GAAG,MAAM;AAC/D;AAEA,IAAM,UAAU,cAAc,UAAU,IAAI,OAAO;AACnD,MAAM,QAAQ,WAAW;","names":["dirname","handlers","program","resolve","dirname"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/generated/program.ts","../../src/generated/contract.ts","../../src/cli/record.ts","../../src/cli/record-hook.ts","../../src/cli/query.ts","../../src/cli/backfill.ts","../../src/cli/handlers.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * aaac-observ CLI entry point.\n *\n * Reads the version from package.json, creates the generated Commander\n * program with hand-written handlers, and executes it.\n */\nimport { readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { createProgram } from \"../generated/program.js\";\nimport { handlers } from \"./handlers.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(\n readFileSync(resolve(__dirname, \"../../package.json\"), \"utf8\"),\n) as { version: string };\n\nconst program = createProgram(handlers, pkg.version);\nawait program.parseAsync();\n","// Auto-generated by cli-contracts. Do not edit.\nimport { Command } from \"commander\";\nimport { CONTRACT_YAML, CONTRACT_JSON_STR } from \"./contract.js\";\n\nexport interface CommandHandlers {\n record: (options: { eventType?: string; lifecycle?: string; spanId?: string; parentSpanId?: string; sessionId?: string; traceId?: string; source?: string; attr?: string; link?: string; db?: string }, parentOpts: Record<string, unknown>) => Promise<void>;\n recordHook: (hookName: string | undefined, options: { mappingConfig?: string; db?: string }, parentOpts: Record<string, unknown>) => Promise<void>;\n backfill: (options: { db?: string; endpoint?: string; serviceName?: string; from?: string; to?: string; eventType?: string; dryRun?: boolean; flushTimeoutMs?: number }, parentOpts: Record<string, unknown>) => Promise<void>;\n query: (options: { kind?: string; traceId?: string; spanId?: string; eventType?: string; taskId?: string; from?: string; to?: string; direction?: string; db?: string }, parentOpts: Record<string, unknown>) => Promise<void>;\n}\n\nexport function createProgram(\n handlers: CommandHandlers,\n version: string,\n): Command {\n const program = new Command();\n program\n .name(\"aaac-observ\")\n .version(version, \"-V, --version\")\n .description(\"aaac-observ — register external events and query the observability store\");\n\n\n program\n .command(\"record\")\n .description(\"Register an external event into the observability pipeline (thin entrypoint for EventCollector.registerExternalEvent)\")\n .option(\"-t, --event-type <value>\", \"Event type (e.g. promotion.commit, process.edit, agent.session)\")\n .option(\"-l, --lifecycle <value>\", \"Event lifecycle phase: open | close | event | instant\")\n .option(\"-s, --span-id <value>\", \"Span ID (auto-generated if omitted)\")\n .option(\"--parent-span-id <value>\", \"Parent span ID for hierarchy\")\n .option(\"--session-id <value>\", \"Session ID to associate with the event\")\n .option(\"--trace-id <value>\", \"Trace ID for distributed tracing\")\n .option(\"--source <value>\", \"Event source identifier (default: external)\")\n .option(\"--attr <value>\", \"Attribute as key=value (repeatable, e.g. --attr git.commit=abc123)\")\n .option(\"--link <value>\", \"Cross-axis link as targetSpanId:linkType[:targetTraceId] (repeatable)\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .action(async (opts, cmd) => {\n await handlers.record(opts, cmd.optsWithGlobals());\n });\n\n program\n .command(\"record-hook\")\n .description(\"Record a Cursor/git hook event — parses stdin JSON, resolves event_mapping into 3-axis spans/links, injects session_id, and emits human-events (fail-open)\")\n .argument(\"<hook-name>\", \"Cursor/git hook name (e.g. afterFileEdit, subagentStart, beforeShellExecution)\")\n .option(\"--mapping-config <value>\", \"Path to event-mapping.json (default: .agent-logs/config/event-mapping.json)\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .action(async (hookName, opts, cmd) => {\n await handlers.recordHook(hookName, opts, cmd.optsWithGlobals());\n });\n\n program\n .command(\"backfill\")\n .description(\"Re-emit historical spans from SQLite to an OTLP backend\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .option(\"--endpoint <value>\", \"OTLP HTTP endpoint URL (fallback: OTEL_EXPORTER_OTLP_ENDPOINT)\")\n .option(\"--service-name <value>\", \"OTEL service name reported to backend (default: @aaac/observability)\")\n .option(\"--from <value>\", \"Backfill spans starting at or after this ISO 8601 time\")\n .option(\"--to <value>\", \"Backfill spans starting at or before this ISO 8601 time\")\n .option(\"--event-type <value>\", \"Filter by event type (e.g. agent.session)\")\n .option(\"--dry-run\", \"Print span count without emitting to OTLP backend\")\n .option(\"--flush-timeout-ms <ms>\", \"Maximum ms to wait for OTLP flush before exit (default: 2000; use ≥30000 for >5k spans)\", (v) => parseInt(v, 10))\n .action(async (opts, cmd) => {\n await handlers.backfill(opts, cmd.optsWithGlobals());\n });\n\n program\n .command(\"query\")\n .description(\"Query the observability store via QueryAdapter\")\n .option(\"-k, --kind <value>\", \"Query kind: trace | span | search | links\")\n .option(\"--trace-id <value>\", \"Trace ID for trace queries (--kind trace)\")\n .option(\"-s, --span-id <value>\", \"Span ID for span/links queries (--kind span or --kind links)\")\n .option(\"--event-type <value>\", \"Event type filter for search queries (--kind search)\")\n .option(\"--task-id <value>\", \"Task ID filter for search queries (--kind search)\")\n .option(\"--from <value>\", \"Start time in ISO 8601 format for search queries (--kind search)\")\n .option(\"--to <value>\", \"End time in ISO 8601 format for search queries (--kind search)\")\n .option(\"-d, --direction <value>\", \"Link traversal direction for links queries (default: both)\")\n .option(\"--db <value>\", \"Path to observability SQLite database (overrides default)\")\n .action(async (opts, cmd) => {\n await handlers.query(opts, cmd.optsWithGlobals());\n });\n\n\n // Built-in extract command (auto-injected by cli-contracts)\n program\n .command(\"extract\")\n .description(\"Extract contract specification for this CLI tool.\")\n .argument(\"[commands...]\", \"Command IDs to extract. Use dot notation.\")\n .option(\"-a, --all\", \"Extract all commands.\", false)\n .option(\"--include-meta\", \"Include extraction metadata.\", true)\n .option(\"-F, --format <format>\", \"Output format (yaml or json).\", \"yaml\")\n .action(async (commands: string[], opts: { all?: boolean; includeMeta?: boolean; format?: string }, cmd: Command) => {\n if (commands.length === 0 && !opts.all) {\n process.stderr.write(JSON.stringify({ code: \"INVALID_ARGS\", message: \"Specify command IDs or use --all\" }) + \"\\n\");\n process.exit(2);\n }\n\n const format = opts.format || \"yaml\";\n const doc = JSON.parse(CONTRACT_JSON_STR);\n const cmdIds = opts.all ? [] : commands;\n\n if (cmdIds.length === 0) {\n // --all: output full contract\n if (format === \"json\") {\n const out: Record<string, unknown> = {};\n if (opts.includeMeta) {\n out._meta = {\n source: \"embedded\",\n type: \"cli-contracts/extract\",\n extractedAt: new Date().toISOString(),\n specVersion: doc.cli_contracts ?? \"0.1.0\",\n commands: [\"aaac-observ.record\",\"aaac-observ.record-hook\",\"aaac-observ.backfill\",\"aaac-observ.query\"],\n };\n }\n Object.assign(out, doc);\n process.stdout.write(JSON.stringify(out, null, 2) + \"\\n\");\n } else {\n // YAML output\n const yamlLines: string[] = [];\n yamlLines.push(\"# aaac-observ extract\");\n yamlLines.push(\"# source: embedded\");\n yamlLines.push(\"# type: cli-contracts/command-extract\");\n if (opts.includeMeta) {\n yamlLines.push(\"---\");\n yamlLines.push(\"source: embedded\");\n yamlLines.push(\"type: cli-contracts/command-extract\");\n yamlLines.push(\"extractedAt: \" + new Date().toISOString());\n yamlLines.push(\"spec_version: \" + (doc.cli_contracts ?? \"0.1.0\"));\n yamlLines.push(\"commands:\");\n for (const id of [\"aaac-observ.record\",\"aaac-observ.record-hook\",\"aaac-observ.backfill\",\"aaac-observ.query\"]) {\n yamlLines.push(\" - \" + id);\n }\n }\n yamlLines.push(\"---\");\n yamlLines.push(CONTRACT_YAML);\n process.stdout.write(yamlLines.join(\"\\n\") + \"\\n\");\n }\n } else {\n // Filter specific commands\n const filtered: Record<string, unknown> = {\n cli_contracts: doc.cli_contracts,\n info: doc.info,\n command_sets: {},\n };\n const fcs = filtered.command_sets as Record<string, Record<string, unknown>>;\n for (const [setId, cs] of Object.entries(doc.command_sets ?? {})) {\n const cmds = (cs as Record<string, unknown>).commands as Record<string, unknown> | undefined;\n if (!cmds) continue;\n const matched: Record<string, unknown> = {};\n for (const [cmdId, cmdDef] of Object.entries(cmds)) {\n const fullId = setId + \".\" + cmdId;\n if (cmdIds.some((id) => id === cmdId || id === fullId || cmdId.startsWith(id + \".\"))) {\n matched[cmdId] = cmdDef;\n }\n }\n if (Object.keys(matched).length > 0) {\n const setCopy = { ...(cs as Record<string, unknown>) };\n setCopy.commands = matched;\n fcs[setId] = setCopy;\n }\n }\n if (doc.components) filtered.components = doc.components;\n process.stdout.write(JSON.stringify(filtered, null, 2) + \"\\n\");\n }\n process.exit(0);\n });\n return program;\n}\n","// Auto-generated by cli-contracts. Do not edit.\n// Embedded contract for the extract subcommand.\n\nexport const CONTRACT_YAML: string = \"# yaml-language-server: $schema=./node_modules/cli-contracts/schemas/cli-contract.schema.json\\ncli_contracts: 0.1.0\\n\\ninfo:\\n title: AaaC Observability CLI\\n version: 0.1.0\\n description: aaac-observ — external event registration and query for @aaac/observability\\n\\ncommand_sets:\\n aaac-observ:\\n summary: aaac-observ — register external events and query the observability store\\n executable: aaac-observ\\n commands:\\n record:\\n summary: Register an external event into the observability pipeline (thin entrypoint for EventCollector.registerExternalEvent)\\n options:\\n - name: event-type\\n aliases: [t]\\n schema: { type: string }\\n description: \\\"Event type (e.g. promotion.commit, process.edit, agent.session)\\\"\\n - name: lifecycle\\n aliases: [l]\\n schema:\\n type: string\\n enum: [open, close, event, instant]\\n description: \\\"Event lifecycle phase: open | close | event | instant\\\"\\n - name: span-id\\n aliases: [s]\\n schema: { type: string }\\n description: Span ID (auto-generated if omitted)\\n - name: parent-span-id\\n schema: { type: string }\\n description: Parent span ID for hierarchy\\n - name: session-id\\n schema: { type: string }\\n description: Session ID to associate with the event\\n - name: trace-id\\n schema: { type: string }\\n description: Trace ID for distributed tracing\\n - name: source\\n schema: { type: string }\\n description: \\\"Event source identifier (default: external)\\\"\\n - name: attr\\n schema:\\n type: array\\n items: { type: string }\\n description: \\\"Attribute as key=value (repeatable, e.g. --attr git.commit=abc123)\\\"\\n - name: link\\n schema:\\n type: array\\n items: { type: string }\\n description: \\\"Cross-axis link as targetSpanId:linkType[:targetTraceId] (repeatable)\\\"\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n exits:\\n '0':\\n description: Event registered successfully\\n stdout:\\n format: json\\n schema:\\n type: object\\n properties:\\n eventId:\\n type: string\\n spanId:\\n type: string\\n '1':\\n description: Registration failed (validation error or write error)\\n stderr:\\n format: text\\n\\n record-hook:\\n summary: Record a Cursor/git hook event — parses stdin JSON, resolves event_mapping into 3-axis spans/links, injects session_id, and emits human-events (fail-open)\\n arguments:\\n - name: hook-name\\n index: 0\\n required: true\\n schema: { type: string }\\n description: \\\"Cursor/git hook name (e.g. afterFileEdit, subagentStart, beforeShellExecution)\\\"\\n options:\\n - name: mapping-config\\n schema: { type: string }\\n description: \\\"Path to event-mapping.json (default: .agent-logs/config/event-mapping.json)\\\"\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n exits:\\n '0':\\n description: Hook recorded (or no-op when stdin/mapping unavailable) — always fail-open\\n stdout:\\n format: json\\n schema:\\n type: object\\n properties:\\n recorded:\\n type: integer\\n fallback:\\n type: boolean\\n\\n backfill:\\n summary: Re-emit historical spans from SQLite to an OTLP backend\\n description: |\\n Reads closed/instant spans from the local SQLite database and emits them\\n via OtelEmitter to an OTLP-compatible backend.\\n\\n IMPORTANT — idempotency: The OTel SDK does not support specifying custom\\n spanIds, so each backfill invocation creates NEW spans in the backend.\\n Repeated invocations will produce DUPLICATE data. Use --from/--to to\\n control scope. See #125 §7 for full idempotency guidance.\\n options:\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n - name: endpoint\\n schema: { type: string }\\n description: \\\"OTLP HTTP endpoint URL (fallback: OTEL_EXPORTER_OTLP_ENDPOINT)\\\"\\n - name: service-name\\n schema: { type: string }\\n description: \\\"OTEL service name reported to backend (default: @aaac/observability)\\\"\\n - name: from\\n schema: { type: string }\\n description: Backfill spans starting at or after this ISO 8601 time\\n - name: to\\n schema: { type: string }\\n description: Backfill spans starting at or before this ISO 8601 time\\n - name: event-type\\n schema: { type: string }\\n description: \\\"Filter by event type (e.g. agent.session)\\\"\\n - name: dry-run\\n schema: { type: boolean }\\n description: Print span count without emitting to OTLP backend\\n exits:\\n '0':\\n description: Backfill completed\\n stdout:\\n format: json\\n schema:\\n type: object\\n properties:\\n spansFound:\\n type: integer\\n spansEmitted:\\n type: integer\\n dryRun:\\n type: boolean\\n '1':\\n description: Backfill failed (missing endpoint, DB error, etc.)\\n stderr:\\n format: text\\n\\n query:\\n summary: Query the observability store via QueryAdapter\\n options:\\n - name: kind\\n aliases: [k]\\n schema:\\n type: string\\n enum: [trace, span, search, links]\\n description: \\\"Query kind: trace | span | search | links\\\"\\n - name: trace-id\\n schema: { type: string }\\n description: Trace ID for trace queries (--kind trace)\\n - name: span-id\\n aliases: [s]\\n schema: { type: string }\\n description: Span ID for span/links queries (--kind span or --kind links)\\n - name: event-type\\n schema: { type: string }\\n description: Event type filter for search queries (--kind search)\\n - name: task-id\\n schema: { type: string }\\n description: Task ID filter for search queries (--kind search)\\n - name: from\\n schema: { type: string }\\n description: Start time in ISO 8601 format for search queries (--kind search)\\n - name: to\\n schema: { type: string }\\n description: End time in ISO 8601 format for search queries (--kind search)\\n - name: direction\\n aliases: [d]\\n schema:\\n type: string\\n enum: [forward, reverse, both]\\n description: \\\"Link traversal direction for links queries (default: both)\\\"\\n - name: db\\n schema: { type: string }\\n description: Path to observability SQLite database (overrides default)\\n exits:\\n '0':\\n description: Query succeeded — results as JSON array\\n stdout:\\n format: json\\n schema:\\n type: object\\n '1':\\n description: Query failed\\n stderr:\\n format: text\\n\";\n\nexport const CONTRACT_JSON_STR: string = \"{\\n \\\"cli_contracts\\\": \\\"0.1.0\\\",\\n \\\"info\\\": {\\n \\\"title\\\": \\\"AaaC Observability CLI\\\",\\n \\\"version\\\": \\\"0.1.0\\\",\\n \\\"description\\\": \\\"aaac-observ — external event registration and query for @aaac/observability\\\"\\n },\\n \\\"command_sets\\\": {\\n \\\"aaac-observ\\\": {\\n \\\"summary\\\": \\\"aaac-observ — register external events and query the observability store\\\",\\n \\\"executable\\\": \\\"aaac-observ\\\",\\n \\\"commands\\\": {\\n \\\"record\\\": {\\n \\\"summary\\\": \\\"Register an external event into the observability pipeline (thin entrypoint for EventCollector.registerExternalEvent)\\\",\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"event-type\\\",\\n \\\"aliases\\\": [\\n \\\"t\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Event type (e.g. promotion.commit, process.edit, agent.session)\\\"\\n },\\n {\\n \\\"name\\\": \\\"lifecycle\\\",\\n \\\"aliases\\\": [\\n \\\"l\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\",\\n \\\"enum\\\": [\\n \\\"open\\\",\\n \\\"close\\\",\\n \\\"event\\\",\\n \\\"instant\\\"\\n ]\\n },\\n \\\"description\\\": \\\"Event lifecycle phase: open | close | event | instant\\\"\\n },\\n {\\n \\\"name\\\": \\\"span-id\\\",\\n \\\"aliases\\\": [\\n \\\"s\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Span ID (auto-generated if omitted)\\\"\\n },\\n {\\n \\\"name\\\": \\\"parent-span-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Parent span ID for hierarchy\\\"\\n },\\n {\\n \\\"name\\\": \\\"session-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Session ID to associate with the event\\\"\\n },\\n {\\n \\\"name\\\": \\\"trace-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Trace ID for distributed tracing\\\"\\n },\\n {\\n \\\"name\\\": \\\"source\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Event source identifier (default: external)\\\"\\n },\\n {\\n \\\"name\\\": \\\"attr\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"array\\\",\\n \\\"items\\\": {\\n \\\"type\\\": \\\"string\\\"\\n }\\n },\\n \\\"description\\\": \\\"Attribute as key=value (repeatable, e.g. --attr git.commit=abc123)\\\"\\n },\\n {\\n \\\"name\\\": \\\"link\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"array\\\",\\n \\\"items\\\": {\\n \\\"type\\\": \\\"string\\\"\\n }\\n },\\n \\\"description\\\": \\\"Cross-axis link as targetSpanId:linkType[:targetTraceId] (repeatable)\\\"\\n },\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Event registered successfully\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\",\\n \\\"properties\\\": {\\n \\\"eventId\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"spanId\\\": {\\n \\\"type\\\": \\\"string\\\"\\n }\\n }\\n }\\n }\\n },\\n \\\"1\\\": {\\n \\\"description\\\": \\\"Registration failed (validation error or write error)\\\",\\n \\\"stderr\\\": {\\n \\\"format\\\": \\\"text\\\"\\n }\\n }\\n }\\n },\\n \\\"record-hook\\\": {\\n \\\"summary\\\": \\\"Record a Cursor/git hook event — parses stdin JSON, resolves event_mapping into 3-axis spans/links, injects session_id, and emits human-events (fail-open)\\\",\\n \\\"arguments\\\": [\\n {\\n \\\"name\\\": \\\"hook-name\\\",\\n \\\"index\\\": 0,\\n \\\"required\\\": true,\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Cursor/git hook name (e.g. afterFileEdit, subagentStart, beforeShellExecution)\\\"\\n }\\n ],\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"mapping-config\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to event-mapping.json (default: .agent-logs/config/event-mapping.json)\\\"\\n },\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Hook recorded (or no-op when stdin/mapping unavailable) — always fail-open\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\",\\n \\\"properties\\\": {\\n \\\"recorded\\\": {\\n \\\"type\\\": \\\"integer\\\"\\n },\\n \\\"fallback\\\": {\\n \\\"type\\\": \\\"boolean\\\"\\n }\\n }\\n }\\n }\\n }\\n }\\n },\\n \\\"backfill\\\": {\\n \\\"summary\\\": \\\"Re-emit historical spans from SQLite to an OTLP backend\\\",\\n \\\"description\\\": \\\"Reads closed/instant spans from the local SQLite database and emits them\\\\nvia OtelEmitter to an OTLP-compatible backend.\\\\n\\\\nIMPORTANT — idempotency: The OTel SDK does not support specifying custom\\\\nspanIds, so each backfill invocation creates NEW spans in the backend.\\\\nRepeated invocations will produce DUPLICATE data. Use --from/--to to\\\\ncontrol scope. See #125 §7 for full idempotency guidance.\\\\n\\\",\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n },\\n {\\n \\\"name\\\": \\\"endpoint\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"OTLP HTTP endpoint URL (fallback: OTEL_EXPORTER_OTLP_ENDPOINT)\\\"\\n },\\n {\\n \\\"name\\\": \\\"service-name\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"OTEL service name reported to backend (default: @aaac/observability)\\\"\\n },\\n {\\n \\\"name\\\": \\\"from\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Backfill spans starting at or after this ISO 8601 time\\\"\\n },\\n {\\n \\\"name\\\": \\\"to\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Backfill spans starting at or before this ISO 8601 time\\\"\\n },\\n {\\n \\\"name\\\": \\\"event-type\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Filter by event type (e.g. agent.session)\\\"\\n },\\n {\\n \\\"name\\\": \\\"dry-run\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"boolean\\\"\\n },\\n \\\"description\\\": \\\"Print span count without emitting to OTLP backend\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Backfill completed\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\",\\n \\\"properties\\\": {\\n \\\"spansFound\\\": {\\n \\\"type\\\": \\\"integer\\\"\\n },\\n \\\"spansEmitted\\\": {\\n \\\"type\\\": \\\"integer\\\"\\n },\\n \\\"dryRun\\\": {\\n \\\"type\\\": \\\"boolean\\\"\\n }\\n }\\n }\\n }\\n },\\n \\\"1\\\": {\\n \\\"description\\\": \\\"Backfill failed (missing endpoint, DB error, etc.)\\\",\\n \\\"stderr\\\": {\\n \\\"format\\\": \\\"text\\\"\\n }\\n }\\n }\\n },\\n \\\"query\\\": {\\n \\\"summary\\\": \\\"Query the observability store via QueryAdapter\\\",\\n \\\"options\\\": [\\n {\\n \\\"name\\\": \\\"kind\\\",\\n \\\"aliases\\\": [\\n \\\"k\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\",\\n \\\"enum\\\": [\\n \\\"trace\\\",\\n \\\"span\\\",\\n \\\"search\\\",\\n \\\"links\\\"\\n ]\\n },\\n \\\"description\\\": \\\"Query kind: trace | span | search | links\\\"\\n },\\n {\\n \\\"name\\\": \\\"trace-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Trace ID for trace queries (--kind trace)\\\"\\n },\\n {\\n \\\"name\\\": \\\"span-id\\\",\\n \\\"aliases\\\": [\\n \\\"s\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Span ID for span/links queries (--kind span or --kind links)\\\"\\n },\\n {\\n \\\"name\\\": \\\"event-type\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Event type filter for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"task-id\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Task ID filter for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"from\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Start time in ISO 8601 format for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"to\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"End time in ISO 8601 format for search queries (--kind search)\\\"\\n },\\n {\\n \\\"name\\\": \\\"direction\\\",\\n \\\"aliases\\\": [\\n \\\"d\\\"\\n ],\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\",\\n \\\"enum\\\": [\\n \\\"forward\\\",\\n \\\"reverse\\\",\\n \\\"both\\\"\\n ]\\n },\\n \\\"description\\\": \\\"Link traversal direction for links queries (default: both)\\\"\\n },\\n {\\n \\\"name\\\": \\\"db\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"string\\\"\\n },\\n \\\"description\\\": \\\"Path to observability SQLite database (overrides default)\\\"\\n }\\n ],\\n \\\"exits\\\": {\\n \\\"0\\\": {\\n \\\"description\\\": \\\"Query succeeded — results as JSON array\\\",\\n \\\"stdout\\\": {\\n \\\"format\\\": \\\"json\\\",\\n \\\"schema\\\": {\\n \\\"type\\\": \\\"object\\\"\\n }\\n }\\n },\\n \\\"1\\\": {\\n \\\"description\\\": \\\"Query failed\\\",\\n \\\"stderr\\\": {\\n \\\"format\\\": \\\"text\\\"\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n}\";\n","/**\n * record handler — thin entrypoint for EventCollector.registerExternalEvent.\n *\n * Wires the CLI options to the write pipeline:\n * options → EventCollector.registerExternalEvent\n * → Normalizer → Correlator → Enricher → SqliteSink + OtelEmitter\n *\n * architecture.md §9 / OBSERVABILITY_TASKS.md Phase 3-2\n * shift-left-event-mapping.md: aaac-observ record is the thin entrypoint\n */\nimport { createPipeline, generateId, DEFAULT_DB_PATH } from \"../index.js\";\nimport type { CanonicalLink, AttrValue, Lifecycle } from \"../types/canonical-event.js\";\n\n// ── Parsers ──────────────────────────────────────────────────────────────────\n\n/**\n * Parse comma-separated key=value attribute string into a Record.\n * Also accepts a JSON object string.\n *\n * Examples:\n * \"git.commit=abc123,git.branch=main\"\n * '{\"git.commit\":\"abc123\",\"git.branch\":\"main\"}'\n */\nexport function parseAttr(attrStr: string | undefined): Record<string, AttrValue> {\n if (!attrStr) return {};\n const trimmed = attrStr.trim();\n if (trimmed.startsWith(\"{\")) {\n try {\n return JSON.parse(trimmed) as Record<string, AttrValue>;\n } catch {\n // fall through to key=value parsing\n }\n }\n const result: Record<string, AttrValue> = {};\n for (const pair of trimmed.split(\",\")) {\n const eqIdx = pair.indexOf(\"=\");\n if (eqIdx > 0) {\n const key = pair.slice(0, eqIdx).trim();\n const val = pair.slice(eqIdx + 1).trim();\n result[key] = val;\n }\n }\n return result;\n}\n\n/**\n * Parse comma-separated link string into a CanonicalLink array.\n * Format per item: targetSpanId:linkType[:targetTraceId]\n *\n * Example: \"spanId123:materializes_as_commit,spanId456:contains_change:traceId789\"\n */\nexport function parseLinks(linkStr: string | undefined): CanonicalLink[] {\n if (!linkStr) return [];\n const links: CanonicalLink[] = [];\n for (const item of linkStr.split(\",\")) {\n const parts = item.trim().split(\":\");\n if (parts.length >= 2) {\n const targetSpanId = parts[0].trim();\n const linkType = parts[1].trim();\n const targetTraceId = parts[2]?.trim() || undefined;\n if (targetSpanId && linkType) {\n links.push({ targetSpanId, linkType, targetTraceId });\n }\n }\n }\n return links;\n}\n\n// ── Handler ──────────────────────────────────────────────────────────────────\n\n/**\n * Options as parsed from the generated CommandHandlers interface.\n * NOTE: attr and link are strings (last value from --option) not arrays,\n * because the generated Commander program does not use a collector.\n * Comma-separate multiple values: --attr \"key1=val1,key2=val2\"\n */\nexport interface RecordHandlerOptions {\n eventType?: string;\n lifecycle?: string;\n spanId?: string;\n parentSpanId?: string;\n sessionId?: string;\n traceId?: string;\n source?: string;\n attr?: string;\n link?: string;\n db?: string;\n}\n\n/**\n * Handle `aaac-observ record`.\n *\n * Required options: --event-type, --lifecycle\n * On success: writes the event through the full pipeline and prints\n * { eventId, spanId } to stdout.\n * On error: writes to stderr and exits with code 1.\n */\nexport async function handleRecord(\n options: RecordHandlerOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n // ── Validate required options ──────────────────────────────────────────────\n if (!options.eventType) {\n process.stderr.write(\"Error: --event-type (-t) is required\\n\");\n process.exit(1);\n }\n const validLifecycles: readonly string[] = [\"open\", \"close\", \"event\", \"instant\"];\n if (!options.lifecycle) {\n process.stderr.write(\n `Error: --lifecycle (-l) is required (${validLifecycles.join(\"|\")})\\n`,\n );\n process.exit(1);\n }\n if (!validLifecycles.includes(options.lifecycle)) {\n process.stderr.write(\n `Error: --lifecycle must be one of: ${validLifecycles.join(\"|\")}\\n`,\n );\n process.exit(1);\n }\n\n // ── Build event payload ────────────────────────────────────────────────────\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const spanId = options.spanId ?? generateId();\n const attributes = parseAttr(options.attr);\n const links = parseLinks(options.link);\n\n // Inject well-known scalars into attributes so the Normalizer picks them up\n if (options.sessionId) {\n attributes[\"session_id\"] = options.sessionId;\n }\n // trace_id stored as attribute for user reference; canonical traceId is\n // managed by Normalizer/Correlator (propagated via parentSpanId chain)\n if (options.traceId) {\n attributes[\"trace_id\"] = options.traceId;\n }\n\n // ── Build & execute pipeline ───────────────────────────────────────────────\n let capturedEventId: string | undefined;\n\n const { collector, sink } = createPipeline({\n dbPath,\n // Use afterCorrelate to capture the event id before it is written\n afterCorrelate: (event) => {\n capturedEventId = event.id;\n return event;\n },\n // Enable the default enrichment rules (R1–R5). This is the path the git\n // post-commit hook uses to record promotion.commit (close) with\n // committed_files; R5 (cross-axis) must run here to add the\n // materializes_as_commit link to task spans whose modified files intersect\n // the commit. R3/R4 accumulation persists in the SQLite-backed cache of the\n // same db file, so R5 sees it across the process boundary (#143 / #140).\n // Enricher is fail-open, so a rule error never blocks recording.\n });\n\n try {\n collector.registerExternalEvent({\n source: options.source ?? \"external\",\n eventType: options.eventType,\n lifecycle: options.lifecycle as Lifecycle,\n spanId,\n parentSpanId: options.parentSpanId,\n attributes,\n links,\n });\n } catch (err) {\n process.stderr.write(\n `Error: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n sink.close();\n process.exit(1);\n }\n\n sink.close();\n\n const result = { eventId: capturedEventId, spanId };\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n}\n","/**\n * record-hook handler — stdin-aware Cursor/git hook recorder.\n *\n * This is the runtime entrypoint for `.cursor/hooks/observ-record.sh`. Unlike the\n * thin `record` command (scalar flags only), `record-hook`:\n *\n * 1. parses the hook JSON payload from stdin (conversation_id + hook-specific fields)\n * 2. loads `.agent-logs/config/event-mapping.json` and resolves the matching\n * mapping rule into 3-axis spans + cross-axis links (evaluateMapping)\n * 3. injects session_id = conversation_id on every emitted event (correlation key\n * with @aaac/runtime in-process events)\n * 4. emits human-interaction events (human.instruction / quality_gate.result /\n * promotion.pr) for the relevant hooks\n * 5. manages the short-lived git context file `.agent-logs/.observ-context.json`\n * (write on beforeShellExecution for git commit/push/merge, delete on\n * afterShellExecution) so git hooks can correlate (read side: #115)\n *\n * It is strictly fail-open: any parse/IO/config error degrades to the generic\n * fallback recording (or a no-op) and never throws — recording must NEVER block\n * the underlying hook operation.\n *\n * Issue #114 / shift-left-event-mapping.md §6 (option B).\n */\nimport { mkdir, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport {\n createPipeline,\n generateId,\n DEFAULT_DB_PATH,\n loadEventMappingConfig,\n evaluateMapping,\n emitHumanInstruction,\n emitQualityGateResult,\n emitPromotionPr,\n} from \"../index.js\";\nimport type { EventCollector } from \"../collector/event-collector.js\";\nimport type { AttrValue, CanonicalLink } from \"../types/canonical-event.js\";\nimport type { EventMappingConfig, EventMappingRule } from \"../event-mapping/types.js\";\n\n// ── Constants ──────────────────────────────────────────────────────────────────\n\n/** git subcommands that warrant propagating session context to git hooks. */\nconst GIT_CONTEXT_COMMAND_RE = /\\bgit\\s+(?:commit|push|merge)\\b/;\n\n/** Hook names that map to git.* event types in the generic fallback. */\nconst GIT_HOOK_NAMES = new Set([\n \"pre-commit\",\n \"post-commit\",\n \"pre-push\",\n \"post-merge\",\n \"post-checkout\",\n]);\n\n// ── Options ──────────────────────────────────────────────────────────────────\n\nexport interface RecordHookOptions {\n mappingConfig?: string;\n db?: string;\n}\n\n/** Parsed result of running the hook recorder (also written to stdout as JSON). */\nexport interface RecordHookResult {\n /** Number of events emitted into the pipeline. */\n recorded: number;\n /** True when no mapping rule matched and the generic fallback was used. */\n fallback: boolean;\n}\n\n// ── Path helpers ───────────────────────────────────────────────────────────────\n\n/** Default event-mapping config path, derived from the db directory. */\nexport function defaultMappingConfigPath(dbPath: string): string {\n return join(dirname(dbPath), \"config\", \"event-mapping.json\");\n}\n\n/** Short-lived git context file path, derived from the db directory. */\nexport function contextFilePath(dbPath: string): string {\n return join(dirname(dbPath), \".observ-context.json\");\n}\n\n// ── stdin parsing ────────────────────────────────────────────────────────────\n\n/**\n * Read the entire stdin stream as a string.\n * Resolves \"\" when stdin is a TTY (no payload) or on any error — the git-hook\n * path frequently provides no stdin, which must be handled gracefully (AC-1).\n */\nexport async function readStdin(): Promise<string> {\n if (process.stdin.isTTY) return \"\";\n return new Promise<string>((resolve) => {\n let data = \"\";\n let settled = false;\n const finish = (): void => {\n if (settled) return;\n settled = true;\n resolve(data);\n };\n try {\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", finish);\n process.stdin.on(\"error\", finish);\n process.stdin.on(\"close\", finish);\n // Safety net: never hang the hook if stdin is left open.\n const t = setTimeout(finish, 1000);\n if (typeof t.unref === \"function\") t.unref();\n } catch {\n finish();\n }\n });\n}\n\n/** Parse a stdin payload into an object; returns {} for empty/invalid JSON. */\nexport function parseHookInput(raw: string): Record<string, unknown> {\n const trimmed = raw.trim();\n if (!trimmed) return {};\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n return parsed !== null && typeof parsed === \"object\"\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\n// ── Field coercion ───────────────────────────────────────────────────────────\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\n// ── Emission ─────────────────────────────────────────────────────────────────\n\n/**\n * Emit the 3-axis spans + cross-axis links resolved from a mapping rule.\n * session_id (and parent_conversation_id on subagentStart) are injected on every\n * span so all hook-derived events share the correlation key.\n */\nfunction emitMappedSpans(\n collector: EventCollector,\n hook: string,\n rule: EventMappingRule,\n hookInput: Record<string, unknown>,\n sessionId: string,\n): number {\n const { spans, links } = evaluateMapping(rule, hookInput);\n\n // Group resolved links by their source spanId so they can be attached to the\n // emitting (source) event as CanonicalLink entries.\n const linksBySpan = new Map<string, CanonicalLink[]>();\n for (const link of links) {\n const arr = linksBySpan.get(link.fromSpanId) ?? [];\n arr.push({ targetSpanId: link.toSpanId, linkType: link.linkType });\n linksBySpan.set(link.fromSpanId, arr);\n }\n\n const parentConversationId =\n hook === \"subagentStart\" ? asString(hookInput.parent_conversation_id) : undefined;\n\n for (const span of spans) {\n const attributes: Record<string, AttrValue> = { ...span.attributes };\n if (sessionId) attributes[\"session_id\"] = sessionId;\n if (parentConversationId) {\n attributes[\"parent_conversation_id\"] = parentConversationId;\n }\n collector.emit({\n source: \"cursor-hook\",\n eventType: span.eventType,\n lifecycle: span.lifecycle,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId,\n attributes,\n links: linksBySpan.get(span.spanId) ?? [],\n });\n }\n\n return spans.length;\n}\n\n/**\n * Emit a single generic instant event (current pre-#114 behaviour) when no\n * mapping rule matches — preserves fail-open recording (AC-3).\n */\nfunction emitGenericFallback(\n collector: EventCollector,\n hook: string,\n sessionId: string,\n): number {\n const eventType = (GIT_HOOK_NAMES.has(hook) ? \"git.\" : \"cursor.\") + hook;\n const attributes: Record<string, AttrValue> = { \"hook.name\": hook };\n if (sessionId) attributes[\"session_id\"] = sessionId;\n collector.emit({\n source: \"cursor-hook\",\n eventType,\n lifecycle: \"instant\",\n attributes,\n });\n return 1;\n}\n\n/** Emit human-interaction events for the relevant hooks (AC-5). */\nfunction emitHumanEvents(\n collector: EventCollector,\n hook: string,\n hookInput: Record<string, unknown>,\n sessionId: string,\n): number {\n let count = 0;\n\n if (hook === \"beforeSubmitPrompt\") {\n const prompt = asString(hookInput.prompt);\n if (prompt !== undefined) {\n const attachments = Array.isArray(hookInput.attachments)\n ? (hookInput.attachments as unknown[])\n : [];\n emitHumanInstruction(collector, { sessionId, prompt, attachments });\n count += 1;\n }\n } else if (hook === \"afterShellExecution\") {\n const command = asString(hookInput.command);\n if (command !== undefined) {\n const exitCode = asNumber(hookInput.exit_code) ?? asNumber(hookInput.exitCode) ?? 0;\n const durationMs = asNumber(hookInput.duration);\n if (emitQualityGateResult(collector, { sessionId, command, exitCode, durationMs })) {\n count += 1;\n }\n const output = asString(hookInput.output) ?? \"\";\n if (emitPromotionPr(collector, { sessionId, command, output })) {\n count += 1;\n }\n }\n }\n\n return count;\n}\n\n// ── Context file lifecycle ──────────────────────────────────────────────────\n\n/**\n * Manage the short-lived git context file (AC-4).\n *\n * beforeShellExecution + git commit/push/merge → atomic write\n * afterShellExecution + git commit/push/merge → delete (fail-open)\n *\n * Atomic write uses write-to-temp + rename so a git hook never observes a\n * partially written file. Non-git commands never write the file.\n */\nasync function manageContextFile(\n hook: string,\n hookInput: Record<string, unknown>,\n sessionId: string,\n dbPath: string,\n): Promise<void> {\n const command = asString(hookInput.command) ?? \"\";\n const isGitContextCommand = GIT_CONTEXT_COMMAND_RE.test(command);\n const file = contextFilePath(dbPath);\n\n if (hook === \"beforeShellExecution\" && isGitContextCommand) {\n await mkdir(dirname(file), { recursive: true });\n const payload =\n JSON.stringify({\n session_id: sessionId || null,\n nonce: generateId(),\n created_at_ms: Date.now(),\n }) + \"\\n\";\n const tmp = `${file}.${process.pid}.${generateId()}.tmp`;\n await writeFile(tmp, payload, \"utf8\");\n await rename(tmp, file);\n } else if (hook === \"afterShellExecution\" && isGitContextCommand) {\n await unlink(file).catch(() => {\n // rm -f semantics: missing file is not an error.\n });\n }\n}\n\n// ── Core (testable) ────────────────────────────────────────────────────────────\n\n/**\n * Run the hook recorder against an already-parsed hook input.\n *\n * Separated from {@link handleRecordHook} (which reads stdin) so it can be unit\n * tested without mocking process.stdin.\n */\nexport async function runRecordHook(args: {\n hook: string;\n hookInput: Record<string, unknown>;\n dbPath: string;\n mappingConfigPath: string;\n}): Promise<RecordHookResult> {\n const { hook, hookInput, dbPath, mappingConfigPath } = args;\n const sessionId = asString(hookInput.conversation_id) ?? \"\";\n\n // Context-file lifecycle is independent of recording and must not block it.\n await manageContextFile(hook, hookInput, sessionId, dbPath).catch(() => {\n // fail-open\n });\n\n // Load mapping config; absence/parse-error → generic fallback (AC-3).\n let config: EventMappingConfig | undefined;\n try {\n config = await loadEventMappingConfig(mappingConfigPath);\n } catch {\n config = undefined;\n }\n const rule = config?.mappings?.[hook];\n\n let recorded = 0;\n let fallback = false;\n\n // Enable the default enrichment rules (R1–R5) so hook-derived spans/links are\n // enriched on the same SQLite-backed cache the runtime populates, allowing\n // cross-axis (R5) linking across the process boundary (#143 / #140). The\n // Enricher is fail-open, so a rule error never blocks the underlying hook.\n const { collector, sink } = createPipeline({ dbPath });\n try {\n if (rule) {\n recorded += emitMappedSpans(collector, hook, rule, hookInput, sessionId);\n } else {\n recorded += emitGenericFallback(collector, hook, sessionId);\n fallback = true;\n }\n recorded += emitHumanEvents(collector, hook, hookInput, sessionId);\n } finally {\n sink.close();\n }\n\n return { recorded, fallback };\n}\n\n// ── Handler ─────────────────────────────────────────────────────────────────\n\n/**\n * Handle `aaac-observ record-hook <hook-name>`.\n *\n * Reads the hook JSON from stdin, records the resolved events, and prints\n * `{ recorded, fallback }` to stdout. Strictly fail-open: never throws and\n * always returns; the calling shell wrapper additionally guarantees exit 0.\n */\nexport async function handleRecordHook(\n hookName: string | undefined,\n options: RecordHookOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n const hook = hookName ?? \"unknown\";\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const mappingConfigPath = options.mappingConfig ?? defaultMappingConfigPath(dbPath);\n\n let result: RecordHookResult = { recorded: 0, fallback: false };\n try {\n const hookInput = parseHookInput(await readStdin());\n result = await runRecordHook({ hook, hookInput, dbPath, mappingConfigPath });\n } catch (err) {\n // Recorder is fail-open: report to stderr but never block the operation.\n process.stderr.write(\n `record-hook: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n}\n","/**\n * query handler — read path via QueryAdapter.\n *\n * Routes --kind to the appropriate SqliteQueryAdapter method and emits\n * results as JSON to stdout.\n *\n * Supported kinds:\n * trace → QueryAdapter.getTrace(--trace-id)\n * span → QueryAdapter.getSpan(--span-id) [+ QueryAdapter.getSpanEvents]\n * search → QueryAdapter.querySpans({ eventType, taskId, from, to })\n * links → QueryAdapter.getLinks(--span-id, --direction)\n *\n * architecture.md §12 / OBSERVABILITY_TASKS.md Phase 3-2 (record CLI + query)\n */\nimport { SqliteQueryAdapter, DEFAULT_DB_PATH } from \"../index.js\";\nimport { isoToUnixNano } from \"../types/ids.js\";\nimport type { LinkDirection } from \"../query/models.js\";\n\n// ── Handler ───────────────────────────────────────────────────────────────────\n\n/**\n * Options as parsed from the generated CommandHandlers interface.\n */\nexport interface QueryHandlerOptions {\n kind?: string;\n traceId?: string;\n spanId?: string;\n eventType?: string;\n taskId?: string;\n from?: string;\n to?: string;\n direction?: string;\n db?: string;\n}\n\n/** JSON replacer that serialises BigInt as a string. */\nfunction bigIntReplacer(_key: string, value: unknown): unknown {\n return typeof value === \"bigint\" ? value.toString() : value;\n}\n\n/**\n * Handle `aaac-observ query`.\n *\n * Required option: --kind (trace|span|search|links)\n * On success: writes a JSON array/object to stdout.\n * On error: writes to stderr and exits with code 1.\n *\n * DESIGN NOTE: all required-arg validation happens BEFORE the adapter is\n * created, so that when process.exit is mocked to throw in tests there is no\n * risk of a double-close on the database connection.\n */\nexport async function handleQuery(\n options: QueryHandlerOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n const validKinds = [\"trace\", \"span\", \"search\", \"links\"] as const;\n type QueryKind = (typeof validKinds)[number];\n\n // ── Validate options (before opening the adapter) ─────────────────────────\n if (!options.kind) {\n process.stderr.write(\n `Error: --kind (-k) is required (${validKinds.join(\"|\")})\\n`,\n );\n process.exit(1);\n }\n if (!validKinds.includes(options.kind as QueryKind)) {\n process.stderr.write(\n `Error: --kind must be one of: ${validKinds.join(\"|\")}\\n`,\n );\n process.exit(1);\n }\n\n const kind = options.kind as QueryKind;\n\n // Validate sub-command required args (before adapter creation)\n if (kind === \"trace\" && !options.traceId) {\n process.stderr.write(\"Error: --trace-id is required for --kind trace\\n\");\n process.exit(1);\n }\n if (kind === \"span\" && !options.spanId) {\n process.stderr.write(\"Error: --span-id is required for --kind span\\n\");\n process.exit(1);\n }\n if (kind === \"links\" && !options.spanId) {\n process.stderr.write(\"Error: --span-id is required for --kind links\\n\");\n process.exit(1);\n }\n\n // ── Open adapter ──────────────────────────────────────────────────────────\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const adapter = new SqliteQueryAdapter(dbPath);\n\n try {\n let result: unknown;\n\n switch (kind) {\n // ── trace: all spans in a trace ─────────────────────────────────────\n case \"trace\": {\n // options.traceId is guaranteed by pre-validation above\n result = adapter.getTrace(options.traceId!);\n break;\n }\n\n // ── span: single span + its events ──────────────────────────────────\n case \"span\": {\n // options.spanId is guaranteed by pre-validation above\n const span = adapter.getSpan(options.spanId!);\n const events = adapter.getSpanEvents(options.spanId!);\n result = span !== undefined ? { span, events } : null;\n break;\n }\n\n // ── search: spans matching event-type / task-id / time range ─────────\n case \"search\": {\n const filter: Parameters<typeof adapter.querySpans>[0] = {};\n if (options.eventType) filter.eventType = options.eventType;\n if (options.taskId) filter.taskId = options.taskId;\n if (options.from) filter.fromTimeUnixNano = isoToUnixNano(options.from);\n if (options.to) filter.toTimeUnixNano = isoToUnixNano(options.to);\n result = adapter.querySpans(filter);\n break;\n }\n\n // ── links: link traversal ─────────────────────────────────────────────\n case \"links\": {\n const validDirections = [\"forward\", \"reverse\", \"both\"] as const;\n type Dir = (typeof validDirections)[number];\n const dir: Dir =\n options.direction !== undefined &&\n validDirections.includes(options.direction as Dir)\n ? (options.direction as Dir)\n : \"both\";\n result = adapter.getLinks(options.spanId!, dir as LinkDirection);\n break;\n }\n }\n\n process.stdout.write(JSON.stringify(result, bigIntReplacer) + \"\\n\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n\n // Graceful handling: an un-initialised (fresh empty) database has no\n // tables yet. Return an empty / null result rather than an error so that\n // `aaac-observ query` on a machine with no recorded events behaves\n // predictably.\n if (msg.includes(\"no such table\") || msg.includes(\"no such column\")) {\n const emptyResult = kind === \"span\" ? null : [];\n process.stdout.write(JSON.stringify(emptyResult, bigIntReplacer) + \"\\n\");\n adapter.close();\n return;\n }\n\n process.stderr.write(`Error: ${msg}\\n`);\n adapter.close();\n process.exit(1);\n }\n\n adapter.close();\n}\n","/**\n * backfill handler — re-emit historical spans from SQLite to an OTLP backend.\n *\n * Reads closed/instant spans from the local SQLite database and emits them\n * via OtelEmitter to an OTLP-compatible backend (e.g. OTel Collector →\n * ClickHouse).\n *\n * ## Idempotency design (important)\n *\n * The OTel SDK does NOT support specifying a custom spanId when creating spans.\n * Therefore, each backfill invocation will create NEW spans in the OTLP backend\n * with different spanIds than the originals recorded in SQLite. Repeated\n * invocations will produce DUPLICATE data in the backend (e.g. ClickHouse).\n *\n * Recommended idempotency strategies:\n * 1. Run backfill only once per SQLite DB / time range.\n * 2. Use --from / --to to backfill specific time windows; track which windows\n * have already been backfilled externally.\n * 3. Truncate the ClickHouse target table before re-running (destructive; safe\n * for dev environments).\n * 4. Use ClickHouse ReplacingMergeTree / FINAL for approximate deduplication\n * (requires schema changes; not the default otel_traces schema).\n *\n * The --dry-run flag prints span metadata without emitting; use it to verify\n * scope before committing to a real backfill.\n *\n * architecture.md §11 / docs/observability-setup.md / #125 §7\n */\nimport { SqliteQueryAdapter, OtelEmitter, DEFAULT_DB_PATH, isoToUnixNano } from \"../index.js\";\nimport { mapAllEventsToSpans } from \"../otel/span-mapper.js\";\nimport type { MappedSpan, MappedSpanLink } from \"../otel/span-mapper.js\";\nimport type { SpanRecord, LinkRecord } from \"../query/models.js\";\n\n// ── Handler options ───────────────────────────────────────────────────────────\n\nexport interface BackfillHandlerOptions {\n /** SQLite database path. Defaults to DEFAULT_DB_PATH. */\n db?: string;\n /**\n * OTLP HTTP endpoint URL.\n * Fallback: OTEL_EXPORTER_OTLP_ENDPOINT env var.\n * Required unless --dry-run is set.\n */\n endpoint?: string;\n /** OTEL service name reported to the backend. Default: '@aaac/observability'. */\n serviceName?: string;\n /** Filter: only backfill spans starting at or after this ISO 8601 time. */\n from?: string;\n /** Filter: only backfill spans starting at or before this ISO 8601 time. */\n to?: string;\n /** Filter: only backfill spans of this event type (e.g. 'agent.session'). */\n eventType?: string;\n /**\n * Print span metadata to stdout without actually emitting to the OTLP backend.\n * Useful for previewing scope before committing to a real backfill.\n */\n dryRun?: boolean;\n /**\n * Maximum milliseconds to wait for the OTLP flush before the CLI exits.\n * Default: 2000 ms (preserves existing vitest compatibility — unreachable\n * endpoints resolve immediately via connection-refused, so tests are unaffected\n * by the default value).\n *\n * For large backfills (> 5 000 spans) the BatchSpanProcessor needs significantly\n * more time. Recommended production value: 30 000 ms.\n *\n * Rule of thumb: allow ≥ 400 ms per 512-span batch\n * (i.e. ceil(spansFound / 512) * 400 ms, rounded up generously).\n */\n flushTimeoutMs?: number;\n}\n\n// ── MappedSpan reconstruction ─────────────────────────────────────────────────\n\n/**\n * Reconstruct a MappedSpan from a stored SpanRecord + its forward links.\n *\n * Backfill works at the \"span\" level (not the raw event level) because\n * SqliteSink materialises open+close into the `spans` table at write time.\n * Only closed or instant spans carry meaningful duration information.\n */\nfunction spanRecordToMappedSpan(\n span: SpanRecord,\n links: LinkRecord[],\n): MappedSpan {\n const start = span.startTime ?? 0n;\n const end = span.endTime ?? start;\n\n // Reconstruct MappedSpanLinks from the stored canonical_links rows.\n const mappedLinks: MappedSpanLink[] = links.map((l) => ({\n targetSpanId: l.targetSpanId,\n targetTraceId: l.targetTraceId ?? undefined,\n attributes: {\n link_type: l.linkType,\n ...(l.attributes ?? {}),\n },\n }));\n\n return {\n spanId: span.spanId,\n traceId: span.traceId ?? \"\",\n parentSpanId: span.parentSpanId ?? undefined,\n name: span.eventType,\n startTimeUnixNano: start,\n endTimeUnixNano: end,\n attributes: span.attributes,\n spanEvents: [], // span events are not stored in the spans table\n links: mappedLinks,\n };\n}\n\n// ── Handler ───────────────────────────────────────────────────────────────────\n\n/**\n * Handle `aaac-observ backfill`.\n *\n * Emits historical spans from the SQLite store to an OTLP backend.\n * Prints a JSON summary to stdout:\n * { spansFound: number, spansEmitted: number, dryRun: boolean }\n *\n * On error: writes to stderr and exits with code 1.\n *\n * IMPORTANT — idempotency: Re-running backfill without --from/--to restriction\n * will re-emit all matching spans, creating DUPLICATES in the OTLP backend.\n * See module-level comment for mitigation strategies.\n */\nexport async function handleBackfill(\n options: BackfillHandlerOptions,\n _parentOpts: Record<string, unknown>,\n): Promise<void> {\n const dbPath = options.db ?? DEFAULT_DB_PATH;\n const dryRun = options.dryRun ?? false;\n\n // ── Validate endpoint (not needed for dry-run) ────────────────────────────\n const endpoint = options.endpoint ?? process.env[\"OTEL_EXPORTER_OTLP_ENDPOINT\"];\n if (!dryRun && !endpoint) {\n process.stderr.write(\n \"Error: --endpoint is required (or set OTEL_EXPORTER_OTLP_ENDPOINT) unless --dry-run\\n\",\n );\n process.exit(1);\n }\n\n // ── Validate and parse time filters ───────────────────────────────────────\n // isoToUnixNano() silently falls back to currentTimeUnixNano() for invalid\n // ISO strings (shared utility — behaviour unchanged for other callers).\n // Backfill must validate explicitly so a typo in --from/--to causes exit 1\n // rather than a silent wrong-boundary backfill (F1 / issue #125).\n let fromNano: bigint | undefined;\n let toNano: bigint | undefined;\n if (options.from) {\n if (Number.isNaN(Date.parse(options.from))) {\n process.stderr.write(\n `Error: invalid --from value \"${options.from}\" — expected ISO 8601\\n`,\n );\n process.exit(1);\n }\n fromNano = isoToUnixNano(options.from);\n }\n if (options.to) {\n if (Number.isNaN(Date.parse(options.to))) {\n process.stderr.write(\n `Error: invalid --to value \"${options.to}\" — expected ISO 8601\\n`,\n );\n process.exit(1);\n }\n toNano = isoToUnixNano(options.to);\n }\n\n // ── Query spans from SQLite ────────────────────────────────────────────────\n const adapter = new SqliteQueryAdapter(dbPath);\n let spans: SpanRecord[];\n try {\n spans = adapter.querySpans({\n ...(options.eventType ? { eventType: options.eventType } : {}),\n ...(fromNano !== undefined ? { fromTimeUnixNano: fromNano } : {}),\n ...(toNano !== undefined ? { toTimeUnixNano: toNano } : {}),\n });\n // Only backfill spans that have completed (closed or instant).\n // Open spans are missing their end_time and would emit with zero duration.\n spans = spans.filter((s) => s.status === \"closed\" || s.status === \"instant\");\n } catch (err) {\n process.stderr.write(\n `Error: failed to query SQLite — ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n adapter.close();\n process.exit(1);\n return; // unreachable, but satisfies TS control-flow\n }\n\n const spansFound = spans.length;\n\n if (dryRun) {\n adapter.close();\n const result = { spansFound, spansEmitted: 0, dryRun: true };\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n return;\n }\n\n // ── Reconstruct MappedSpans with their links ──────────────────────────────\n const mappedSpans: MappedSpan[] = [];\n for (const span of spans) {\n let links: LinkRecord[] = [];\n try {\n links = adapter.getLinks(span.spanId, \"forward\");\n } catch {\n // fail-open: missing links are non-fatal for backfill\n }\n mappedSpans.push(spanRecordToMappedSpan(span, links));\n }\n\n adapter.close();\n\n // ── Large-backfill warning ────────────────────────────────────────────────\n // Warn before emitting when the operator-supplied (or default) flush timeout\n // is likely too short for the span count. Rule of thumb: each 512-span batch\n // takes ~400 ms → 1 000 spans ≈ 2 batches ≈ 800 ms, well under 2 s, but\n // 13 000 spans ≈ 26 batches ≈ 10 400 ms, which exceeds the 2 s default.\n // Emitting the warning here (before the emit loop) lets the operator ^C and\n // re-run with --flush-timeout-ms 30000 before any data is sent.\n const effectiveFlushMs = options.flushTimeoutMs ?? 2000;\n if (spansFound > 1000 && effectiveFlushMs < 10000) {\n process.stderr.write(\n `Warning: ${spansFound} spans queued but --flush-timeout-ms is ` +\n `${effectiveFlushMs} ms (< 10 000 ms). Large batches may not fully ` +\n `flush before the deadline. Recommended: --flush-timeout-ms 30000\\n`,\n );\n }\n\n // ── Emit via OtelEmitter ──────────────────────────────────────────────────\n const emitter = new OtelEmitter({\n endpoint,\n serviceName: options.serviceName,\n });\n\n let spansEmitted = 0;\n for (const mapped of mappedSpans) {\n try {\n emitter.emit(mapped);\n spansEmitted++;\n } catch {\n // fail-open: individual span failures are non-fatal\n }\n }\n\n // Flush pending batch before reporting success.\n // Race against effectiveFlushMs so that an unreachable OTLP endpoint\n // never causes the CLI to hang indefinitely. OtelEmitter.shutdown() already\n // swallows its own errors, so the race is purely a time-bound escape hatch.\n // Default 2 000 ms preserves vitest idempotency-test compatibility (unreachable\n // endpoints resolve immediately via connection-refused; the timeout is never hit\n // in tests). For production use with > 5 000 spans pass --flush-timeout-ms 30000.\n await Promise.race([\n emitter.shutdown(),\n new Promise<void>((resolve) => setTimeout(resolve, effectiveFlushMs)),\n ]);\n\n const result = { spansFound, spansEmitted, dryRun: false };\n process.stdout.write(JSON.stringify(result) + \"\\n\");\n}\n","/**\n * CLI command handlers for aaac-observ.\n *\n * Implements the CommandHandlers interface generated by cli-contracts and\n * delegates to the domain-specific handler modules.\n *\n * Usage (in index.ts):\n * import { handlers } from './handlers.js';\n * import { createProgram } from '../generated/program.js';\n * const program = createProgram(handlers, version);\n * await program.parseAsync();\n */\nimport type { CommandHandlers } from \"../generated/program.js\";\nimport { handleRecord } from \"./record.js\";\nimport { handleRecordHook } from \"./record-hook.js\";\nimport { handleQuery } from \"./query.js\";\nimport { handleBackfill } from \"./backfill.js\";\n\nexport const handlers: CommandHandlers = {\n record: handleRecord,\n recordHook: handleRecordHook,\n query: handleQuery,\n backfill: handleBackfill,\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAOA,SAAS,oBAAoB;AAC7B,SAAS,WAAAA,UAAS,eAAe;AACjC,SAAS,qBAAqB;;;ACR9B,SAAS,eAAe;;;ACEjB,IAAM,gBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAE9B,IAAM,oBAA4B;;;ADMlC,SAAS,cACdC,WACA,SACS;AACT,QAAMC,WAAU,IAAI,QAAQ;AAC5B,EAAAA,SACG,KAAK,aAAa,EAClB,QAAQ,SAAS,eAAe,EAChC,YAAY,+EAA0E;AAGzF,EAAAA,SACG,QAAQ,QAAQ,EAChB,YAAY,uHAAuH,EACnI,OAAO,4BAA4B,iEAAiE,EACpG,OAAO,2BAA2B,uDAAuD,EACzF,OAAO,yBAAyB,qCAAqC,EACrE,OAAO,4BAA4B,8BAA8B,EACjE,OAAO,wBAAwB,wCAAwC,EACvE,OAAO,sBAAsB,kCAAkC,EAC/D,OAAO,oBAAoB,6CAA6C,EACxE,OAAO,kBAAkB,oEAAoE,EAC7F,OAAO,kBAAkB,uEAAuE,EAChG,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,OAAO,MAAM,QAAQ;AAC3B,UAAMD,UAAS,OAAO,MAAM,IAAI,gBAAgB,CAAC;AAAA,EACnD,CAAC;AAEH,EAAAC,SACG,QAAQ,aAAa,EACrB,YAAY,iKAA4J,EACxK,SAAS,eAAe,gFAAgF,EACxG,OAAO,4BAA4B,6EAA6E,EAChH,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,OAAO,UAAU,MAAM,QAAQ;AACrC,UAAMD,UAAS,WAAW,UAAU,MAAM,IAAI,gBAAgB,CAAC;AAAA,EACjE,CAAC;AAEH,EAAAC,SACG,QAAQ,UAAU,EAClB,YAAY,yDAAyD,EACrE,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,sBAAsB,gEAAgE,EAC7F,OAAO,0BAA0B,sEAAsE,EACvG,OAAO,kBAAkB,wDAAwD,EACjF,OAAO,gBAAgB,yDAAyD,EAChF,OAAO,wBAAwB,2CAA2C,EAC1E,OAAO,aAAa,mDAAmD,EACvE,OAAO,2BAA2B,gGAA2F,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,EACnJ,OAAO,OAAO,MAAM,QAAQ;AAC3B,UAAMD,UAAS,SAAS,MAAM,IAAI,gBAAgB,CAAC;AAAA,EACrD,CAAC;AAEH,EAAAC,SACG,QAAQ,OAAO,EACf,YAAY,gDAAgD,EAC5D,OAAO,sBAAsB,2CAA2C,EACxE,OAAO,sBAAsB,2CAA2C,EACxE,OAAO,yBAAyB,8DAA8D,EAC9F,OAAO,wBAAwB,sDAAsD,EACrF,OAAO,qBAAqB,mDAAmD,EAC/E,OAAO,kBAAkB,kEAAkE,EAC3F,OAAO,gBAAgB,gEAAgE,EACvF,OAAO,2BAA2B,4DAA4D,EAC9F,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,OAAO,MAAM,QAAQ;AAC3B,UAAMD,UAAS,MAAM,MAAM,IAAI,gBAAgB,CAAC;AAAA,EAClD,CAAC;AAIH,EAAAC,SACG,QAAQ,SAAS,EACjB,YAAY,mDAAmD,EAC/D,SAAS,iBAAiB,2CAA2C,EACrE,OAAO,aAAa,yBAAyB,KAAK,EAClD,OAAO,kBAAkB,gCAAgC,IAAI,EAC7D,OAAO,yBAAyB,iCAAiC,MAAM,EACvE,OAAO,OAAO,UAAoB,MAAiE,QAAiB;AACnH,QAAI,SAAS,WAAW,KAAK,CAAC,KAAK,KAAK;AACtC,cAAQ,OAAO,MAAM,KAAK,UAAU,EAAE,MAAM,gBAAgB,SAAS,mCAAmC,CAAC,IAAI,IAAI;AACjH,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,MAAM,KAAK,MAAM,iBAAiB;AACxC,UAAM,SAAS,KAAK,MAAM,CAAC,IAAI;AAE/B,QAAI,OAAO,WAAW,GAAG;AAEvB,UAAI,WAAW,QAAQ;AACrB,cAAM,MAA+B,CAAC;AACtC,YAAI,KAAK,aAAa;AACpB,cAAI,QAAQ;AAAA,YACV,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,YACpC,aAAa,IAAI,iBAAiB;AAAA,YAClC,UAAU,CAAC,sBAAqB,2BAA0B,wBAAuB,mBAAmB;AAAA,UACtG;AAAA,QACF;AACA,eAAO,OAAO,KAAK,GAAG;AACtB,gBAAQ,OAAO,MAAM,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAAA,MAC1D,OAAO;AAEL,cAAM,YAAsB,CAAC;AAC7B,kBAAU,KAAK,uBAAuB;AACtC,kBAAU,KAAK,oBAAoB;AACnC,kBAAU,KAAK,uCAAuC;AACtD,YAAI,KAAK,aAAa;AACpB,oBAAU,KAAK,KAAK;AACpB,oBAAU,KAAK,kBAAkB;AACjC,oBAAU,KAAK,qCAAqC;AACpD,oBAAU,KAAK,mBAAkB,oBAAI,KAAK,GAAE,YAAY,CAAC;AACzD,oBAAU,KAAK,oBAAoB,IAAI,iBAAiB,QAAQ;AAChE,oBAAU,KAAK,WAAW;AAC1B,qBAAW,MAAM,CAAC,sBAAqB,2BAA0B,wBAAuB,mBAAmB,GAAG;AAC5G,sBAAU,KAAK,SAAS,EAAE;AAAA,UAC5B;AAAA,QACF;AACA,kBAAU,KAAK,KAAK;AACpB,kBAAU,KAAK,aAAa;AAC5B,gBAAQ,OAAO,MAAM,UAAU,KAAK,IAAI,IAAI,IAAI;AAAA,MAClD;AAAA,IACF,OAAO;AAEL,YAAM,WAAoC;AAAA,QACxC,eAAe,IAAI;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,cAAc,CAAC;AAAA,MACjB;AACA,YAAM,MAAM,SAAS;AACrB,iBAAW,CAAC,OAAO,EAAE,KAAK,OAAO,QAAQ,IAAI,gBAAgB,CAAC,CAAC,GAAG;AAChE,cAAM,OAAQ,GAA+B;AAC7C,YAAI,CAAC,KAAM;AACX,cAAM,UAAmC,CAAC;AAC1C,mBAAW,CAAC,OAAO,MAAM,KAAK,OAAO,QAAQ,IAAI,GAAG;AAClD,gBAAM,SAAS,QAAQ,MAAM;AAC7B,cAAI,OAAO,KAAK,CAAC,OAAO,OAAO,SAAS,OAAO,UAAU,MAAM,WAAW,KAAK,GAAG,CAAC,GAAG;AACpF,oBAAQ,KAAK,IAAI;AAAA,UACnB;AAAA,QACF;AACA,YAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACnC,gBAAM,UAAU,EAAE,GAAI,GAA+B;AACrD,kBAAQ,WAAW;AACnB,cAAI,KAAK,IAAI;AAAA,QACf;AAAA,MACF;AACA,UAAI,IAAI,WAAY,UAAS,aAAa,IAAI;AAC9C,cAAQ,OAAO,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,IAC/D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH,SAAOA;AACT;;;AE9IO,SAAS,UAAU,SAAwD;AAChF,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,QAAQ;AAAA,IAER;AAAA,EACF;AACA,QAAM,SAAoC,CAAC;AAC3C,aAAW,QAAQ,QAAQ,MAAM,GAAG,GAAG;AACrC,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,QAAI,QAAQ,GAAG;AACb,YAAM,MAAM,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK;AACtC,YAAM,MAAM,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK;AACvC,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,WAAW,SAA8C;AACvE,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,QAAM,QAAyB,CAAC;AAChC,aAAW,QAAQ,QAAQ,MAAM,GAAG,GAAG;AACrC,UAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,GAAG;AACnC,QAAI,MAAM,UAAU,GAAG;AACrB,YAAM,eAAe,MAAM,CAAC,EAAE,KAAK;AACnC,YAAM,WAAW,MAAM,CAAC,EAAE,KAAK;AAC/B,YAAM,gBAAgB,MAAM,CAAC,GAAG,KAAK,KAAK;AAC1C,UAAI,gBAAgB,UAAU;AAC5B,cAAM,KAAK,EAAE,cAAc,UAAU,cAAc,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AA+BA,eAAsB,aACpB,SACA,aACe;AAEf,MAAI,CAAC,QAAQ,WAAW;AACtB,YAAQ,OAAO,MAAM,wCAAwC;AAC7D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,kBAAqC,CAAC,QAAQ,SAAS,SAAS,SAAS;AAC/E,MAAI,CAAC,QAAQ,WAAW;AACtB,YAAQ,OAAO;AAAA,MACb,wCAAwC,gBAAgB,KAAK,GAAG,CAAC;AAAA;AAAA,IACnE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,gBAAgB,SAAS,QAAQ,SAAS,GAAG;AAChD,YAAQ,OAAO;AAAA,MACb,sCAAsC,gBAAgB,KAAK,GAAG,CAAC;AAAA;AAAA,IACjE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,SAAS,QAAQ,UAAU,WAAW;AAC5C,QAAM,aAAa,UAAU,QAAQ,IAAI;AACzC,QAAM,QAAQ,WAAW,QAAQ,IAAI;AAGrC,MAAI,QAAQ,WAAW;AACrB,eAAW,YAAY,IAAI,QAAQ;AAAA,EACrC;AAGA,MAAI,QAAQ,SAAS;AACnB,eAAW,UAAU,IAAI,QAAQ;AAAA,EACnC;AAGA,MAAI;AAEJ,QAAM,EAAE,WAAW,KAAK,IAAI,eAAe;AAAA,IACzC;AAAA;AAAA,IAEA,gBAAgB,CAAC,UAAU;AACzB,wBAAkB,MAAM;AACxB,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,CAAC;AAED,MAAI;AACF,cAAU,sBAAsB;AAAA,MAC9B,QAAQ,QAAQ,UAAU;AAAA,MAC1B,WAAW,QAAQ;AAAA,MACnB,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA,cAAc,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,OAAO;AAAA,MACb,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA;AAAA,IAC5D;AACA,SAAK,MAAM;AACX,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,OAAK,MAAM;AAEX,QAAM,SAAS,EAAE,SAAS,iBAAiB,OAAO;AAClD,UAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,IAAI,IAAI;AACpD;;;AC1JA,SAAS,OAAO,QAAQ,QAAQ,iBAAiB;AACjD,SAAS,SAAS,YAAY;AAkB9B,IAAM,yBAAyB;AAG/B,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAoBM,SAAS,yBAAyB,QAAwB;AAC/D,SAAO,KAAK,QAAQ,MAAM,GAAG,UAAU,oBAAoB;AAC7D;AAGO,SAAS,gBAAgB,QAAwB;AACtD,SAAO,KAAK,QAAQ,MAAM,GAAG,sBAAsB;AACrD;AASA,eAAsB,YAA6B;AACjD,MAAI,QAAQ,MAAM,MAAO,QAAO;AAChC,SAAO,IAAI,QAAgB,CAACC,aAAY;AACtC,QAAI,OAAO;AACX,QAAI,UAAU;AACd,UAAM,SAAS,MAAY;AACzB,UAAI,QAAS;AACb,gBAAU;AACV,MAAAA,SAAQ,IAAI;AAAA,IACd;AACA,QAAI;AACF,cAAQ,MAAM,YAAY,MAAM;AAChC,cAAQ,MAAM,GAAG,QAAQ,CAAC,UAAU;AAClC,gBAAQ;AAAA,MACV,CAAC;AACD,cAAQ,MAAM,GAAG,OAAO,MAAM;AAC9B,cAAQ,MAAM,GAAG,SAAS,MAAM;AAChC,cAAQ,MAAM,GAAG,SAAS,MAAM;AAEhC,YAAM,IAAI,WAAW,QAAQ,GAAI;AACjC,UAAI,OAAO,EAAE,UAAU,WAAY,GAAE,MAAM;AAAA,IAC7C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAGO,SAAS,eAAe,KAAsC;AACnE,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,QAAS,QAAO,CAAC;AACtB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,WAAO,WAAW,QAAQ,OAAO,WAAW,WACvC,SACD,CAAC;AAAA,EACP,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAIA,SAAS,SAAS,OAAoC;AACpD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,SAAS,OAAoC;AACpD,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,EAAG,QAAO;AAChE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAI;AACpD,UAAM,IAAI,OAAO,KAAK;AACtB,QAAI,OAAO,SAAS,CAAC,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AASA,SAAS,gBACP,WACA,MACA,MACA,WACA,WACQ;AACR,QAAM,EAAE,OAAO,MAAM,IAAI,gBAAgB,MAAM,SAAS;AAIxD,QAAM,cAAc,oBAAI,IAA6B;AACrD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,YAAY,IAAI,KAAK,UAAU,KAAK,CAAC;AACjD,QAAI,KAAK,EAAE,cAAc,KAAK,UAAU,UAAU,KAAK,SAAS,CAAC;AACjE,gBAAY,IAAI,KAAK,YAAY,GAAG;AAAA,EACtC;AAEA,QAAM,uBACJ,SAAS,kBAAkB,SAAS,UAAU,sBAAsB,IAAI;AAE1E,aAAW,QAAQ,OAAO;AACxB,UAAM,aAAwC,EAAE,GAAG,KAAK,WAAW;AACnE,QAAI,UAAW,YAAW,YAAY,IAAI;AAC1C,QAAI,sBAAsB;AACxB,iBAAW,wBAAwB,IAAI;AAAA,IACzC;AACA,cAAU,KAAK;AAAA,MACb,QAAQ;AAAA,MACR,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK;AAAA,MACnB;AAAA,MACA,OAAO,YAAY,IAAI,KAAK,MAAM,KAAK,CAAC;AAAA,IAC1C,CAAC;AAAA,EACH;AAEA,SAAO,MAAM;AACf;AAMA,SAAS,oBACP,WACA,MACA,WACQ;AACR,QAAM,aAAa,eAAe,IAAI,IAAI,IAAI,SAAS,aAAa;AACpE,QAAM,aAAwC,EAAE,aAAa,KAAK;AAClE,MAAI,UAAW,YAAW,YAAY,IAAI;AAC1C,YAAU,KAAK;AAAA,IACb,QAAQ;AAAA,IACR;AAAA,IACA,WAAW;AAAA,IACX;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGA,SAAS,gBACP,WACA,MACA,WACA,WACQ;AACR,MAAI,QAAQ;AAEZ,MAAI,SAAS,sBAAsB;AACjC,UAAM,SAAS,SAAS,UAAU,MAAM;AACxC,QAAI,WAAW,QAAW;AACxB,YAAM,cAAc,MAAM,QAAQ,UAAU,WAAW,IAClD,UAAU,cACX,CAAC;AACL,2BAAqB,WAAW,EAAE,WAAW,QAAQ,YAAY,CAAC;AAClE,eAAS;AAAA,IACX;AAAA,EACF,WAAW,SAAS,uBAAuB;AACzC,UAAM,UAAU,SAAS,UAAU,OAAO;AAC1C,QAAI,YAAY,QAAW;AACzB,YAAM,WAAW,SAAS,UAAU,SAAS,KAAK,SAAS,UAAU,QAAQ,KAAK;AAClF,YAAM,aAAa,SAAS,UAAU,QAAQ;AAC9C,UAAI,sBAAsB,WAAW,EAAE,WAAW,SAAS,UAAU,WAAW,CAAC,GAAG;AAClF,iBAAS;AAAA,MACX;AACA,YAAM,SAAS,SAAS,UAAU,MAAM,KAAK;AAC7C,UAAI,gBAAgB,WAAW,EAAE,WAAW,SAAS,OAAO,CAAC,GAAG;AAC9D,iBAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAaA,eAAe,kBACb,MACA,WACA,WACA,QACe;AACf,QAAM,UAAU,SAAS,UAAU,OAAO,KAAK;AAC/C,QAAM,sBAAsB,uBAAuB,KAAK,OAAO;AAC/D,QAAM,OAAO,gBAAgB,MAAM;AAEnC,MAAI,SAAS,0BAA0B,qBAAqB;AAC1D,UAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,UAAM,UACJ,KAAK,UAAU;AAAA,MACb,YAAY,aAAa;AAAA,MACzB,OAAO,WAAW;AAAA,MAClB,eAAe,KAAK,IAAI;AAAA,IAC1B,CAAC,IAAI;AACP,UAAM,MAAM,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,WAAW,CAAC;AAClD,UAAM,UAAU,KAAK,SAAS,MAAM;AACpC,UAAM,OAAO,KAAK,IAAI;AAAA,EACxB,WAAW,SAAS,yBAAyB,qBAAqB;AAChE,UAAM,OAAO,IAAI,EAAE,MAAM,MAAM;AAAA,IAE/B,CAAC;AAAA,EACH;AACF;AAUA,eAAsB,cAAc,MAKN;AAC5B,QAAM,EAAE,MAAM,WAAW,QAAQ,kBAAkB,IAAI;AACvD,QAAM,YAAY,SAAS,UAAU,eAAe,KAAK;AAGzD,QAAM,kBAAkB,MAAM,WAAW,WAAW,MAAM,EAAE,MAAM,MAAM;AAAA,EAExE,CAAC;AAGD,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,uBAAuB,iBAAiB;AAAA,EACzD,QAAQ;AACN,aAAS;AAAA,EACX;AACA,QAAM,OAAO,QAAQ,WAAW,IAAI;AAEpC,MAAI,WAAW;AACf,MAAI,WAAW;AAMf,QAAM,EAAE,WAAW,KAAK,IAAI,eAAe,EAAE,OAAO,CAAC;AACrD,MAAI;AACF,QAAI,MAAM;AACR,kBAAY,gBAAgB,WAAW,MAAM,MAAM,WAAW,SAAS;AAAA,IACzE,OAAO;AACL,kBAAY,oBAAoB,WAAW,MAAM,SAAS;AAC1D,iBAAW;AAAA,IACb;AACA,gBAAY,gBAAgB,WAAW,MAAM,WAAW,SAAS;AAAA,EACnE,UAAE;AACA,SAAK,MAAM;AAAA,EACb;AAEA,SAAO,EAAE,UAAU,SAAS;AAC9B;AAWA,eAAsB,iBACpB,UACA,SACA,aACe;AACf,QAAM,OAAO,YAAY;AACzB,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,oBAAoB,QAAQ,iBAAiB,yBAAyB,MAAM;AAElF,MAAI,SAA2B,EAAE,UAAU,GAAG,UAAU,MAAM;AAC9D,MAAI;AACF,UAAM,YAAY,eAAe,MAAM,UAAU,CAAC;AAClD,aAAS,MAAM,cAAc,EAAE,MAAM,WAAW,QAAQ,kBAAkB,CAAC;AAAA,EAC7E,SAAS,KAAK;AAEZ,YAAQ,OAAO;AAAA,MACb,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA;AAAA,IAClE;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,IAAI,IAAI;AACpD;;;AC/UA,SAAS,eAAe,MAAc,OAAyB;AAC7D,SAAO,OAAO,UAAU,WAAW,MAAM,SAAS,IAAI;AACxD;AAaA,eAAsB,YACpB,SACA,aACe;AACf,QAAM,aAAa,CAAC,SAAS,QAAQ,UAAU,OAAO;AAItD,MAAI,CAAC,QAAQ,MAAM;AACjB,YAAQ,OAAO;AAAA,MACb,mCAAmC,WAAW,KAAK,GAAG,CAAC;AAAA;AAAA,IACzD;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,CAAC,WAAW,SAAS,QAAQ,IAAiB,GAAG;AACnD,YAAQ,OAAO;AAAA,MACb,iCAAiC,WAAW,KAAK,GAAG,CAAC;AAAA;AAAA,IACvD;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,QAAQ;AAGrB,MAAI,SAAS,WAAW,CAAC,QAAQ,SAAS;AACxC,YAAQ,OAAO,MAAM,kDAAkD;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,SAAS,UAAU,CAAC,QAAQ,QAAQ;AACtC,YAAQ,OAAO,MAAM,gDAAgD;AACrE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,MAAI,SAAS,WAAW,CAAC,QAAQ,QAAQ;AACvC,YAAQ,OAAO,MAAM,iDAAiD;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,UAAU,IAAI,mBAAmB,MAAM;AAE7C,MAAI;AACF,QAAI;AAEJ,YAAQ,MAAM;AAAA;AAAA,MAEZ,KAAK,SAAS;AAEZ,iBAAS,QAAQ,SAAS,QAAQ,OAAQ;AAC1C;AAAA,MACF;AAAA;AAAA,MAGA,KAAK,QAAQ;AAEX,cAAM,OAAO,QAAQ,QAAQ,QAAQ,MAAO;AAC5C,cAAM,SAAS,QAAQ,cAAc,QAAQ,MAAO;AACpD,iBAAS,SAAS,SAAY,EAAE,MAAM,OAAO,IAAI;AACjD;AAAA,MACF;AAAA;AAAA,MAGA,KAAK,UAAU;AACb,cAAM,SAAmD,CAAC;AAC1D,YAAI,QAAQ,UAAW,QAAO,YAAY,QAAQ;AAClD,YAAI,QAAQ,OAAQ,QAAO,SAAS,QAAQ;AAC5C,YAAI,QAAQ,KAAM,QAAO,mBAAmB,cAAc,QAAQ,IAAI;AACtE,YAAI,QAAQ,GAAI,QAAO,iBAAiB,cAAc,QAAQ,EAAE;AAChE,iBAAS,QAAQ,WAAW,MAAM;AAClC;AAAA,MACF;AAAA;AAAA,MAGA,KAAK,SAAS;AACZ,cAAM,kBAAkB,CAAC,WAAW,WAAW,MAAM;AAErD,cAAM,MACJ,QAAQ,cAAc,UACtB,gBAAgB,SAAS,QAAQ,SAAgB,IAC5C,QAAQ,YACT;AACN,iBAAS,QAAQ,SAAS,QAAQ,QAAS,GAAoB;AAC/D;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM,KAAK,UAAU,QAAQ,cAAc,IAAI,IAAI;AAAA,EACpE,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAM3D,QAAI,IAAI,SAAS,eAAe,KAAK,IAAI,SAAS,gBAAgB,GAAG;AACnE,YAAM,cAAc,SAAS,SAAS,OAAO,CAAC;AAC9C,cAAQ,OAAO,MAAM,KAAK,UAAU,aAAa,cAAc,IAAI,IAAI;AACvE,cAAQ,MAAM;AACd;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM,UAAU,GAAG;AAAA,CAAI;AACtC,YAAQ,MAAM;AACd,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,MAAM;AAChB;;;AC7EA,SAAS,uBACP,MACA,OACY;AACZ,QAAM,QAAQ,KAAK,aAAa;AAChC,QAAM,MAAM,KAAK,WAAW;AAG5B,QAAM,cAAgC,MAAM,IAAI,CAAC,OAAO;AAAA,IACtD,cAAc,EAAE;AAAA,IAChB,eAAe,EAAE,iBAAiB;AAAA,IAClC,YAAY;AAAA,MACV,WAAW,EAAE;AAAA,MACb,GAAI,EAAE,cAAc,CAAC;AAAA,IACvB;AAAA,EACF,EAAE;AAEF,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,WAAW;AAAA,IACzB,cAAc,KAAK,gBAAgB;AAAA,IACnC,MAAM,KAAK;AAAA,IACX,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,YAAY,KAAK;AAAA,IACjB,YAAY,CAAC;AAAA;AAAA,IACb,OAAO;AAAA,EACT;AACF;AAiBA,eAAsB,eACpB,SACA,aACe;AACf,QAAM,SAAS,QAAQ,MAAM;AAC7B,QAAM,SAAS,QAAQ,UAAU;AAGjC,QAAM,WAAW,QAAQ,YAAY,QAAQ,IAAI,6BAA6B;AAC9E,MAAI,CAAC,UAAU,CAAC,UAAU;AACxB,YAAQ,OAAO;AAAA,MACb;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAOA,MAAI;AACJ,MAAI;AACJ,MAAI,QAAQ,MAAM;AAChB,QAAI,OAAO,MAAM,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG;AAC1C,cAAQ,OAAO;AAAA,QACb,gCAAgC,QAAQ,IAAI;AAAA;AAAA,MAC9C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,eAAW,cAAc,QAAQ,IAAI;AAAA,EACvC;AACA,MAAI,QAAQ,IAAI;AACd,QAAI,OAAO,MAAM,KAAK,MAAM,QAAQ,EAAE,CAAC,GAAG;AACxC,cAAQ,OAAO;AAAA,QACb,8BAA8B,QAAQ,EAAE;AAAA;AAAA,MAC1C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,aAAS,cAAc,QAAQ,EAAE;AAAA,EACnC;AAGA,QAAM,UAAU,IAAI,mBAAmB,MAAM;AAC7C,MAAI;AACJ,MAAI;AACF,YAAQ,QAAQ,WAAW;AAAA,MACzB,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,MAC5D,GAAI,aAAa,SAAY,EAAE,kBAAkB,SAAS,IAAI,CAAC;AAAA,MAC/D,GAAI,WAAW,SAAY,EAAE,gBAAgB,OAAO,IAAI,CAAC;AAAA,IAC3D,CAAC;AAGD,YAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY,EAAE,WAAW,SAAS;AAAA,EAC7E,SAAS,KAAK;AACZ,YAAQ,OAAO;AAAA,MACb,wCAAmC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA;AAAA,IACrF;AACA,YAAQ,MAAM;AACd,YAAQ,KAAK,CAAC;AACd;AAAA,EACF;AAEA,QAAM,aAAa,MAAM;AAEzB,MAAI,QAAQ;AACV,YAAQ,MAAM;AACd,UAAMC,UAAS,EAAE,YAAY,cAAc,GAAG,QAAQ,KAAK;AAC3D,YAAQ,OAAO,MAAM,KAAK,UAAUA,OAAM,IAAI,IAAI;AAClD;AAAA,EACF;AAGA,QAAM,cAA4B,CAAC;AACnC,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAsB,CAAC;AAC3B,QAAI;AACF,cAAQ,QAAQ,SAAS,KAAK,QAAQ,SAAS;AAAA,IACjD,QAAQ;AAAA,IAER;AACA,gBAAY,KAAK,uBAAuB,MAAM,KAAK,CAAC;AAAA,EACtD;AAEA,UAAQ,MAAM;AASd,QAAM,mBAAmB,QAAQ,kBAAkB;AACnD,MAAI,aAAa,OAAQ,mBAAmB,KAAO;AACjD,YAAQ,OAAO;AAAA,MACb,YAAY,UAAU,2CACnB,gBAAgB;AAAA;AAAA,IAErB;AAAA,EACF;AAGA,QAAM,UAAU,IAAI,YAAY;AAAA,IAC9B;AAAA,IACA,aAAa,QAAQ;AAAA,EACvB,CAAC;AAED,MAAI,eAAe;AACnB,aAAW,UAAU,aAAa;AAChC,QAAI;AACF,cAAQ,KAAK,MAAM;AACnB;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AASA,QAAM,QAAQ,KAAK;AAAA,IACjB,QAAQ,SAAS;AAAA,IACjB,IAAI,QAAc,CAACC,aAAY,WAAWA,UAAS,gBAAgB,CAAC;AAAA,EACtE,CAAC;AAED,QAAM,SAAS,EAAE,YAAY,cAAc,QAAQ,MAAM;AACzD,UAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,IAAI,IAAI;AACpD;;;AChPO,IAAM,WAA4B;AAAA,EACvC,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AACZ;;;APVA,IAAM,YAAYC,SAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,IAAM,MAAM,KAAK;AAAA,EACf,aAAa,QAAQ,WAAW,oBAAoB,GAAG,MAAM;AAC/D;AAEA,IAAM,UAAU,cAAc,UAAU,IAAI,OAAO;AACnD,MAAM,QAAQ,WAAW;","names":["dirname","handlers","program","resolve","result","resolve","dirname"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -781,6 +781,17 @@ declare class OtelEmitter {
|
|
|
781
781
|
private readonly tracer;
|
|
782
782
|
private readonly enabled;
|
|
783
783
|
constructor(options?: OtelEmitterOptions);
|
|
784
|
+
/**
|
|
785
|
+
* Returns true when a valid OTLP endpoint is configured and the emitter
|
|
786
|
+
* is active. Used in tests to verify that createPipeline received the otel
|
|
787
|
+
* config (F-002 / issue #125).
|
|
788
|
+
*
|
|
789
|
+
* @internal
|
|
790
|
+
* @remarks Only for test/diagnostic use to verify pipeline wiring.
|
|
791
|
+
* Not part of the stable public API contract — callers outside
|
|
792
|
+
* the test suite should not depend on this method.
|
|
793
|
+
*/
|
|
794
|
+
isEnabled(): boolean;
|
|
784
795
|
/**
|
|
785
796
|
* Emit a single MappedSpan to the configured OTLP backend.
|
|
786
797
|
*
|
package/dist/index.js
CHANGED